// modulr.sync.js (c) 2010 Tobie Langel
(function(exports) {
  var _factories = {},
      _modules = {},
      PREFIX = '__module__', // Poor man's hasOwnProperty
      RELATIVE_IDENTIFIER_PATTERN = /^\.\.?\//;
      
  function makeRequire(id, main) {
    // Find the requirer's dirname from it's id.
    var path = id.substring(0, id.lastIndexOf('/') + 1);
    
    function require(identifier) {
      var id = resolveIdentifier(identifier, path),
          key = PREFIX + id,
          mod = _modules[key];

      // Check if this module's factory has already been called.
      if (!mod) {
        _modules[key] = mod = { id: id, exports: {} };

        var fn = _factories[key];
        delete _factories[key]; // no longer needed.

        if (!fn) { throw 'Can\'t find module "' + identifier + '".'; }

        // lazy eval
        if (typeof fn === 'string') {
          fn = new Function('require', 'exports', 'module', fn);
        }

        // Create an instance of `require` per module. Each instance has a
        // reference to the path it was called from to be able to properly
        // resolve relative identifiers.
        // `main` isn't defined until we actually require the program's
        // entry point.
        var r = makeRequire(id, main || mod);
        fn(r, mod.exports, mod);
      }
      return mod.exports;
    }

    require.main = main;
    return require;
  }

  function resolveIdentifier(identifier, dir) {
    var parts, part, path;
    
    if (!RELATIVE_IDENTIFIER_PATTERN.test(identifier)) {
      return identifier;
    }

    parts = (dir + identifier).split('/');

    path = [];
    for (var i = 0, length = parts.length; i < length; i++) {
      part = parts[i];
      switch (part) {
        case '':
        case '.':
          continue;
        case '..':
          path.pop();
          break;
        default:
          path.push(part);
      }
    }
    return path.join('/');
  }
  
  function define(id, factory) {
    _factories[PREFIX + id] = factory;
  }
  
  exports.define = define;
  exports.require = makeRequire('');
})(this);

define("bolt/binding", function(require, exports, module) {
/**
 * The Binding class controls the connection between a Model and a View.
 *
 * When the specified property on the model is updated, the corresponding
 * property on the view is also updated.
 *
 * It is also possible to listen to events on the View, which when fired
 * retrieves the latest value from the View and updates the model.
 *
 * Usually this class is not created directly, and is instead constructed
 * by calling the setBinding function of a View.
 *
 * The Binding constructor takes the model and view as arguments as well as an
 * options object containing:
 * - modelProperty: the name of the property of the model
 * - viewProperty: the name of the property on the view
 * - property: If the name of the model and view property are equal, which
 *   is often the case, simply specify this value instead of modelProperty and
 *   viewProperty.
 * - viewEvent: the event on the View to listen to in order to update the
 *   model. Can be either a String or an array of Strings.
 * - sync: A Boolean. If false, the View is not immediately updated with
 * its corresponding model value. Otherwise it is.
 */
var util   = require('./util');
var core   = require('./core');
var getter = util.getter;
var setter = util.setter;

var Binding = exports.Binding = core.createClass({
  name: 'Binding',

  properties: {
    // the model to bind to
    model: null,

    // the model property to bind to
    modelProperty: 'value',

    // the view to bind to
    view: null,

    // the view event to listen for
    // note that the model event is `changed`
    // by default we don't listen to any view event
    viewEvent: null,

    // the view property to bind to
    viewProperty: 'value',

    // shortcut for setting both view and model property when they are the same
    property: 'value'
  },

  /**
   * Create a new Binding to synchronize state between a view and a model
   * @constructor
   *
   * @param {View} view The view to bind to
   * @param {Model} model The model to bind
   * @param {Object} options The options to use in binding
   * @param {String} options.modelProperty The model property to bind to
   * @param {String} options.viewProperty The view property to bind to
   * @param {String} options.property A shortcut for setting both the model
   *   and view property when they are the same
   * @param {String} options.viewEvent the event from the view that should
   *   trigger the binding to sync
   *
   * note that the model event is always `changed`
   */
  construct: function(view, model, options) {
    options = options || {};
    this.setView(view);
    this.setModel(model);

    // default the modelProperty and viewProperty to property if not specified
    if (options.property && !options.modelProperty && !options.viewProperty) {
      options.modelProperty = options.viewProperty = options.property;
    }

    this._modelPropertyIsFunction = util.isFunction(options.modelProperty);

    // if we don't specify a viewEvent but there's a setter on the
    // model property, set view event to 'change'.
    // TODO:wbailey - we need to discuss if we really want this default
    //                behavior. This is potentially pretty expensive and
    //                I don't understand fully why the presence of a model
    //                setter should trigger this default.
    if (!('viewEvent' in options) &&
      !this._modelPropertyIsFunction &&
      util.setter(options.modelProperty) in model) {
      options.viewEvent = 'change';
    }

    var sync = options.sync;
    delete options.sync;

    // setup the rest of the options
    for (var name in options) {
      if (typeof options[name] !== 'undefined') {
        this[util.setter(name)](options[name]);
      }
    }

    // TODO: wrap this and only include in development mode
    // check to make sure this is a valid binding before setting up listeners
    var validModelProperty = (this._modelPropertyGetter &&
      this._modelPropertySetter) || this._modelPropertyIsFunction;
    if (!this._model || !this._view || !this._viewPropertyGetter ||
      !validModelProperty) {
      this.destroy();
      throw 'invalid binding: require properties not specified';
    }

    // add listeners for view events
    var viewEvent = this.getViewEvent();

    if (viewEvent) {
      this.viewTokens = [];

      if (viewEvent instanceof String || typeof viewEvent === 'string') {
        this.viewTokens.push(this._view.addListener(
          viewEvent, this.updateModel, this));
      } else {
        for (var i = 0, token, ev; i < viewEvent.length; i++) {
          ev = viewEvent[i];
          if (ev) {
            token = this._view.addListener(ev, this.updateModel, this);
            this.viewTokens.push(token);
          }
        }
      }
    }

    // add a listener for the model event
    this.modelToken =
      this.getModel().addListener('changed', this.updateView, this);

    // if the sync property is set then we should immediately synchronize
    // the model and the view.
    if (sync !== false) {
      this.setViewValue(this.getModelValue());
    }
  },

  /**
   * store the view and cache it for internal fast lookups
   * @param {View} view The view to bind the model to
   */
  setView: function(view) {
    if (this._view) {
      this._view.removeBinding();
    }
    this._view = view;
    this.set('view', view);
  },

  /**
   * store the model and cache it for internal fast lookups
   * @param {Model} model The model to bind the view to
   */
  setModel: function(model) {
    this.set('model', model);
    this._model = model;
  },

  /**
   * store the model property and cache it for internal fast lookups
   * @param {String} proeprty the model property to bind to
   */
  setModelProperty: function(property) {
    this.set('modelProperty', property);
    // bindings allow inline functions to serve as model properties for
    // transforming state before passing it to the view.
    this._modelPropertyIsFunction = util.isFunction(property);
    this._modelProperty = property;
    if (!this._modelPropertyIsFunction) {
      this._modelPropertyGetter = getter(property);
      this._modelPropertySetter = setter(property);
    }
  },

  /**
   * store the view property and cache it for internal fast lookups
   * @param {String} proeprty the view property to bind to
   */
  setViewProperty: function(property) {
    this.set('viewProperty', property);
    this._viewProperty = property;
    this._viewPropertyGetter = getter(property);
    this._viewPropertySetter = setter(property);
  },

  /**
   * destroy the binding and clean up its observers
   */
  destroy: function() {
    if (this.isDestroyed) {
      return;
    }
    this.isDestroyed = true;
    this.setModel(null);
    this.setView(null);
    this.setModelProperty(null);
    this.setViewProperty(null);
    util.run(this.viewTokens || [], 'remove');
    if (this.modelToken) {
      this.modelToken.remove();
      this.modelToken = null;
    }
  },

  /**
   * get the bound view value
   */
  getViewValue: function() {
    return this._view[this._viewPropertyGetter]();
  },

  /**
   * set the bound view value
   * @param value
   */
  setViewValue: function(value) {
    this._view[this._viewPropertySetter](value);
    return this;
  },

  /**
   * get the model value
   */
  getModelValue: function() {
    if (this._modelPropertyIsFunction) {
      // TODO: Replace context with the owner
      return this._modelProperty.call(null, this._model);
    }
    return this._model.getSafe(this._modelProperty);
  },

  /**
   * set the model value
   * @param value
   */
  setModelValue: function(value) {
    // inline model properties don't have setters yet
    if (!this._modelPropertyIsFunction) {
      this._model.setSafe(this._modelProperty, value);
    }
    return this;
  },

  /**
   * update the model state due to a change in view state
   * @param {Event} event the view event triggered by the state change
   */
  updateModel: function(event) {
    if (this.isDestroyed) {
      throw 'destroyed binding invoked';
    }
    // TODO: wbailey seems like we might want to be more strict about
    //       the api here. Right now bindings can silently fail due to a getter
    //       or setter not being implemented. I propose that we be explict and
    //       require a `one way` or `two way` property for each binding. Then
    //       if the appropriate getter/setter is not found we should throw.
    if (this._view[this._viewPropertyGetter]) {
      var viewValue = this.getViewValue();
      if (!util.isEqual(viewValue, this.getModelValue())) {
        this.setModelValue(viewValue);
      }
    }
  },

  /**
   * Update the view when a model state change is triggered
   * @param {Event} event the model event triggered by the state change
   */
  updateView: function(e) {
    if (this.isDestroyed) {
      throw 'destroyed binding invoked';
    }
    if (e.changedProperties) {
      // this change is relevant if it directly changes the modelProperty that
      // we are bound to, or a derived property (which cannot be a base
      // property, and will always be evaluated on every model change)

      // TODO:wbailey we should try annotating our derived properties with the
      //              base properties they depend on so we can trigger bindings
      //              more selectively. Checkout how sproutcore does this.
      if (this._modelPropertyIsFunction ||
        e.changedProperties.hasOwnProperty(this._modelProperty) ||
        !this._model.isBaseProperty(this._modelProperty)) {

        var modelValue = this.getModelValue();
        if (this._view[this._viewPropertyGetter]) {
          if (!util.isEqual(this.getViewValue(), modelValue)) {
            this.setViewValue(modelValue);
          }
        } else {
          this.setViewValue(modelValue);
        }
      }
    }
  }

});

});

define("bolt/builder", function(require, exports, module) {
var util          = require('./util');
var core          = require('./core');
var ClassRegistry = core.ClassRegistry;

var Builder = core.createClass({
  name: 'Builder',

  build: function(configuration, owner) {
    if (util.isArray(configuration)) {
      return util.map(configuration, function(configurationItem) {
        return this._buildOne(configurationItem, owner);
      }, this);
    }
    return this._buildOne(configuration, owner);
  },

  _buildOne: function(configuration, owner) {
    /**
     * Then the configuration was already built.
     */
    if (configuration.setup) {
      return configuration;
    }

    /* If you specify a particular view class, that takes precedence, if you
     * specify a tagName and no view class then we build an instance of TagView,
     * with your specified tagName, otherwise we just build the view base class.
     */
    configuration.owner = configuration.owner || owner;
    var viewConstructor = this._resolveViewConstructor(configuration);
    return new viewConstructor(configuration);
  },

  _resolveViewConstructor: function(configuration) {
    var providedView = configuration.view;
    /* By default, if you don't provide a view name, we'll make a tag view, and
     * if you provided a tagName, we'll use that - otherwise default to div.
     */
    if (!providedView) {
      return require('./tag_view').TagView;
    } else {
      /* This is a bit nuanced. We obtain 'View' from the class registry because
       * different stacks may alias 'View' to be a custom view that has
       * additional capabilities (such as layouts etc.). Aliasing in general is
       * discouraged - but in the case of Views, it's so core that it might make
       * sense to allow it.
       */
      return util.isFunction(providedView) ?
        providedView :
        ClassRegistry[providedView];
    }
  }
});

var builder = new Builder();

exports.build = function(configuration, owner) {
  return builder.build(configuration, owner);
};

exports.setBuilder = function(customBuilder) {
  builder = customBuilder;
};

exports.Builder = Builder;

});

