May 08, 2009

jQuery Bookmarklet

It's kind of an obsession. You mix a somehow usual browsing session with some GREAT tools like a real browser, Firebug and jQuery and - Voilà! - you can do virtually anything.

You can fight the DOM, add events, modify every web as if it was your own. A la Seamonkey, if you want, but more hand-made. Please welcome... jQuerify.

jQuerify

Some time ago I found jQuerify, a bookmarklet that lets you do a simple thing: To load jQuery into any page with one click. It's simple and easy, but powerful enough.

Sure it is, but I, being the damn perfectionist I am, worked a little on it, putting all my javascript-fu in the oven. I've always wanted to create a bookmarklet and I only needed a reason. Even a tiny itty-bitty one. The result of some developing and searching is the xPh jQuerify Bookmarklet. Now, to the details!

Assembling the monster

First came first, so I read and (tried to) understand how jQuerify works and make some touch here and there. The jQuerify workflow is pretty simple:

  1. Find if jQuery is loaded in the current page. If yes, exit gracefully
  2. Load jQuery from Google API repository
  3. Wait jQuery loading and call .noConflict if another library owns $

// Encapsulation
(function(){
  // Check if jQuery is loaded
  if(typeof window.jQuery != 'undefined') {
    message('jQuery already loaded')
  } else {
    // Check for conflicts
    var conflict = typeof window.$ != 'undefined';
    // Create the script and point to Google API
    var script = document.createElement('script');
    script.setAttribute('src','http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js');
    // Add the script to the 'head' for processing
    document.getElementsByTagName('head')[0].appendChild(script);
    // Create a way to wait until script loading
    var attempts = 15;
    (function(){
      // Check again if jQuery is undefined
      if(typeof window.jQuery == 'undefined') {
        if(--attempts > 0) {
          // Calls himself in a few milliseconds
          window.setTimeout(arguments.callee, 250)
        } else {
          // Too much attempts to load, send error
          alert('An error ocurred while loading jQuery')
        }
      } else {
        message('jQuery '+jQuery.fn.jquery+' loaded'+
          (conflict && jQuery.noConflict() ? ' with noConflict' : ''))
      }
    })();
  }
  // The message function assumes jQuery is loaded
  function message(msg) {
    var element = jQuery('<a>')
      .html(msg)
      .attr('href', '#')
      .css({
        width: 'auto',
        opacity: 0.9,
        position: 'fixed',
        zIndex: 9000,
        top: '15px',
        right: '20px',
        background: '#000',
        'float': 'right',
        padding: '7px 10px',
        color: '#fff',
        border: 'solid 2px #fff',
        textDecoration: 'none',
        textAlign: 'center',
        font: '12px "Lucida Grande",Helvetica,Tahoma bold',
        borderRadius: '5px',
        MozBorderRadius: '5px',
        MozBoxShadow: '0 0 20px #000',
        WebkitBorderRadius: '5px',
        WebkitBoxShadow: '0 0 20px #000'
      })
      .click(function(evt){
        evt.preventDefault();
        jQuery(this).fadeOut('slow', function(){jQuery(this).remove()});
      })
      .appendTo('body');
    window.setTimeout(function(){ element.trigger('click') }, 2500);
  };
})()

Bookmark creation

Well, that's it! Almost done. The next step is to publish it. It was more difficult than I thought, actually. I run a compressor on the code, to reduce it's size at minimum. The best minifier site I found is CompressorRater. It allows to do a comparison between most known JS minifier utilities, like Packer, JS Min, YUI Compressor and Dojo ShrinkSafe.

With the minified script (1152 bytes), the next step is to convert it in a URL. So I run urlencode on it. In fact I only urlencoded some characters, namely, spaces (%20), double quotes (" = %22), question marks (? = %3F), ampersands (& = %26) and html angles (< = %3C and > = %3E). Then put "javascript:" at front and that's all, a brand almost-new jQuerify Bookmarklet ready to put in any website, ready to grab to your favlist.

It's alive!

The style of the message is taken from WTFramework, another nice bookmarklet to recognize which frameworks a site uses. I hope the author doesn't bother, otherwise, my apologizes.

Hoping this can be of help to someone, this was my daily war. And today, I won