Skip to content

Instantly share code, notes, and snippets.

@voidfiles
Created November 27, 2011 08:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save voidfiles/1397205 to your computer and use it in GitHub Desktop.
Save voidfiles/1397205 to your computer and use it in GitHub Desktop.
Breakdown of flickrs pre script loading event handler
Production Tear Down
How does Flickr handle the problems of loading scripts asynchronously.
If you are using an asynch loader, or even if you are just putting your scripts at the bottom of your DOM, you have a problem. In some cases your scripts will load after the user has clicked on something that requires there to be a javascript function to handle the click. It's possible you have a non-js flow, but if the user has JS we want them to use that flow, even if the JS hasn't loaded yet. You need some way of handling events before all of your scripts have finished loading.
There are a number of ways we could do this, but it's helpful to look at a working implementation. This is going to be a two part series. First, we are going to look at how Flickr does this. In the second part, we can take the code that flickr uses and extract the main features so that anyone can use the code.
In all of the code that Flickr loads before the body this is the part that matters to us.
https://gist.github.com/1394593
You might have questions about some of the pieces. F is the global Flickr object that contains all of Flickrs' javascript. Not only is this a common pattern among Frontends, this technique is widely taught, and accepted at Yahoo. By keeping all of your sites functionality in one global object you are not polluting the global namespace. It also is a great way to organize your code.
## What's the Gist
Let's break down what the driving force behind this code is. First, if a user beats all your code from loading, you want to handle the users click somehow. You may not need to handle it completely, you just want your interface to be response. You might want to run some code in between the time that the click event is fired, and when the module that can handle the event is loaded. Finally, you will want to run some code as soon as the rest of your code has finished loading.
So, basically, there are two phases. interim, and cleanup. Interim code will be the code you run right away, as soon as the user clicks something. Cleanup code will be the code that gets run as soon as the rest of your code has finished loading. If you look at the flickr code you can see that they use this terminology interim, and cleanup.
Flickr calls this module, that handles events before your code loads, the actionQueue. Given that we now understand the basics of how the actionQueue the first step is to register a click_queue handler. An easy one to see in this in action is to look at how the handle the fav button.
## How the fav button is suppose to work.
You can see that in the un-faved state the star is not highlighted
http://dl.dropbox.com/u/133599/Screenshots/x1jg.png
Once you have liked it you can it will turn purple.
http://dl.dropbox.com/u/133599/Screenshots/_8wh.png
There are two things that need to happen when a person clicks on the favorite button.
1. The button needs to change state to purple.
1. An AJAX call needs to be made register the state change.
The visual state change is as simple as adding a class to the element. Very little code is required for that. The ajax operation on the other hand is going to require a lot more code. So, if you were going to use the actionQueue you are going to register an action that in the interim you can change the visual state, and on the cleanup you will do the ajax operation.
The reason you do this is so users will get immediate feedback. Once the module has loaded to you can then also fire off the ajax operation. You can see that this is how Flickr breaks up that operation.
https://gist.github.com/1394631
So, the register function only handles potential actions, and not actions that have actually been triggered. That is what the queue_click function is for.
The queue_click can be called when an actual event has happened. In the case of the fav button, this will be a click event.
Now, this is where things get awesome. I am a fan of killing sacred cows. One of those in the front-end community is to not use onclick attributes, its certainly become dogma for many. Clearly we can see Flickr doesn't care. I don't know the details of why Flickr is using onclick, but I have to assume its because it is the lowest common denominator, and it works.
So, if we look at the the HTML of the favorite button. You can see that the queue_click is just called from the onclick handler. In turn the function will return false if the page is still waiting for code to load, thus canceling the browsers default operation.
https://gist.github.com/1394649
And, that's it. In this manner Flickr is able to handle all of us who are able to click faster then javascript is able to load. After breaking this technique down I wondered if there might be an easier way to handle actions before they loaded.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment