Archive for June, 2009

Game changing CSS Image news

Thursday, June 25th, 2009

I spotted this on Ajaxian today:

Vlad Vuki?evi?, a leader in the Mozilla community (and brought us cool stuff like Canvas 3D!) has spoken up on the internals of the browser, which shows you the trade-offs for the spriting approach:

The biggest problem with CSS sprites is memory usage. Unless the sprite image is carefully constructed, you end up with incredible amounts of wasted space. My favourite example is from WHIT TV’s web site, where this image is used as a sprite. Note that this is a 1299×15,000 PNG. It compresses quite well — the actual download size is around 26K — but browsers don’t render compressed image data. When this image is downloaded and decompressed, it will use almost 75MB in memory (1299 * 15000 * 4). If the image didn’t have any alpha transparency, this could be maybe optimized to 1299 * 15000 * 3, though often at the expense of rendering speed. Even then, we’d be talking about 55MB. The vast majority of this image is blank; there is nothing there, no useful content whatsoever. Just loading the main WHIT page will cause your browser’s memory usage to go up by at least 75+MB, just due to that one image.

That’s not the right tradeoff to make for a website.

I know it’s fairly obvious but I never realised that the browser put all that uncompressed image data into memory before, but it explains A LOT.

For the last few years it seems we’ve focused on how to compress and compress the data we sent over the wire so our load times would be faster, but with this luxury of smaller file sizes we’ve fallen into a trap where we forgot how the browser would cope with all this extra data.

It’s a bit like when you order a 10 foot flat pack wardrobe from Ikea. The 100 mile delivery of the item from Ikea central to your house is easy. We have built a sophisticated road network and big articulated lorries and also you pay someone else to do all that bit for you.

The problem arises when it’s deposited on your doorstep, you wield the gigantic pieces of glass and chipboard through your house into your bedroom, unpack it, get out your drill, screw it all together.

Then you stop for a few hours wondering how the fuck you get this monstrously heavy behemoth off it’s back and against the correct wall of your room. This is the part we did not think about when we ordered it (hint: it usually involves several convoluted contortions, but don’t put pressure on the joints!).

I stole this image

I stole this image

When we made the initial decision, the only problem we could see was the large one immediately in front of us of how to get it to our house, we didn’t stop to think about the problems that might occur after that.  This is what we have done with images and browsers.

If it’s true it means a paradigm shift in everyday rounded corner box background images as well as an overall awareness for the weight of images in your site vs. client performance.

One of my favourite apps of this year is spotify, the reason is that as opposed to itunes’ avoirdupois nature spotify has a 16 meg ram footprint. This makes it much faster and responsive than 100meg+ depending on your library size (why itunes should be anywhere near this much and dependant on your library size is beyond me - it’s just one screen of pixels guys!). This matters to me and I suspect on a subconscious levels matters to most of spotify’s fans.  So the difference between my website devouring 150meg of your ram (if using firefox x5) vs 15meg DOES ACTUALLY MATTER.

It matters to you, your users and your clients as at the end of the day, your slowness is their bottom line.

Going back to the round corner box CSS case, it means in order to produce performant apps, we should NOT do this:

<div class="wrapper">

 <div class="inner">

 </div>

</div>

Where we stick long background image on two wrapper divs and then use the bottom one as the footer (example), but we actually HAVE to do this:

<div>

 <span class="header"></span>

 <div class="content"></div>

 <span class="footer"></span>

</div>

Where as opposed to the first example we have a repeating background on the content div which could potentially result in a 70meg ram saving for your app! This also aligns a lot better with OOCCS and I think is actually more readable on the flip side it is semantically worse as it has two extra empty divs, but lets face it two wrapping divs is hardly perfect and results in a massive image and slow site! An example is here.

a practical example of using custom events in jQuery

Sunday, June 21st, 2009

I’ve recently been converted to the practice of using jQuery custom events. At first I didn’t really see the point but then as time wore on it started to dawn on me how much more extensible it made the jQuery plug-in architecture and allowed a level of pseudo MVC, where the DOM translates literally into your view.

The example I’m going to illustrate it’s usefulness is a simple drag and drop, I recently found myself having to re-implement a drag and drop plug-in in jQuery as the standard UI plug-in although quick to implement was simply not very performant due to the incredible amount of configurability it has.

At first taking from the jQuery UI drag and drop template I started off with an implementation that was invoked by calling the following:

$("foo").dragLite({

containment : "parent",

axis : "xy",

startDrag: function() {foo.bar},

stopDrag: function() {foo.bar}

});

