jQuery UI Spinner update

Sorry for no news these past few months. It's been very hectic since the new family addition back in Dec which I managed to keep low key. ;) I feel so guilty now for neglecting this blog and my readers (don't think I have any regulars anyway so I guess nothing missed!), but hey priorities are priorities!

Right, the reason for this post is that there has been some recent exciting updates to the spinner which I would love to get feedback on from the public. Thanks to Brant Burnett, the Spinner has been re-invigorated and looks set to become a kick ass component in the making!

We've added a bunch of new features and updates including:

  • support for jquery 1.3.2
  • support for ThemeRoller
  • spinning hexidecimals and other numbering systems
  • ability to auto-hide buttons and show on hover with customizable speeds
  • better keyboard interaction - you could now use PgUp/PgDn to setup up/down in a large increment set by options

We also have a lot more in the works, such as:

  • ability to spin time and date
  • segment spinning based on formatter
  • HTML5 support
  • and more...

If interested, check out the latest demo

We're still in the planning / development stage so any features you see now or currently being planned may not necessarily land in the final release. It all depends on what you want - collectively that is! So if there is something you really think should be added please shout in the dev mailing list or on the UI planning wiki.

Looking forward to some feedback.

Thanks!

jQuery UI 1.7 released

Today marks the release of jQuery UI 1.6 1.7. Kudos to UI team members who've done a fantastic job!

I'm pretty excited not only because I'm now part of this fantastic team but also with where UI is headed and how it has progressed thus far. UI is still pretty young compared to other UI libraries so there is much to learn from the likes of Dojo, ExtJS and YUI - all great frameworks in their own right.

1.7 see's a total refactor of the UI CSS Framework and ThemeRoller v2. This must be by far the greatest visible improvement in this version of UI. Though it is but one part of the hard work put into this release.

For full details on this release see the official release announcement.

Cross browser equal height that works

Note: This article was first posted to the Lemon Digital Blog.

Since its dawn, CSS has been plagued with the lack of a bullet proof technic to produce equal height columns, boxes and grids. The fortunate few have been able to avoid this problem by "designing for the Web" — no crazy fonts; no equal height.

For those unfortunate millions, it isn't so cut 'n' dry. Many designers continue to create vertically aligned and beautifully designed mock-ups in PhotoShop fully expecting the end result to look the same on the Web (and quite rightly so); if not, at least the columns should remain at equal height in all scenarios!

Thankfully display:table-cell and display:inline-block come to the rescue. Like magic, these change the characteristics of any block level element in amazing ways giving elements table-cell like behaviour; The latter even allows proper element tiling in an orderly fashion. If you come from the hybrid-layout era you'd know how convenient tables for layout were. These two CSS properties give the best of both worlds - better markup semantics with grid-like features.

This sounds like fancy stuff but really, it is quite simple. Code always speaks louder than words so here's an example to get the juices going: Working with cells in CSS

Now, let me take you through the code once you've had a gander through the source code...

.grid { display: table; }
.grid li { display: table-cell; }

These two lines are all we need to change a list into a table row. But here's the catch — this only works in Mozilla, Opera and Safari browsers; as usual IE is the odd one out. The forthcoming IE8 will support these display values but for now we have to hack our way to a solution that really works. Here's where things get interesting.

To get equal height in IE we turn to inline-block. IE has some buggy CSS support. inline-block only works in IE if we duplicate it with an inline call afterwards, like so:

.grid {
  width: 100%;
  height: 1%;
}
.grid li {
  display: inline-block;
  vertical-align: top;
  height: 100%;
}
.grid li {
  display: inline;
  width: 24.9%;
}

In the above we're specifying a width of 24.9% — this value will be different depending on the number of cells in a row. Our example has four, so in theory it should be 25%. This weird value is just evidence how bad IE's support is when it comes to CSS.

Finally to produce equal height columns we increase the bottom padding to a very high value to overcome the varying content height:

/* equal column height hack - for IE6 & IE7 only */
.grid {
  voice-family: "\"}\"";
  voice-family: inherit;
  overflow: hidden;
}
.grid li {
  voice-family: "\"}\"";
  voice-family: inherit;
  padding-bottom: 9999px;
  margin-bottom: -9999px;
}

