Archive

Posts Tagged ‘Web Development’

The past present and future, all at your command with HTML5

November 8th, 2011 No comments

Dear Diary,

With the onset of HTML5 becoming increasingly supported among the many browsers out there, there are going to be a number of important changes coming to the way things work. Things such as… the MathML and SVG support, a large number of new elements and deprecation of some older obsolete ones, and most importantly (for the purposes of this article) an important change to the history API functionality!

Unfortunately, HTML5 isn’t supported in every browser… largely because older versions of browser either can’t support it or just aren’t being updated to support it. People should update their browser anyway… so many unnecessary headaches caused by having to go back and debug some random old version of IE or Firefox because someone is reluctant to update. I will say, props to Chrome for silently updating itself to the latest version and indicating that a core app restart is required with those little coloured arrows!

Due to this lack of support in all browser, *glares at IE*, another solution is required to properly combat this looming headache menace! One of the best tools at our disposal as web developers is the History.js HTML5/HTML4 wrapper.

You can find it here: https://github.com/balupton/history.js
…and a demo here: http://balupton.github.com/history.js/demo/

Straight from the description on github: “History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState.”

The key thing that the History.js adds is complete cross browser support for history behaviour on all websites. Of course, browsers that support HTML5 have a much nicer experience, but it still works very neatly in general. Thankfully, it also includes plugins for major javascript frameworks, including jQuery, Mootools and Prototype.

An implementation using History.js

One of the tasks I was working on at work was to transition an aging web application which was still using a frameset for it’s layout into a single-page application. The catch was that part of the page load was an EXTREMELY heavy client side javascript menu. As a result, simply loading the entire page each time while navigating around the application was a bit of a performance issue, resulting in page load times nearly doubled.

My solution was to implement a chromeless loading system based around caching pages in the DOM and utilizing HTML5 history API calls wherever possible to allow for fast page transitions going back and forward in the browser.

I quickly found that HTML5 wasn’t fully supported (as expected), and also that it there was still inconsistent behaviour between different browsers. After a bit of searching around online, I came across History.js, realized its potential, and began implementing it into the application.

The basic idea behind what I wanted to do was keep enough meta information about each page the user navigated to such that I could determine if it was either cached already and could be swapped in, or if it needed to be requested and cached again. This was particularly important, because closing the browser would typically cause you to lose your history for that session, but it is possible to keep track of your history even between browser loads with History.js.

As a result, the general behaviour was to to either push a new page on to the history when performing new navigation, replace an existing cached page when a forced load was required (stale data or no longer cached due to browser reload), and wrap normal browser back and forward with a history state change event.

I actually found a funny little bug while working on this solution (which may be fixed now, I haven’t bothered to confirm), where if you are using the amplify.store.js storage solution for page caching via History.js, after 1000 page loads it would simply go into an infinite loop because it couldn’t find the next “unique” page identifier to use. Page identifiers were generated by selecting a number at random between 1 and 1000… and of course testing this on development, I would constantly be reloading pages and changing states… which lead to some fun times debugging the infinite loop.

Ultimately I had to skip using the storage system, and I implemented a version of it myself in the DOM itself. I like this solution better anyway, because it gave me direct control over what was cached and how it was manipulated more so than the storage system would.

At any rate, here are a few simple code snippets of how I was using History.js:

// set up history change event
var History = window.History;
History && History.Adapter.bind(window, 'statechange', function(){});
 
// pushing new state data (History.pushState and History.replaceState have identical syntax)
History.pushState({
	state: customState,
	timestamp: pageLoadTimestamp,
	page: pageKey,
	extraData: dataObject
}, pageTitle, pageUrl, false);
 
// state change event
var onHistoryStateChange = function(e){
	var HistoryState = History.getState();
 
	// access the custom data you've assigned to the history state
	// HistoryState .data.state;
	// HistoryState .data.timestamp;
	// HistoryState .data.page;
	//
	// handle state change by either loading new page or loading cached page etc ...
}

And lastly for more reading about manipulating the browser history, Mozilla Dev has a nice article that I found useful on it here:

https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history

Your friend,
Jeff

The secrets of an elusive santa

November 27th, 2010 No comments

At some point late last year I decided thefamilywishlist.com should have a secret Santa tool. As useful a feature as it may be, I couldn’t decide on the details of integration. And as most of you know without a clear idea for a solution or interface, it’s easier to just put a feature off. There are just so many potential complications.

So put it off is what I did. However, I confidently marked Friday November 27, 2010 off on my calendar as the day that I would implement the secret Santa tool. And as unexpected as expected, that day eventually came.

I’m only partially joking. I did in fact mark November 27 for secret santa development, but did so on November 25. Less impressive, true, but — well, just less impressive all around.

I ended up adding it as a tool that can be used by registered and anonymous guests. As such, when logged in it appears under the tools menu. When not logged in, it appears as the item furthest right in the main menu.

You don’t have to be a family wishlist user to take advantage of the secret Santa tool, but it’s neater if you are. The participants you add don’t have to be registered users either, but it’s neater if they are.

 

Using the secret Santa tool

A secret Santa event is made up of some descriptive data, and a list of participants.

 

Event details

Title — The events title should be pretty self-explanatory. It lets your participants know which secret Santa the email they receive refers to. This should be especially useful if you are a participant in more than one, and if there is some participant overlap.
The initial event title is generated as “[current year] Secret Santa of [some word]“, but feel free to set the title to anything relevant to your event.

