Author: Barry van Oudtshoorn

  • Google Wave & iPhone

    I just tried out Google Wave on the iPhone. Interestingly, despite an initial “your browser is not supported” message, the actual system sports a rather snazzy app-like interface on the iPhone.

    I’ll be interested to see what kind of support Wave will ‘officially’ have on mobile platforms, and perhaps even more interested in what ‘unofficial’ support there’ll be.

  • CSS Columns

    In this post, I will walk through the new columns specification that arrived in CSS 3. I will show you the current implementation state of columns in the four major rendering engines: Gecko (Firefox), Webkit (Safari & Chrome), Trident (Internet Explorer), and Presto (Opera).

    Before we get on to platform-specific issues and workarounds, though, we’ll look at the various CSS properties available for working with columns.

    For more in-depth information on columns, you should check out the W3C working draft and Mozilla’s MDC page on columns. The Webkit blog also has an article, but it’s not particularly informative.

    Contents

    I will add more to this entry as I discover more about columns — the goal is to make it an easy-to-understand reference.

    Browser capabilities

    PropertyGeckoWebkitTridentPresto
    column-count-moz-column-count-webkit-column-count
    column-width-moz-column-width-webkit-column-width
    columns-webkit-columns
    column-gap-moz-column-gap-webkit-column-gap
    column-rule-color-moz-column-rule-color-webkit-column-rule-color
    column-rule-style-moz-column-rule-style-webkit-column-rule-style
    column-rule-width-moz-column-rule-width-webkit-column-rule-width
    column-rule-moz-column-rulecolumn-rule
    column-span
    column-fill
    break-before
    break-inside

    Browsers used for testing: Firefox 3.5.4 (Windows), Safari 4.0.2 (Windows), Internet Explorer 8.0.6001, Opera 10.00 (Windows)

    Please let me know if this table is inaccurate, and I will update it.

    Browser bugs

    These are the bugs that I have encountered using CSS columns — if you know of more, please let me know, and I’ll add them to these lists.

    Gecko bugs

    • Specifying an “overflow” (or “overflow-x” or “overflow-y”) property on an element with columns prevents the column rule from being rendered at all.
    • Column rules occasionally don’t render, regardless of the “overflow” property.
    • There is no way to break columns.

    Webkit bugs

    • Pixel creep: Pixels from a later column can creep back to the bottom of the previous column. This can happen with plain text, but it is much more noticeable when you use a non-layout altering effect like text-shadow or box-shadow.
    • Text that overflows the column horizontally is chopped off
    • There is no way to break columns.

    Properties

    column-count

    Value: | auto
    Initial value: auto

    If you don’t set the column-width property, column-count specifies the number of columns into which the content should be flowed.

    If you specify column-width, column-count imposes a limit on the maximum number of columns to be rendered if you supply a numeric value.

    column-width

    Value: | auto
    Initial value: auto

    This property indicates the optimal column width — columns may be rendered narrower or wider by the UA, according to the available space.

    If column-width has the value “auto”, then the width of the columns is determined by other means (for example, column-count).

    columns

    Value: column-width && column-count

    The columns property is a short-hand property, used to set both column-width and column-count simultaneously.

    column-gap

    Value: | normal
    Initial value: normal

    Use column-gap to specify the size of the gutter that lies between columns. Most UAs will render “normal” as 1em.

    column-rule-color

    Value:

    When a column-rule is specified, you may use column-rule-color to set the colour for the line drawn between columns. This property is approximately equivalent to the various border-(?)-color properties.

    column-rule-style

    Value:

    By using column-rule-style, you may determine how the line between columns is to be rendered, if at all. Similar to border-(?)-style.

    column-rule-width

    Value:
    Initial value: medium

    column-rule-width sets the width of the line rendered in the gutter between columns. Basically, it’s the same as the border-(?)-width properties.

    column-rule

    Value: column-rule-width && column-rule-style & & column-rule-color

    Shorthand for setting all three column-rule properties.

    column-span

    Value: 1 | all
    Initial value: 1

    By using column-span, you can allow an element to span either the entire set of columns, or none at all.

    Note that you cannot set an arbitrary number of columns to span — this property essentially ‘interrupts’ the column flow and restarts it below the spanned element.

    column-fill

    Value: auto | balance
    Initial value: balance

    If you have set a height for your columnified element, setting column-fill to ‘auto’ will cause the columns to be ‘filled’ in turn, rather than have the content balanced equally between them.

  • New theme!

    Well, I spent the weekend quickly working up a new theme for my site. I wanted something was a) a lot simpler, and b) showed off some of the cool new CSS 3 features available.

    Cool CSS features used:

    • Columns (Gecko, Webkit, Presto)
    • Web fonts (Gecko, Webkit, Presto, Trident)
    • CSS gradients (Webkit)
    • CSS transforms (Gecko, Webkit)
    • Text shadow (Gecko, Webkit, Presto)
    • Assorted CSS3 selectors and pseudo-selectors (Gecko, Webkit, Presto)

    In case you’re wondering, Gecko is Firefox’s rendering engine, Webkit is Chrome & Safari, Presto is Opera, and Trident is Internet Explorer. Now you know. Tell your friends!

    All in all, lots of fun stuff to play with.

    Rendering bugs

    Of course, the fun thing about playing with cutting edge features is that you get to find all sorts of bizarre glitches and rendering issues. Here are a few that I’ve noticed during development.

    Missing letters (Presto)

    Letters just seem to go missing randomly from words — “you” becomes “yo”, for example. I think that this is caused either wholly by the downloaded font, the use of columns, or a combination of the two. Quite annoying.

    Pixel creep in columns (Webkit)

    Every now and then, pixels from a word in column B will find their way to the very bottom of column A. It’s even worse when you set a box-shadow on an element — the top of the shadow is rendered in the previous column. I’m guessing that Webkit’s column-rendering algorithm basically renders the entire area in a long strip, then cuts it into chunks and shoves them on the page. Annoying.

    Disappearing column rules (Gecko)

    Apparently, setting the “overflow” property (or “overflow-x” or “overflow-y”) on an element that is rendered in columns prevents the column rule from being rendered in Gecko. I really have no idea why this should be the case — it’s a very strange behaviour.

    HTML 5 element styling (Trident)

    Internet Explorer can’t style elements that aren’t bog-standard HTML. Unless you use “document.createElement(‘elemName’)” on them first. Ridiculous.

  • MooTools object messaging

    Events

    In JavaScript, we often tend to use events all over the place. In MooTools, the custom ‘domready’ event is particularly prevalent. However, events suffer from a few drawbacks:

    You can’t attach events to non-existent objects.

    Pretty self-explanatory, really. What this means in practice, though, is that you can’t easily let object A know when object B exists.

    If an object starts to listen for an event after it’s already fired, it’ll never hear it.

    Because content on the web isn’t always delivered in perfect order (especially when you’re loading scripts synchronously), it’s possible for an object to try to listen for an event after it’s already been fired. Obviously, this means that your listener object will never run the code that’s dependent on that event, which could be Bad Thing™.

    It’s not particularly easy to know which object is listening for which events.

    There are ways around this, but you can’t just dir() the listeners in Firebug.

    A messaging system

    For all of these reasons (and probably a few more that I’ve forgotten about), a messaging system can be an invaluable addition to your arsenal when writing JavaScript. How does a messaging system work? Well, interested objects ‘register’ themselves as listeners for particular message ‘handles’, and other objects can send messages using those ‘handles’. Below is a very simple MooTools messaging system that I knocked up, which has a few cool features, including:

    • When you register() a listener, you can have its callback immediately fire if that message has ever been sent before.
    • You can very easily see which callbacks are associated with which messages by simply dir()-ing the ‘listeners’ member.
    • You can unregister() a listener at any time (provided you’ve got a reference to the function and the handle).
    • Handles can be any valid JavaScript type — Strings, Numbers, even Objects.

    Feel free to use and extend this system — as I mentioned, this is a very simple system. If you do extend it, let me know in the comments!

    Let me know what you think about this system in the comments.

    [sourcecode language=”javascript”]
    barryvan.base.Messaging = new Class({
    listeners: $H(),
    sentMessages: [],

    initialize: function() {

    },

    /**
    * Register a listener for a particular handle.
    * handle [String]: The message ‘handle’ to listen for.
    * callback [Function]: The function to be called when the handle is sent a message. The contents of the messages will be included in the function call.
    * dontCheck [Boolean]: If falsey and the handle has had a message sent to it, immediately call the callback function (without contents), and continue to add the listener as normal.
    */
    register: function(handle, callback, dontCheck) {
    if ($type(callback) !== ‘function’) return;

    if (!dontCheck && this.sentMessages[handle]) {
    callback();
    }

    if (!this.listeners.has(handle)) this.listeners[handle] = [];
    this.listeners[handle].push(callback);
    },

    /**
    * Unregister a listener for a particular handle.
    * handle [String]: The message ‘handle’ to cease listening for.
    * callback [Function]: The function which was earlier assigned as the callback for the messages.
    */
    unregister: function(handle, callback) {
    if (this.listeners.has(handle)) {
    this.listeners[handle].erase(callback);
    }
    },

    /**
    * Send a message to the given handle with the given contents — send the contents to all the registered listeners for that handle.
    * handle [String]: The message ‘handle’ to transmit to.
    * contents [Mixed]: The contents to be sent to the listeners.
    */
    send: function(handle, contents) {
    this.sentMessages.include(handle);
    if (this.listeners.has(handle)) {
    this.listeners[handle].each(function(callback) {
    callback(contents);
    });
    }
    }
    });
    [/sourcecode]

  • SA Trip: Photographs

    As promised — the photographs! Click on a thumbnail for a larger view.

    Cape Town

    Gordon’s Bay

    Stellenbosch

    Tulbagh

    Drakenstein Lion Park

  • SA Trip: Part two

    As I write this, I’m sitting on the aeroplane somewhere east of Madagascar, on my way back to Australia. My voyage to South Africa is complete – all that now remains is the (lengthy) flight home.

    Tulbagh

    We spent the second half of the holiday based around Tulbagh, a small country town near Ceres, north of Cape Town; my grandfather lives just outside the town. Tulbagh is a very small, and quite pleasant little town, with only one (albeit sizeable) apparent problem: hayfever.

    I have never had hayfever quite so bad as that I experienced in Tulbagh. I ended up using both pills, nasal sprays, and even a surgical mask to attempt to alleviate the symptoms. And I’m not alone – not only did both of my parents also succumb to it, but a sizeable proportion of the local population also suffer from it.

    Apart from the hayfever, however, I really enjoyed it. I got the chance to essentially meet my grandfather and his wife for the first time. He has quite severe cancer, and the chemotherapy has rather unpleasant side-effects, for all its efficacy. Surprisingly, however, he was in much better shape than I had anticipated – he spends his days doing quite hard manual labour on his small-holding, growing lots of fresh produce and tending to seven dogs.

    My grandfather’s wife, Esti, is a fantastic cook, and, fortunately for us, insisted that we take most of our meals with her. It was great. 🙂

    Coffee in South Africa

    Tulbagh, and the various country towns around Tulbagh, are very quiet, sleepy places – a far cry from the cosmopolitan Stellenbosch, where, incidentally, I discovered the only café that I think worthy of that appelation in South Africa. In Australia, where there is a strong Mediterranean influence, the coffee culture is quite vibrant, and there are a multitude of cafés that actually only concern themselves with coffee. By contrast, the “cafés” in South Africa were essentially miniature restaurants, nearly all with pretty terrible coffee. As I say, I could only find one café that actually was about coffee: Vida e Café (or something similar) in Stellenbosch. Check it out if you get a chance.

    Ariel and I also went to drop a few things off for a friend at their parents’ house, and, wonder of wonders, they had an espresso machine. With decent beans. I had two cups – I really had been starved of good coffee, and their house was like a desert oasis. It actually made the three hour round trip to Piketberg to deliver chocolate biscuits, shampoo, and lollies worthwhile. (But seriously – chocolate biscuits, shampoo, and lollies. Sigh.)

    Photos

    I’m going to start culling and processing the photos we took on the trip when I get back to my desktop computer at home, and then I’ll put them up here. I might even put one or two up on Facebook for the very lazy, who I can safely insult, as they will never read this. It should all be up in a day or two.

    And hey, if you’re lucky, I might even include more of my rambling ruminations with the photos.

    Read part one

    [Posted a day after writing]

  • SA Trip: Part one

    Well, the first half of our South African sojourn has been pretty good. We spent the first week with my paternal uncle and aunt in Cape Town, or, to be more accurate, alternating between two points on either side of the city — Gordon’s Bay and Bloubergstrand.

    We also spent a night at Lanzerac Manor, which was absolutely stunning — fantastic food, accommodation, and service. We both indulged in a massage at the Lanzerac Spa, which was great. That’s the beauty of the RSA-Aus exchange rate — five star hotels and spas suddenly become affordable.

    [Pictures coming when we’re back in Australia]

    South Africa is a strange country — everywhere you look there is a stark contrast between rich and poor. There’s an awful lot of wealth, but there’s far more poverty — real poverty — than there is wealth. At nearly every traffic light in town, groups of people hawk goods — from phone chargers to rubbish collection. The slums, or “informal housing” areas stretch for miles — there’s one particularly large area just outside the Cape Town airport, which you see both from the air and driving down the motorway.

    At the same time, though, there’s an awful lot of good going on — the country town of Paarl has built brick houses to replace the vast majority of tin shacks in the “informal housing” areas, and many country towns have a similar “scheme”. Also, because of the World Cup Soccer soon to be played out in South Africa, you can see that there is a concerted effort to “clean the place up” — there’s very little rubbish on the sides of the streets, and large infrastructure works and repairs are under way. This means more jobs, less poverty, and more traffic jams, so on balance it’s a good thing.

    We’re now in the small country town of Tulbagh, near Ceres, roughly 200km inland from Cape Town. It’s nice, but unfortunately has an exceptionally high pollen count, which has pretty much left me debilitated, although it’s left Ariel unfazed.

    As I pointed out earlier, we’ll be uploading photos when we get back to Australia — for now, the internet connection we’re using here, in a small internet cafe, is too abominably slow to do anything much.

  • South African Holiday

    Well, tomorrow my wife and I, together with my parents, leave for South Africa for two weeks. It should be good — catching up with family, visiting various lion parks, and so on.

    I fully intend to post photos, notes, and whatever here during the trip, but I also fully anticipate that this won’t happen. 🙂 Nevertheless, I will endeavour to put something up about the holiday, even if it’s after the fact.

  • Cartoon

    A cartoon my wife drew for me

    Here is a cartoon that my wife drew for me. I think that it is particularly clever. 😀

  • Apple Keyboard & Windows

    At work, I recently moved to one of the slim aluminium Apple keyboards, and I love it. Linux and the keyboard play nicely together without any hassles whatsoever. So, emboldened by this success, I bought another one for use at home — with my Windows machine. The results were, well, less than dazzling.

    Whilst the keyboard’s basic functions pose no problem to Windows — it is, after all, just a USB keyboard — there were some problems, especially with the Function keys. Basically, the [fn] key doesn’t seem to generate a recognisable keycode for Windows, which meant that I didn’t have access to all the spiffy multimedia controls and so on.

    After much googling and installation of keyboard drivers originally distributed with Apple’s Boot Camp, I eventually stumbled across a great little utility by Petr Laštovička, which allows a fairly clean and simple remapping of keys to functions. [For the Googlers who’ve arrived here looking for a solution to the Mac Keyboard + Windows problem, it beats out Sharpkeys for me because it can handle key combos.]

    So, ultimately, I have ended with a very good-looking, nice-feeling keyboard that works 99% of the way I want it to. My biggest gripe is that changing the volume now requires me to press [Command]+[Fn]+[F10/F11/F12], rather than just [Fn]+[F10/F11/F12], as I can in Linux. I’m quite happy with this keyboard — although it’s not 100%, it’s definitely much better than most similarly-priced keyboards (at $69AUD).

  • Terminal

    My first track in quite a while. :/ This one is a bit of a different from my usual stuff (although I tend to say that a lot nowadays… Hmm…). Not quite sure why I had such a long hiatus, but hopefully this track spells the end of it. We’ll see.

    I made use of some of the samples that my friends at ModPlug Central gave me for a wedding present, as well as mutilating some of my other sample libraries.

    [audio:http://www.barryvan.com.au/music/Terminal.mp3]

    Download

  • CSS minifier and alphabetiser

    Update: This project is now hosted on GitHub: https://github.com/barryvan/CSSMin/

    There are quite a few CSS minifiers out there, which can bring the raw size of your CSS files down substantially. There are, however, significant gains to be made if the CSS is minified so that it gzips better. To that end, I’ve written a small Java application that will read in a CSS file and output its contents to stdout or another file in a format that’s optimised for gzipping.

    The problem

    A gzipped file will be stored most efficiently when there are many recurring strings in the file. This means that when writing CSS files, this code:
    [sourcecode language=”css”].pony {
    border: solid red 1px;
    font-weight: bold;
    }
    .lemur {
    border: solid red 1px;
    font-weight: normal;
    }[/sourcecode]
    will be better-compressed than this:
    [sourcecode language=”css”].pony {
    border: solid red 1px;
    font-weight: bold;
    }
    .lemur {
    font-weight: normal;
    border: red solid 1px;
    }[/sourcecode]
    In the first sample, notice that we have a very long string that occurs twice:

     {
    border-style: solid red 1px;
    font-weight: 

    In the second sample, there are strings that occur more than once, but they’re much shorter. The gzip algorithm can, in the first case, replace that entire long string with a much shorter placeholder.

    What it does

    So, how can we optimise CSS for gzipping, then? A file that’s minified using this CSS Minifier will have these operations applied:

    • All comments removed.
    • The properties within all selectors ordered alphabetically.
    • The values for all properties ordered alphabetically.
    • All unnecessary whitespace removed.
    • Font weights replaced by their numeric counterparts (which are shorter).
    • Quotes stripped wherever possible.
    • As much text as possible transformed to lowercase.
    • Prefixed properties (for example, -moz-box-sizing) placed before the unprefixed variant (box-sizing).
    • Colours simplified from rgb() to six- or three-digit hex values, or simple names.
    • Units on values of 0 stripped.
    • Multi-parameter items simplified to as few parameters as possible.
    • Various other small tweaks and adjustments made.

    By way of example, the following CSS snippet:
    [sourcecode language=”css”]body {
    padding: 8px;
    margin: 0;
    background-color: blue;
    color: white;
    font-family: “Trebuchet MS”, sans-serif;
    }

    h1 {
    margin: 0;
    padding: 0;
    font-size: 200%;
    color: #0F0;
    font-weight: bold;
    }

    p {
    margin: 0 0 2em;
    line-height: 2em;
    }[/sourcecode]
    would be formatted to the following (note that line breaks have been added for legibility — no line breaks appear in the final output):

    body{background-color:blue;color:#fff;font-family:"trebuchet ms",sans-serif;
    margin:0;padding:8px}h1{color:#0f0;font-size:200%;font-weight:700;margin:0;
    padding:0}p{line-height:2em;margin:0 0 2em}

    Compression results

    These are the results of compressing the main CSS file for one of the webapps I develop at work.

     Original size (bytes)Gzipped size (bytes)
    Plain8193812291
    YUI6443410198
    LotteryPost6360910165
    CSS Drive6927510795
    CSSMin637919896

    Download

    Head over to GitHub to download the source.

    Usage

    First, if you haven’t done so yet, compile the code:
    [sourcecode]# javac CSSMin.java[/sourcecode]
    Then, you can call the minifier by running
    [sourcecode]# java CSSMin in.css [out.css][/sourcecode]
    If you do not specify an output file, the resultant CSS will be printed to stdout (and can then be redirected as you wish).

    Contact

    If you have any questions or comments about this app, or if you find a bug or some weird behaviour, just comment on this post, and I’ll see what I can do.

    You can also raise issues on GitHub, fork the project, commit changes, and more.

    If you find this utility useful, let me know!