define("bolt/collection", function(require, exports, module) {
var util = require('./util');
var core = require('./core');
var Model = require('./model').Model;
var Events = require('./mixins/events').Events;

/**
 * Collections allow you to observe a set of models and receive notifications
 * when collection membership changes occur via adding and removing models.
 * Collections also proxy property change notifications on their models on to
 * the observer. This allows views to update the ui to reflect model state
 * within an observed collection.
 *
 * The Collection class was inspired by and borrows heavily from backbone.js
 * http://documentcloud.github.com/backbone/
 */
var Collection = core.createClass({
  name: 'Collection',

  /**
   * create a new collection
   */
  construct: function(options) {
    this.length = 0;
    this.models = [];
    this._byCid = {};
    this._byId = {};
    this._listeners = {};
    options = options || {};
    this.modelType = options.modelType || this.klass.modelType;
  },

  statics: {
    modelType: Model
  },

  mixins: [Events],

  /**
   * add a model or a hash to a collection and invoke the modelAdded event
   * if a hash is passed in, the collection's default type is used to
   * construct a model for it
   * if the quiet flag is passed the modelAdded event will not be invoked.
   * if a comparator is provided the collection will maintain sort order
   * as items are added
   */
  add: function(model, quiet) {
    if (!model) return false;
    if (!model.klass) {
      model = new this.modelType(model);
    } else {
      var chain = model.klass.inheritanceChain;
      if (!chain || chain[chain.length-1].klassName !== 'Model') {
        model = new this.modelType(model);
      }
    }
    var cid = model.cid;
    var id = model.id;
    if (!this._byCid[cid] && (!id || !this._byId[id])) {
      var idx = this.comparator ?
        this.sortedIndex(model, this.comparator) : this.length;
      this.models.splice(idx, 0, model);
      this._byCid[cid] = model;
      if (model.id !== null) {
        this._byId[id] = model;
      }
      this.length++;
      this._listeners[cid] = model.addListener('changed',
        this._onModelChanged, this);
      if (!quiet) {
        this.invoke({ type: 'modelAdded', model: model, index: idx });
      }
      return model;
    }
    return false;
  },

  /**
   * remove a model from the collection and invoke the modelRemoved event
   * if the quiet flag is passed the modelRemoved event will not be invoked
   */
  remove: function(model, quiet) {
    if (!model) return false;
    var cid = model.cid;
    var id = model.id;
    if (this._byCid[cid]) {
      delete this._byCid[cid];
      delete this._byId[id];
      var idx = this.indexOf(model);
      this.models.splice(idx, 1);
      this.length--;
      if (!quiet) {
        this.invoke({ type: 'modelRemoved', model: model, index: idx });
      }
      var listener = this._listeners[cid];
      listener && listener.remove();
      delete this._listeners[cid];
      return true;
    }
    return false;
  },

  /**
   * clear all models from the collection can be performed silently if the
   * quiet flag is passed in
   */
  clear: function(quiet, batchUpdateEvents) {
    var models = this.models;
    var _listeners = this._listeners;
    this._byCid = {};
    this._byId = {};
    this.models = [];
    this.length = 0;
    util.forEach(models, function(model) {
      var cid = model.cid;
      var listener = _listeners[cid];
      listener && listener.remove();
      delete _listeners[cid];
    });
    if (!quiet) {
      if (batchUpdateEvents) {
        this._beginBatchUpdate();
        util.forEach(models, function(model, idx) {
          this.invoke({ type: 'modelRemoved', model: model, index: idx });
        }, this);
        this._endBatchUpdate();
      } else {
        this.invoke({ type: 'updated', action: 'clear', collection: this });
      }
    }
  },

  /**
   * clears all models in the collection and replaces them
   * with the models passed in. The updated event is inovked upon
   * completion if the quiet flag is not passed in.
   */
  replace: function(models, quiet) {
    this.clear(true);
    this.merge(models, quiet);
  },

  /**
   * merge the passed in set of models into the collection by updating
   * or adding
   */
  merge: function(models, quiet, batchUpdateEvents) {
    var updated = false;
    if (!util.isArray(models)) {
      models = [models];
    }
    if (!quiet && batchUpdateEvents) {
      this._beginBatchUpdate();
    }
    util.forEach(models, function(model) {
      var existingModel = this.getById(model.id);
      // TODO: we have a weird case here where if a model is added without
      // an id it can appear to be a duplicate of any other models without
      // ids. Should we allow models without ids to be added? what use cases
      // does that break currently if we remove it.
      if (!existingModel) {
        var added = this.add(model, !batchUpdateEvents);
        if (added) {
          updated = true;
        }
      } else {
        var ret = existingModel.merge(
          model.toObject ? model.toObject() : model,
          !batchUpdateEvents);
        updated = updated || !!ret;
      }
    }, this);
    if (batchUpdateEvents) {
      this._endBatchUpdate();
    } else if (updated && !quiet) {
      this.invoke({ type: 'updated', action: 'merge', collection: this });
    }
  },

  // helper function to see if we actually need to sort
  // basically, sort only if elements are out of order
  _shouldSort: function() {
    var comparator = this.comparator;
    if (!comparator) {
      return false;
    }
    var elem, nextElem;
    nextElem = this.at(0);
    for (var i = 1; i < this.length; i++) {
      elem = nextElem;
      nextElem = this.at(i);
      if (comparator(elem) > comparator(nextElem)) {
        return true;
      }
    }
    return false;
  },

  /**
   * sort the collection using the comparator
   */
  sort: function(quiet) {
    if (!this.comparator) {
      return false;
    }
    if (!this._shouldSort()) {
      // this is more to optimize the possibly high cost of the updated event
      // than the cost of the sort
      return false;
    }
    this.models = this.sortBy(this.comparator);
    if (!quiet) {
      this.invoke({ type: 'updated', action: 'sort', collection: this });
    }
    return this;
  },

  /**
   * get a model by id from the collection
   */
  getById: function(id) {
    return this._byId[id];
  },

  /**
   * get the ids of all the models
   */
  getIds: function() {
    return this.map(function(m) {
      return m.id;
    });
  },

  /**
   * get a model by client id from the collection
   */
  getByCid: function(cid) {
    return this._byCid[cid];
  },

  /**
   * get a model at a given index from the collection
   */
  at: function(idx) {
    return this.models[idx];
  },

  slice: function(a, b) {
    return this.models.slice(a, b);
  },

  /**
   * proxy on a model change event
   */
  _onModelChanged: function(evt) {
    var model = evt.model;
    var index = this.indexOf(model);
    if (index < 0) {
      // index can be undefined if model was removed before we get here, e.g.
      // if this is a filterable collection and the base collection removed
      // the model
      return;
    }
    this.invoke(util.defaults({ type: 'modelChanged', index: index }, evt));

    var comparator = this.comparator;
    var prevModel = (index > 0) && this.at(index - 1);
    var nextModel = (index < this.length - 1) && this.at(index + 1);
    var sortNeeded = (
      // comparator exists
      comparator &&
      // sortKey property was changed
      !util.isUndefined((evt.changedProperties || {})[this.sortKey]) &&
      // model is not in the correct position
      (
        (prevModel && comparator(prevModel) > comparator(model)) ||
        (nextModel && comparator(model) > comparator(nextModel))
      )
    );
    if (sortNeeded) {
      this.sort();
    }
  },

  _beginBatchUpdate: function() {
    this.invoke('beginUpdate');
  },

  _endBatchUpdate: function() {
    this.invoke('endUpdate');
  },
  
  destroy: function() {
    this.removeListener();
    this.clear(true);
  },

  // COMPAT
  listen: function(type, callback, contextOrNull) {
    function handleAll(event) {
      this.listener.apply(
        this.context,
        [event.type].concat(arguments));
    }

    function handleSingle() {
      this.listener.apply(this.context, arguments);
    }

    require('./core').deprecated('listen', 'addListener');
    var token = this.addListener(type, callback, contextOrNull || this);
    token.boundListener = type === 'all' ? handleAll : handleSingle;
    return token;
  }

});

var methods = [
  'filter', 'forEach', 'each', 'map', 'include', 'without',
  'find', 'first', 'last', 'isEmpty', 'toArray', 'select',
  'reject', 'indexOf', 'sortBy', 'sortedIndex', 'max', 'min'
];

util.forEach(methods, function(method) {
  Collection.prototype[method] = function() {
    return util[method].apply(
      this,
      [this.models].concat(util.toArray(arguments)));
  };
});

exports.Collection = Collection;

});

define("bolt/compat/util", function(require, exports, module) {
/**
* Copyright (c) 2011, Facebook, Inc.
*/
var util = require('../util');

util.copy = function(dest, source, keepExisting) {
  require('../core').deprecated('util.copy');
  for (var name in source) {
    if (!keepExisting || !dest.hasOwnProperty(name)) {
      dest[name] = source[name];
    }
  }
  return dest;
};

util.reject = function(obj, iterator, context) {
  require('../core').deprecated('util.reject');
  if (!obj) {
    return [];
  }
  var hasLength = util.isNumber(obj.length);
  var results = (hasLength ? [] : {});
  util.forEach(obj, function(value, index, list) {
    if (!iterator.call(context, value, index, list)) {
      if (hasLength) {
        results[results.length] = value;
      } else {
        results[index] = value;
      }
    }
  });
  return results;
};

util.rejectKeys = function(obj, keys) {
  require('../core').deprecated('util.rejectKeys');
  return util.reject(obj, function(value, key) {
    return util.contains(keys, key);
  });
};

util.filterKeys = function(obj, keys) {
  require('../core').deprecated('util.filterKeys');
  // use reject because filter doesn't work on objects
  return util.reject(obj, function(value, key) {
    return !util.contains(keys, key);
  });
};

util.isBlank = function(obj) {
  require('../core').deprecated('util.isBlank');
  return util.isUndefined(obj) || util.isNull(obj) || (!util.isNumber(obj) && util.isEmpty(obj));
};

util.toBoolean = function(obj) {
  require('../core').deprecated('util.toBoolean');
  if (!util.isBoolean(obj)) {
    if (util.isString(obj)) {
      obj = ((/^t/i).test(obj)) || ('0' === obj);
    } else {
      obj = !!obj;
    }
  }
  return obj;
};

function _getProp(/*Array*/parts, /*Boolean*/create, /*Object*/context){
  var obj = context || window;
  for(var i = 0, p; obj && (p = parts[i]); i++) {
   obj = (p in obj ? obj[p] : (create ? obj[p] = {} : undefined));
  }
  return obj; // mixed
}

util.getObject = function(/*String*/name, /*Boolean?*/create, /*Object?*/context) {
  require('../core').deprecated('util.getObject');
  // summary:
  //    Get a property from a dot-separated string, such as "A.B.C"
  //  description:
  //    Useful for longer api chains where you have to test each object in
  //    the chain, or when you have an object reference in string format.
  //  name:
  //    Path to an property, in the form "A.B.C".
  //  create:
  //    Optional. Defaults to `false`. If `true`, Objects will be
  //    created at any point along the 'path' that is undefined.
  //  context:
  //    Optional. Object to use as root of path. Defaults to
  //    'dojo.global'. Null may be passed.
  return _getProp(name.split("."), create, context); // Object
};

});

define("bolt/core", function(require, exports, module) {
var util = require('./util');

// prefix for storing properties on the object. This is a holdover from Javelin.
var PROP_PREFIX = '__auto__';

// these keys are handled specially and are not
// automatically added to the protototype of the new Class
var SPECIAL_KEYS = {
  statics:            true,
  members:            true,
  mixins:             true,
  extend:             true,
  properties:         true,
  delegateProperties: true,
  events :            true,
  name :              true,
  beforeCreateClass:  true,
  afterCreateClass:   true
};

var seenDeprecations = {};
var deprecated = exports.deprecated = function(what, replacement) {
  var msg = what + ' is deprecated.';
  if (replacement) {
    msg += '\nUse ' + replacement + ' instead.';
  }
  if (!seenDeprecations[msg]) {
    seenDeprecations[msg] = true;
    console.warn(msg);
  }
};


// This is a hold over from JX. Sometimes folks are declaring classes
// with string values for extends. We need to track the classes that
// have been declared by name as a result.
var ClassRegistry = exports.ClassRegistry = {};

// Base object used in prototype chaining
var Base = function() {};

// setup the inheritance chain from parent to child
var inherit = exports.inherit = function(__super__, construct) {
  var klass;

  // if we have a constructor then use it otherwise provide a constructor
  // that automatically invokes the parent;
  if (construct) {
    klass = construct;
  } else {
    klass = function() {return __super__.apply(this, arguments);};
  }

  // setup the prototype chain without instantiating the superclass
  Base.prototype = __super__.prototype;
  klass.prototype = new Base();

  // set the constructor property of the klass
  klass.prototype.constructor = klass;

  return klass;
};

// createClass exported and also aliased as declare
var createClass = exports.createClass = exports.declare = function(config) {
  // setup the inheritance chain
  var __super__ = config.extend;
  var klass;
  if (__super__) {
    klass = inherit(__super__, config.construct);
  } else {
    klass = config.construct || function() {};
  }

  // set the klassName property
  ClassRegistry[config.name] = klass;
  klass.klassName = config.name || '';

  // Add the default implementation of getDeclaredClass
  klass.prototype.getDeclaredClass = getDeclaredClass;

  // setup mixins
  config.mixins && addMixins(klass, config.mixins);
  // add the instance methods
  addPrototypeMembers(klass, config);
  // add the static class methods
  config.statics && util.extend(klass, config.statics);
  // setup properties
  addProperties(klass, config.properties);
  addDelegateProperties(klass, config.delegateProperties);

  // the stuff should probably be removed. Keeping it for backwards compat
  // for now
  doClassHierarchyTracking(klass, __super__);

  return klass;
};

function addPrototypeMembers(klass, config) {
  // JX had a convention of putting instance properties/methods into a members
  // key in the config. We are maintaining actively deprecated this
  // functionality.
  if (config.members) {
    console.warn('Member is deprecated, please fix ' + config.name + '.');
  }
  config.members = config.members || {};
  for (var key in config) {
    if (!SPECIAL_KEYS[key]) {
      config.members[key] = config[key];
    }
  }
  util.extend(klass.prototype, config.members);
}

// mixins are added to the prototype and optionally provide a mixinReady hook
// Must run AFTER inheriting from parent class but before declaring current
// class so that mixins can override parent class members but can be
// overwritten by current class members.
function addMixins(klass, mixins) {
  var mixinReadyFunctions = [];
  var proto = klass.prototype;
  while(mixins.length) {
    var mixin = mixins.shift();
    for (var key in mixin) {
      if (!proto.hasOwnProperty(key) && key !== 'mixinReady' && key !== 'properties') {
        proto[key] = mixin[key];
      }
    }
    mixin.mixinReady && mixinReadyFunctions.push(mixin.mixinReady);
    mixin.properties && addProperties(klass, mixin.properties);
    mixin.delegateProperties &&
      addDelegateProperties(klass, mixin.delegateProperties);
  }

  if (mixinReadyFunctions.length > 0) {
    proto.mixinReadyFunctions = mixinReadyFunctions;
  }
}

// declared properties automatically create getters and setters
function addProperties(klass, properties) {
  var getter, setter, proto = klass.prototype;
  proto.get || (proto.get = getProperty);
  proto.set || (proto.set = setProperty);

  if (!proto.setProperty) {
    proto.setProperty = function() {
      deprecated('setProperty', 'set');
      return setProperty.apply(this, arguments);
    };
  }
  if (!proto.getProperty) {
    proto.getProperty = function() {
      deprecated('getProperty', 'get');
      return getProperty.apply(this, arguments);
    };
  }

  if (!properties) {
    return;
  }
  util.each(properties, function(defaultValue, key) {
    setter = util.setter(key);
    getter = util.getter(key);

    proto[PROP_PREFIX + key] = defaultValue;

    if (!proto.hasOwnProperty(setter)) {
      proto[setter] = function(v, _extra) {
        return this.set(key, v, _extra);
      };
    }
    if (!proto.hasOwnProperty(getter)) {
      proto[getter] = function() {
        var value = this.get(key);
        // NB: wbailey
        // we still need to check the default property value
        // here since we've added support for models to use
        // declared properties. We need to revisit this soon, since
        // models and normal classes store their properties differently.
        // This can lead to a lot of subtle bugs.
        return value === undefined ? defaultValue : value;
      };
    }
  }, this);
}

// this is legacy support. I'd really like to clean this up
// soon.
function addDelegateProperties(klass, delegateProperties) {
  var proto = klass.prototype;

  util.each(delegateProperties, function(names, target) {
    util.forEach(names, function(name) {
      if (target === (name.alias || name)) {
        console.warn('Do not give a delegateProperty target and property (or ' +
          'property alias) the same name. Fix delegateProperty "' + target +
          '" in class "' + klass.klassName + '".');
      }
      var aliasSetValue  = util.setter(name.alias || name);
      var aliasGetValue  = util.getter(name.alias || name);

      var getTarget = util.getter(target);
      // Support both simple string names and objects of the
      // form {alias: 'src name', name: 'target name'}, e.g.
      // {alias: 'content', name: 'innerHTML'}
      var setValue = util.setter(name.name || name);
      var getValue = util.getter(name.name || name);
      if (!proto.hasOwnProperty(aliasSetValue)) {
        proto[aliasSetValue] = function(value) {
          // Support both getting a value directly from the refs
          // object created by the builder, and from a target with a
          // defined getter
          var obj = (this.findRef ? this.findRef(target) : null) || this[getTarget]();
          if (obj[setValue]) {
            obj[setValue](value);
          } else {
            if (value !== undefined) {
              obj[name.name || name] = value;
            }
          }
          return this;
        };
      }

      if (!proto.hasOwnProperty(aliasGetValue)) {
        proto[aliasGetValue] = function() {
          /* We check for a getter first, because not all classes will have a
           * member called findRef - we could take reference to findRef out of
           * core.js */
          var obj = (this.findRef ? this.findRef(target) : null) || this[getTarget]();
          return obj[getValue] ? obj[getValue]() : obj[name.name || name];
        };
      }
    });
  });
}

// shared getProperty method
function getProperty(key) {
  return this[PROP_PREFIX + key];
}

// shared setProperty method
function setProperty(key, value) {
  this[PROP_PREFIX + key] = value;
  return this;
}

function doClassHierarchyTracking(klass, __super__) {
  klass.prototype.klass = klass;
  klass.superKlass = __super__;
  klass.inheritanceChain = __super__ ?
    [klass].concat(__super__.inheritanceChain) :
    [klass];
}

function getDeclaredClass() {
  return this.klass.klassName;
}

});