That's it! Pretty simple if it wasn't for IE! ;)

Here are two more examples based on the concepts talked about in this article:

Further reading:

Go crazy!

@font-face in IE

An indepth article just out by Jon Tang on how to make @font-face work in IE. A recommended read for all interested in typopgraphy for the Web:

@font-face in IE: Making Web Fonts Work

We're one step closer to ditching sIFR and Flir et al.

jQuery: how to tell if you’re scroll to bottom?

This is a question a jQuery user asked recently. It's a simple question without a simple answer. There is no inverse equivalent to scrollTop=0 (i.e. scrollBottom=0) so the solution requires some thought.

The scenario is this — we have a fixed height div with overflow:auto and we want to use JavaScript to programmatically scroll to bottom and also to execute some code if we're at the bottom. Our div looks like this (using inline styles for the sake of this example):

<div id="box" style="height:300px; overflow:auto;">
  <!-- Your content goes here -->
</div>

To scroll to bottom programmatically we do:

$('#box').animate({scrollTop: $('#box')[0].scrollHeight});

And to check whether we're scrolled to bottom:

var elem = $('#box');
if (elem[0].scrollHeight - elem.scrollTop() == elem.outerHeight()) {
  // We're at the bottom.
}

That's pretty easy, right? As noticed scrollHeight is the key to this solution.

A bit of info about scrollHeight: First introduced by MSIE and supported since version 4, [1] scrollHeight gets the height of an element's content including padding but not margins. Though scrollHeight is currently supported by all major browsers it is not part of a W3C recommendation so still considered proprietary. [2]

Now, some of you reading this might not like scrollHeight because it's not a W3C recommendation. So for the interest of this group let's explore an alternative solution.

Your first stab at the alternative to check whether we're scrolled to bottom might look something like this:

if ($('#box').scrollTop() == $('#box').outerHeight()) {
  // We're at the bottom.
}

Novel, but that doesn't work! scrollTop is quite an arbitrary value. In our case depending on which browser you choose the answer could be anything from 244px (Safari) to 289px (IE7). Clearly this is not a viable solution.

To determine whether we're truely at rock bottom we have to get the height of the element's content and do a calculation based on that. Now we're immediately faced with another problem — there is no sane way of determining the actual height of an element's content because .outerHeight() always gives 300px plus padding as the answer. We could use an inner div to get over this problem:

<div id="box" style="height:300px; overflow:auto;">
  <div class="inner">
    <!-- Your content goes here -->
  </div>
</div>

So now we have a way of determining content height we can scroll to bottom:

$('#box').animate({scrollTop: $('#box > .inner').outerHeight()});

And to check whether we're scrolled to bottom we use the offset method:

var elem = $('#box');
var inner = $('#box > .inner');
if ( Math.abs(inner.offset().top) + elem.height() + elem.offset().top >= inner.outerHeight() ) {
  // We're at the bottom!
}

Not as striaght forward as scrollHeight aye?

Here's a test page encompassing the stuff talked about in this article.

References:
[1] scrollHeight Property
[2] element.scrollHeight

FON Free WiFi

I'm sure you will agree this is nothing new but I've been intrigued by the FON Free WiFi service for quite some time, just never got round to sharing my thoughts.

With the recent horror stories about wireless mobile subscribers racking up thousands of dollars in mobile data charges I thought I'd finally blog a bit about FON.

Martin Varsavsky founded FON on February 2006 in Madrid, Spain. FON’s mission is to stimulate the growth of WiFi around the world by creating a global Community of “Foneros”. FON is the largest WiFi community and recently reached 1 million members this September.

FON's goal is to provide Free WiFi access everywhere. To do this they had the idea that to receive you must first give — plant a small mustard seed and receive 10, 20 and 100 folds.

When I first heard about FON, the concept of opening my WiFi to public was a bit scary. For starters you're asking for trouble because it involves sharing on an unencrypted channel, leaving you vulnerable to malicous attacks. However, I later discovered to share a connection with FON you need their Fonero router. This router has two APs built-in, one for personal use (encrypted via WPA) and the other open to public (unencrypted). It was instant buy-in for me after that. :)

