Articles in the ‘JavaScript’ Category

CSS3 Object-fit Polyfill

TL;DR; I’ve made a polyfill for CSS3 Object-fit. Download it from Github here:

The need for object-fit

A month ago, I was looking into creating a responsive grid full of images for a client. The width of the columns would vary depending upon device, and the dimensions and aspect ratio of the provided images could not be guaranteed.

The issue for me is keeping the images looking great, without skewing the dimensions and distorting the results, but I also needed them to expand or shrink to fit the boxes that they had been provided with.

A skewed picture

Knowing CSS, the property background-size: cover|contain would do this perfectly (See this A List Apart article for lots more detail), but this is for background images, and semantically, the images in my grid are part of the content, so should not be background images.
Looking for an equivalent, I found Object-fit: part of the CSS3 Image Values and Replaced Content spec. Unfortunately, browser support for this is very poor; this is the current browser implementation of this property:

As you can see, as of September 2012, only Opera support this feature! Side note: there is one other browser (there has to be for this to be for the spec to reach candidate recommendation) which is the HP TouchPad, not very useful for the majority of users

This isn’t going to get anyone very far, given that over 90% of all browser usage doesn’t support this feature. So, whilst browsers catch up, we have to use a polyfill to re-create this functionality with JavaScript.

Object-fit polyfill

The polyfill is based on jquery-object-fit by Simon Schmid, to which I’ve made some improvements:

  • Added support for cover
  • Fixed the implementation for IE and Firefox
  • Added feature detection so it uses the native implementation where possible
  • Made it re-calculate on resizing the browser for responsive layouts
  • Added a more tests to the suite

The results

Object-Fit tests

Object-fit grid of images

A responsive grid of images with the correct aspect ratios

What you get is a simple polyfill for object-fit which follows the spec as closely as it can. There is one main difference:

  • In a native implementation the image size remains the same and the picture within the image changes its dimensions, revealing grey letterboxed content. In the poly fill, an extra div is created around the image to take its dimensions and then the image is resized within that to provide the effect.

The source code is on github so please contribute if you can. I’ll be keeping this up-to-date so follow me @steveworkman on Twitter for the latest updates.

My thanks to Chris Mills of Opera for his articles and helping to explain how on earth all this works, and to Tab Atkins and the CSS WG for spelling it out. Hopefully there will be some more work on this feature soon. You can track the status of its implementation in Gecko (Firefox) and Webkit (Chrome et al) on their bug trackers (see links).

Please, let me know what you think in the comments and on github.

Interacting with HTML5 Video Players

HTML5 video players are incredibly useful, enabling developers to display video on non-flash devices (I’m looking at you, Apple). It’s really simple to get started with HTML5 video, but when you want to do something more complicated, there’s not much documentation. Thankfully, it’s really quite simple, and this article will show you how to use the HTML5 video JavaScript API to interact with the videos.

Basic video

This is the HTML:

<video id="firstvideo" style="width:100%" controls>
	<source src="" >
	<source src="" />

This is your standard HTML5 video player, with the standard browser video controls. The video has multiple sources so browsers that only support certain codecs (FireFox and Ogg for example) get the right video.

Let’s say you want the video to start when you click a button. That’s pretty easy, and looks like this:

