Why do we bother with IE?

Posted on October 18th, 2007 in On My Mind by Patrick

Why do we web developers spend so many hours making web pages work for broken browsers like Internet Explorer? Aside from the technical challenge it's a complete waste of our collective energy, and every time you implement a work-around you're giving people one less reason to ditch the non-standards-compliant browser. Ok, if you're building a site for someone else they'll probably stipulate that you need to make the site as accessible as possible, so go ahead and apply the hacks for them. But if it's your own site, what's your excuse?

Firefox is obviously my browser of choice but there's also plenty of other alternatives to Internet Explorer. As of today, anyone viewing this site in Internet Explorer will be presented with a message across the top of the site encouraging them to ditch IE for a browser that supports the Open Web.

For those interested in implementing a similar scheme on their wordpress blogs, the code I have used is shown below (a modified version of Markus Opolka's Anti IE Bar wordpress plugin)

<?php

function wp_anti_ie_bar() {
        $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
        $isOpera = !(strpos($ua, "opera") === false);
        $isIE = !$isOpera && !(strpos($ua, "msie") === false);
        if ($isIE) {
                echo "<div class='meta'>";
                echo "It looks like you're using <strong><a href='http://en.wikipedia.org/wiki/Criticism_of_Internet_Explorer' target='_blank'>Microsoft Internet Explorer</a></strong> to browse the web. For the sake of <a href='http://www.alternativebrowseralliance.com/why.html' target='_blank'>the open web and the future of the internet</a>, not to mention your own <a href='http://www.mozilla-europe.org/en/products/firefox/features/#experience' target='_blank'>web browsing experience</a> and <a href='http://www.mozilla-europe.org/en/products/firefox/features/#secure' target='_blank'>security</a>, please do yourself a favour and switch to <a href='http://getfirefox.com' target='_blank'>Firefox</a> (follow the link for instructions on how to download and install Firefox).";
                echo "< /div>";
        }       
}

function wp_anti_ie_bar_header() {
        if (function_exists ('wp_anti_ie_bar')) {
                wp_anti_ie_bar();
        }
}

add_action('wp_head', 'wp_anti_ie_bar_header');
?>

  • Comments Off

Multiple Columns Bookmarklet

Posted on October 5th, 2007 in Bookmarklets by Patrick

Reading large chunks of text on a widescreen monitor can be a real pain if your eyes have to read across long horizontal lines. That's why newspapers print articles in columns! Ideally, websites should too, at least when you're trying to view them on a large monitor. Obviously you can't expect webpage designers to predict the size of your screen, but if you're using Firefox you can use this simple bookmarklet I wrote to reformat a selection of text (or the whole page) into multiple columns yourself.

How to use it the Multiple Columns Bookmarklet:
This is the link to my Multiple Columns Bookmarklet.

For starters, try it out yourself on this page! Select a few words in the first paragraph of this page and click the bookmarklet link. You should see it magically reformat into multiple columns 200px wide.

Now select two continuous paragraphs and click the bookmarklet link. You should see the entire article reformatted into easy to read columns. Cool huh?

If you want to use the bookmarklet on other pages, bookmark it now. When you're on a page that you want to reformat select the chunk of text and click on the bookmarklet. voila!

If you select text a single paragraph, only that paragraph will be turned into columns. If you select multiple paragraphs, the containing DOM element will be reformated (this isn't perfect but it usually does what you want). If no text is selected when you launch the bookmarklet, the entire page will be turned into multiple columns (that won't look great on my blog, but it's handy on pages with minimal styling)

If you add a keyword such as col to your bookmarklet link (Right Click > Properties), then you can launch the bookmarklet from the location bar by typing col rather than clicking on the link.

Finally, if you provide an argument of max, eg. col max then the maximum height of the columns will be set to the size of your web browser window. This is really handy if you're viewing a long document and you don't want the columns to scroll vertically for miles and miles (by setting the column height the columns will instead continue horizonally, just like a large-format newspaper).

In case you're wondering, the bookmarklet is only intended for Firefox because none of the other browsers have implemented any column-related CSS features.

Getting lazy in Perl

Posted on October 1st, 2007 in Perl by Patrick

Maybe it's a sign I've been spending too much time playing with javascript lately, but when I revisited some code I'd written in Perl recently I suddenly realised that the tangled web of private object initialisers I was staring at would be so much simpler if I used lazy initialisation instead. Javascript makes lazy initialisation easy because its a functional programming language:

function lazy() {
        var lazyVar = "initialValue";
        lazy = function() {return lazyVar;};
        return lazyVar;
}
console.log("Before first call: " + lazy.toString());
console.log("First call returns: " + lazy());
console.log("After first call: " + lazy.toString());
console.log("Second call returns: " + lazy());

If you run the above in a javascript console such as Firebug, you'll see that after the first call which initialises lazyVar, the function is redefined to be the closure which eliminates the initialisation step on all subsequent calls.

So anyway, I started wondering how I'd achieve the same thing in Perl. It's easy enough to see how you'd cause the initialisation to be lazy (without actually redefining the subroutine to speed up subsequent calls):

sub lazySub {
        my $self = shift;
        my $priv = "_lazy";
        return $self->{$priv} if exists $self->{$priv};
       
        return $self->{$priv} = 'initialValue';
}

The above is a handy template, but things would be a lot easier to use if we encapulated the above into a subroutine of its own:

sub lazyInit(\&) {
        my $self = shift;
        my $priv = shift;
        my $f    = shift;
        return $self->{$priv} if exists $self->{$priv};
        return $self->{$priv} = &$f;
}
sub lazy {
        my $self = shift;
        return $self->lazyInit("_lazy", sub {
                return 'initialValue';
        });
}

Now that's looking better, we're passing in a string to use as the private identifier and an anonymous subroutine to use as the initialiser.

Now when I actually started using this, I realised that the private identifier that I was using was always the name of the subroutine (with an underscore prefix to indicate that it's private). So I eliminated the first argument altogether by using caller();

sub lazyInit(\&) {
        my $self = shift;
        my $f    = shift;
       
        my $priv = "_" . (split("::", (caller(1))[3]))[-1];
       
        return $self->{$priv} if exists $self->{$priv};
       
        return $self->{$priv} = &$f;
}
sub lazy {
        my $self = shift;
        return $self->lazyInit(
                sub {
                        return "initalValue";
                }
        );
}

That's all well and good, but what if we want to be able to overwrite the value? Or force the initialising function to be called again?

sub lazyInit(\&) {
        my ($self, $initialiser, %args) = @_;
       
        my $priv = "_" . (split("::", (caller(1))[3]))[-1];
               
                if (exists $args{overwrite}) {
                        return $self->{$priv} = $args{overwrite};
                } elsif (not exists $self->{$priv} or defined $args{forceReload}) {
                return $self->{$priv} = &$initialiser;
            } else {
                return $self->{$priv};
            }
}
sub lazy {
        my ($self, %args) = @_;
        return $self->lazyInit(
                sub {
                        return "lazyValue";
                }, %args
        );
}
$self->lazy; # get value
$self->lazy(overwrite => 'newLazyValue'); # overwrite value
$self->lazy(reload => 1); # cause initialisation subroutine to be called again, returning value to 'lazyValue'
 

And you're free to use other paramaters of your own chosing in the anonymous closure (just don't use 'overwrite' or 'forceReload' to avoid conflicts!)

Finally, if the value only needs to be read-only, we can redine the subroutine after its first use (yes you can do this in Perl!) so that subsequent calls don't require the unnecessary (if defined) test:

sub lazyInit(\&) {
        my $self   = shift;
        my $f      = shift;
        my $overrideName = shift;
       
        my $priv;
        my $method;
        if (defined $overrideName) {
                $priv = "_" . (split("::", $overrideName))[-1];
                $method = $overrideName;
        } else {
                $priv = "_" . (split("::", (caller(1))[3]))[-1];
                $method = (caller(1))[3];
        }
       
        #       $self->debug("slow - $method");
        $self->{$priv} = &$f;
        {
                no warnings 'redefine';
                no strict 'refs';
                *{ $method } = sub {
                        # $self->debug("fast - $method");
                        return $self->{$priv};
                };
        }
        return $self->{$priv};
}

If you uncomment the comments and run this, you will see that the first time it is run "slow - $method" is printed, but on all subsequent calls "fast - $method" is called. I've also added the ability to override the method name used, which actually lets you achieve read-write if you call lazyInit() from a different function and have it redifine a suboutine of your chosing.

Cool huh?

  • Comments Off