gavinhewitt
6/11/2011 - 4:31 AM

advanced bookmarklet template

advanced bookmarklet template

// this js should be loaded in your iframe to communicate with the bookmarklet

// this is the interface for the parent window
// and the bookmarklet

$(function() {

    // when client sends message
    window.addEventListener('message', function(e) {

        var data = e.data;

        // it's trying to trigger
        // an arbitrary custom event
        if(!!data && data.event) {
            $('body').trigger(data.event, data.args);
        }

    }, false);

});

// example close button, which can communicate back with the bookmarklet code
$(function() {

    $('a.ui-close').click(function(e) {
        $(this).trigger('post-message', [{
            event: 'unload-bookmarklet'
        }]);
        e.preventDefault();
    });

});

$('body')
    .live('post-message', function(e, d) {
        window.parent.postMessage(d, '*');
    });
var your_bookmarklet = (function() {

    // some things we need in here
    var host = 'http://localhost/',
        iframe_url = host + 'your_iframe',
        $ = false,
        doc = document,
        head = doc.getElementsByTagName('head')[0],
        body = doc.getElementsByTagName('body')[0],
        messageListeners = [],
        iframe;
 
    // general utils
    var Utils = {

        // load a javascript file
        loadJs: function(src) {
            var js = doc.createElement('script');
            js.type = 'text/javascript';
            js.src = src;
            js.async = true;
            head.appendChild(js);
        },

        addMessageListener: function(message, callback) {
            messageListeners[message] = callback;
        },

        // if jquery does not exist, load it
        // and callback when jquery is loaded
        loadJquery: function(cb) {
            // always load jquery because they might have
            // a prototyped version on page
            Utils.loadJs(host + '/js/lib/jquery.js');
            // start checking every 100ms to see
            // if the jQuery object exists yet
            (function poll() {
                setTimeout(function() {
                    // jquery exists, callback
                    if(window.jQuery) {
                        $ = window.jQuery;
                        cb();
                    // jquery doesn't exist,
                    // keep trying
                    } else {
                        poll();
                    }
                }, 100);
            })();
        }

    }

    var Bookmarklet = {

        hide: function() {
            iframe.fadeOut('fast');
        },

        show: function(dimensions) {
            if(dimensions) {
                iframe.css(dimensions);
            }
            if(!iframe.is(':visible')) {
                iframe.fadeIn('fast');
            }
        },
        
        // this is accessed by itself
        // when it wants to create a new one
        reset: init
        
    }

    window.addEventListener('message', function(e) {
        var data = e.data;
        // the window is trying to execute
        // some arbitrary custom event
        if(!!data.event) {
            messageListeners[data.event](data.args);
        }
    }, false);

    // listen for calls from iframe
    Utils.addMessageListener('unload-bookmarklet', function() {
        Bookmarklet.hide();
    });

    Utils.addMessageListener('resize-iframe', function(dimensions) {
        Bookmarklet.show(dimensions);
    });

    // creates a way to proxy
    // POST methods to the website directly
    var Channel = function(path) {

        if(iframe) {
            iframe.remove();
            iframe = false;
        }

        iframe = createIframe(path);

        var c = this,
            cw = iframe[0].contentWindow;

        // provide a way for bookmarklet
        // to trigger custom events in iframe
        this.trigger = function(event, args) {
            cw.postMessage({
                event: event,
                args: args 
            }, '*');
        }

        // generate the iframe to proxy
        function createIframe(url) {
            var i = $('<iframe />')
                .attr('src', url)
                .appendTo(body);
            return i;
        }

        return this;

    }
    
    function init() {
        
        // load jquery
        Utils.loadJquery(function() {

            // when jquery is loaded,
            // create bookmarklet channel
            new Channel(iframe_url); 

        });
        
        return this;
    
    };
    
    init();

    return Bookmarklet;

})();
javascript:(function() {

    if(!window.your_bookmarklet) {

        var doc = document,
            js = doc.createElement('script');

        js.type = 'text/javascript';
        js.src = 'loader.js';
        js.async = true;

        doc.getElementsByTagName('head')[0].appendChild(js);

    }

})();