define("bolt/dom", function(require, exports, module) {
var util = require('./util');

var expando = 'bt' + (+new Date);

var trans = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#x27;'
};

/**
 * Dom convinience methods
 */
var dom = module.exports = {
  /**
   * Convenience wrapper around document.createElement
   * Creates dom element with given tagName, cssText and innerHTML
   *
   * @param {string} tagName
   * @param {string=} cssText
   * @param {string=} innerHTML
   * @returns {Element} created element
   */
  createElement: function(tagName, options, children) {
    var e = document.createElement(tagName);
    util.forEach(options || {}, function(value, name) {
      if (name === 'innerHTML') {
        dom.dangerouslyInjectHtml(e, value);
      } else if(name === 'content') {
        dom.replaceText(e, value);
      } else if (name === 'style') {
        e.style.cssText = value;
      } else {
        e[name] = value;
      }
    });
    children && util.forEach(children, function(c) {
      e.appendChild(c);
    });
    return e;
  },

  removeElement: function(element) {
    if (element && element.parentNode) {
      element.parentNode.removeChild(element);
    }
  },

  fromHTML: function(html) {
    var fragment = document.createElement('div');
    fragment.innerHTML = html;
    return fragment.firstChild;
  },

  hasClass: function(elem, className) {
    return (' ' + elem.className + ' ').indexOf(' ' + className + ' ') > -1;
  },

  addClass: function(elem, classNames) {
    var string = elem.className;
    util.forEach(classNames.split(/\s+/), function(className) {
      if (!dom.hasClass(elem, className)) {
        string += (string ? ' ' : '') + className;
      }
    });
    elem.className = string;
  },

  removeClass: function(elem, classNames) {
    var string = elem.className;
    util.forEach(classNames.split(/\s+/), function(className) {
      string = util.trim(string
        .replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)', 'g'), ' ')
        .replace(/\s{2,}/g, ' '));
    });
    elem.className = string;
  },

  toggleClass: function(elem, className, condition) {
    if (arguments.length < 3) {
      condition = !dom.hasClass(elem, className);
    }
    condition ? dom.addClass(elem, className) :
      dom.removeClass(elem, className);
  },

  alterClass: function(elem, className, condition) {
    require('./core').deprecated('alterClass', 'toggleClass');
    return this.toggleClass.apply(this, arguments);
  },

  /**
   * Converts unsafe symbols to entities
   *
   * @param {string} html
   * @returns {string} escaped html
   */
  escapeHTML: function(html) {
    return (html + '').replace(/[&<>\"\']/g, function(c) { return trans[c]; });
  },

  htmlize: function(html) {
    console.warn('htmlize is deprecated, please use escapeHTML.');
    return this.escapeHTML(html);
  },

  identify: function(elem) {
    return elem[expando] = elem[expando] || util.generateCID();
  },

  clear: function(node) {
    node.innerHTML = '';
  },

  dangerouslyInjectHtml: function(node, html) {
    node.innerHTML = html;
  },

  replaceText: function(node, text) {
    node.innerHTML = dom.escapeHTML(text);
  }

};


});

