Archive for category Javascript
Understanding Time Zone Detection in JavaScript
Posted by Jon in Developer, Javascript on March 5, 2011
Since writing this post, the code has changed dramatically. The code below still serves to describe the algorithm though. Read on!
After some hard searching online for help with automatically detecting user’s timezones with Javascript, I only came up with this one really good hit. Josh Fraser had done some preliminary work on the subject here. And his script worked really well for many cases.
However it soon became clear that there is an extreme abundance of ambiguities when it comes to time zones. And it all comes down to daylight saving time (DST), without which, the world would be a better place. :)
The difficult part is distinguishing between timezones,
- in the same UTC offset,
- in the same hemisphere,
- and that all use daylight saving time,
- but use daylight saving time differently!
My favorite example is the UTC+2 region, where many timezones differ only in which hour of the day DST starts yearly.
Anyway, for many reasons, it is very handy to have a robust determination of a user’s timezone at hand, I and wanted to do this the right way.
I set out trying to improve on Josh Fraser’s script and had two goals in mind:
- Automatically detect all unique modern time zones. (I don’t care about timezones as they were in the 18th century, and I don’t care that Helsinki time and Istanbul time are different historically, in modern time they are indistinguishable).
- Map these timezones to the Olson zoneinfo database, so that I can save a user’s time zone for use in system generated mails, batches, and even for displaying server generated pages to the user in their local time.
Using a simple algorithm wherein all known ambiguities regarding daylight savings are sorted out, I set about doing just this. The result of my work is now open sourced as the project jsTimezoneDetect on Bitbucket. And you can test the demo of it here.
Just to briefly describe the algorithm, it goes a little something like this. Imagine that you are in Alaska when you read this code:
function get_timezone_info() { // Alaska offset in january is -540 minutes from UTC var january_offset = get_january_offset(); // Alaska offset in june is -480 minutes from UTC var june_offset = get_june_offset(); // returns 480 // There's a -60 minutes offset difference between january and june in Alaska var diff = january_offset - june_offset; // Diff = -60, so we know that this region uses daylight savings, // and is in the northern hemisphere. Also we know that the January // offset is the common denominator for the timezone, i.e 540 minutes = 9 hours if (diff < 0) { return {'utc_offset' : january_offset, 'dst': 1, 'hemisphere' : HEMISPHERE_NORTH} } // This is where we end up for southern hemisphere daylight savings time zones else if (diff > 0) { return {'utc_offset' : june_offset, 'dst' : 1, 'hemisphere' : HEMISPHERE_SOUTH} } // this is returned for non DST time zones return {'utc_offset' : january_offset, 'dst': 0, 'hemisphere' : HEMISPHERE_UNKNOWN} }
Here are some return examples from the function, for different timezones:
// Central Australian Time (Audelaide): {utc_offset=570, dst=1, hemisphere="south"} // Central Australian Standard Time (Darwin) {utc_offset=570, dst=0, hemisphere="N/A"} // Central European Time {utc_offset=60, dst=1, hemisphere="north"} // Alaska {utc_offset=-540, dst=1, hemisphere="north"} // Mountain Time {utc_offset=-420, dst=1, hemisphere="north"}
Using the info provided by this function I can map to a list of Olson timezone info keys. However, there are ambiguities. In many cases it is not enough to check January and June to make a granular enough distinction. Therefore I added the added knowledge of ambiguous time zones to the script, and when it detects possible ambiguities it will sort them out for you by checking known dates when DST started in different regions.
If you feel the need to use this script, check out the Bitbucket repository for the complete source code.
If you just want to test it, go to the demo page.
Use tap events instead of click events in iPhone browser
Posted by Jon in iPhone, Javascript on June 18, 2010
When working on a web app for embedding in a iPhone application we came across jQTouch, a really nifty little jQuery plugin which makes it easy to create a web application UI that really resembles that of a native iPhone application.
We soon encountered a problem due to the fact that click events are rather slow to fire on the iPhone. There is a delay due to the fact that the iPhone waits for the user to complete a gesture before deciding that the intended gesture was in fact a click.
JQTouch uses divs to navigate between screens, so for example if you have the div
<div id="primary-view"></div>
you can simply navigate to it through a normal anchor link, and the transition will thanks to jQTouch be really “iPhone like”.
<a href="#primary-view">Primary view</a>
Our main problem is that we load our content dynamically through Ajax. So our links looked like this:
<a onclick="fetchContent();" href="#primary-view">Primary view</a>
This resulted in a race condition. The anchor link listens to the tap event which is fired much earlier than the click event, and therefore we mostly ended up in empty views. So we needed to replace all onclicks to ontap listeners. The problem then is that we could no longer test our webapp in a normal desktop based Safari browser.
So, we decided to happily go along and write inline onclick events on our links and other interaction elements. But while in the iPhone we see to it that the onClicks are removed and replaced with tap listeners.
That function looks like this:
function rebindClicks(){ var userAgent = navigator.userAgent.toLowerCase(); var isIphone = (userAgent.indexOf('iphone') != -1) ? true : false; if (isIphone) { // For each event with an inline onclick $('[onclick]').each(function() { var onclick = $(this).attr('onclick'); $(this).removeAttr('onclick'); // Remove the onclick attribute $(this).bind("click", preventClickEvent); // See to it that clicks never happen $(this).bind('tap', onclick); // Point taps to the onclick }); } } function preventClickEvent(event) { event.preventDefault(); }
We now call this little function everytime the DOM is changed. If something turns up with an inline onclick. It is will be rerouted by jQuery to a tap listener instead.
Again, we felt we needed to do this because many of our developers do not have a Mac (and hence do not have the iPhone simulator). And testing on the iPhone can be really time consuming. So for testing during development we wanted to use onClick, and when testing on iPhone we wanted to use taps instead.
But the biggest bonus was without a doubt that things are overall much faster in the web application. Taps fire much faster than clicks in the iPhone.
Here’s how it looks running the same app both in desktop safari and embedded into the iPhone simulator.
So you wanna be a front end developer?
Posted by Olle in Javascript on May 13, 2009
Back in the day when I was a young boy in the big IT-industry I wanted to become the greatest front end developer the web had seen. Due to circumstances, out of my hands of course, I did not reach my goal, but I did get to “know” some great ones along the way!
So I guess you possibly have some schooling to bring to the table, or you have been working with back-end stuff stuff for quite some time, you know what object oriented programming is or at least want to learn, and most importantly you have the will to learn!
When I started to become really interested in front end development back in the late 90′s, front end development was not looked upon as real programming, real programming was C++, Java and the likes. But now, we have job titles like Senior Front End Developer at for instance Yahoo and Google, so I guess that the understanding of the importance of good front end code has really elevated.
So my way of learning the craftsmanship, was to study the masters below, downloaded their code, read it, and then write my own! If it worked for me, I’m sure it will for you!
Scott Andrew LePera
What really got me started was a guy named Scott Andrew LePera(http://www.scottandrew.com/). He got me all warm and fuzzy talking about for instance event handlers in javascript and how event bubbles
Aaron Boodman
After that I stumbled over Aaron Boodman, the youngpup (and creator of Greasemonky among things) showed me all about how to create the menus that we love to have, how to make the Javascripts run smooth in animations, and how drag of elements shall be done. Back in the beginning of the 2000 he had the coolest UI on his blog, and nothing I have seen since has turned me on as much as viewing youngpup.net for the first time(except possibly 13thparallel)!
13thparallel
13thparallel made me think about coding for portability, introduced me to the concept of the Viewport among other things.
WebFX
Emil A Eklund and Erik Arvidsson at WebFX showed me that it was possible to create a forum on the web with outstanding functionality and speed(unfortunately it only looks good in MS IE), how to work with XML in advanced Javascript.
Peter-Paul Koch @Quirksmode
Quirksmode helped me really understand the differences between browsers and what do do about it. He also really introduced me to Unobtrusive JavaScript.
Remember that most of the examples above have been written back in 2001-2002, and they still work..What does this tell us, well to use the standards, and no browser specific hack, because browsers change and you will end up chasing your own tail to make things work in new browsers.