(function (Backbone) {
  var isIE = (function() {A thin layer on top of Backbone’s view class to add nested child views.
(function (Backbone) {
  var isIE = (function() {MSIE < 11
    if (document.all) {
      return true;
    }MSIE 11
    return (!(window.ActiveXObject) && 'ActiveXObject' in window);
  })();
  Backbone.Component = Backbone.View.extend({Override constructor so Components can use initialize normally.
    constructor: function(options) {
      this._setup();Remove undefined options.
      _.each(options, function(v, k) {
        if (typeof v === 'undefined') {
          delete options[k];
        }
      });Extend with defaults.
      options = _.extend({}, _.result(this, 'defaults'), options);
      Backbone.View.call(this, options);
    },Add a child view to the end of the element.
Optionally specify a selector within the view to attach to.
Aliased to add.
    append: function(view, selector) {
      this._addChild(view, selector, 'append');
      return this;
    },Add a child view to the beginning of the view’s element. Optionally specify a selector within the view to attach to.
    prepend: function(view, selector) {
      this._addChild(view, selector, 'prepend');
      return this;
    },Retrieve the list of child views.
    children: function() {
      return _.pluck(this._children, 'view');
    },Remove all child views added to this one.
    empty: function() {
      this._removeChildren();
      return this;
    },Render the existing template with the provided data.
    renderTemplate: function(data) {
      this.$el.html(this._compile(this.template)(data));
      return this;
    },Wraps _.template. Can be replaced by any object that responds to
compile and returns a compiled template function.
    renderer: {
      compile: function(template) {
        this._template = this._template || _.partial(_.template, template);
        return this._template;
      }
    },Initial setup. Create new child array, and wrap render and remove
methods.
    _setup: function() {Mixin renderer to view instance, so that compiled templates aren’t shared.
      _.extend(this, { _compile: this.renderer.compile });
      this._children = [];
      this.render = this._wrapRender();
      this.remove = this._wrapRemove();
    },Add a child view to an internal array, keeping a reference to the element and attach method it should use.
    _addChild: function(view, selector, method) {
      var child = { view: view, selector: selector, method: method || 'append' };Assign a method to the child so it can remove itself from _children
array when it’s removed.
Written as an anonymous function to prevent it being bound multiple times
in grandparent-parent-child situations.
      var removeFromParent = function(child) {
        this._children = _.without(this._children, child);
      };
      view._removeFromParent = _.bind(removeFromParent, this, child);
      this._children.push(child);
    },Call remove for each child added to the view.
    _removeChildren: function() {
      _.invoke(this.children(), 'remove');
      this._children = [];
    },Replaced by a function scoped to the parent if the component is added as a
child (in _addChild) but otherwise does nothing (as the component
wouldn’t have a parent).
    _removeFromParent: function() {
    },Wrap render to automatically attach all children.
    _wrapRender: function() {
      var wrapper = function(render) {
        var args = _.rest(arguments);
        if (isIE) {
          this._detachChildren();
        }
        render.apply(this, args);
        this._attachChildren();
        return Backbone.Component.prototype.render.apply(this, args);
      };
      var originalRender = _.bind(this.render, this);
      return _.wrap(originalRender, wrapper);
    },Wrap remove to automatically remove all children and itself from its
parent.
    _wrapRemove: function() {
      var wrapper = function(remove) {
        var args = _.rest(arguments);
        this._removeFromParent();
        this._removeChildren();
        remove.apply(this, args);
        return Backbone.Component.prototype.remove.apply(this, args);
      };
      var originalRemove = _.bind(this.remove, this);
      return _.wrap(originalRemove, wrapper);
    },Attach child to the correct element and with the correct method. Defaults
to this.$el and append.
Only call render on the child the first time.
    _attachChild: function(child) {
      var target = child.selector ? this.$(child.selector) : this.$el;
      if (!child.rendered) {
        child.view.render();
        child.rendered = true;
      }
      target[child.method](child.view.$el);
    },Attach all children in the right order, and call delegateEvents for each
child view so handlers are correctly bound after being attached.
    _attachChildren: function() {
      _.each(this._children, function(child) {
        this._attachChild(child);
        child.view.delegateEvents();
      }, this);
    },Detach children to avoid this bug in IE: http://bugs.jquery.com/ticket/11473
    _detachChildren: function() {
      _.each(this._children, function(child) {
        if (child.view.$el) {
          child.view.$el.detach();
        }
      });
    }
  });Alias add to append.
  Backbone.Component.prototype.add = Backbone.Component.prototype.append;
})(Backbone);