define("bolt/dom_event", function(require, exports, module) {
/**
* Copyright (c) 2011, Facebook, Inc.
*/
var util = require('./util');
var core = require('./core');
var dom  = require('./dom');

var TokenList = require('./token_list').TokenList;


function returnTrue() { return true; }
function returnFalse() { return false; }

var EventMethods = {
  getTargetView: function() {
    if (this._targetView === undefined) {
      this._targetView = require('./mixins/container').findClosest(this.target);
    }
    return this._targetView;
  },

  // simulateBubbling: false,

  preventDefault: function() {
    var e = this.baseEvent;
    if (e) {
      if (e.preventDefault) {
        e.preventDefault();
      } else {
        e.returnValue = false;
      }
    } else {
      if (this._preventDefault) {
        this._preventDefault();
      } else {
        this.returnValue = false;
      }
    }
    this.isDefaultPrevented = returnTrue;
  },

  stopPropagation: function() {
    var e = this.baseEvent;
    if (e) {
      if (e.stopPropagation) {
        e.stopPropagation();
      } else {
        e.cancelBubble = true;
      }
    } else {
      if (this._stopPropagation) {
        this._stopPropagation();
      } else {
        this.cancelBubble = true;
      }
    }
    this.isPropagationStopped = returnTrue;
  },

  isDefaultPrevented: returnFalse,
  isPropagationStopped: returnFalse,

  getRawEvent: function() {
    core.deprecated('event.getRawEvent', 'event');
    return this;
  },

  hasEventApi: true
};


function normalize(e) {
  // Fix target property, if necessary
  if (!e.target) {
    e.target = e.srcElement || document;
  }

  // check if target is a textnode (safari)
  if (e.target.nodeType === 3) {
    e.target = e.target.parentNode;
  }

  // Add relatedTarget, if necessary
  if (!e.relatedTarget && e.fromElement) {
    e.relatedTarget = e.fromElement === e.target ? e.toElement : e.fromElement;
  }

  // Calculate pageX/Y if missing and clientX/Y available
  if (e.pageX == null && e.clientX != null) {
    var doc = document;
    var body = doc.body;

    e.pageX = e.clientX +
      (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
      (doc && doc.clientLeft || body && body.clientLeft || 0);
    e.pageY = e.clientY +
      (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
      (doc && doc.clientTop  || body && body.clientTop  || 0);
  }

  // Add which for key events
  if (e.which == null && (e.charCode != null || e.keyCode != null)) {
    e.which = e.charCode != null ? e.charCode : e.keyCode;
  }

  // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
  if (e.metaKey === undefined) {
    e.metaKey = e.metaKey || e.ctrlKey;
  }

  // Add which for click: 1 === left; 2 === middle; 3 === right
  // Note: button is not normalized, so don't use it
  if (!e.which && e.button !== undefined) {
    e.which = (e.button & 1 ? 1 :
              (e.button & 2 ? 3 :
              (e.button & 4 ? 2 : 0 )));
  }

  return e;
};

/**
* Store all the handlers manually so we can override event behaviour
* {
*   node_id_1: {
*     click: [...],
*     change: [...],
*     selection: [...]
*   }
*   node_id_2: {
*     click: [...]
*   }
* }
*/
var tokenLists = {};

/**
* Need a connection between node on which addListener was called an it's
* listeners, so this is a hash of
* {
*   node_id_1: bound domHandler
*   node_id_2: bound domHandler
* }
*/
var domHandlers = {};

var eventProps = "altKey attrChange attrName bubbles button cancelable charCode clientX clientY clipboardData ctrlKey currentTarget data dataTransfer detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement type view wheelDelta which".split(" ");


/**
* Handle all listener calls. Should be called with dom element as this
*/
function domHandler(e) {
  e = e || window.event;
  e._preventDefault = e._preventDefault || e.preventDefault;
  e._stopPropagation = e._stopPropagation || e.stopPropagation;
  e = util.extend(e, EventMethods);
  evt.invoke(this, normalize(e));
}


function EventWrapper () {}

/**
* Adds missing methods to custom events
*/
function wrapCustomEvent(baseEvent) {
  // Poor man Object.create() here.
  // It's generally cheaper to build a prototype chain for a
  // dynamicaly created event object than to copy all properties
  // from base event.
  EventWrapper.prototype = baseEvent;
  e = new EventWrapper();
  util.extend(e, EventMethods);
  e.baseEvent = baseEvent;
  return e;
}


function ExtEventWrapper() {}

util.extend(ExtEventWrapper.prototype, EventMethods);

/**
* More expensive version of wrapCustomEvent for dom events
*/
function wrapDomEvent(baseEvent) {
  e = new ExtEventWrapper();
  e.baseEvent = baseEvent;
  // This is expensive. I'd rather use much faster createEvent() here.
  // Unfortunately firefox uses read only properties on native events,
  // thus preventing modification even in descendants.
  // IE9 does not support prototype chain alltogehter throwing
  // 'Invalid calling object'.
  for (var i = eventProps.length, prop; i >= -1; i--) {
    prop = eventProps[i];
    e[prop] = baseEvent[prop];
  }
  return e;
}

function DomTokenList(element) {
  this.element = element;
}

DomTokenList.prototype = new TokenList();

DomTokenList.prototype.addListener = function(type, listener, context, args) {
  // if this is the first listener added to el for type
  // then create a handler
  if (!this.hasTokensForType(type)) {
    if (evt.special[type]) {
      evt.special[type].setup(this.element);
    } else {
      var id = dom.identify(this.element);
      domHandlers[id] = domHandlers[id] || util.bind(domHandler, this.element);
      this.element.addEventListener ?
        this.element.addEventListener(type, domHandlers[id], false) :
        this.element.attachEvent('on' + type, domHandlers[id]);
    }
  }
  return TokenList.prototype.addListener
    .call(this, type, listener, context, args);
};

DomTokenList.prototype.removeListener = function(type, listener, context) {
  TokenList.prototype.removeListener.call(this, type, listener, context);

  // when removing the last listener also remove listener from the dom
  if (!this.hasTokensForType(type)) {
    var id = dom.identify(this.element);
    if (evt.special[type]) {
      evt.special[type].teardown(this.element);
    } else {
      this.element.removeEventListener ?
        this.element.removeEventListener(type, domHandlers[id], false) :
        this.element.detachEvent('on' + type, domHandlers[id]);
      delete domHandlers[id];
    }
    
    // it's not very cool that we're deleting the reference in here
    // however that's the only place we can reach when developer explictly
    // calls .remove() on a token (bypassing domEvent)
    if (this.isEmpty()) {
      delete tokenLists[id];
    }
  }
};


var evt = module.exports = {

  wrapDomEvent: wrapDomEvent,

  wrapCustomEvent: wrapCustomEvent,

  // public extension API. check mouseleave, mouseenter for an example
  special: {},

  // exposed for debugging, so we can find all the listeneres on a given node
  tokenLists: tokenLists,

  invoke: function(el, e/*, args*/) {
    if (!e.hasEventApi) { e = wrapCustomEvent(e); }
    if (!e.target) { e.target = el; }

    var tokenListForEl = tokenLists[dom.identify(el)];
    var args = util.toArray(arguments).slice(1);

    if (tokenListForEl) {
      var tokens = tokenListForEl.getTokensForType(e.type);
      for (var i = 0, l = tokens.length; i < l; i++) {
        var item = tokens[i];
        var listener = item.listener;
        listener.apply(item.context || this, item.args.concat(args));
      }
    }

    if (e.simulateBubbling && !e.isPropagationStopped() && el.parentNode) {
      evt.invoke.apply(evt, [el.parentNode].concat(args));
    }
    return !e.isDefaultPrevented();
  },

  addListener: function(el, type, listener, contextOrNull) {
    var id = dom.identify(el);

    tokenLists[id] = tokenLists[id] || new DomTokenList(el);
    var args = util.toArray(arguments).slice(4);
    return tokenLists[id].addListener(type, listener, contextOrNull, args);
  },

  removeListener: function(el, type, listener, contextOrNull) {
    var id = dom.identify(el);
    if (!id || !tokenLists[id]) return;
    tokenLists[id].removeListener(type, listener, contextOrNull);
  },

  preventDefaultHandler: function(e) {
    e && e.preventDefault();
    return false;
  }
};

util.forEach({
  mouseover: 'mouseenter',
  mouseout: 'mouseleave'
}, function(specialName, origName) {

  function handler(e) {
    var parent = e.relatedTarget;
    try {
      while (parent && parent !== this) {
        parent = parent.parentNode;
      }

      if (parent !== this) {
        var wrapped = wrapDomEvent(e, {
          type: specialName,
          simulateBubbling: true
        });
        evt.invoke(this, wrapped);
      }
    } catch(e) { }
  }

  evt.special[specialName] = {
    setup: function(el, listener) {
      evt.addListener(el, origName, handler);
    },
    teardown: function( el, listener ){
      evt.removeListener(el, origName, handler);
    }
  };
});

});

define("bolt/mixins/container", function(require, exports, module) {
var util     = require('../util');
var core     = require('../core');
var dom      = require('../dom');
var builder  = require('../builder');
var domEvent = require('../dom_event');

var Binding  = require('../binding').Binding;
var TokenList = require('../token_list').TokenList;

/* This options are special. They are handled during or event before setup
 * There's no way to define normal options with the given names */
var SETUP_OPTIONS = {
  owner: true,
  childViews: true,
  view: true,
  tagName:true
};

var ContainerRegistry = {};

/**
 * Mixin for dom-node-rooted containers.
 * A Container is a dom-node-rooted object that provides the functionality:
 *  1. Ability to contain other Containers.
 *  2. May be contained within another Container.
 *  3. Partially participates in reference tracking - to the extent that it
 *     may *be a reference* of it's owner.
 *
 * The requirements for using this mixin are:
 *  1. The class who mixes this in must provide the container's node when
 *      requested with this.getNode(). The mixer may allocate the node in any
 *      way they wish, but it mustn't be appended to the dom yet. The BoltJs
 *      system will handle placing the container into the heirarchy and
 *      eventually placing the entire tree into the dom.
 *  2. Before invoking the constructor from this mixin, the ability to provide
 *     this.getNode() must be implemented - the node needs to be allocated and
 *     available before invoking this mixin's 'construct' function.
 *
 * Does *not* provide functionality for:
 *  1. Keeping track of it's own references. There should never be references
 *    to this.refs. This mixin might be used in mixers who do not track their
 *    references (TagView etc.)
 *  2. Delegating any properties to it's node. (This might not be true - but
 *    we should try to make it true.)
 *
 * Any class that mixes in Container also receive seters and getters on some
 * very commonly used attributes that are relevant to any view that is a
 * container.
 *
 * @jwalke todo: consider removing ownership tracking (at least from this
 *                mixin. It can consume a lot of time for mixers who don't
 *                need to establish ownership).
 *
 */

var findClosest = exports.findClosest = function(node) {
  while (node) {
    var id = dom.identify(node);
    if (ContainerRegistry[id]) {
      return ContainerRegistry[id];
    }
    node = node.parentNode;
  }
  return null;
};

var Container = exports.Container = {

  properties: {
    model: null,
    node: null,
    owner: null,
    parentView: null,
    persistentDisplay: 'block',
    inDocument: false
  },

  delegateProperties: {
    node: [
      'className',
      /* @jwalke let's not delegate tagName, it's just extra CPU to set,
       * is redundant, and if you want to get the tagName, you should know it
       * because you set it!        // this'tagName', */
      'scrollTop',
      'scrollLeft',
      'scrollHeight',
      'scrollWidth',
      { name: 'innerHTML', alias: 'content'},
      { name: 'innerHTML', alias: 'dangerouslyInjectedHtml' }
    ]
  },

  setContent: function(content) {
    this.clearChildren();
    dom.replaceText(this.getNode(), content);
  },

  setDangerouslyInjectedHtml: function(dangerouslyInjectedHtml) {
    this.clearChildren();
    dom.dangerouslyInjectHtml(this.getNode(), dangerouslyInjectedHtml);
  },

  /**
   * This sets up the child views, establishing ownership, and sets the options.
   *
   * Before: this.getNode() must return the container node.
   */
  setup: function(options) {

    // owner is used in various places during the setup process so we
    // guarantee that it is always set before any other options.
    if ('owner' in options) { this.setOwner(options.owner); }

    // childViews is always handled first. This means that we setup the
    // hierarchy recursively depth first. This is important because it
    // allows the full hierarchy of refs to be defined before any potential
    // delegate properties are setup which might need to reference a child.
    if ('childViews' in options) { this.setChildViews(options.childViews); }


    this.setupOptions(options);

    /* register a reference on the dom node, so we can find the view later
     * from it. To prevent possible memory leaks in some of the browsers
     * register through an id instead of an attribute on a node */
    ContainerRegistry[dom.identify(this.getNode())] = this;
  },


  /**
   * Mixers may override this to do something more optimial.
   */
  setupOptions: function(options) {
    /*
     * This likely doesn't belong in the 'Container' mixin. Containers only
     * provide functionality for managing a set of children under a dom node
     * root.
     */
    for (var key in options) {
      if (!SETUP_OPTIONS[key]) {
        this._setupOption(key, options[key]);
      }
    }
  },


  /**
   * #todoverysoon: This probably doesn't belong in this base class and we
   * should not automatically set things on the node by default when we can't
   * find a setter.
   */
  _setupOption: function(key, value) {
    var setter = util.setter(key);

    if (this[setter]) {
      // if we have a setter, just set
      this[setter](value);
    } else if (key.substring(0,2) === 'on') {
      // if it looks like event, add an event listener
      var context = null;
      if (typeof value === 'string') {
        var owner = this.getOwner();
        if (owner[value]) {
          context = owner;
        } else {
          // Must be able to assign a listener to yourself from declare()
          context = this;
        }
        value = context[value];
      }
      this.addListener(key.substring(2), value, context);
    } else {
      // as a last resort set the value on the node directly
      this.getNode().setAttribute(key, value);
    }
  },

  getOwner: function() {
    var owner = this.get('owner');
    if (!owner) {
      owner = (this.getParentView() && this.getParentView().getOwner()) || this;
      this.set('owner', owner);
    }
    return owner;
  },


  /**
   * DATA BINDING
   */

  /**
   * TODO:wbailey revisit this
   */
  setBinding: function(options) {
    // NB:wbailey deprecating the 3 arguments signature in favor of passing
    // a single object argument that contains the three required keys.
    var model, bindingOptions, defaultBindingOptions;
    if (arguments.length === 1 && typeof options === 'object') {
      model = options.model;
      bindingOptions = options.options;
      defaultBindingOptions = options.defaultOptions;
    } else {
      model = arguments[0];
      bindingOptions = arguments[1];
      defaultBindingOptions = arguments[2];
    }
    this.set('model', model);
    this.removeBinding();
    this._binding = [];

    // Create multiple binding objects, one per property binding.
    // This creates a listener per binding.  It optimizes for the use
    // case where a widget will almost always have just one binding.
    // The alternative is to create a single binding that listens to
    // a single 'onChange' method on a view, then does a map lookup
    // for each view-to-model binding and executes it.  At runtime
    // this will be much less performant, hence this approach.
    var opt;
    if (!util.isArray(bindingOptions)) {
      bindingOptions = [bindingOptions];
    }
    for (var i = 0; i < bindingOptions.length; i++) {
      opt = util.extend({}, bindingOptions[i]);
      if (defaultBindingOptions) {
        opt = util.copy(opt, defaultBindingOptions, true);
      }
      this._binding.push(new Binding(this, model, opt));
    }
  },

  /**
   * remove the view binding
   */
  removeBinding: function() {
    this._binding && util.run(this._binding, 'destroy');
  },


  /**
   * LAYOUT PROPERTIES
   */

  /**
   * show the view
   */
  show: function(disp) {
    if (disp) {
      core.deprecated('view.show(disp)',
        'view.show() (override the value of persistent display)');

      // Override the persistent display
      this.setPersistentDisplay(disp);
    }

    var currentDisplay = this.getStyle().display;
    if (!currentDisplay || currentDisplay === 'none')  {
      this.getStyle().display = this.getPersistentDisplay() || '';
    }
    return this;
  },

  /**
   * hide the view
   */
  hide: function() {
    var currentDisplay = this.getStyle().display || '';
    if (currentDisplay && currentDisplay !== 'none') {
      this.setPersistentDisplay(currentDisplay);
    }
    this.getStyle().display = 'none';
    return this;
  },

  toggle: function(state) {
    if (typeof state === 'undefined') {
      state = this.getStyle().display === 'none';
    }
    return state ? this.show() : this.hide();
  },

  /**
   * This is simply a duplication of the functions above, but in a form that is
   * suitable for properties in buidler views.
   */
  setIsDisplayed: function(isDisplayed) {
    if(isDisplayed) {
      this.show();
    } else {
      this.hide();
    }
    return this;
  },

  getIsDisplayed: function() {
    return this.getStyle().display !== 'none';
  },

  /**
   * add a class to the view
   */
  addClass: function(className) {
    dom.addClass(this.getNode(), className);
    return this;
  },

  /**
   * remove a class from the view
   */
  removeClass: function(className) {
    dom.removeClass(this.getNode(), className);
    return this;
  },

  // add a class if it is not present; remove it if it is
  toggleClass: function(className) {
    dom.toggleClass.apply(
      dom,
      [this.getNode()].concat(util.toArray(arguments)));
    return this;
  },

  // COMPAT
  conditionClass: function() {
    core.deprecated('view.conditionClass', 'view.toggleClass');
    return this.toggleClass.apply(this, arguments);
  },

  hasClass: function(className) {
    return dom.hasClass(this.getNode(), className);
  },

  /**
   * apply a css class that is mutually exclusive with other classes
   * in a given set and save the state in an instance variable
   *
   * e.g.
   *
   * setMode('flavor', 'chocolate');
   * setMode('flavor', 'vanilla');
   * setMode('flavor', 'strawberry');
   * would toggle between flavor-chocolate, flavor-vanilla and
   * strawberry-flavor css classes and capture the value in this.modes.state.
   *
   * This is useful when you have a view that has various mutually exclusive
   * modes that can be transitioned through via a top level css class.
   */
  setMode: function(mode, setting) {
    var node = this.getNode(),
        classes = node.className.split(/\s+/),
        newClasses = '',
        regexp = new RegExp('^' + mode + '-');
    for (var i = 0; i < classes.length; i++) {
      var cssClass = classes[i];
      if (!regexp.test(classes[i])) {
        newClasses += ' ' + cssClass;
      }
    }
    // if the mode being set is false then we remove
    // any set mode.
    this._modes = this._modes || {};
    if (setting) {
      newClasses += ' ' + mode + '-' + setting;
      this._modes[mode] = setting;
    } else {
      delete this._modes[mode];
    }
    node.className = util.trim(newClasses);
    return this;
  },

  /**
   * get a mode value from the cache
   */
  getMode: function(mode) {
    this._modes = this._modes || {};
    return this._modes[mode];
  },

  getStyle: function() {
    return this.getNode().style;
  },

  /**
   * set attributes on the node
   */
  setAttributes: function(attributes) {
    util.forEach(attributes, function(value, key) {
      this.getNode().setAttribute(key, value);
    }, this);
  },

  /**
   * build a layout from a layout spec with the specified owner
   */
  build: function(config, owner) {
    return builder.build(config, owner || this);
  },

  /**
   * build and append a layout
   */
  setLayout: function(layout, owner) {
    this.append(this.build(layout, owner));
  },

  /**
   * get the bounding rect for the view
   */
  getRect: function() {
    return this.getNode().getBoundingClientRect();
  },

  /**
   * apply a set of styles to the view
   */
  setStyle: function(styles) {
    var styleObj = this.getNode().style;
    if (typeof(styles) == 'string') {
      styleObj.cssText += ';' + styles;
    } else {
      for (var name in styles) {
        styleObj[name] = styles[name];
      }
    }
    return this;
  },

  /**
   * REFERENCES
   */

  /**
   * get the reference for this view
   */
  getRef: function() {
    return this.get('ref');
  },

  /**
   * set the reference for the view
   */
  setRef: function(ref) {
    this.set('ref', ref);
    this.getNode().setAttribute('data-ref', ref);

    var owner = this.getOwner();
    owner.refs = owner.refs || {};
    owner.refs[ref] = this;
    return this;
  },

  _clearRef: function() {
    var owner = this.getOwner();
    var ref   = this.getRef();
    if (ref && owner.refs) {
      delete owner.refs[ref];
    }
  },


  /**
   * insert the view into a node at the requested position
   */
  placeIn: function(node, position) {
    position = position || 'append';
    var n = this.getNode();
    switch (position) {
      case 'append':
        node.appendChild(n);
        break;
      case 'before':
        node.parentNode.insertBefore(n, node);
        break;
      case 'prepend':
        node.insertBefore(n, node.firstChild);
        break;
      default:
        throw "Invalid node placement: " + position;
    }
    this.setInDocument(true);
    return this;
  },


  setInDocument: function(state) {
    state = !!state;
    var old = this.get('inDocument');
    if (old !== state) {
      if (state && this.onDocumentInsertion) {
        this.onDocumentInsertion();
      }
      util.invoke(this.getChildViews(), 'setInDocument', state);
      this.set('inDocument', state);
    }
    return this;
  },

  setParentView: function(view) {
    this.set('parentView', view);
    return this.setInDocument(view && view.getInDocument());
  },

  /**
   * remove the view from the dom without destroying it
   */
  remove: function() {
    dom.removeElement(this.getNode());
    return this;
  },

  /**
   * destroy a view
   *  - removes child views
   *  - removes listeners
   *  - cleans up references
   */
  destroy: function() {
    delete ContainerRegistry[dom.identify(this.getNode())];
    if (this._eventTokens) {
      util.invoke(this._eventTokens, 'remove');
      this._eventTokens = null;
    }
    util.invoke(this.getChildViews(), 'destroy');
    this._clearRef();
    this.remove();
    this.removeBinding();
    this.isDestroyed = true;
  },

  /**
   * CHILD VIEWS
   */

  getChildViews: function() {
    var childViews = this.get('childViews');
    if (!childViews) {
      childViews = [];
      this.set('childViews', childViews);
    }
    return childViews;
  },

  setChildViews: function(childViews) {
    util.forEach(
      this.getChildViews(),
      this.removeChild,
      this);
    util.forEach(
      builder.build(childViews, this.getOwner()),
      this.appendChild,
      this);
  },

  removeChild: function(child, doNotDestroy) {
    child.setParentView(null);
    this.set('childViews', util.without(this.getChildViews(), child));
    this._removeChildNode(child);
    doNotDestroy || child.destroy();
    return this;
  },

  _removeChildNode: function(child) {
    dom.removeElement(child.getNode());
  },

  append: function(arg) {
    if (util.isArray(arg)) {
      util.forEach(arg, this.appendChild, this);
    } else {
      this.appendChild(arg);
    }
  },

  appendChild: function(child) {
    this.getChildViews().push(child);
    this._appendChildNode(child);
    child.setParentView(this);
    return this;
  },

  prependChild: function(child) {
    this.insertChild(child, 0);
  },

  clearChildren: function() {
    this.setChildViews([]);
  },

  // protected
  _appendChildNode: function(child) {
    this.getNode().appendChild(child.getNode());
  },

  insertChild: function(child, position) {
    var children = this.getChildViews();
    if (position === undefined) { position = children.length; }
    if (position >= children.length) {
      this.appendChild(child);
    } else {
      position = Math.max(0, position);
      this._insertAt(child, position);
    }
    return this;
  },

  _insertAt: function(child, position) {
    var children = this.getChildViews();
    var beforeChild = children[position];
    children.splice(position, 0, child);
    this._insertNodeBefore(child, beforeChild);
    child.setParentView(this);
    return this;
  },

  // protected
  _insertNodeBefore: function(child, beforeChild) {
    this.getNode().insertBefore(child.getNode(), beforeChild.getNode());
  },

  addListener: function(type, listener, contextOrNull) {
    var args = util.toArray(arguments);
    args[2] = contextOrNull || this;
    var node = this._nodeForEvent(type);
    this._eventTokens || (this._eventTokens = []);
    args.unshift(node);
    var token = domEvent.addListener.apply(domEvent, args);
    this._eventTokens.push(token);
    return token;
  },

  // COMPAT
  listen: function(type, listener, contextOrNull) {
    if (typeof listener === 'string') {
      throw new Error('listen(string, string) is no longer supported');
    }
    core.deprecated('container.listen', 'container.addListener');
    return this.addListener.apply(this, arguments);
  },

  removeListener: function(type, listener, contextOrNull) {
    contextOrNull = contextOrNull || this;
    var node = this._nodeForEvent(type);
    domEvent.removeListener(node, type, listener, contextOrNull);
    return this;
  },

  invoke: function(evtObject/*, args */) {
    if (util.isString(evtObject)) {
      evtObject = { type: evtObject };
    }
    var args = util.toArray(arguments);
    args.unshift(this._nodeForEvent(evtObject.type));
    return domEvent.invoke.apply(domEvent, args);
  },

  /**
   * find a reference within the views hierarchy
   */
  findRef: function(ref) {
    if (this.refs) {
      return this.refs[ref];
    }
    return null;
  },

  _nodeForEvent: function(name) {
    return this.getNode();
  }
};

});

define("bolt/mixins/events", function(require, exports, module) {
var util = require('../util');
var TokenList = require('../token_list').TokenList;

var Events = exports.Events = {
  // Bind an event, specified by a string name, `ev`, to a `listener` function.
  // Passing `"all"` will bind the listener to all events fired.
  addListener : function(type, listener, contextOrNull) {
    contextOrNull = contextOrNull || this;

    var list = this._tokenList || (this._tokenList = new TokenList());
    var args = util.toArray(arguments).slice(3);
    return list.addListener(type, listener, contextOrNull, args);
  },

  // Remove one or many listeners. If `listener` is null, removes all
  // listeners for the event. If `ev` is null, removes all bound listeners
  // for all events.
  removeListener : function(type, listener, contextOrNull) {
    if (this._tokenList) {
      this._tokenList.removeListener(type, listener, contextOrNull || this);
    }
    return this;
  },

  // Invoke an event, firing all bound listeners.
  invoke : function(eventObject) {
    if (!this._tokenList) { return this; }
    if (util.isString(eventObject)) {
      eventObject = { type: eventObject };
    }
    var args = util.toArray(arguments);

    var tokens = this._tokenList.getTokensForType(eventObject.type)
      .concat(this._tokenList.getTokensForType('all'));

    for (var i = 0, l = tokens.length; i < l; i++) {
      var item = tokens[i];
      if (!item.isDestroyed) {
        if (item.boundListener) {
          item.boundListener.apply(item, item.args.concat(args));
        } else {
          item.listener.apply(item.context || this, item.args.concat(args));
        }
      } else {
        item._destroyedInvocations = this._destroyedInvocations || 0;
        item._destroyedInvocations++;
        if (item._destroyedInvocations > 1) {
          // NB:wbailey
          // a token's listener may be invoked when it's destroyed if the
          // listeners are mutated in the course of invocation. This should
          // never happen more than one time per token since after the
          // original loop is completed the removed token should be dead and
          // should never be invoked again.
          throw 'a destroyed token outside of its original run loop';
        }
      }
    }
    return this;
  }
};

// COMPAT

var deprecated = require('../core').deprecated;
var slice = Array.prototype.slice;

function handleAll(event) {
  this.listener.apply(
    this.context,
    [event.type].concat(slice.call(arguments, 1)));
}

function handleSingle() {
  this.listener.apply(this.context, slice.call(arguments, 1));
}

Events.listen = function(type, callback, contextOrNull) {
  deprecated('listen', 'addListener');
  var token = this.addListener(type, callback, contextOrNull || this);
  token.boundListener = type === 'all' ? handleAll : handleSingle;
  return token;
};

Events.stopListening = function(){
  deprecated('stopListening', 'removeListener');
  Events.removeListener.apply(this, arguments);
};

});

define("bolt/model", function(require, exports, module) {
var util = require('./util');
var core = require('./core');
var Events = require('./mixins/events').Events;


/**
 * Models provide observable sets of properties that you can use to model
 * your domain logic.
 *
 * The Model class was inspired by and borrows heavily from backbone.js
 * http://documentcloud.github.com/backbone/
 */
var Model = exports.Model = core.createClass({
  name: 'Model',

  mixins: [Events],

  properties: {
    id: undefined
  },

  /**
   * Create a new model
   */
  construct: function(data) {
    this._properties = {};
    data = data || {};
    if (!('id' in data) || data.id === null) { // we allow 0 as an id
      data.id = this.generateId();
    }
    this.merge(data);
    this.cid = 'c' + util.generateCID();
  },

  /**
   * Returns whether something is a base property
   */
  isBaseProperty: function(key) {
    return this._properties.hasOwnProperty(key);
  },

  /**
   * Wrapper to get property using getter if available or .get() if not
   */
  getSafe: function(key) {
    var getter = util.getter(key);
    return this[getter] ? this[getter]() : this.get(key);
  },

  /**
   * Wrapper to set property using setter if available or .set() if not
   */
  setSafe: function(key, value, quiet) {
    var setter = util.setter(key);
    return this[setter] ?
      this[setter](value, quiet) :
      this.set(key, value, quiet);
  },

  /**
   * Low-level api to get property directly bypassing getter function
   * get a property of the of model
   */
  get: function(key) {
    return this._properties[key];
  },

  /**
   * Low-level api to set property directly bypassing setter function
   *
   * set a property of the model
   * optionally pass quiet parameter to avoid
   * invoke changed event
   *
   * @return false if there is no change; or an object for changeset
   */
  set: function(key, value, quiet) {
    var prev = this._properties[key];
    if (!util.isEqual(prev, value)) {
      this._properties[key] = value;
      if (key === 'id') {
        // TODO:wbailey depending on how we decide to handle id changes
        //              we may want to fire an additional event here
        //              if we can always send the client id up when syncing
        //              then this is not necessary.
        this.id = value;
      }
      var change = this._changeQueue || {};
      change[key] = prev;
      if (!quiet && !this._changeQueue) { this._invokeChanged(change); }
      return change;
    }
    return false;
  },

  /**
   * Low-level api to clear property
   *
   * unset a property of the model
   * optionally pass quiet parameter to avoid
   * invoke changed event
   *
   * @return false if not changed, the change set object if changed.
   */
  unset: function(key, quiet) {
    var prev = this._properties[key];

    // The following block is similar to set(key, null), while the
    // key difference is that we are checking prev not defined and prev
    // not equal to null. see unittest of testModel with the case of
    // 'unset an undefined property'
    if (prev !== undefined && prev !== null) {
      this._properties[key] = null;
      var change = {};
      change[key] = prev;
      if (!quiet) { this._invokeChanged(change); }
      return change;
    }
    return false;
  },

  /**
   * Low-level api to set mutliple properties at once sending only 1 event
   *
   * set multiple properties in one call
   * takes an optional quiet flag avoid invoking
   * changed event
   */
  /** UNSET PROPERTIES that are not defined **/
  setAll: function(obj, quiet) {
    var changedProperties = this._changeQueue = {};
    util.forEach(obj, function(value, key) {
      this.set(key, value);
    }, this);
    this._changeQueue = undefined;

    if (!util.isEmpty(changedProperties)) {
      if (!quiet) { this._invokeChanged(changedProperties); }
      return changedProperties;
    }
    return false;
  },

  _invokeChanged: function(changedProperties) {
    this.invoke({
      type: 'changed',
      model: this,
      changedProperties: changedProperties
    });
  },

  /**
   * merge a set of properties of the model -- this is similar to setAll,
   * but actually calls setters
   *
   * @return false if not changed, the change set object if changed.
   */
  merge: function(obj, quiet) {
    var changedProperties = this._changeQueue = {};
    util.forEach(obj, function(value, key) {
      this.setSafe(key, value);
    }, this);
    this._changeQueue = undefined;
    if (!util.isEmpty(changedProperties)) {
      if (!quiet) { this._invokeChanged(changedProperties); }
      return changedProperties;
    }
    return false;
  },

  /**
   * Function to be overridden to provide validity checks for
   * model values
   */
  isValid: function(key) {
    return true;
  },

  /**
   * iterate over each data property of the model
   */
  eachProperty: function(func, context) {
    util.forEach(this._properties, func, context);
  },

  /**
   * get the data properties of an object
   */
  toObject: function() {
    return util.extend({}, this._properties);
  },

  /**
   * generate a unique ID for a model
   *
   * By default, this uses a built-in UUID generator, though subclasses
   * can override this behavior.
   */
  generateId: function() {
    return util.generateUUID();
  },

  listen: function(type, callback, contextOrNull) {
    function handleAll(event) {
      this.listener.apply(
        this.context,
        [event.type].concat(arguments));
    }

    function handleSingle() {
      this.listener.apply(this.context, arguments);
    }

    require('./core').deprecated('listen', 'addListener');
    var token = this.addListener(type, callback, contextOrNull || this);
    token.boundListener = type === 'all' ? handleAll : handleSingle;
    return token;
  },
  
  destroy: function() {
    this.removeListener();
  }
});

});

define("bolt/tag_view", function(require, exports, module) {
var util     = require('./util');
var core     = require('./core');
var dom      = require('./dom');

var Container = require('./mixins/container').Container;

/**
 * A special (final) class that should be private to the builder. Noone should
 * ever need to instantiate an instance of TagView except the builder. View
 * classes in general do not need to delegate html attributes to the container
 * node, because many of them just don't make sense from the perspective of a
 * general container component. However a TagView is a container component that
 * is intended to be treated as a lower level building block in a build paln, or
 * declare() statement, so control over all attributes is important.
 */

var TagView = exports.TagView = core.createClass({

  name: 'TagView',

  mixins: [Container],

  /**
   * Accepts options and tagName. Usually tagName will be in the options, but
   * if you're allocating a TagView, you likely allready found the tagName -
   * pass it in so we don't need to look it up again.
   */
  construct: function(options) {
    options = options || {};
    this.setNode(dom.createElement(options.tagName || 'div'));
    this.setup(options);
  },

  setName: function(name) {
    this.__auto__node.name = name;
    return this;
  },
  getName: function() {
    return this.__auto__node.name;
  },
  setHref: function(href) {
    this.__auto__node.href = href;
    return this;
  },
  getHref: function() {
    return this.__auto__node.href;
  },
  setId: function(id) {
    this.__auto__node.id = id;
    return this;
  },
  getId: function() {
    return this.__auto__node.id;
  },
  setTagName: function(tagName) {
    // Do nothing - just make sure noone tries to set a tag name on a dom node
    // directly - causing an error in IE.
    return this;
  },
  getTagName: function() {
    return this.__auto__node.tagName;
  },

  delegateProperties: {
    node: [
      'disabled',
      'id',
      'tabIndex',
      'src',
      'cellpadding',
      'cellspacing',
      'htmlFor',
      'colspan',
      'rowspan',

      // Just in case someone uses additionalClasses on a tag view, expecting
      // it to gracefully append a className. In the case of tag views, there's
      // nothing to gracefully append to so we just set the class.
      { name: 'className', alias: 'additionalClasses'}
    ],
    style: [
      'height',
      'width'
    ]
  }

});


});

define("bolt/token_list", function(require, exports, module) {
/**
* Copyright (c) 2011, Facebook, Inc.
*/
function noop() {};

function Token(list, type, listener, context, args) {
  this.list = list;
  this.type = type;
  this.listener = listener;
  this.context = context;
  this.args = args;
};

Token.prototype.remove = function() {
  this.isDestroyed = true;
  this.list.removeListener(this.type, this.listener, this.context);
  this.list = null;
  this.remove = noop;
};


function TokenList() {}

TokenList.prototype.addToken = function(token) {
  this._listeners || (this._listeners = {});
  this._listeners[token.type] || (this._listeners[token.type] = []);
  this._listeners[token.type].push(token);
  return token;
};

TokenList.prototype.addListener = function(type, listener, context, args) {
  return this.addToken(new Token(this, type, listener, context, args));
};

TokenList.prototype.isEmpty = function() {
  if (!this._listeners) {
    return true;
  }
  for (var type in this._listeners) {
    if (this._listeners.hasOwnProperty(type)) {
      return false;
    }
  }
  return true;
};



TokenList.prototype.removeListener = function(type, listener, contextOrNull) {
  if (!this._listeners) { return; }
  if (!type) {
    delete this._listeners;
  } else if (!listener) {
    delete this._listeners[type];
  } else {
    if (!this._listeners || !this._listeners[type]) { return; }
    var list = this._listeners[type];
    for (var i = 0, l = list.length; i < l; i++) {
      var item = list[i];
      if (listener === item.listener && contextOrNull === item.context) {
        list.splice(i--, 1);
        l--;
      }
    }
    if (!list.length) {
      delete this._listeners[type];
    }
  }
};

TokenList.prototype.getTokensForType = function(type) {
  return this._listeners && this._listeners[type] || [];
};

TokenList.prototype.hasTokensForType = function(type) {
  return this._listeners &&
    this._listeners[type] && this._listeners[type].length;
};

exports.TokenList = TokenList;

});

define("bolt/util", function(require, exports, module) {
module.exports = exports = require('./vendor/_');

var _cid = 1;

var createTransformer = function(prefix) {
  var names = {};
  return function(name) {
    if (!names[name]) {
      names[name] = prefix + exports.capitalize(name);
    }
    return names[name];
  };
};

exports.setter = createTransformer('set');
exports.getter = createTransformer('get');
exports.eventHandler = createTransformer('on');

/**
 * Generates a setter for a property that directly manipulates a CSS class.
 *
 * For a button consider the following properties declaration:
 *
 *   properties: {
 *     color: null,
 *     enabled: null,
 *   }
 *
 * Then to have those properties directly manipulate CSS classes the setters
 * should be overriden as follows:
 *
 *   setColor: util.modeSetter('color', ['green', 'red', 'blue']),
 *   setEnabled: util.modeSetter('enabled')
 *
 * @param mode - the property name
 * @param classes - If this is a boolean property (where truthy values will add
 *    <mode> to the className of the object and falsy values will remove <mode>
 *    from the className) then do not pass in a second argument. If this is a
 *    enumerated property with several mutually excluded options include an
 *    array of string options for what those properties may be. When one gets
 *    set the others get unset and a generated class is added to the classname
 *    of the form <mode>-<value>. If a value that isn't in the enumerated values
 *    is passed in, an exception is thrown.
 *
 * NOTE: Currently properties do not call their setter on construction so
 *  to set a default value, you'll need to call the setter in the ready
 *  function.
 */
exports.modeSetter = function(mode, classes) {
  if (exports.isBlank(classes)) {
    // toggle mode
    return function(value) {
      this.set(mode, !!value);
      return this.toggleClass(mode, value);
    };
  } else {
    // enum mode
    var classesHash = {};
    for (var i = 0; i < classes.length; i++) {
      classesHash[classes[i]] = true;
    }
    return function(value) {
      if (!(value in classesHash)) {
        throw this.getDeclaredClass() + ' does not support value "' +
          value + '" for mode "' + mode + '".';
      }
      this.set(mode, value);
      this.setMode(mode, value);
    };
  }
};

exports.bind = function(func, obj) {
  var slice = Array.prototype.slice;
  var args = slice.call(arguments, 2);
  var nativeBind = Function.prototype.bind;

  if (typeof func === "string") {
    return function() {
      return obj[func].apply(obj, args.concat(slice.call(arguments)));
    };
  } else {
    if (func.bind === nativeBind && nativeBind) {
      return nativeBind.apply(func, slice.call(arguments, 1));
    }
    return function() {
      return func.apply(obj, args.concat(slice.call(arguments)));
    };
  }
};

var stringTransform = function(str, separator) {
  var UP = /[A-Z]/, SEP = /[^A-za-z0-9]/;
  for (var i = 0, l = str.length, out = [], cur, next, prior; i < l; i++) {
    cur = str[i];
    next = str[i + 1];
    prior = str[i - 1];
    if (SEP.test(cur)) {
      if (out[out.length - 1] !== separator) {
        out.push(separator);
      }
    } else {
      if (prior && next && UP.test(cur) && (!UP.test(next) || !UP.test(prior))) {
        out.push(separator);
      }
      out.push(cur.toLowerCase());
    }
  }
  return out.join('');
};

exports.hyphenate = function(str) {
  return stringTransform(str, '-');
};

exports.underscore = function(str) {
  return stringTransform(str, '_');
};

exports.trim = String.prototype.trim ?
  function(str){ return str.trim(); } :
  function(str){ return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');};

exports.capitalize = function(value) {
  if (!value || !value.length) {
    return value;
  }
  return value.charAt(0).toUpperCase() + value.slice(1);
};

/**
 * Call a method on multiple contexts.
 * This is similar to util.invoke, but is more lightweight. Whereas
 * util.invoke builds an object with the return values of all the
 * function calls, util.run simply executes the functions and returns
 * nothing. This uses less memory and has one less function call.
 *
 * @param obj An array of contexts, each of which contains the method
 * @params method Either a function, or the string name of a function
 * in the context
*/
exports.run = function(obj, method) {
  var args = arguments.length > 2 ?
  Array.prototype.slice.call(arguments, 2) : undefined;
  var context;
  for (var i = 0; i < obj.length; i++) {
    context = obj[i];
    (method.call ? method || context : context[method]).apply(context, args);
  }
};

exports.generateUUID = function() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = Math.random() * 16 | 0;
    var v = c == 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  }).toUpperCase();
};

/**
 * Used to create an identifier that is intended to be unique per page load.
 * Do not persist this id and expect it to be unique in any offline system.
 */
exports.generateCID = function() {
  return _cid++;
};

exports.isBlank = function(obj) {
  return exports.isUndefined(obj)
    || exports.isNull(obj)
    || (!exports.isNumber(obj) && exports.isEmpty(obj));
};

require('./compat/util');

});

