Loading an external Javascript from a bookmarklet (Safari)

Loading an external javascript file from a bookmarklet is a good way to give superpowers to your favelet, and achieve what we really want, without care about the stupid 512 characters limit Internet Explorer has or without write all the code as an ugly one liner. And not to mention other advantages like server compression (i.e. js chunked and minified, gzip, …), PHP pre-processing and so on, that makes this technique in a very powerful resource when developing bookmarklets.

This post is because I recently discovered that Safari browser is a little picky when using this technique.

For example, what in other browsers (Firefox, Opera and IE) works like a charm, in Safari does not:

Note: Examples are really one liners but presented multiline for better reading.


<a href="javascript:void(
        z = document.body.appendChild(document.createElement('script'));
    );
    void( z.language = 'javascript' );
    void( z.type = 'text/javascript' );
    void( z.src = 'http://blabla.com/test.js' );
    void( z.id = 'testScript' );
">

To make Safari happy we have to polish it a little bit:


<a href="javascript:( function() {
    function load(source,ident) {
        var d = document;
        if ( !d.getElementById(i) ) {
            var scriptExt = d.createElement('script');
            scriptExt.src = source;
            scriptExt.id = ident;
            d.body.appendChild(scriptExt);
         }
    }
    load('http://blabla.com/test.js','testScript')
})();
">

Notice the closure in the bookmarklet. That’s a very good practice specially for bookmarklets as you don’t know in which page is your bookmarklet going to run. So our external javascript file should have another closure on it to avoid a namespace crash.

And last but not least, another little picky thing from Safari. This time when loading an external style sheet from the bookmarklet itself:


var cssFile = d.createElement("link");
cssFile.rel = "Stylesheet";
cssFile.type="text/css";
cssFile.id="testCSS";
cssFile.href="http://blabla/test.css";

document.body.appendChild(cssFile);

That’d work in all browsers but Safari. Now let’s see the truly cross-browser version:


var cssFile = d.createElement("link");
cssFile.rel = "Stylesheet";
cssFile.type="text/css";
cssFile.id="testCSS";
cssFile.href="http://blabla/test.css";

//we have to create the css in the head instead of the body for Safari
var h = d.getElementsByTagName("head")[0];
if (!h || h == undefined) {
    //creating head under html
    d.documentElement.appendChild( d.createElement(’head’) );
    h = d.getElementsByTagName(”head”)[0];
}
h.appendChild(cssFile);

As you may already noticed the difference is in inserting the CSS in the head element. Before the insertion, we check if there’s a head element and if not, we create it under html. As before, you don’t know in what kind of pages your bookmarklet will run, so better be prepared.

Compártelo
October 7th, 2007 | Development, English, Javascript, Web |

Categories

Syndication

my favorite pictures

    Archives

    Cerrar
    Enviar por Correo