Working on http://hotelscombined.com.au we have a JS bundling process in place which is pretty interesting. There's an executable that runs as part of the TFS build that combines and minifies the JS files into specified a bundle file. It's a pretty old solution so obviously has legacy implications to changing anything.

Firstly we have to deal with affiliates and the white label version of the site. We must maintain backwards compatibility with these sites at all cost and we have a rather interesting http handler which serves a JS file bundle based on a requested file name.

So we have to maintain this lookup of legacy filenames to bundles but I really want to switch to the newer MVC bundling process, then I can look at introducing JSLint/JSHint locally and get build time errors.

Using the MVC bundling creating the bundles is pretty straight forward, I then replaced the links to our legacy JavaScript manager.

bundles.Add(  
    new ScriptBundle("~/Bundles/Master").Include(
        new[]
            {
                "~/Script/jquery-uncompressed.js"
                ...
            }));

Next step is the more complicated one. I created a legacy lookup dictionary containing the old file names and the newer bundle names so we maintain backwards compatibility. We then need to dynamically load the contents of a bundle and serve it via the handler, this also needs to serve minified and unminified versions depending on the environment.

This is the code that I came up with to handle this. It's still in proof of concept stage right now so may change.

var bundle = BundleTable.Bundles.FirstOrDefault(b => b.Path == bundleName);  
if (bundle != null)  
{

    var bundleContext = new BundleContext(
        context, BundleTable.Bundles, bundleName)
        {
            EnableOptimizations = true
        };
    var defaultBundleBuilder = new DefaultBundleBuilder();
    var bundleContent = defaultBundleBuilder.BuildBundleContent(
        bundle, bundleContext,
        bundle.EnumerateFiles(bundleContext));
    var response = new BundleResponse(
        bundleContent, bundle.EnumerateFiles(bundleContext))
        { ContentType = "application/javascript" };

    if (minify)
    {
        var minifier = new JsMinify();
        minifier.Process(bundleContext, response);
    }

    return response;
}
development, javascript, jquery

The codebase I'm currently working on uses $.extend quite a lot. It's a jQuery feature I've not used much myself.

I created a set of default options that could be overwritten by passed in options. This worked for the most part.

The issue I was having came when changing the passed in options to better support RTL, (switching left configured elements to be positioned right etc). I found that changing the position of the first would change the position of the second too.

It took me a while to track this one down, I originally assumed there was some kind of scope issue with the options. But it turns out $.extend doesn't quite do what I expected it would.

var defaults = {  
    param: {
        value1: 1,
        value2: 2
    }
}

var test = $.extend({}, defaults, { something: 'else' });  
var test2 = $.extend({}, defaults);

console.log(test2.param.value1); // = 1  
test.param.value1 = 3;  
console.log(test2.param.value1); // = 3  

I was expecting by default a deep copy. So that in the above scenario test.param and test2.param could be updated independantly.

Turns out what I needed to do in this case is this:

var test = $.extend(true, {}, defaults, { something: 'else' });  
var test2 = $.extend(true, {}, defaults);