define("bolt/vendor/_", function(require, exports, module) {
//     Underscore.js 1.1.7
//     (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
//     Underscore is freely distributable under the MIT license.
//     Portions of Underscore are inspired or borrowed from Prototype,
//     Oliver Steele's Functional, and John Resig's Micro-Templating.
//     For all details and documentation:
//     http://documentcloud.github.com/underscore

(function() {

  // Baseline setup
  // --------------

  // Establish the root object, `window` in the browser, or `global` on the server.
  var root = this;

  // Save the previous value of the `_` variable.
  var previousUnderscore = root._;

  // Establish the object that gets returned to break out of a loop iteration.
  var breaker = {};

  // Save bytes in the minified (but not gzipped) version:
  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;

  // Create quick reference variables for speed access to core prototypes.
  var slice            = ArrayProto.slice,
      unshift          = ArrayProto.unshift,
      toString         = ObjProto.toString,
      hasOwnProperty   = ObjProto.hasOwnProperty;

  // All **ECMAScript 5** native function implementations that we hope to use
  // are declared here.
  var
    nativeForEach      = ArrayProto.forEach,
    nativeMap          = ArrayProto.map,
    nativeReduce       = ArrayProto.reduce,
    nativeReduceRight  = ArrayProto.reduceRight,
    nativeFilter       = ArrayProto.filter,
    nativeEvery        = ArrayProto.every,
    nativeSome         = ArrayProto.some,
    nativeIndexOf      = ArrayProto.indexOf,
    nativeLastIndexOf  = ArrayProto.lastIndexOf,
    nativeIsArray      = Array.isArray,
    nativeKeys         = Object.keys,
    nativeBind         = FuncProto.bind;

  // Create a safe reference to the Underscore object for use below.
  var _ = function(obj) { return new wrapper(obj); };

  // Export the Underscore object for **CommonJS**, with backwards-compatibility
  // for the old `require()` API. If we're not in CommonJS, add `_` to the
  // global object.
  if (typeof module !== 'undefined' && module.exports) {
    module.exports = _;
    _._ = _;
  } else {
    // Exported as a string, for Closure Compiler "advanced" mode.
    root['_'] = _;
  }

  // Current version.
  _.VERSION = '1.1.7';

  // Collection Functions
  // --------------------

  // The cornerstone, an `each` implementation, aka `forEach`.
  // Handles objects with the built-in `forEach`, arrays, and raw objects.
  // Delegates to **ECMAScript 5**'s native `forEach` if available.
  var each = _.each = _.forEach = function(obj, iterator, context) {
    if (obj == null) return;
    if (nativeForEach && obj.forEach === nativeForEach) {
      obj.forEach(iterator, context);
    } else if (obj.length === +obj.length) {
      for (var i = 0, l = obj.length; i < l; i++) {
        if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
      }
    } else {
      for (var key in obj) {
        if (hasOwnProperty.call(obj, key)) {
          if (iterator.call(context, obj[key], key, obj) === breaker) return;
        }
      }
    }
  };

  // Return the results of applying the iterator to each element.
  // Delegates to **ECMAScript 5**'s native `map` if available.
  _.map = function(obj, iterator, context) {
    var results = [];
    if (obj == null) return results;
    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
    each(obj, function(value, index, list) {
      results[results.length] = iterator.call(context, value, index, list);
    });
    return results;
  };

  // **Reduce** builds up a single result from a list of values, aka `inject`,
  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
    var initial = memo !== void 0;
    if (obj == null) obj = [];
    if (nativeReduce && obj.reduce === nativeReduce) {
      if (context) iterator = _.bind(iterator, context);
      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
    }
    each(obj, function(value, index, list) {
      if (!initial) {
        memo = value;
        initial = true;
      } else {
        memo = iterator.call(context, memo, value, index, list);
      }
    });
    if (!initial) throw new TypeError("Reduce of empty array with no initial value");
    return memo;
  };

  // The right-associative version of reduce, also known as `foldr`.
  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
    if (obj == null) obj = [];
    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
      if (context) iterator = _.bind(iterator, context);
      return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
    }
    var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
    return _.reduce(reversed, iterator, memo, context);
  };

  // Return the first value which passes a truth test. Aliased as `detect`.
  _.find = _.detect = function(obj, iterator, context) {
    var result;
    any(obj, function(value, index, list) {
      if (iterator.call(context, value, index, list)) {
        result = value;
        return true;
      }
    });
    return result;
  };

  // Return all the elements that pass a truth test.
  // Delegates to **ECMAScript 5**'s native `filter` if available.
  // Aliased as `select`.
  _.filter = _.select = function(obj, iterator, context) {
    var results = [];
    if (obj == null) return results;
    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
    each(obj, function(value, index, list) {
      if (iterator.call(context, value, index, list)) results[results.length] = value;
    });
    return results;
  };

  // Return all the elements for which a truth test fails.
  _.reject = function(obj, iterator, context) {
    var results = [];
    if (obj == null) return results;
    each(obj, function(value, index, list) {
      if (!iterator.call(context, value, index, list)) results[results.length] = value;
    });
    return results;
  };

  // Determine whether all of the elements match a truth test.
  // Delegates to **ECMAScript 5**'s native `every` if available.
  // Aliased as `all`.
  _.every = _.all = function(obj, iterator, context) {
    var result = true;
    if (obj == null) return result;
    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
    each(obj, function(value, index, list) {
      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
    });
    return result;
  };

  // Determine if at least one element in the object matches a truth test.
  // Delegates to **ECMAScript 5**'s native `some` if available.
  // Aliased as `any`.
  var any = _.some = _.any = function(obj, iterator, context) {
    iterator = iterator || _.identity;
    var result = false;
    if (obj == null) return result;
    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
    each(obj, function(value, index, list) {
      if (result |= iterator.call(context, value, index, list)) return breaker;
    });
    return !!result;
  };

  // Determine if a given value is included in the array or object using `===`.
  // Aliased as `contains`.
  _.include = _.contains = function(obj, target) {
    var found = false;
    if (obj == null) return found;
    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
    any(obj, function(value) {
      if (found = value === target) return true;
    });
    return found;
  };

  // Invoke a method (with arguments) on every item in a collection.
  _.invoke = function(obj, method) {
    var args = slice.call(arguments, 2);
    return _.map(obj, function(value) {
      return (method.call ? method || value : value[method]).apply(value, args);
    });
  };

  // Convenience version of a common use case of `map`: fetching a property.
  _.pluck = function(obj, key) {
    return _.map(obj, function(value){ return value[key]; });
  };

  // Return the maximum element or (element-based computation).
  _.max = function(obj, iterator, context) {
    if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
    var result = {computed : -Infinity};
    each(obj, function(value, index, list) {
      var computed = iterator ? iterator.call(context, value, index, list) : value;
      computed >= result.computed && (result = {value : value, computed : computed});
    });
    return result.value;
  };

  // Return the minimum element (or element-based computation).
  _.min = function(obj, iterator, context) {
    if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
    var result = {computed : Infinity};
    each(obj, function(value, index, list) {
      var computed = iterator ? iterator.call(context, value, index, list) : value;
      computed < result.computed && (result = {value : value, computed : computed});
    });
    return result.value;
  };

  // Sort the object's values by a criterion produced by an iterator.
  _.sortBy = function(obj, iterator, context) {
    return _.pluck(_.map(obj, function(value, index, list) {
      return {
        value : value,
        criteria : iterator.call(context, value, index, list)
      };
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }), 'value');
  };

  // Groups the object's values by a criterion produced by an iterator
  _.groupBy = function(obj, iterator) {
    var result = {};
    each(obj, function(value, index) {
      var key = iterator(value, index);
      (result[key] || (result[key] = [])).push(value);
    });
    return result;
  };

  // Use a comparator function to figure out at what index an object should
  // be inserted so as to maintain order. Uses binary search.
  _.sortedIndex = function(array, obj, iterator) {
    iterator || (iterator = _.identity);
    var low = 0, high = array.length;
    while (low < high) {
      var mid = (low + high) >> 1;
      iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
    }
    return low;
  };

  // Safely convert anything iterable into a real, live array.
  _.toArray = function(iterable) {
    if (!iterable)                return [];
    if (iterable.toArray)         return iterable.toArray();
    if (_.isArray(iterable))      return slice.call(iterable);
    if (_.isArguments(iterable))  return slice.call(iterable);
    return _.values(iterable);
  };

  // Return the number of elements in an object.
  _.size = function(obj) {
    return _.toArray(obj).length;
  };

  // Array Functions
  // ---------------

  // Get the first element of an array. Passing **n** will return the first N
  // values in the array. Aliased as `head`. The **guard** check allows it to work
  // with `_.map`.
  _.first = _.head = function(array, n, guard) {
    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
  };

  // Returns everything but the first entry of the array. Aliased as `tail`.
  // Especially useful on the arguments object. Passing an **index** will return
  // the rest of the values in the array from that index onward. The **guard**
  // check allows it to work with `_.map`.
  _.rest = _.tail = function(array, index, guard) {
    return slice.call(array, (index == null) || guard ? 1 : index);
  };

  // Get the last element of an array.
  _.last = function(array) {
    return array[array.length - 1];
  };

  // Trim out all falsy values from an array.
  _.compact = function(array) {
    return _.filter(array, function(value){ return !!value; });
  };

  // Return a completely flattened version of an array.
  _.flatten = function(array) {
    return _.reduce(array, function(memo, value) {
      if (_.isArray(value)) return memo.concat(_.flatten(value));
      memo[memo.length] = value;
      return memo;
    }, []);
  };

  // Return a version of the array that does not contain the specified value(s).
  _.without = function(array) {
    return _.difference(array, slice.call(arguments, 1));
  };

  // Produce a duplicate-free version of the array. If the array has already
  // been sorted, you have the option of using a faster algorithm.
  // Aliased as `unique`.
  _.uniq = _.unique = function(array, isSorted) {
    return _.reduce(array, function(memo, el, i) {
      if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el;
      return memo;
    }, []);
  };

  // Produce an array that contains the union: each distinct element from all of
  // the passed-in arrays.
  _.union = function() {
    return _.uniq(_.flatten(arguments));
  };

  // Produce an array that contains every item shared between all the
  // passed-in arrays. (Aliased as "intersect" for back-compat.)
  _.intersection = _.intersect = function(array) {
    var rest = slice.call(arguments, 1);
    return _.filter(_.uniq(array), function(item) {
      return _.every(rest, function(other) {
        return _.indexOf(other, item) >= 0;
      });
    });
  };

  // Take the difference between one array and another.
  // Only the elements present in just the first array will remain.
  _.difference = function(array, other) {
    return _.filter(array, function(value){ return !_.include(other, value); });
  };

  // Zip together multiple lists into a single array -- elements that share
  // an index go together.
  _.zip = function() {
    var args = slice.call(arguments);
    var length = _.max(_.pluck(args, 'length'));
    var results = new Array(length);
    for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
    return results;
  };

  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
  // we need this function. Return the position of the first occurrence of an
  // item in an array, or -1 if the item is not included in the array.
  // Delegates to **ECMAScript 5**'s native `indexOf` if available.
  // If the array is large and already in sort order, pass `true`
  // for **isSorted** to use binary search.
  _.indexOf = function(array, item, isSorted) {
    if (array == null) return -1;
    var i, l;
    if (isSorted) {
      i = _.sortedIndex(array, item);
      return array[i] === item ? i : -1;
    }
    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
    for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
    return -1;
  };


  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
  _.lastIndexOf = function(array, item) {
    if (array == null) return -1;
    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
    var i = array.length;
    while (i--) if (array[i] === item) return i;
    return -1;
  };

  // Generate an integer Array containing an arithmetic progression. A port of
  // the native Python `range()` function. See
  // [the Python documentation](http://docs.python.org/library/functions.html#range).
  _.range = function(start, stop, step) {
    if (arguments.length <= 1) {
      stop = start || 0;
      start = 0;
    }
    step = arguments[2] || 1;

    var len = Math.max(Math.ceil((stop - start) / step), 0);
    var idx = 0;
    var range = new Array(len);

    while(idx < len) {
      range[idx++] = start;
      start += step;
    }

    return range;
  };

  // Function (ahem) Functions
  // ------------------

  // Create a function bound to a given object (assigning `this`, and arguments,
  // optionally). Binding with arguments is also known as `curry`.
  // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
  // We check for `func.bind` first, to fail fast when `func` is undefined.
  _.bind = function(func, obj) {
    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
    var args = slice.call(arguments, 2);
    return function() {
      return func.apply(obj, args.concat(slice.call(arguments)));
    };
  };

  // Bind all of an object's methods to that object. Useful for ensuring that
  // all callbacks defined on an object belong to it.
  _.bindAll = function(obj) {
    var funcs = slice.call(arguments, 1);
    if (funcs.length == 0) funcs = _.functions(obj);
    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
    return obj;
  };

  // Memoize an expensive function by storing its results.
  _.memoize = function(func, hasher) {
    var memo = {};
    hasher || (hasher = _.identity);
    return function() {
      var key = hasher.apply(this, arguments);
      return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
    };
  };

  // Delays a function for the given number of milliseconds, and then calls
  // it with the arguments supplied.
  _.delay = function(func, wait) {
    var args = slice.call(arguments, 2);
    return setTimeout(function(){ return func.apply(func, args); }, wait);
  };

  // Defers a function, scheduling it to run after the current call stack has
  // cleared.
  _.defer = function(func) {
    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
  };

  // Internal function used to implement `_.throttle` and `_.debounce`.
  var limit = function(func, wait, debounce) {
    var timeout;
    return function() {
      var context = this, args = arguments;
      var throttler = function() {
        timeout = null;
        func.apply(context, args);
      };
      if (debounce) clearTimeout(timeout);
      if (debounce || !timeout) timeout = setTimeout(throttler, wait);
    };
  };

  // Returns a function, that, when invoked, will only be triggered at most once
  // during a given window of time.
  _.throttle = function(func, wait) {
    return limit(func, wait, false);
  };

  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds.
  _.debounce = function(func, wait) {
    return limit(func, wait, true);
  };

  // Returns a function that will be executed at most one time, no matter how
  // often you call it. Useful for lazy initialization.
  _.once = function(func) {
    var ran = false, memo;
    return function() {
      if (ran) return memo;
      ran = true;
      return memo = func.apply(this, arguments);
    };
  };

  // Returns the first function passed as an argument to the second,
  // allowing you to adjust arguments, run code before and after, and
  // conditionally execute the original function.
  _.wrap = function(func, wrapper) {
    return function() {
      var args = [func].concat(slice.call(arguments));
      return wrapper.apply(this, args);
    };
  };

  // Returns a function that is the composition of a list of functions, each
  // consuming the return value of the function that follows.
  _.compose = function() {
    var funcs = slice.call(arguments);
    return function() {
      var args = slice.call(arguments);
      for (var i = funcs.length - 1; i >= 0; i--) {
        args = [funcs[i].apply(this, args)];
      }
      return args[0];
    };
  };

  // Returns a function that will only be executed after being called N times.
  _.after = function(times, func) {
    return function() {
      if (--times < 1) { return func.apply(this, arguments); }
    };
  };


  // Object Functions
  // ----------------

  // Retrieve the names of an object's properties.
  // Delegates to **ECMAScript 5**'s native `Object.keys`
  _.keys = nativeKeys || function(obj) {
    if (obj !== Object(obj)) throw new TypeError('Invalid object');
    var keys = [];
    for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
    return keys;
  };

  // Retrieve the values of an object's properties.
  _.values = function(obj) {
    return _.map(obj, _.identity);
  };

  // Return a sorted list of the function names available on the object.
  // Aliased as `methods`
  _.functions = _.methods = function(obj) {
    var names = [];
    for (var key in obj) {
      if (_.isFunction(obj[key])) names.push(key);
    }
    return names.sort();
  };

  // Extend a given object with all the properties in passed-in object(s).
  _.extend = function(obj) {
    each(slice.call(arguments, 1), function(source) {
      for (var prop in source) {
        if (source[prop] !== void 0) obj[prop] = source[prop];
      }
    });
    return obj;
  };

  // Fill in a given object with default properties.
  _.defaults = function(obj) {
    each(slice.call(arguments, 1), function(source) {
      for (var prop in source) {
        if (obj[prop] == null) obj[prop] = source[prop];
      }
    });
    return obj;
  };

  // Create a (shallow-cloned) duplicate of an object.
  _.clone = function(obj) {
    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
  };

  // Invokes interceptor with the obj, and then returns obj.
  // The primary purpose of this method is to "tap into" a method chain, in
  // order to perform operations on intermediate results within the chain.
  _.tap = function(obj, interceptor) {
    interceptor(obj);
    return obj;
  };

  // Perform a deep comparison to check if two objects are equal.
  _.isEqual = function(a, b) {
    // Check object identity.
    if (a === b) return true;
    // Different types?
    var atype = typeof(a), btype = typeof(b);
    if (atype != btype) return false;
    // Basic equality test (watch out for coercions).
    if (a == b) return true;
    // One is falsy and the other truthy.
    if ((!a && b) || (a && !b)) return false;
    // Unwrap any wrapped objects.
    if (a._chain) a = a._wrapped;
    if (b._chain) b = b._wrapped;
    // One of them implements an isEqual()?
    if (a.isEqual) return a.isEqual(b);
    if (b.isEqual) return b.isEqual(a);
    // Check dates' integer values.
    if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
    // Both are NaN?
    if (_.isNaN(a) && _.isNaN(b)) return false;
    // Compare regular expressions.
    if (_.isRegExp(a) && _.isRegExp(b))
      return a.source     === b.source &&
             a.global     === b.global &&
             a.ignoreCase === b.ignoreCase &&
             a.multiline  === b.multiline;
    // If a is not an object by this point, we can't handle it.
    if (atype !== 'object') return false;
    // Check for different array lengths before comparing contents.
    if (a.length && (a.length !== b.length)) return false;
    // Nothing else worked, deep compare the contents.
    var aKeys = _.keys(a), bKeys = _.keys(b);
    // Different object sizes?
    if (aKeys.length != bKeys.length) return false;
    // Recursive comparison of contents.
    for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
    return true;
  };

  // Is a given array or object empty?
  _.isEmpty = function(obj) {
    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
    for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
    return true;
  };

  // Is a given value a DOM element?
  _.isElement = function(obj) {
    return !!(obj && obj.nodeType == 1);
  };

  // Is a given value an array?
  // Delegates to ECMA5's native Array.isArray
  _.isArray = nativeIsArray || function(obj) {
    return toString.call(obj) === '[object Array]';
  };

  // Is a given variable an object?
  _.isObject = function(obj) {
    return obj === Object(obj);
  };

  // Is a given variable an arguments object?
  _.isArguments = function(obj) {
    return !!(obj && hasOwnProperty.call(obj, 'callee'));
  };

  // Is a given value a function?
  _.isFunction = function(obj) {
    return !!(obj && obj.constructor && obj.call && obj.apply);
  };

  // Is a given value a string?
  _.isString = function(obj) {
    return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
  };

  // Is a given value a number?
  _.isNumber = function(obj) {
    return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed));
  };

  // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript
  // that does not equal itself.
  _.isNaN = function(obj) {
    return obj !== obj;
  };

  // Is a given value a boolean?
  _.isBoolean = function(obj) {
    return obj === true || obj === false;
  };

  // Is a given value a date?
  _.isDate = function(obj) {
    return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
  };

  // Is the given value a regular expression?
  _.isRegExp = function(obj) {
    return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
  };

  // Is a given value equal to null?
  _.isNull = function(obj) {
    return obj === null;
  };

  // Is a given variable undefined?
  _.isUndefined = function(obj) {
    return obj === void 0;
  };

  // Utility Functions
  // -----------------

  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
  // previous owner. Returns a reference to the Underscore object.
  _.noConflict = function() {
    root._ = previousUnderscore;
    return this;
  };

  // Keep the identity function around for default iterators.
  _.identity = function(value) {
    return value;
  };

  // Run a function **n** times.
  _.times = function (n, iterator, context) {
    for (var i = 0; i < n; i++) iterator.call(context, i);
  };

  // Add your own custom functions to the Underscore object, ensuring that
  // they're correctly added to the OOP wrapper as well.
  _.mixin = function(obj) {
    each(_.functions(obj), function(name){
      addToWrapper(name, _[name] = obj[name]);
    });
  };

  // Generate a unique integer id (unique within the entire client session).
  // Useful for temporary DOM ids.
  var idCounter = 0;
  _.uniqueId = function(prefix) {
    var id = idCounter++;
    return prefix ? prefix + id : id;
  };

  // By default, Underscore uses ERB-style template delimiters, change the
  // following template settings to use alternative delimiters.
  _.templateSettings = {
    evaluate    : /<%([\s\S]+?)%>/g,
    interpolate : /<%=([\s\S]+?)%>/g
  };

  // JavaScript micro-templating, similar to John Resig's implementation.
  // Underscore templating handles arbitrary delimiters, preserves whitespace,
  // and correctly escapes quotes within interpolated code.
  _.template = function(str, data) {
    var c  = _.templateSettings;
    var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
      'with(obj||{}){__p.push(\'' +
      str.replace(/\\/g, '\\\\')
         .replace(/'/g, "\\'")
         .replace(c.interpolate, function(match, code) {
           return "'," + code.replace(/\\'/g, "'") + ",'";
         })
         .replace(c.evaluate || null, function(match, code) {
           return "');" + code.replace(/\\'/g, "'")
                              .replace(/[\r\n\t]/g, ' ') + "__p.push('";
         })
         .replace(/\r/g, '\\r')
         .replace(/\n/g, '\\n')
         .replace(/\t/g, '\\t')
         + "');}return __p.join('');";
    var func = new Function('obj', tmpl);
    return data ? func(data) : func;
  };

  // The OOP Wrapper
  // ---------------

  // If Underscore is called as a function, it returns a wrapped object that
  // can be used OO-style. This wrapper holds altered versions of all the
  // underscore functions. Wrapped objects may be chained.
  var wrapper = function(obj) { this._wrapped = obj; };

  // Expose `wrapper.prototype` as `_.prototype`
  _.prototype = wrapper.prototype;

  // Helper function to continue chaining intermediate results.
  var result = function(obj, chain) {
    return chain ? _(obj).chain() : obj;
  };

  // A method to easily add functions to the OOP wrapper.
  var addToWrapper = function(name, func) {
    wrapper.prototype[name] = function() {
      var args = slice.call(arguments);
      unshift.call(args, this._wrapped);
      return result(func.apply(_, args), this._chain);
    };
  };

  // Add all of the Underscore functions to the wrapper object.
  _.mixin(_);

  // Add all mutator Array functions to the wrapper.
  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
    var method = ArrayProto[name];
    wrapper.prototype[name] = function() {
      method.apply(this._wrapped, arguments);
      return result(this._wrapped, this._chain);
    };
  });

  // Add all accessor Array functions to the wrapper.
  each(['concat', 'join', 'slice'], function(name) {
    var method = ArrayProto[name];
    wrapper.prototype[name] = function() {
      return result(method.apply(this._wrapped, arguments), this._chain);
    };
  });

  // Start chaining a wrapped Underscore object.
  wrapper.prototype.chain = function() {
    this._chain = true;
    return this;
  };

  // Extracts the result from a wrapped and chained object.
  wrapper.prototype.value = function() {
    return this._wrapped;
  };

})();

});