The potential for FON is huge, especially in a small city like Hong Kong. WiFi mobility is a key step towards the evolution of the Internet. To move from stationary workstations to mobile on-the-go always-on access the public needs affordable, available and reliable access with good coverage. FON might just have the right sort of ecosystem to provide for Hong Kong.

Microsoft to adopt jQuery

Some exciting news just came out — Microsoft plans to adopt jQuery making it part of their official development platform. So it will be shipped with Visual Studio and have all that intellisense goodness. I'm pretty excited about this news. Though I no longer use Microsoft development products it is a testiment to the world of jQuery's continual growth and rise as one of the best JavaScript libraries in existance.

Read the official annoucements:

Another Barcamp bites the dust

Barcamp Hong Kong 2008 sponsors
Photo: Ryanne Lai

Like last year, this years' Barcamp Hong Kong attracted some amazing people. The sponsors have clearly grown too with big names such as Yahoo!, Adobe and Microsoft added to the pot.

Unfortunately I missed most of the morning talks, including the HKSUA launch. I arrived just in time to catch the last few slides of Julien Wong's YUI Library talk. During the talk there were some interesting discussions on other JavaScript frameworks, a question that always pops up in such talks. I voiced my opinion saying that it is a matter of taste and in terms of core features, the offering amongst popular JavaScript frameworks are more or less the same.

Next I sat in the Making iPhone Apps (English) session. Wasn't too impressed with Objective-C, actually more disappointed by the many pitfalls and gotchas that William Taysom, co-founder of JadeTower was alluring to. Didn't get much out of this one unfortunately.

Gary Sweeting - Open Source and Microsoft
Photo: Ryanne Lai

The Open Source and Microsoft talk by Gary Sweeting, Platform Strategy Lead at Microsoft was very interesting. Gary tries to implant the idea of good business sense. What I got was Open Source Software (OSS) only makes sense to a certain degree in order for M$ to make an annual turnover of $60+ billion and that OSS and Proprietary can work together as mixed source (corrected from comment by Gary — was "can work together and converge at a neutral point"). In a way I could understand his arguments. Who wants to earn less when they know they could earn more? But on thinking about the philosophy of OSS it is not about making money but rather knowledge sharing and collective intelligence — much like the scientific world.

Napoleon Biggs - Twitter Visualisations
Photo: Belle Liu

The Twitter - Visualising Conversations talk was a real eye opener. I always found tweets very noisy; most tweeters use it to satisfy their own egos — who wants to know you're brushing your teeth or in your pyjams?!? Napoleon Biggs took us through a journey of meaningful aggregation of twitter conversations through analysing people's emotions. The highlight of his talk was wefeelfine.org which is an artwork of human emotions using visualisation movements — the Madness movements look a lot like code_swarm. Napoleon finishes off with a challenge for someone to create a Chinese version of wefeelfine.org. Is anyone out there up to the challenge? I'm tempted but don't have such time on my hands. If wefeelfine.org started aggregating conversations in Chinese their API would be very enticing [hint]. ;)

Edison Wong demonstrates Drupal theming. He gave us some useful tips on how to manage a single theme across version 5, 6 & 7. Hong Kong Drupallers have yearned for a meet-up and this talk is the catalyst! A Drupal meet-up will be happening sometime this month! Keep an eye on groups.drupal.org/hongkong and the Hong Kong Drupal User Group.

The highlight of the day must surely be the Start-up Lightening talks! Each person with a start-up idea had 4 minutes to pitch it to the audience. The winner gets an Xbox 360. I voted for no. 8 as it was similar to an idea that's been brewing in my mind for months! I hope he manages to pull this off!

Now that Barcamp is finally over all we could do is reminisce the past and look forward to the next Barcamp.

The story behind Google Chrome

Niall Kennedy tells us the story behind Google Chrome. A facinating read and interesting karma behind staff hires and acquisitions that made Chrome possible. Whether by chance or calculation it is a Win win situation for all of us!

Django: cheat sheet

The guys at Mercurytide have released a new Django 1.0 cheat sheet. Thanks guys this will be very handy indeed!