This is one of those ‘took me awhile to figure out so I’ll post so I don’t have to figure it out again’ posts.

At work we now have a widget which people can embed in their sites (well, soon) which was built by an external company and is pretty slick. The problem is that it wasn’t designed to be skinnable so customizing it for different clients is impossible.

The model for skinning we arrived at was that there would be a ‘clients’ directory which will contain a number of other directories to hold the client specific stuff and to have it dynamically load things for the clients correctly. And because it is javascript which is sent to the client in a readable format, here is the code I wrote to do it (sorry to the RSS only people; this syntax plugin doesn’t do RSS properly it seems)

$.ajax({url: options.widget_url+"clients/"+options.clientid+"/javascripts/config.js", 
        type:"HEAD",
        cache: true,                
        beforeSend: function() {
          if(typeof(options.clientid) == "undefined") {
              options.clientid = 'zerofootprint';
          }  
        }, 
        error: function() {
                    options.pcm_url = "http://www.zerofootprint.net";
                },
        success: function() {
                $.ajaxSetup({ async: false }); 
                $.getScript(options.widget_url+"clients/"+options.clientid+"/javascripts/config.js", 
                            function (data, textStatus) {
                            configs = $('script[@src*=zfpcalculator.js]').clientConfig(calcUrl[0]);
                            options = $.extend(options, configs);
                            });
                $.ajaxSetup({ async: true });     
                },
        complete: function() {
    		$.getScript(calcUrl[0]+'/javascripts/typewatch.js');
    		$.getScript(calcUrl[0]+'/javascripts/zfp_calculator_controller.js',
    		            function() {			
    			            $('script[@src*=zfpcalculator.js]').zfpCalculator(options);
    			        });
        }
});

Annotations

  • 4 – 8: The widget takes an optional ‘clientid’ parameter. I check here whether it exists (parameters were parsed earlier) and if not I set a default value so there will always be a clientid.
  • 1 – 3: Make a HEAD request for a file which will exist inside a client directory if one exists.
  • 9 – 11: Essentially, this is the error handling section that gets executed if the file requested doesn’t exist. You should put your default settings in here.
  • 12 – 20: This is the guts of the magic is. First we have to turn of the Async aspect of AJAX. Yes, seems a bit silly but without doing that what happens is the getScript is called but we don’t wait for it to finish so we cannot know for sure whether it was loaded or not when the next chunk is executed. Speaking of the getScript, what is does is load (and execute) the file we originally requested in line 1 – 3 and executes a clientConfig method and adds the array it gets back to the options one we are carrying around. And I remembered to make AJAX calls run async again.
  • 21 – 27: This section gets called after either the success or error blocks were run. From here I load and execute the chunk of code that actually is the core of the widget.

I think it is pretty trick, even if it does add an extra request (the HEAD) into the flow.