function Jsboot(app, $) {
  var jsb;

  app.jsboot = app.jsboot || { callbacks: {} };
  jsb = app.jsboot;

  // callback functions expect one parameter, a
  // data object that is stored in the inline
  // application/json script tags
  jsb.on = function(key, fun) {
    key = key.replace('#', '-');
    jsb.callbacks['jsboot-' + key] = fun;
  };

  jsb.runBootstrapping = function(el) {
    var $el = $(el),
        id = $el.attr('id'),
        fun = jsb.callbacks[id],
        jsonText, data;

    if (typeof(fun) === 'function') {
      jsonText = $el.html();
      data = JSON.parse(jsonText);
      fun(data);
    }
  };

  jsb.runAllBootstrapping = function() {
    $('script.jsboot-data').each(function(idx, el){
      jsb.runBootstrapping(el);
    });

    Object.freeze(jsb.callbacks);
  };

  $(function(){
    jsb.runAllBootstrapping();
  });
}

function Jsboot(app, $) {
  var jsb;

  app.jsboot = app.jsboot || { callbacks: {} };
  jsb = app.jsboot;

  // callback functions expect one parameter, a
  // data object that is stored in the inline
  // application/json script tags
  jsb.on = function(key, fun) {
    key = key.replace('#', '-');
    jsb.callbacks['jsboot-' + key] = fun;
  };

  jsb.runBootstrapping = function(el) {
    var $el = $(el),
        id = $el.attr('id'),
        fun = jsb.callbacks[id],
        jsonText, data;

    if (typeof(fun) === 'function') {
      jsonText = $el.html();

      if (jsonText === "") {
        data = {};
      } else {
        data = JSON.parse(jsonText);
      }

      fun(data);
    }
  };

  jsb.runAllBootstrapping = function() {
    $('script.jsboot-data').each(function(idx, el){
      jsb.runBootstrapping(el);
    });

    Object.freeze(jsb.callbacks);
  };

  $(function(){
    jsb.runAllBootstrapping();
  });
}

Handle cases where a boot tag has no data
Handle cases where a boot tag has no data

This is useful if you want to use js boot but don't have data
you need to provide for bootstrapping
