• You are currently browsing the Christian Heilmann blog archives for July, 2007.

  • Archive for July, 2007

    Looking for inline code editors

    Monday, July 30th, 2007

    Hmm, now here is an interesting task. I was asked to find an inline “code editor” which means a script or a flash widget or a (shudder) applet that allows for editing of code (PHP, JavaScript, HTML, CSS) inside an application. There are a lot of inline Rich Text editors and even some WYSIWYG editors, but the online editor that allows you to properly code inside an HTML document is CodePress.

    Have you come across others?

    [tags]CMS,inline editing,code editors,syntax highlighting[/tags]

    Show love to the Module Pattern

    Tuesday, July 24th, 2007

    Back in February 2006 I declared my love for the object literal explaining that it is a great way of making sure your scripts don’t interfere with others as all you expose to the world is a single object name. Instead of

    function init(){}
    function doStuff(){}
    var myMessage = 'oi, gerrof!';

    which might be easily overwritten you can use

    myScript = {
    init:function(){},
    doStuff:function(){},
    myMessage:'oi, gerrof!'
    }

    and this way make sure that they don’t get overwritten or overwrite other methods or variables. You can access them as myScript.init(), myScript.doStuff() and myScript.myMessage. I liked this idea so much I argued for a length of time with my technical editor at that time that I want my book to be based on this kind of scripting or not at all.

    The only annoyance I had with this is that it still leads to rather big methods, as you have to use the long name for every call of variables inside the object. True, you can use this, but when you use event handling and you don’t use the scope correction of the YUI event you’ll use that for the element the event occured on.

    myScript = {
    init:function(){
    this.doStuff();
    },
    doStuff:function(){},
    myMessage:'oi, gerrof!'
    }

    Is therefore not necessarily possible, so you need to use:

    myScript = {
    init:function(){
    myScript.doStuff();
    },
    doStuff:function(){},
    myMessage:'oi, gerrof!'
    }

    This, in much more complex scripts, can lead to a lot of code and typing (unless you use an IDE) and just seems bloated. I had a lot of problems fitting object literal scripts into 80 character code templates for the book and magazine articles for example.

    The solution to shorter code is once again a thing from the mad JavaScript scientist’s lab of Douglas Crockford called the Module Pattern. If you want a very detailed and good explanation of what it does in terms of OO sorcery, check out the easy to follow explanation of the Module Pattern by Eric Miraglia on the YUI blog.

    What the Module Pattern does for me on top of that is that it keeps my code short. I only expose those methods as public that need to be and then I can call them inside the main object by name of the method and not by objectname.methodname.

    myScript = {
    massivelyLongVariableProbablyGerman:1,
    thisIsReallyLong:function(n){},
    doStuff:function(n){},
    init:function(){
    myScript.doStuff(myScript.massivelyLongVariableProbablyGerman);
    myScript.thisIsReallyLong(myScript.massivelyLongVariableProbablyGerman);
    }
    }
    myScript.init();

    becomes

    myScript = function(){
    var massivelyLongVariableProbablyGerman = 1;
    function thisIsReallyLong(n){};
    function doStuff(n){};
    return {
    init:function(){
    doStuff(massivelyLongVariableProbablyGerman);
    thisIsReallyLong(massivelyLongVariableProbablyGerman);
    }
    };
    }();
    myScript.init();

    However, there are two problems remaining: if you want to call one public method from another public method you’d still need to go either via the this route or by prepending the main object name:

    myScript = function(){
    var massivelyLongVariableProbablyGerman = 1;
    function thisIsReallyLong(n){};
    function doStuff(n){};
    return {
    init:function(){
    doStuff(massivelyLongVariableProbablyGerman);
    thisIsReallyLong(massivelyLongVariableProbablyGerman);
    
    otherPublic() // < - has MASSIVE FAIL!
    this.otherPublic() // <- works
    myScript.otherPublic() // <- works
    
    },
    otherPublic:function(){
    }
    };
    }();
    myScript.init();

    The other problem is that I am not too happy about the return {} with all the public methods in it, it still looks a bit alien to me. Caridy Patiño offered a solution to that problem on the YUIblog by simply creating an object with a short name inside the main object that can act as a shortcut for public methods to call each other:

    var myScript = function(){
    var pub = {};
    var massivelyLongVariableProbablyGerman = 1;
    function thisIsReallyLong(n){};
    function doStuff(n){};
    pub.init = function(){
    doStuff(massivelyLongVariableProbablyGerman);
    thisIsReallyLong(massivelyLongVariableProbablyGerman);
    pub.otherPublic();
    };
    pub.otherPublic = function(){
    };
    return pub;
    }();
    myScript.init();

    This also saves me one level of indentation which means I can fit even more code in 80 characters. I will use that much more in earnest now.

    UPDATE

    If you like what you see here, take it up another notch with the revealing module pattern

    [tags]douglascrockford,module pattern,javascript,object literal,webdevtrick,code optimization,oo[/tags]

    Planning a \”Make me a speaker\” event

    Friday, July 20th, 2007

    As some of you know, Meri Williams has set up a Wiki for people who want to become speakers at summits and events at http://www.makemeaspeaker.com/ (currently spammed :-() and I am a very big fan of the idea (even pimped it in my Highland Fling Talk).

    However, except for some minor changes to the Wiki and some posts about it not much happened, which is why I am taking the initiative to take it a bit further. I already chatted to several people and we’ll organize “Make me a Speaker” events in London soon. The format will be pretty straight forward:

    • Prospective speakers have 5-10 minutes (depending on how many sign up) to present a topic of choice
    • A panel of “experts” (organizers of events, experienced speakers) will give advise and praise afterwards as to what was good and what needs improvement
    • Both the panel and the audience vote for the best presentation of the evening and the winners will get a small prize.

    I already got feedback from Foyles (the bookstore) to sponsor books as prizes and I am thinking of using the Yahoo! office in Covent Garden, London and BBC’s Bush House in Charing Cross, London (with thanks to Ian Forrester) alternately as the location of the event.

    All that is left now is to sort out a date when to do this (and my calendar is quite full right now) and actually gauging if there is interest in something like that.

    So what say you?

    [tags]makemeaspeaker,public speaking,meriwilliams,christianheilmann,ianforrester,bbc,yahoo,london[/tags]

    Return of the HTTP overhead delay – this time without a server side component

    Tuesday, July 10th, 2007

    Following my post yesterday about delaying the loading of avatar images to cut down on HTTP requests I was wondering if there is a way to do this without having to resort to a server side solution. In short, there is.

    Using the script is dead easy, simply include it in your page and make sure to include avatar images in the following format:

    
    <img src="default.gif#http://avatarurl" ... >
    

    The default.gif is your placeholder followed by a hash and the real URL. All the script does is go through all the images, check which one has a hash in its src attribute and remove everything up to the hash. If you don’t want to loop through all the images in the document, you can change two variables in the script: You can provide the ID of an element to constrain the loop to in parentID and you can provide a class that is applied to all the avatar images in avtClass. The script is Creative Commons Attibution licensed, so go nuts using it.

    Here is the script’s saga: the internet’s Drew McLellan commented yesterday on the blog about the usefulness of the idea and we talked over lunch and then Messenger how we could make it JS-only. First Drew considered the real URL as a parameter after the placeholder, but that messed with the caching as each default.gif?foo would be considered an unique URL. We then thought about fragment identifiers, as for a browser foo.html and foo.html#bar is the same resource.

    We weren’t sure about the validity of a real URL as a fragment identifier, and as we are too lazy to look these up I consulted the walking standards encyclopedia, David Dorward and got the green light for the fragment identifier idea. On my way out the office I put the idea past Lawrence Carvalho who thought it necessary to allow for a parent ID and a class to constrain the amount of replaced images. Five stops later on the Picadilly line the script was done and now I am uploading it. It is great to have the right people working next to you.

    [tags]performance,httpoverheaddelay,webdevtrick,javascript,images[/tags]

    Thinking lowsrc – how to make sites appear to be available a lot faster

    Monday, July 9th, 2007

    *ZOMG Update!*: We put our heads together and came up with a client side solution without a PHP component that does the same as this one explained in detail here.

    Those of you who’ve been around some years may remember an otherwise forgotten non-standardized HTML attribute called lowsrc. It was supported by Netscape browsers and allowed you to define a black and white preview picture of the real picture. The browser would load the “diet” black and white shot first and then load the “full fat” colour shot and overlay the preview picture line by line. Alongside progressive JPGs (which load in lower quality first and then progressively get clearer) and interlaced GIFs (which loaded every second line first and then subsequently filled up the rest) this was a killer trick to speed up your web site in the times when 56K Modems were luxury items.

    How come that we have fast connections but sites are still slow?

    Most of us are on faster connections these days and yet we constantly get annoyed at how long it takes for some pages to finish loading. The reason is that we embed too many resources (videos, images, scripts) in the page.

    Browsers in general seem to download two resources in parallel and stall the rest of the dependencies from loading until these are done. When you use a lot of images, especially from different servers this leads to a long delay, as for each of these images the browser needs to initiate an HTTP request, convert the URL to a DNS and IP and pull the image.

    Furthermore the browser shows us an endless spinning wheel or progress bar and informs us that “10 of 73 resources” have been loaded. While this does not necessarily mean that we cannot use the current document (browsers these days at least don’t stop rendering halfway through – unless you use inline scripting that fails) it still gives us an impression that things still happen and the document is not ready for us yet.

    The most common example where this happens is when you use avatars on your site – the small images depicting the user that contributed the content adjacent to it. Using a lot of these can make the page appear very slow, as the following example which loads and display fifty results from Yahoo! Answers with avatars shows.

    • Load fifty answers with avatars (opens in a new window) avatars.php

    During testing on this connection using Firebug’s network monitor this loaded 30 resources with 125kb in overall 14.92 seconds.

    This delay also means that scripts that get fired via the onload handler of the window will get delayed until all the images were loaded, which is why libraries have to use methods like onAvailable , onDOMReady or onContentReady to run our scripts.

    However, if you are in control of the middle tier of your server than there is a solution to make this delay less painful for the end user and seemingly deliver your pages quicker.

    • Load fifty answers with avatars delayed (opens in a new window) avatarsdelay.php

    During testing on this connection using Firebug’s network monitor this loaded 30 resources with 125kb in overall 12.7 seconds, however the wheel of the browser stopped spinning after 3 seconds and I got the impression all is done. What was the difference?

    The avatars.php example uses CURL and PHP to load information from the Yahoo! Answers API. We serialize the return value and spit out the HTML:

    <?php
    $url = 'http://answers.yahooapis.com/AnswersService/V1/questionSearch?appid=YahooDemo&query=sport&results=50&output=php';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($ch);
    curl_close($ch);
    $output = unserialize($result);
    foreach($output['Questions'] as $key=>$p){
    echo '<div><img src="'.$p['UserPhotoURL'].'" alt="'.$p['UserNick'].'" width="48" height="48">';
    echo '<h2>'.$p['Subject'].'</h2>';
    echo '<p>'.$p['Content'].'</p></div>';
    }
    ?>

    This results in all of the HTTP requests that delay the user-felt availability of the site. A simple trick and small change to the script makes this delay obsolete.

    Shifting the HTTP overhead further down the timeline

    Using JavaScript we have the option to delay the loading of extra content that is “not really needed” for the enjoyment and availability of your site. As the avatars are not really necessary to get the gist of the answers page, we can alter the backend script to harvest the image URLs and replace all the images with different URLs with a placeholder – say a “grey man” picture. In order to allow us to identify the pictures later and link them to the harvested URL, we add a dynamic ID.

    <?php
    $url = 'http://answers.yahooapis.com/AnswersService/V1/questionSearch?appid=YahooDemo&query=sport&results=50&output=php';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($ch);
    curl_close($ch);
    $output = unserialize($result);
    foreach($output['Questions'] as $key=>$p){
    echo '<div><img <strong>id="i-'.$key.'"</strong> src="http://us.i1.yimg.com/us.yimg.com/i/us/sch/gr2/nophoto3_48x48.gif" width="48" height="48" alt="'.$p[UserNick].'">';
    echo '<h2>'.$p['Subject'].'</h2>';
    echo '<p>'.$p['Content'].'</p></div>';
    <strong>$out[$key]='''.$p['UserPhotoURL'].''';</strong>
    }
    ?>

    When the page and all the other assets have finished loading we load the rest of the pictures by replacing the src attribute of all the placeholders with the real URLs. This script should go to the end of the document.

    <script>
    YAHOO.util.Event.on(window,'load',
    function(){
    var avatars = [<?php echo implode($out,',');?>];
    for(var i=0;avatars[i];i++){
    document.getElementById('i-'+i).src = avatars[i];
    }
    }
    );
    </script>

    Yes, this makes your avatars dependent on JavaScript, but it has no real impact on accessibility or SEO as the alternative text of each avatar is still available. The only impact it has is that visitors will see a transition from a “grey man” to the user’s avatar and as most of the time avatars are outside the initial viewport or at its boundaries the majority of users won’t be the wiser about our little trick – but they get page that seems to have loaded a lot faster.

    Delaying the delivery of heavy screen furniture

    While this trick is most efficient with third party images, we could also go further in our optimization and take another leaf out of the book of tricks of the days of slow connections.

    When Netscape 4 and other older browsers still made up a substantial part of the overall visitor numbers, the main trick to cater for these browsers and newer ones was to use the @import directive to add a style sheet for newer browsers and have a simple LINK to add the one for these oldies:

    <link type="text/css" rel="stylesheet" href="lo-fi.css">
    <style type="text/css">
    @import url('hi-fi.css');
    </style>

    (The single quotes also blocked out MSIE 5/Mac)

    We can do something like that easily for the document, too. Simply create a more basic style sheet that for example uses background-colours instead of fancy gradients, massive bevels or pretty but very large nature shots. Then create an extra style sheet that adds all of these background-images. As URLs in CSS are as much an HTTP request as embedded images are, this’ll give us the same gain. In the document’s onload handler, all you’ll need to do is create a new LINK element pointing to the style sheet with the images and add it to the head of the document.

    <link type="text/css" rel="stylesheet" href="lo-fi.css">
    [...]
    <script>
    YAHOO.util.Event.on(window,'load',
    function(){
    var hiLink = document.createElement('link');
    hiLink.href = 'hi-fi.css';
    hiLink.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(hiLink);
    }
    );
    </script>

    This’ll add all the fancy imagery after the main document was loaded and replace background colours that did the job until the page was ready and we can go and make it prettier.

    [tags]optimization,speed,avatars,php,javascript,faster pages,webdevtrick[/tags]