define("bolt/view", function(require, exports, module) {
var util     = require('./util');
var core     = require('./core');
var dom      = require('./dom');

var Container = require('./mixins/container').Container;

var View = exports.View = core.createClass({

  name: 'View',

  mixins: [Container],

  // Override declare in your subclasses to provide default options for your
  // specific View. This actually removes the need for a custom render
  // function, since childViews are just another part of setup. Views that
  // render in the old way will still work for backwards compatibility.
  //
  //   declaring a custom view can now be as simple as this:
  //   createClass({
  //     name: 'CustomView',
  //     extend: View,
  //     declare: {
  //       color: 'red'
  //       childViews: [
  //         {content: 'foo'}
  //       ]
  //     }
  //   }
  //
  // NOTE: wbailey 5-10-2011
  // The way we are do setLayout inside of render obscures what is
  // actually happening. The setChildViews setter at each level of the
  // hierarchy actually does the recursion. Thus a cleaner api is to just let
  // this happen during setup and provide a way to *declare* overridable default
  // options.
  declare: function() {},

  construct: function(options) {

    // the options for the view are now derived by extending a shallow copy
    // of the the *declared* options on the prototype. This allows you to
    // specify any property of the parent in the declare block and optionally
    // override it with options passed to the constructor.
    var declOptions = this.declare(options);

    // voloko: extremly hacky, and supports only childViews property. So
    // leftChildViews and rightChildViews will not work.
    // Set the owner of each of the childViews to default to this View
    if (declOptions && declOptions.childViews) {
      util.forEach(
        declOptions.childViews,
        function(viewSpec) {
          viewSpec.owner = viewSpec.owner || this;
        },
        this);
    }

    // if both declOptions and options given => extend, otherwise use available
    var optionsToUse =
      declOptions && options ? util.extend(declOptions, options || {}) :
      declOptions || options || {};

    // should probably remove this guys to save some memory
    this.refs = {};

    this.createDom(optionsToUse);

    if (this.render) {
      require('./core').deprecated('View.render', 'View.setup');
      this.render(optionsToUse);
    }

    // if we haven't yet captured the cssClass for this view class use the
    // inheritance chain to create a list of css classes generated from the
    // js class name and cache it on the js class for future use.
    var klass = this.klass;
    if (!klass.cssClass) {
      var inheritanceChain = klass.inheritanceChain, classes = [];
      for (var i = 0, l = inheritanceChain.length; i < l; i++) {
        classes.unshift('bt-' + util.hyphenate(inheritanceChain[i].klassName));
      }
      klass.cssClass = classes.join(' ');
    }

    this.setup(optionsToUse);

    // the initial css class for a view should be its inherited class followed
    // by any passed in className or additionalClasses properties.
    // e.g. bt-view custom-class-foo
    var existingClass, classToSet, inheritedClass;
    existingClass = this.getClassName();
    classToSet = inheritedClass = klass.cssClass;

    if (existingClass) {
      classToSet = inheritedClass + ' ' + existingClass;
    }
    this.setClassName(classToSet);

    // call any mixinReady functions
    if (this.mixinReadyFunctions) {
      for (var i = 0; i < this.mixinReadyFunctions.length; i++) {
        this.mixinReadyFunctions[i].call(this);
      }
    }

    // hook to setup any post construct handlers
    this.ready && this.ready();
  },

  properties: {
    metadata: null
  },

  // Set up the delegated properties. A property that is just a string sets up
  // a setter and getter with that name on the parent widget, e.g. the property
  // of 'label' delegated to 'node' will set up a setLabel and getLabel function
  // that looks for either this.node or a referenced child widget in
  // this.refs['node'], then sets and gets the label on it.  A property that is
  // a JSON object, with both an 'alias' and 'name' member works slightly
  // differently.  A getter and setter for the alias are added to the parent
  // widget, but these functions look for the 'name' in the child property.
  // E.g. a property {alias: 'label', name: 'value '} delegated to 'node'
  // would create the functions 'getLabel' and 'setLabel' on the parent view,
  // but would get and set the 'value' property of 'node'.
  // By default, anything extending the View class will have these properties
  // delegated to the node returned from getNode().
  delegateProperties: {
    node: [
      'data-ref',
      'disabled',
      'id',
      'name',
      'tabIndex'
      /* We won't delegate tagName because it will be slow and redundant to set
       * it, if the creator doesn't know it's kind after creating it, then
       * they're not very organized.
       * We won't delegate innerHtml because you should create and remove
       * children in a way that doesn't leak memory removeChildViews().
       */
    ],
    style: [
      'height',
      'width'
    ]
  },


  /*
   * set the data attribute on the DOM node
   */
  setMetadata: function(obj) {
    this.set('metadata', obj);
    var node = this.getNode();
    for (var name in obj) {
      node.setAttribute('data-' + name, obj[name]);
    }
  },

  /**
   * create the dom node for this view to render within
   * options
   *   - tagName: specify a tag name to use when creating the dom node
   *              other than the default div
   */
  createDom: function(options) {
    var node = this.getNode();
    if (!node) {
      this.setNode(dom.createElement(options.tagName || 'div'));
      node = this.getNode();
    }
    return node;
  },

  /**
   * find the nearest ref for a given node
   * this is useful for event handling
   */
  findContainingRef: function(node) {
    var touchedButton = null;
    while (node !== this.getNode()) {
      var ref = node.getAttribute('data-ref');
      if (ref && this.refs && this.refs[ref]) {
        return this.refs[ref];
      }
      node = node.parentNode;
    }
    return false;
  },

  /**
   * add additional classes to the node for this view
   */
  setAdditionalClasses: function(classes) {
    if (util.isArray(classes)) { classes = classes.join(' '); }
    return this.addClass(classes);
  }

});


});