var firstvideo = document.getElementById('firstvideo');
var playButton = document.getElementById('playfirstVideo');
playButton.addEventListener('click', function(e) {;
//jQuery version
$('#playfirstVideo').on('click', function(e) {

And if you want to pause it:

var stopButton = document.getElementById('stopfirstVideo');
stopButton.addEventListener('click', function(e) { 
//jQuery version
$('#stopfirstVideo').on('click', function(e) {

Subscribable events

That’s cool, you can interact with the element through JavaScript. If you’re a fan of the regular video controls, you can still access events fired by the video. The main ones you’ll be interested in are:

  • play – triggered when the video starts playing
  • playing – triggered whilst the video is playing
  • canplay – triggered when the video has been loaded and it can be played
  • pause – triggered when the video is paused
  • ended – triggered when the video has finished

There are lots of others too, a full list can be seen on the W3C demo for HTML5 video. These include events triggered when the video is seeked (skipped forward or backwards in time) and when the time on the video has changed.

It’s simple to hook these up using event listeners to see what’s going on.

Video state:

Try it out using this video, watching the label which says which event was fired last.

	var secondvideo = document.getElementById('secondvideo');
	var statelabel = document.getElementById('videoState');
	secondvideo.addEventListener('play', function(e) { // Repeat this for other events
		// The video is playing
		statelabel.innerHTML = "Playing";
	// jQuery example
	var statelabel = $('#videoState');
	$('#secondvideo').on('play', function(e) { // Repeat this for other events
		// The video is playing

That's the basics, from there you can use the timing event to make a caption system (tag words with data elements and mark them when their time hits in the video).

What about YouTube?

With YouTube and other embedded video players there's no direct access to the video element, which makes interacting with videos in the way shown above very difficult.
Thankfully, the kind folks at Google have thought of this and provided an API to help us through. The whole documentation is on YouTube developers and there's a great player demo, but here's the gist of it.

There's a few gotchas you need to be aware of:

  1. You've got to be using a served web page, local files won't work.
  2. If you're trying to interact more than one YouTube embed on a page, you will need to address each one individually with unique IDs, otherwise the browser won't know which video to interacti with

Got it? Great, let's head into the code.
This first section, is the embed code needed to include the video in the page. This should be standard YouTube embedding stuff.

// The element that the player will be inserted into
<div id="ytplayer"></div>
// Load the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// Replace the 'ytplayer' element with an <iframe> and
// YouTube player after the API code downloads.
var player;
function onYouTubePlayerAPIReady() {
  player = new YT.Player('ytplayer', {
    height: '390',
    width: '640',
    videoId: 'g8evyE9TuYk',
    events: {
      'onStateChange': "onytplayerStateChange"

Video state:

That's your YouTube video, now we need to subscribe to the events N.B. there's no need to subscribe to the onYouTubePlayerReady event as you've effectively done this when the API loads

function onytplayerStateChange(e) {
	document.getElementById('ytvideoState').innerHTML =;
// jQuery version
function onytplayerStateChange(e) {

As the state changes, a different value appears at the bottom. These are: unstarted (-1), ended (0), playing (1), paused (2), buffering (3), video cued (5). From there you can access any function of the YouTube JavaScript API, which mimics the HTML5 spec with a few small changes, such as the play command is playVideo() instead of just play(). Take a look at the documentation for full details about what you can do.

Vimeo too?

Yes, Vimeo can do this too. The API is similar to YouTube, but isn't quite as simple without their Frogaloop library, so have a look at their documentation for the Vimeo JavaScript API.


So, there you have it, a few bits of code to control different types of HTML5 video that are common on the web. They're really useful for counting the number of views of a video, captions, and generally making videos more interactive. Let me know what uses you come up with for it in the comments.

Node & Tell at London Web Standards #lwsnode

February 2012′s London Web Standards event at Forward London was an introduction to Node.js, the server-side javscript framework designed for high concurrency and real-time events. There were two sessions at the event, George Ornbo (@shapeshed) giving an introduction to Node, and a “Node & Tell” session, where four sets of developers came and told the gathered crowd how they’d been using Node in their work.

LWSNode - George Ornbo

Introduction to Node.js – George Ornbo

George is a front-end javascript developer who wanted a simpler way to create web apps quickly, and in a language that he knows. Enter Node.js, with its “Event driven I/O”, or better put as “Network programming with javascript”.

George fired up his browser, and gave the attendees the IP address of his laptop, which was running a simple Node.js chat server, which coped incredibly well with 100 people trying to join from their phones and laptops, showing how resilient it can be on a small laptop. We were then treated to a demo of a “Love/Hate” measure, taking a data feed from Twitter in real-time, it counted and displayed a graph of the percentage of love and hate on Twitter within the last 10 minutes. Seeing the data streaming in, and then the 30 lines of code used to create that was amazing. Node is a framework that does all the hard stuff for you, and enables you to write applications quickly and efficiently.

George then explained why it was so fast – Node works on an event loop, rather than threads. The idea is that no operation should be blocking so that Node can always keep getting http requests and fire of requests to the database or any other data sources asyncronously. It’s a big of a head scratcher to anyone who hasn’t done much high-performance javascript before, but it’s a very efficient way to program. George showed two graphs (roughly transcribed to the notes) on node performance vs apache for high concurrency and memory usage: node wipes the floor with it. Note: since this talk took place, Apache 2.4 has come out. These graphs are a bit different now but Ngix is still well ahead on speed

In summary, Node is great for high concurrency situations and for making server back-ends quickly. It’s a break from your normal programming style but is is just JavaScript when you’re over that hurdle. Give it a go!

Node and Tell Sessions

Node & Tell

All of these 4 people gave it a go and were kind enough to show us what they’d been doing.

First was Maired Buchan from Head who had made a voting system based on an Arduino and Node to collect the data. Other than that the voting machine use marble runs to capture votes, she explained that they’d tried a number of places to put the Node server to get maximum performance, eventually settling on a separate server, allowing the Arduino to just count and send a message to Node. The source code is now on GitHub.

The second talk was from Andrew Nesbitt talking about the London Node User Group (which me mentioned on and off), and showing off how he’d made the LNUG website with Node and GitHub.

The third talk was Simon Thompson talking about how he’s used Node as a prototyping language, making a drag & drop filing cabinet backed by a MongoDB. He was really impressed with how simple everything was and how little setup you needed to do before everything was working.

The final talk from Daniel Knell and Jason Grant showed a responsive web app that found interesting things to do in your local area. Using Node to help them make some of the more complex geolocation calculations, the web app is a very simple idea that is well executed. It is so good that it won first place at a recent hack day, and they finished in half the time they were given.

Node Training

If you want to learn more, go to or look into Remy Sharp’s training course, which is an excellent introduction to Node

London Web Standard crowd at Forward

London Web Standard crowd at Forward

Improving Javascript XML Node Finding Performance by 2000%

In my work, I’m parsing web services all of the time. Most of the time, they’re XML, which does not make the best use of bandwidth/CPU time (compared to JSON), however, if it’s all that you’re given then you can certainly get by. I’ve been looking into ways to speed up the XML document traversal in with jQuery after the current best practice method was removed.

The basic way to find certain nodes in an XML web service is to use the .find() method. This is used heavily by the SPServices jQuery helper (which is, in general, a great library).

$(xData.responseXML).find("[nodeName='z:row']").each(function() {
// Do stuff

That’s absolutely fine – it’s going to find the attribute nodeName with a value of z:row. However, since jQuery 1.7, this method does not work. I raised this regression in the jQuery bug tracker and was encouraged to find a solution; another selector that worked in all browsers. Unfortunately, at the time I couldn’t come up with anything better than this:

$(xData.responseXML).find("z\\:row, row").each(function() {
// Do stuff

The “z\\:row” selector works in IE and Firefox, and the “row” selector works in Chrome and Safari (I’m unable to test in Opera here, sorry). This was flagged as the solution to the problem and they wouldn’t be making any fixes to the jQuery core.

After a few weeks of using this method, I noticed that the site had been slowing down, especially in IE, and I thought this new selector was the cause. So, I looked into the performance numbers using jsPerf and I raised a bug too. My first test was to see what the current solution was doing, and whether jQuery 1.7 had made things worse.
Test case:

So, performance in Chrome is identical for each of the selectors (and it’s the same in Firefox and Safari) but IE drops nearly half of its operations because it has to perform that second selector.

It’s still not very high performance though, and so I looked for other solutions.

Dmethvin suggested:

Did you try the custom plugin in the ticket? If you’re having performance issues that should be much faster.

The plugin he’s referring to is this:

jQuery.fn.filterNode = function(name){
   return this.filter(function(){
      return this.nodeName === name;

This filters content by their nodeName and compares it against the name that you gave it. The issue with this is that .filter() does not traverse down the tree, staying at the level of the set of objects that it was given. Therefore, a quick solution was this:

$(xData.responseXML).children().children().children().children().children().children().children().filterNode('z:row').each(function() {
// Do stuff

jsPerf Test:

Wow, that’s about 50 times faster. Even IE beats Chrome when doing this operation. The simple reason is that it’s got a smaller set of objects to go through and it’s comparing a single attribute rather than parsing the text of the XML to try and find the namespaced element.

Still, I wasn’t satisfied as in order to achieve that performance, I had to know how deep I was going to be going in order to retrieve the set. So, back to the bug and another suggestion by dmethvin:

If you’re going that deep, use a filter function passed to .find(). How does that fare?

After a few attempts, a colleague of mine came up with this beauty:

$.fn.filterNode = function(name) {
      return this.find('*').filter(function() {
        return this.nodeName === name;

jsPerf test:

Incredible performance increase using .find('*').filterNode('z:row')

Using .find(‘*’).filter() increased performance to 200x faster than the original .find(‘z:row’) selector

I mean, wow, that’s incredible. On the graph, those tiny little bits of colour are the original selectors, and those only 20% of the way up are the previous massive performance increase by using filter. It should also be noted that IE8 performance using this selector increased in jQuery 1.7 in comparison to when using jQuery 1.6.

Side-note: IE10′s javascript performance is almost equal to that of Google Chrome. In comparison, IE9 (not shown) is about half of that.

The reason for this massive increase is that it’s backed by native selectors. A .find(‘*’) will translate into element.querySelectorAll(‘*’) which is very fast when compared to doing 8 .children() calls.

Dealing with large amounts of data from web services needs to be fast. Using a simple .find() on the node name no-longer works and alternatives have been investigated. The fastest method, using a short one-line plug-in, improves performance by up to 2000% compared to the old methodology.

I’ll be notifying the SPServices group of this post, and hopefully they can improve the performance of their library.