Name — The name field lets your participants know who set up the event. Useful if they need to contact you for any additional information, and in hope that when recognizing your name they won’t immediately discard the e-mail as spam.
If you’re logged in, the name field will not appear – the tool will use your name automatically.

Description — Provides a bit of space for any additional information you might like to convey (rules, gift-exchange location and time, or anything else you can think of).

 

Participants

There are two ways to add participants to your event. The easiest is if you’re logged in. Simply click on the users in the list of your friends to the left.
Additionally, You can enter e-mail addresses into the add field, and click the add » button. If the email address is already associated with a user of the system, their name will be displayed. If not, it will show their e-mail address.
If you make a mistake, click [oops] next to a participant to remove.

If you’re not logged in, don’t forget to add yourself!

 

 

Once you’ve set up your event, click the Done! (send the emails!) button. Participants will be randomly paired, and e-mails to each queued for sending.

Don’t be alarmed if they don’t receive the emails immediately. I’ve implemented a queuing system do distribute the actual mailing.
As long as the system is not in heavy use, e-mails should be sent within ten minutes. After that, you will still have to wait for them to make their way across the internet (or tangled mess, as we call it in the business).
Seriously though, I’ve called it that maybe once before.

 

The Result

Each participant is sent an e-mail which lets them know who they’re to purchase a gift for.

This should be especially useful for secret Santa events involving physically distant participants, who may otherwise need to be drawn for by another participant.

 

Tips

If you need ideas for a gift, an obvious place to look is the wishlist of the participant you’ve been assigned. If they’re not a registered user, you can add them as a friend and they’ll be invited. Beware, though, the invitation e-mail will reveal who they were invited by, which can spoil the surprise of a secret Santa. At that point, you may as well just call it Santa.

An obvious solution is to add all participants as friends before creating the event. This way, they will all receive invitations from you (the organizer) and what’s more, it will be easier for you to add them to the event.
An alternate (if less elegant) solution is to manually request that a friend invite them.

 

 

If you’ve gotten this far I expect you’re a little alarmed but not at all disgusted that I could write so many words on such a simple subject, and that I would choose to do so.
But why not put that wonder aside, and head over to the family wishlist to try out its entirely new secret santa tool?

 

128×128 and 256×256 icons and polls

November 5th, 2010 No comments

On June 2, 2007, I received an e-mail requesting that I add 128×128 and 256×256 pixel icons to the .ICO resource Bradicon creates. I added them on Bradicon’s dev site, and replied that same day, but have yet to receive an email back. I didn’t end up publishing the changes to Bradicon.

That was a long time ago!

Luke brought it up again last night, and I started to think about it. The changes to the code would be super, super easy. I am a little worried that people may be upset if their icons are suddenly ~22 times as large in file size, which is a substantial increase. ~0.3 MB seems excessive for a favicon.

It really comes down to what people are using the icons for, and it looks like a lot of them are as custom shortcuts for their desktops. For many of these people, the additional sizes will be useful and the increased file size should not be an issue.
On the other hand, I use Bradicon to create favicons and, on rare occassions, application icons. I’m sure some percent of people use it for this same purpose, but (based on the sites that link to Bradicon) I suspect that percent is small.

One option is to add a checkbox that says something along the lines of Add large icons, and have it default to checked. While this offers more flexibility, it will also increase the complexity of the interface. I’ve always kind of felt that one of Bradicon’s strong points was its ease-of-use.

I’ve added a box to Bradicon asking people if they’d welcome the addition. Rather than find a poll system, i’ve added some javascript to the links which will send result page views to Google Analytics.
When users click the links, nothing happens. This is something I should probably change. I could perhaps, replace the links with a Thanks for your input-style message.
I probably won’t do this. If someone really wants their input taken, and clicks the link a bunch of times, I think I am cool with that. That seems like semi-useful information. Also, I am lazy.

Categories: Bradicon!, Dev Tags: ,

Analytics

October 27th, 2010 No comments

Today, I updated the Google Analytics code on a few sites. I wanted to try some things to do with tracking:

 

The family wishlist

Knowing which links people followed to external websites seemed useful. It may allow me to specifically target those sites for advertisement or commission.

I added some javascript to the page which should track all external links:

$('a').each( function(i) {
	if ($(this).attr('href').startsWith('http')) {
		$(this).unbind('click').bind('click', function() {
			_gaq.push(['_trackPageview', $(this).attr('href') ]);
		});
	}
});

A smarter move would have been to strip all info from the href but the domain itself. It would make for neater, and more decipherable reports. It’s something I should do, though I probably won’t bother.

If I were more motivated, I would swap out amazon.com for amazon.ca when visitors are from Canada.

 

Bradicon

Over the past year and a bit, I’ve been manually tracking how many icons are created per day. More fun, though potentially less useful than the family wishlist stuff, I’ve now set up page tracking calls for:

  1. When a file is queued for upload
  2. When conversion from image to icon is complete
  3. When the new *.ico file is downloaded

Downloaded is now a goal in Google Analytics, and there is a funnel consisting of those three events. I’m kind of excited to see what sort of neat information it shows me, but I suspect it won’t be anything very interesting or unexpected. Who knows though?
I will soon, and from now on!