define("lib/controller", function(require, exports, module) {
var core       = require('bolt/core');
var builder    = require('bolt/builder');
var util       = require('bolt/util');
var log        = require('./util').log;

var VERSION_CHECK_RATE = 60 * 1000 * 60 // every hour

// setup facebook authentication
exports.ApplicationController = core.createClass({

  name: 'ApplicationController',

  streams: [
    require('./streams/facebook_stream').FacebookStream,
    require('./streams/butdoesitfloat_stream').ButDoesItFloatStream,
    require('./streams/weather_stream').WeatherStream,
    require('./streams/twitter_stream').TwitterStream
  ],

  construct: function() {
    this.loadUI();
    document.addEventListener('DOMContentLoaded', util.bind(this.start, this));
  },

  start: function() {
    this._fetcher = util.bind(this.fetchStreams, this);
    this._fetcher();
    this.ui.placeIn(document.body);
  },

  loadUI: function() {
    var MainView = require('./views/card').Card;
    this.ui = new MainView({controller: this});
  },

  fetchStreams: function() {
    log('fetching streams');
    this.streams.forEach(function(stream) {
      log('fetching:', stream.source);
      stream.fetch(this);
    }, this);
    setTimeout(this._fetcher, 10000);
  },

  _versionCheck: function() {
    var currentVersion = this.vreq.responseText;
    if (this.version && currentVersion !== this.version) {
      log('upgrading...');
      location.reload();
    }
    if (!this.version) {
      log('setting version to:', currentVersion);
      this.version = currentVersion;
    }
    setTimeout(this._pinger, VERSION_CHECK_RATE);
  },

  facebookDidConnect: function() {
    this.facebookConnected = true;
  },

  twitterDidConnect: function() {
    this.twitterConnected = true;
  }

});

});

define("lib/main", function(require, exports, module) {
var ApplicationController = require('./controller').ApplicationController;
window.app = new ApplicationController();

});

define("lib/model", function(require, exports, module) {
var core       = require('bolt/core');
var Model      = require('bolt/model').Model;
var Collection = require('bolt/collection').Collection;
var util       = require('./util');

var Weather = exports.Weather = core.createClass({
	extend: Model,
	name: 'Weather',
	properties: {
		city: null,
		country: null,
		region: null,
		temp: null,
		desc: null,
		high: null,
		low: null
	}
});
exports.weather = new Weather();

var ContentItem = exports.ContentItem = core.createClass({
  extend: Model,
  name: 'ContentItem'
});

var Content = exports.Content = core.createClass({
  extend: Collection,
  name: 'Content',
  mode: 'sequential',

  createItem: function(data) {
    var item = new ContentItem(data);
    this.add(item);
  },

  next: function() {
    if (this.mode === 'sequential') {
      this.pos = this.pos || 0;
      this.pos++;
      if (this.pos >= this.length) {
        this.pos = 0;
      }
      return this.at(this.pos);
    } else {
      this.pos = util.random(0, this.length - 1);
      return this.at(this.pos);
    }
  }
});

var imageContent   = exports.imageContent  = new Content();
var socialContent  = exports.socialContent = new Content();
socialContent.mode = 'random';
imageContent.mode  = 'random';

});

define("lib/streams/butdoesitfloat_stream", function(require, exports, module) {
var util    = require('../util');
var model   = require('../model');
var content = model.imageContent;
var yql     = util.yql;
var log     = util.log;

// every 6 hours;
var THRESHOLD = 1000 * 60 * 60 * 6;

exports.ButDoesItFloatStream = {
  source: 'butdoesitfloat',
  lastFetch: 0,
  fetch: function(controller) {
    var ts = +new Date;
    query = 'select * from rss where url="http://feeds.feedburner.com/ButDoesItFloat"'

    if (ts - this.lastFetch > THRESHOLD) {
      yql(query, function(results) {
        results = results || {};
        items   = results.item || [];
        var el = document.createElement('div');
        for (var i = 0, l = items.length, desc, imgs, item; i < l; i++) {
          item = items[i]
          desc = item.description;
          el.innerHTML = desc;
          imgs = el.getElementsByTagName('img');
          for (var ii = 0, ll = imgs.length; ii < ll; ii++) {
            this.lastFetch = ts;
            content.createItem({
              id: imgs[ii].src,
              type: 'img',
              url: imgs[ii].src
            });
          }
        }
      });
    }
  }
};

});

define("lib/streams/facebook_stream", function(require, exports, module) {
var util    = require('../util');
var model   = require('../model');
var content = model.socialContent;
var yql     = util.yql;
var log     = util.log;

var THRESHOLD = 60000;

exports.FacebookStream = {
  source: 'facebook',

  lastFetch: 0,

  fetch: function(controller) {
    if (!localStorage.facebookOAuthToken) return;
    var ts= +new Date;
    if (ts - this.lastFetch > THRESHOLD) {
      console.log('here');
      var xhr = new XMLHttpRequest();
      url = '/facebook/feed';
      url = url + '?oauth_token=' + localStorage.facebookOAuthToken;
      xhr.open('GET', url);
      xhr.onload = util.bind(this.processResponse, this, xhr);
      xhr.send();
    }
  },

  processResponse: function(xhr) {
    try {
      this.lastFetch = +new Date;
      var data = JSON.parse(xhr.responseText).data;
      log('facebook', data);
      data.forEach(function(datum) {
        datum.type = 'fb';
        datum.id   = 'facebook-' + datum.id_str;
        content.createItem(datum);
      }, this);
    } catch (e) {
      console.log(e);
    }
  }
};

});