Pretty familiar stuff, like what you’d see on 99% of plug-ins.  So as the age old adage goes “If it ain’t broke…” until another developer came along a few months later and said “I want to hook into your stopDrag event”.

UH OH.

Well, you could do, but the only way to do that is to edit my original initialisation call and add in a call to your function in my anonymous function, which you could do, but is pretty messy, creates two fairly deep dependencies and could mean that if either of our code breaks, the functionality will not fail in a graceful way…

Clink. The penny drops. For the last few months, some people at work, some people on the web (dean edwards for one wrote an interesting post), and random tramps I met on the street, had been banging on and on about the custom event functionality in jQuery and this was why.

In my first example, I had had to pass my anon function into the last function through the initialise code, so my plug-in code looked something like this:

var dragStopped = function(event) {

//some stop drag code here

if(event.data.stopDrag) {

//execute the call back

event.data.stopDrag();

}

}

which as mentioned before means if anyone wants to add in an additional call back they have to do this:

$("foo").dragLite({

containment : "parent",

axis : "xy",

startDrag: function() {foo.bar();},

stopDrag: function() {foo.bar(); someOtherClass.someOtherCallBack();}

});

However, what if we abandon callbacks for custom events instead, so the plug-in code becomes:

var dragStopped = function(event) {

//some stop drag code here

//trigger custom event bindings

$(this).trigger("dragLite.stopDrag");

}

which won’t fail if we have no functions bound and our initialisation call becomes this

$("foo").dragLite({

containment : "parent",

axis : "xy"

}).bind("dragLite.stopDrag",foo.bar) ;

then all my other developer has to do in his code is

$("foo").bind("dragLite.stopDrag", someOtherClass.someOtherCallBack) ;

which he can do anywhere in the code, independent of whether the drag functionality has been implemented yet.

Pretty Neat, and most definitely worth doing for increased stability, better code flow and less work for you!

Why politics is like professional wrestling.

Tuesday, June 9th, 2009

oh crap.

I just read the EU election results. It appears the Tories are ontop, with UKIP coming in a close second and Labour in a head hanging shameful 3rd. To put it bluntly Britain is going down the political shitter, and anyone remaining here is on a long and chaotic ride into the sewer of obscurity with the rest of the democratic faeces of the world.

How do I know this? Because once I had an intimate knowledge of professional wrestling.
Before I developed into the refined individual I am now, I was for a period stuck in my late teens. Often after an evening of experimental indulgence, I would wake up with some sort of drug induced hangover at around one in the afternoon.brownisausten
I developed a routine that involved visiting the kitchen where I would make some sobering marmite toast and orange juice, then shuffle into the front room flick on the TV to spend the afternoon watching WWF (before it legally became a panada) and music television.
This continued pattern of behaviour allowed me to observe with intrigue and analysis the social constructs which gave me a remarkable insight into the inner workings of the social science we call politics.

You see, professional wrestling is a bit like a time lapse version of real world politics. In fact I’m sure if you record 24hours of the BBC parliament channel and speed it up by factor of 1000, it resembles about a minute of professional televised wrestling.

The beauty of professional wrestling revolves around a fairly simple storyline that repeats it’s self over and over again with minor superficial changes.

At the beginning of this loop there exists two main characters a hero and a villain, invariably the villain is the hero of the past who has become corrupt by too much power. As he becomes corrupt his hortatory deeds are slowly revealed to the baying masses ringside, and a feeling of discontent is gently seeded, growing into a tidal wave of hatred and loathing.

During this point an underdog is also presented to the crowd. Someone with the unrecognised athletic prowess who has the potential to be the new champion of the people. However, he inevitably falls foul of the corrupt current champion who halts his title shots with bureaucracy or uses favours from other powerful wrestlers to prevent himself from being usurped.

This scenario is carefully inflated to a point where the bubble of crowd and fan outrage is ready to burst until finally in one climatically cathartic moment of televisual ejaculation, the villain is defeated and the just prevail and win their well deserved title.
Then after a brief interlude of nothing much, enough time has past for the crowd to forget the events of the past and the story starts again.

But I hear you cry, how can such a simple tale be applied to politics, which is far more important and relevant to people’s lives?

Well, my theory is this: people are implicitly looking for the easiest solution, thinking is hard and tiring, a black and white solution is much easier to make a decision on and hence far more appealing than one that requires actual thought. When you consider that millions of people subscribe to the spectacle that is professional wrestling, is it really that much of a jump to think they will be manipulated in the political arena in much the same ways?angleiscameron

In fact, politicians might learn some pretty useful lessons from pro wrestling if they actually analysed it correctly.

