Creating a bookmarklet with easyXDM

March 27, 2010 by: oyvind.kinsey

Bookmarklets has been common for a long time and are quite easy to make. But one thing that you often see when examining the code behind bookmarklets are that most of the code is  just to facilitate simple cross domain communication back to the whatever service the bookmarklet supports.

Following is a sample bookmarklet with support for full RPC and XHR between the page its being applied to and the supporting backend.

For details checkout the sample here, or try it with this bookmark.

If you want to, save the above link as a bookmark, navigate to any page on the internet, and hit the bookmark 🙂

The details

Set up the provider as usual, one example is the xhr provider

The bookmark code

(function(){
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = "http://provider.com/bookmark.js";
    document.getElementsByTagName("head")[0].appendChild(script);
})();

or as it would look like in a link

<a href='javascript:(function(){var script = document.createElement("script");script.type = "text/javascript";script.src = "http://provider.com/bookmark.js";document.getElementsByTagName("head")[0].appendChild(script);})();'>bookmark</a>

The main code (bookmark.js)

(function(){
    var s1, s2, isLoaded = false, xhr, head = document.getElementsByTagName('head')[0];

    function scriptOnLoad(){
        if (isLoaded || typeof easyXDM === "undefined" || typeof JSON === "undefined") {
            return;
        }
        isLoaded = true;
        // here we put the main code, in this case we expose an ajax endpoint
        xhr = new easyXDM.Rpc({
            remote: "http://provider.com/xhr.html",
            onReady: function(){
                xhr.post("example/glossary.php", {
                    param1: "a",
                    param2: "b"
                }, function(json){
                    alert(json.glossary.title);
                });
            }
        }, {
            remote: {
                post: {}
            }
        });
    }
    // load easyXDM
    s1 = document.createElement("script");
    s1.type = "text/javascript";
    s1.src = "http://provider.com/easyXDM.debug.js";
    s1.onreadystatechange = function(){
        if (this.readyState === "complete" || this.readyState === "loaded") {
            scriptOnLoad();
        }
    };
    s1.onload = scriptOnLoad;
    head.appendChild(s1);
    // load JSON if needed
    if (typeof JSON === "undefined" || !JSON) {
        s2 = document.createElement("script");
        s2.type = "text/javascript";
        s2.src = "http://provider.com/json2.js";
        s2.onreadystatechange = function(){
            if (this.readyState === "complete" || this.readyState === "loaded") {
                scriptOnLoad();
            }
        };
        s2.onload = scriptOnLoad;
        head.appendChild(s2);
    }
})();

This code does not require any files to be uploaded to the ‘consumer’.

  • Artemy Nikolsky

    nice

  • Tim Ginn

    I believe with the newest version of the library:
    xhr.post(“example/glossary.php”, {
    param1: “a”,
    param2: “b”
    }

    should be:

    xhr.post({ url: “example/glossary.php”,
     data: {
      param1: “a”, param2: “b” } }