define("lib/streams/twitter_stream", function(require, exports, module) {
var util    = require('../util');
var model   = require('../model');
var content = model.socialContent;
var yql     = util.yql;
var log     = util.log;
var jsonp   = util.requestJSONP;

var THRESHOLD = 60000;

exports.TwitterStream = {
  source: 'twitter',

  lastFetch: 0,

  fetch: function(controller) {
    if (!localStorage.twitterOAuthToken) return;
    var ts= +new Date;
    if (ts - this.lastFetch > THRESHOLD) {
      log('fetching twitter');
      var xhr = new XMLHttpRequest();
      url = '/twitter/home_timeline';
      url = url + '?oauth_token=' + localStorage.twitterOAuthToken;
      url = url + '&oauth_secret=' + localStorage.twitterOAuthSecret;
      xhr.open('GET', url);
      xhr.onload = util.bind(this.processResponse, this, xhr);
      xhr.send();
    }
  },

  processResponse: function(xhr) {
    this.lastFetch = +new Date;
    var data = JSON.parse(xhr.responseText);
    log('twitter', data);
    data.forEach(function(datum) {
      datum.type = 'twitter';
      datum.id   = 'twitter-' + datum.id_str;
      content.createItem(datum);
    }, this);
  }
};

});

define("lib/streams/weather_stream", function(require, exports, module) {
var util    = require('../util');
var model   = require('../model');
var weather = model.weather;
var yql     = util.yql;
var log     = util.log;

// every 6 hours;
var THRESHOLD = 1000 * 60 * 60 * 6;

exports.WeatherStream = {
  source: 'weather',
  lastFetch: 0,
  fetch: function(controller) {
    if (!localStorage.zipcode) return;
    var ts = +new Date;
    if (ts - this.lastFetch > THRESHOLD) {
      query = 'select * from weather.forecast where location=' + localStorage.zipcode;// + localStorage.zipcode;
      yql(query, util.bind(this.processResponse, this));
    }
  },

  processResponse: function(results) {
    log('weather update', results);
    var channel    = results.channel,
        loc        = channel.location || {},
        item       = channel.item     || {},
        condition  = item.condition   || {},
        forecast   = item.forecast[0];

    var obj        = {};
    obj.city       = loc.city;
    obj.country    = loc.country;
    obj.region     = loc.region;
    obj.temp       = condition.temp;
    obj.desc       = condition.text;
    obj.high       = forecast.high;
    obj.low        = forecast.low;
    obj.today_desc = forecast.text;
    weather.setAll(obj);
    this.lastFetch = +new Date;
  }
};

});

define("lib/util", function(require, exports, module) {
var util = require('bolt/util');

util.extend(exports, util);

exports.log = function() {
  console.log.apply(console, arguments);
}

exports.logError = function() {
  console.error.apply(console, arguments);
}

exports.random = function(low, hi) {
  var r, res;
  r = Math.abs(low) + Math.abs(hi) + 1;
  res = Math.random() * r;
  return res = Math.floor(res) + low;
};

var callbacks = {};
var callbackId = 0;
var YQLURL = 'http://query.yahooapis.com/v1/public/yql';

var requestJSONP = exports.requestJSONP = function requestJSONP(url, callback) {
  var callbackName = 'jsonpCallback' + callbackId;
  var script = document.createElement('script');
  url += '&callback=' + callbackName;
  window[callbackName] = function(resp) {
    callback((resp || {}).query.results, resp.query);
    document.body.removeChild(script);
    delete window[callbackName];
  };
  script.src = url;
  document.body.appendChild(script);
  callbackId++;
};

var yql = exports.yql = function(query, callback) {
  var url = YQLURL + '?q=' + escape(query) + '&format=json';
  requestJSONP(url, callback);
};

exports.tempToColor = function(temp) {
  debugger;
  console.log(temp);
  var COLD   = '#ECEEF6',
    CHILLY   = '#A1CDE2',
    COOL     = '#CBEBDF',
    PLEASANT = '#C9EBC9',
    PERFECT  = '#D1F5B7',
    WARM     = '#F5F5A8',
    HOT      = '#F5CC6C',
    HOTTER   = '#F56949';

  if (temp < 32) return COLD;
  if (temp < 50) return CHILLY;
  if (temp < 60) return COOL;
  if (temp < 70) return PLEASANT
  if (temp < 80) return PERFECT;
  if (temp < 90) return HOT;

  return HOTTER;
};

});

define("lib/views/card", function(require, exports, module) {
var core = require('bolt/core');
var View = require('bolt/view').View;

exports.Card = core.createClass({

  name: 'Card',

  extend: View,

  properties: {
    controller: null
  },

  declare: function(options) {
    var SettingsView = require('./settings').SettingsView;
    var Clock        = require('./clock').Clock;
    var Weather      = require('./weather').Weather;
    var Stream       = require('./stream').Stream;

    return {
      className: 'card',
      childViews: [
        {
          className: 'settings',
          childViews: [
            {
              view: SettingsView,
              controller: options.controller
            },
          ]
        },
        {
          className: 'face',
          ref: 'face',
          childViews: [
            {
              view: Stream,
              controller: options.controller
            },
            {view: Clock},
            {view: Weather},
            {
              className:    'settings-grip',
              onclick:      'onGripClick',
              ontouchstart: 'onGripTouchStart',
              ontouchmove:  'onGripTouchMove',
              ontouchend:   'onGripTouchEnd',
            }
          ]
        }
      ]
    };
  },

  onGripClick: function() {
    this.findRef('face').toggleClass('edit-settings');
  },

  onGripTouchStart: function() {

  },

  onGripTouchMove: function() {

  },

  onGripTouchEnd: function() {

  }

});

});

define("lib/views/clock", function(require, exports, module) {
var core = require('bolt/core');
var View = require('bolt/view').View;
var util = require('bolt/util');

exports.Clock = core.createClass({
  name: 'Clock',

  extend: View,

  declare: function() {
    return {
      className: 'clock',
      childViews: [
        {
          ref: 'time',
          className: 'time',
        },
        {
          ref: 'date',
          className: 'date'
        }
      ]
    };
  },

  ready: function() {
    this.updateTime();
  },

  updateTime: function() {
    this.findRef('time').setContent(this.currentTime());
    this.findRef('date').setContent(this.currentDate());
    setTimeout(util.bind(this.updateTime, this), 1000);
  },

  currentDate: function() {
    var d = new Date;
    var day  = d.getDate();
    var mon  = d.getMonth();
    var year = d.getFullYear();
    var months = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul',
      'aug', 'sep', 'oct', 'nov', 'dec'];

    return months[mon] + ' ' + day + ' ' + year;
  },

  currentTime: function() {
    var d = new Date;
    var hour = d.getHours();
    var min  = ''+d.getMinutes();

    ampm = hour >= 12 ? 'p' : 'a';
    hour = hour > 12 ? hour - 12 : hour;
    hour = hour || 12;
    min  = min.length < 2 ? '0' + min : min;

    return hour + ':' + min + '';
  }
});

});

define("lib/views/facebook_tile", function(require, exports, module) {
var core     = require('bolt/core');
var TileView = require('./tile').TileView;
var util     = require('../util');

exports.FacebookTile = core.createClass({
  name: 'FacebookTile',

  RATE: 15000,

  extend: TileView,

  declare: function(options) {
    console.log(options.model);
    return {
      className: 'tile social-tile fb hidden',
      childViews: [
        {
          ref: 'avatar',
          className: 'tile-avatar'
        },
        {
          className: 'tile-content',
          content: options.model.get('message') || options.model.get('story') || ''
        },
        {
          ref: 'image',
          className: 'tile-image'
        }
      ]
    };
  },

  ready: function() {
    var _this = this;
  },

  show: function(callback) {
    var _this = this;
    var img = new Image();
    img.onload = function() {
      _this._loaded = true;
      callback && callback();
      _this.findRef('avatar').setStyle({
        backgroundImage: 'url(' + img.src + ')'
      });
      _this.removeClass('hidden');
    }
    img.src = 'http://graph.facebook.com/' + this.getModel().get('from').id + '/picture?type=large';
  }
});

});

define("lib/views/image_tile", function(require, exports, module) {
var core     = require('bolt/core');
var TileView = require('./tile').TileView;
var util     = require('../util');

exports.ImageTile = core.createClass({

  RATE: 60000,

  name: 'ImageTile',

  extend: TileView,

  declare: function(options) {
    return {
      className: 'tile image-view hidden'
    };
  },

  show: function(callback) {
    this._showCallback = callback;
    this.img = new Image();
    this.img.onload = util.bind(this.onload, this);
    this.img.src = this.getModel().get('url');
  },

  onload: function() {
    this._showCallback();
    var url = this.img.src;
    this.setStyle({
      backgroundImage: 'url(\'' + url + '\')'
    });
    this.removeClass('hidden');
  }
});

});

define("lib/views/settings", function(require, exports, module) {
var core  = require('bolt/core');
var util  = require('bolt/util');
var View  = require('bolt/view').View;
var log   = require('../util').log;

exports.SettingsView = core.createClass({
  extend: View,

  name: 'SettingsView',

  properties: {
    controller: null
  },

  declare: function() {
    return {
      className: 'settings-dialog',
      childViews: [
        {
          className: 'settings-header',
        },
        {
          className: 'setting',
          childViews: [
            {
              tagName: 'label',
              content: 'zipcode: '
            },
            {
              tagName: 'input',
              ref: 'zipcode',
              className: 'weather-zipcode text-input',
              onkeyup: 'onZipcodeChange'
            }
          ]
        },
        {
          className: 'setting',
          childViews: [
            {
              tagName: 'a',
              ref: 'fbAuthButton',
              className: 'btn-auth btn-facebook',
              content: 'Add Facebook Feed',
              onclick: 'onFacebookLoginClick'
            }
          ]
        },
        {
          className: 'setting',
          childViews: [
            {
              tagName: 'a',
              ref: 'twitterAuthButton',
              className: 'btn-auth btn-twitter',
              content: 'Add Twitter Feed',
              onclick: 'onTwitterLoginClick'
            }
          ]
        },
      ]
    };
  },

  ready: function() {
    this._checkForTwitterOauthToken();
    this._checkForFacebookOauthToken();
  },

  _checkForTwitterOauthToken: function() {
    var params = this._getParams();
    if (params.twitter && params.oauth_token && params.oauth_secret) {
      localStorage.twitterOAuthToken  = params.oauth_token;
      localStorage.twitterOAuthSecret = params.oauth_secret;
      location.href='/';
    }
  },

  _checkForFacebookOauthToken: function() {
    var params = this._getParams();
    if (params.facebook && params.oauth_token) {
      localStorage.facebookOAuthToken  = params.oauth_token;
      location.href='/';
    }
  },

  _getParams: function() {
    var params = {},
        parts  = null,
        search = location.search.substr(1);
    util.each(search.split('&'), function(pair) {
      parts = pair.split('=');
      params[parts[0]] = parts[1];
    });
    return params || {};
  },

  onZipcodeChange: function() {
    localStorage.zipcode = this.findRef('zipcode').getNode().value;
  },

  onTwitterLoginClick: function() {
    location.href = 'twitter/oauth';
  },

  onFacebookLoginClick: function() {
    location.href = 'facebook/oauth';
  }
});

});

define("lib/views/stream", function(require, exports, module) {
var core          = require('bolt/core');
var View          = require('bolt/view').View;
var util          = require('../util');
var model         = require('../model');
var socialContent = model.socialContent;
var imageContent  = model.imageContent;
var log           = util.log;
var random        = util.random;

exports.Stream = core.createClass({
  name: 'Stream',

  extend: View,

  content: imageContent,

  declare: function() {
    return {
      className: 'stream-viewer',
      onmousedown: 'onTouchStart'
    };
  },

  ready: function() {
    this._update = util.bind(this._update, this);
    this._update();
  },

  _update: function() {

    if (this.content === imageContent) {
      this.content = socialContent
    } else {
      this.content = imageContent
    }

    var item = this.content.next();

    var view = this._viewForItem(item);
    if (view) {
      log('displaying', item);
      this.append(view);
      view.show(util.bind(function() {
        if (this.currentView) {
          this.currentView.fade();
        }
        this.currentView = view;
      }, this));
      clearTimeout(this._timeout);
      this._timeout = setTimeout(this._update, view.RATE);
      this.pos++;
    } else {
      setTimeout(this._update, 250);
    }
  },

  _viewForItem: function(item) {
    if (!item) return null;
    var view = null;
    switch (item.get('type')) {
      case 'img':
        view = require('./image_tile').ImageTile;
        break;
      case 'fb':
        view = require('./facebook_tile').FacebookTile;
        break;
      case 'twitter':
        view = require('./twitter_tile').TwitterTile;
        break;
      default:
        break;
    }
    return new view({model: item});
  },

  onTouchStart: function() {
    this._update();
  }

});

});

define("lib/views/tile", function(require, exports, module) {
var core = require('bolt/core');
var View = require('bolt/view').View;
var util = require('../util');

exports.TileView = core.createClass({
  extend: View,

  properties: {
    model: null
  },

  fade: function() {
    this.removeClass('current');
    this.addClass('hidden');
    var _this = this;
    this.getNode().addEventListener('webkitTransitionEnd', function() {
      _this.destroy();
    });
  }
});

});

define("lib/views/twitter_tile", function(require, exports, module) {
var core     = require('bolt/core');
var TileView = require('./tile').TileView;
var util     = require('../util');

exports.TwitterTile = core.createClass({
  name: 'TwitterTile',

  RATE: 15000,

  extend: TileView,

  declare: function(options) {
    console.log(options.model);
    return {
      className: 'tile social-tile twitter hidden',
      childViews: [
        {
          ref: 'avatar',
          className: 'tile-avatar'
        },
        {
          className: 'tile-content',
          content: options.model.get('text') || ''
        },
        {
          ref: 'image',
          className: 'tile-image'
        }
      ]
    };
  },

  ready: function() {
    var _this = this;
  },

  show: function(callback) {
    var _this = this;
    var img = new Image();
    img.onload = function() {
      _this._loaded = true;
      callback && callback();
      _this.findRef('avatar').setStyle({
        backgroundImage: 'url(' + img.src + ')'
      });
      _this.removeClass('hidden');
    }
    img.src = this.getModel().get('user').profile_image_url;
  }
});

});

define("lib/views/weather", function(require, exports, module) {
var core    = require('bolt/core');
var View    = require('bolt/view').View;
var util    = require('../util');
var weather = require('../model').weather;

exports.Weather = core.createClass({

  name: 'Weather',

  extend: View,

  properties: {
    temp: null,
    desc: null,
    high: null,
    low: null
  },

  declare: function(options) {
    return {
      className: 'weather',
      childViews: [
        {tagName: 'span', ref: 'temp', className: 'temp'},
        {tagName: 'span', ref: 'desc', className: 'weather-desc'}
      ],
      binding: {
        model: weather,
        options: [
          {property: 'temp'},
          {property: 'desc'},
          {property: 'high'},
          {property: 'low'}
        ]
      }
    };
  },

  setTemp: function(val) {
    if (!val) return;
    var node = this.findRef('temp').getNode();
    node.innerHTML = val + '&#176;';
    // var color = util.tempToColor(parseInt(val, 10));
    // this.setStyle({borderColor: color});
  },

  setDesc: function(val) {
    if (!val) return;
    val = (val || '').toLowerCase();
    this.findRef('desc').setContent(val);
  }

});

});
require("lib/main");