In relating this to current politics, I think the labour party at the moment is very much taking the evil corrupt champion role with Gordon Brown looking more and more like Steve Austin.
Mr Cameron is trying desperately to be the underdog probably trying to emulate the rock but actually coming across more like Kurt Angle without the psychotic prestige and wife beating tendencies.

I like the way Brown has called upon Alan Sugar as a sort of Vince McMahon figure to help him retain his standing, but with the expenses fallacy has lost the support of the undertaker, Kane and probably the big show.

Of course nothing is set in stone, who knows who could come out of the woodwork to swing the balances. One thing though that I’m incredibly weary of was when a moment in wrestling where McMahon and stone cold got too caught up fighting each other they let The Radicalz (Chris BenoitEddie GuerreroPerry SaturnDean Malenko) take slip in unnoticed, now fortunately in professional wrestling this was short lived and they got kicked out pretty quickly. In reality however letting parties like UKIP and the BNP though the door, even if a mistake could have far reaching consequences for the future of the UK and Europe and end up setting back our advanced liberal society by decades. Something I for one am very keen on not letting happen.

Bad website.

Sunday, June 7th, 2009

Wow, I just discovered that my anti-spam plug-in was completely stopping anyone adding comments to these posts. Balls. Sorry about that, just goes to show the importance of testing.

smartTabs :: SEO friendly AJAX tabs

Sunday, June 7th, 2009

I’ve posted before about the problem of AJAX tabs and how they leave an odious flavour of frustration in the mouth of your google search engine users (that’ll be pretty much everyone then).

It’s taken me a while to get round to writing a follow up post that solves this (no, not because I couldn’t come up with a solution) but actually because I’ve been too busy on other things, *honest*.

Now the first solution I intimated back when I wrote the post was to solve it all backend, by creating a degrading experience that loaded in content on the fly. Although this is a tangible solution, it does create the problem of having several pages that have a majority of the same content, so it would work but is not optimal and would cause more work on the search engine side.

I also realised a second problem with AJAX tabs, again which hampers their everyday practicality. The use case I was considering was what happens when your user manipulates an AJAX tab to change the content sees something interesting and then tries to send that to a friend?

The resultant behaviour in fact being that he copies, pastes and emails a URL which by default takes that other user to the vanilla page without the information the original user was viewing visible. Definitely not the desired outcome.

After a while of pondering I came up with a far more elegant solution to these problems that relies on the front end rather than backend using everyone’s favourite language JavaScript. Hence the JQuery plugin “smartTabs” was born.

smartTabs aims to solve these 2 problems by taking advantage of two similar but different bits of functionality native to javascript.

In order to solve the original problem of coming in from a search engine and not being able to see the correct content we take advantage of the document.referrer property, this allows us to see the url that the page was linked to from. So a typical google URL might look something like this:

googleurl1

http://www.google.co.uk/search?source=ig&hl=en&rlz=1G1GGLQ_ENUK317&=&q=Test content 3&btnG=Google+Search&meta=lr%3D

if we analyse the querystring we see it splits into the following parts:

source=ig

hl=en

rlz=1G1GGLQ_ENUK317&

q=Test content 3 //! This is the search term

btnG=Google+Search

meta=lr%3D

now most of that is irrelevant but the q= parameter is the query of the search which is useful.

With this query data we can search the content of our tabs to see if that string exists in th hidden content, then if it does we dynamically switch the default tab to the one with the relevant content. Ta da, no more aggravated user engaging in invidious search activities to locate the content they had been promised by the search engine. To test this out you’ll need a google indexed page, fortunately I’ve hacked one to prove it works, just follow the link on the page.

For the second problem we take advantage of the html anchor hash within which to store data about which tabs are open at that precise moment.  We replicate the query string syntax as it’s familiar and people should be able to understand it easily. The result of which means that whenever you click on a tab your query string updates to something like the following:

smarttabsurl

smartTabs.html#tabSelected=mainTab1:Tab 2

Dissecting the hash string we see:

tabSelected=mainTab1:Tab 2

the tabSelected tells us that smartTabs is on the page, the mainTab1 - is the ID of the tabs & the Tab 2 is the text inside the tab that was last selected.

Our script then traverses the tabs and selects the one that matches the one in the pseudo query hash string, displaying the content that the user was viewing at the time. An example of which can be seen here.

So although my code is far from perfect, it does provide a possible solution to these conundrums. My main hope is that people start to consider the wider reaching usability problems that they introduce when they creating these flashy widgets and all the different scenarios in which they can fail the user’s expectations.

In general the tab wars are long from over, I’ve yet to see a decent aria implementation for example, but at least smartTabs brings us one step closer.