<commit_before>/*global
    Thorax:true,
    $serverSide,
    assignTemplate, createError, createInheritVars, createRegistryWrapper, getValue,
    inheritVars, resetInheritVars,
    ServerMarshal
*/

// Provide default behavior for client-failover
if (typeof $serverSide === 'undefined') {
  window.$serverSide = false;
}

var isIE11 = !!navigator.userAgent.match(/Trident\/7\./);
var isIE = isIE11 || (/msie [\w.]+/).exec(navigator.userAgent.toLowerCase());

//support zepto.forEach on jQuery
if (!$.fn.forEach) {
  $.fn.forEach = function(iterator, context) {
    $.fn.each.call(this, function(index) {
      iterator.call(context || this, this, index);
    });
  };
}

var viewNameAttributeName = 'data-view-name',
    viewCidAttributeName = 'data-view-cid',
    viewHelperAttributeName = 'data-view-helper',

    // Used to identify views that can be restored vs. rerendered on the client side.
    // Values are:
    //  - true - Can be restored
    //  - false - Must be rerendered
    //  - Omitted - Normal HTML element without associated view
    viewRestoreAttribute = 'data-view-restore';

//view instances
var viewsIndexedByCid = {};

if (!Handlebars.templates) {
  Handlebars.templates = {};
}

var Thorax = this.Thorax = {
  templatePathPrefix: '',
  //view classes
  Views: {},

  // Allows tagging of sections of code with a name for debugging purposes.
  // This or onException should be overriden to allow for reporting exceptions to analytics servers
  // or integration with libraries such as Costanza.
  bindSection: function(name, info, callback) {
    if (!callback) {
      callback = info;
      info = undefined;
    }
    return function() {
      try {
        return callback.apply(this, arguments);
      } catch (err) {
        Thorax.onException(name, err, info);
      }
    };
  },
  runSection: function(name, info, callback) {
    return Thorax.bindSection(name, info, callback)();
  },

  onException: function(name, err /* , info */) {
    throw err;
  },

  //deprecated, here to ensure existing projects aren't mucked with
  templates: Handlebars.templates
};

Thorax.View = Backbone.View.extend({
  constructor: function() {
    // store first argument for configureView()
    this._constructorArg = arguments[0];
    var response = Backbone.View.apply(this, arguments);
    delete this._constructorArg;
    _.each(inheritVars, function(obj) {
      if (obj.ctor) {
        obj.ctor.call(this, response);
      }
    }, this);
    return response;
  },

  toString: function() {
    return '[object View.' + this.name + ']';
  },

  // View configuration, _configure was removed
  // in Backbone 1.1, define _configure as a noop
  // for Backwards compatibility with 1.0 and earlier
  _configure: function() {},
  _ensureElement: function () {
    configureView.call(this);

    if (!$serverSide && this.el) {
      var $el = $(_.result(this, 'el'));
      if ($el.length && ($el.attr('data-view-restore') === 'true')) {
        return this.restore($el);
      }
    }

    return Backbone.View.prototype._ensureElement.call(this);
  },


  setElement : function(element) {
    var $element = $(element),
        existingCid = $element.attr('data-view-cid');
    if (existingCid) {
      this._assignCid(existingCid);
    }

    var response = Backbone.View.prototype.setElement.apply(this, arguments);

    // Use a hash here to avoid multiple DOM operations
    var attr = {'data-view-cid': this.cid};
    if (this.name) {
      attr[viewNameAttributeName] = this.name;
    }
    this.$el.attr(attr);

    if (element.parentNode) {
      // This is a view that is attaching to an existing node and is unlikely to be added as
      // a children of any views. Assume that anyone doing this will manage the lifecycle
      // appropriately and destroy so we don't leak due to the `$.view` lookup that we are
      // registering here.
      this.retain();
    }

    return response;
  },
  _assignCid: function(cid) {
    if (this.cid && viewsIndexedByCid[this.cid]) {
      delete viewsIndexedByCid[this.cid];
      viewsIndexedByCid[cid] = this;
    }

    if (this.parent) {
      delete this.parent.children[this.cid];
      this.parent.children[cid] = this;
    }

    this.cid = cid;
  },

  _addChild: function(view) {
    if (this.children[view.cid]) {
      return view;
    }

    view.retain();
    this.children[view.cid] = view;
    // _helperOptions is used to detect if is HelperView
    // we do not want to remove child in this case as
    // we are adding the HelperView to the declaring view
    // (whatever view used the view helper in it's template)
    // but it's parent will not equal the declaring view
    // in the case of a nested helper, which will cause an error.
    // In either case it's not necessary to ever call
    // _removeChild on a HelperView as _addChild should only
    // be called when a HelperView is created.
    if (view.parent && view.parent !== this && !view._helperOptions) {
      view.parent._removeChild(view);
    }
    view.parent = this;
    this.trigger('child', view);
    return view;
  },

  _removeChild: function(view) {
    delete this.children[view.cid];
    view.parent = null;
    view.release();
    return view;
  },

  _destroy: function() {
    _.each(this._boundDataObjectsByCid, this.unbindDataObject, this);
    this.trigger('destroyed');
    delete viewsIndexedByCid[this.cid];

    _.each(this.children, function(child) {
      this._removeChild(child);
    }, this);

    if (this.el) {
      this.undelegateEvents();
      this.remove();  // Will call stopListening()
      this.off();     // Kills off remaining events

      ServerMarshal.destroy(this.$el);
    }

    // Absolute worst case scenario, kill off some known fields to minimize the impact
    // of being retained.
    this.el = this.$el = undefined;
    this.parent = undefined;
    this.model = this.collection = this._collection = undefined;
    this._helperOptions = undefined;
  },

  restore: function(element, forceRerender) {
    // Extract from $ objects if passed
    element = element[0] || element;

    if (this._renderCount) {
      // Ensure that we are registered to the right cid (this could have been reset previously)
      var oldCid = this.$el.attr('data-view-cid');
      if (this.cid !== oldCid) {
        this._assignCid(oldCid);
      }

      $(element).replaceWith(this.$el);

      this.trigger('restore:fail', {
        type: 'previously-rendered',
        view: this,
        element: element
      });
      return;
    }

    this.setElement(element);

    var restoreable = this.$el.attr('data-view-restore') === 'true';
    this.$el.removeAttr('data-view-restore');

    if (!$serverSide && restoreable) {
      // Ensure that our associated template is wired up so that helpers who need to
      // resolve template children are able to do so.
      assignTemplate.call(this, 'template', {
        required: false
      });

      this._renderCount = 1;
      this.trigger('restore', forceRerender);

      var remainingViews = this.$('[data-view-restore]'),
          rerender = _.filter(remainingViews, function(el) {
            // Ignore views that are deeply nested or views that are under a layout element
            // when checking to see if we need to rerender.
            var parent = $(el).parent();
            return !parent.attr('data-layout-cid') && (parent.view({el: true, helper: true})[0] === element);
          });
      if (rerender.length) {
        this.trigger('restore:fail', {
          type: 'remaining',
          view: this,
          element: element,
          rerendered: rerender
        });

        this.render();
      } else if (forceRerender) {
        // We have an explicit rerender that we wanted to defer until the end of the restore process
        this.render();
      }

      this.trigger('after-restore', forceRerender);

      return true;
    } else {
      this.trigger('restore:fail', {<commit_msg>Do not perform remaining lookup in forced rerender<commit_after>/*global
    Thorax:true,
    $serverSide,
    assignTemplate, createError, createInheritVars, createRegistryWrapper, getValue,
    inheritVars, resetInheritVars,
    ServerMarshal
*/

// Provide default behavior for client-failover
if (typeof $serverSide === 'undefined') {
  window.$serverSide = false;
}

var isIE11 = !!navigator.userAgent.match(/Trident\/7\./);
var isIE = isIE11 || (/msie [\w.]+/).exec(navigator.userAgent.toLowerCase());

//support zepto.forEach on jQuery
if (!$.fn.forEach) {
  $.fn.forEach = function(iterator, context) {
    $.fn.each.call(this, function(index) {
      iterator.call(context || this, this, index);
    });
  };
}

var viewNameAttributeName = 'data-view-name',
    viewCidAttributeName = 'data-view-cid',
    viewHelperAttributeName = 'data-view-helper',

    // Used to identify views that can be restored vs. rerendered on the client side.
    // Values are:
    //  - true - Can be restored
    //  - false - Must be rerendered
    //  - Omitted - Normal HTML element without associated view
    viewRestoreAttribute = 'data-view-restore';

//view instances
var viewsIndexedByCid = {};

if (!Handlebars.templates) {
  Handlebars.templates = {};
}

var Thorax = this.Thorax = {
  templatePathPrefix: '',
  //view classes
  Views: {},

  // Allows tagging of sections of code with a name for debugging purposes.
  // This or onException should be overriden to allow for reporting exceptions to analytics servers
  // or integration with libraries such as Costanza.
  bindSection: function(name, info, callback) {
    if (!callback) {
      callback = info;
      info = undefined;
    }
    return function() {
      try {
        return callback.apply(this, arguments);
      } catch (err) {
        Thorax.onException(name, err, info);
      }
    };
  },
  runSection: function(name, info, callback) {
    return Thorax.bindSection(name, info, callback)();
  },

  onException: function(name, err /* , info */) {
    throw err;
  },

  //deprecated, here to ensure existing projects aren't mucked with
  templates: Handlebars.templates
};

Thorax.View = Backbone.View.extend({
  constructor: function() {
    // store first argument for configureView()
    this._constructorArg = arguments[0];
    var response = Backbone.View.apply(this, arguments);
    delete this._constructorArg;
    _.each(inheritVars, function(obj) {
      if (obj.ctor) {
        obj.ctor.call(this, response);
      }
    }, this);
    return response;
  },

  toString: function() {
    return '[object View.' + this.name + ']';
  },

  // View configuration, _configure was removed
  // in Backbone 1.1, define _configure as a noop
  // for Backwards compatibility with 1.0 and earlier
  _configure: function() {},
  _ensureElement: function () {
    configureView.call(this);

    if (!$serverSide && this.el) {
      var $el = $(_.result(this, 'el'));
      if ($el.length && ($el.attr('data-view-restore') === 'true')) {
        return this.restore($el);
      }
    }

    return Backbone.View.prototype._ensureElement.call(this);
  },


  setElement : function(element) {
    var $element = $(element),
        existingCid = $element.attr('data-view-cid');
    if (existingCid) {
      this._assignCid(existingCid);
    }

    var response = Backbone.View.prototype.setElement.apply(this, arguments);

    // Use a hash here to avoid multiple DOM operations
    var attr = {'data-view-cid': this.cid};
    if (this.name) {
      attr[viewNameAttributeName] = this.name;
    }
    this.$el.attr(attr);

    if (element.parentNode) {
      // This is a view that is attaching to an existing node and is unlikely to be added as
      // a children of any views. Assume that anyone doing this will manage the lifecycle
      // appropriately and destroy so we don't leak due to the `$.view` lookup that we are
      // registering here.
      this.retain();
    }

    return response;
  },
  _assignCid: function(cid) {
    if (this.cid && viewsIndexedByCid[this.cid]) {
      delete viewsIndexedByCid[this.cid];
      viewsIndexedByCid[cid] = this;
    }

    if (this.parent) {
      delete this.parent.children[this.cid];
      this.parent.children[cid] = this;
    }

    this.cid = cid;
  },

  _addChild: function(view) {
    if (this.children[view.cid]) {
      return view;
    }

    view.retain();
    this.children[view.cid] = view;
    // _helperOptions is used to detect if is HelperView
    // we do not want to remove child in this case as
    // we are adding the HelperView to the declaring view
    // (whatever view used the view helper in it's template)
    // but it's parent will not equal the declaring view
    // in the case of a nested helper, which will cause an error.
    // In either case it's not necessary to ever call
    // _removeChild on a HelperView as _addChild should only
    // be called when a HelperView is created.
    if (view.parent && view.parent !== this && !view._helperOptions) {
      view.parent._removeChild(view);
    }
    view.parent = this;
    this.trigger('child', view);
    return view;
  },

  _removeChild: function(view) {
    delete this.children[view.cid];
    view.parent = null;
    view.release();
    return view;
  },

  _destroy: function() {
    _.each(this._boundDataObjectsByCid, this.unbindDataObject, this);
    this.trigger('destroyed');
    delete viewsIndexedByCid[this.cid];

    _.each(this.children, function(child) {
      this._removeChild(child);
    }, this);

    if (this.el) {
      this.undelegateEvents();
      this.remove();  // Will call stopListening()
      this.off();     // Kills off remaining events

      ServerMarshal.destroy(this.$el);
    }

    // Absolute worst case scenario, kill off some known fields to minimize the impact
    // of being retained.
    this.el = this.$el = undefined;
    this.parent = undefined;
    this.model = this.collection = this._collection = undefined;
    this._helperOptions = undefined;
  },

  restore: function(element, forceRerender) {
    // Extract from $ objects if passed
    element = element[0] || element;

    if (this._renderCount) {
      // Ensure that we are registered to the right cid (this could have been reset previously)
      var oldCid = this.$el.attr('data-view-cid');
      if (this.cid !== oldCid) {
        this._assignCid(oldCid);
      }

      $(element).replaceWith(this.$el);

      this.trigger('restore:fail', {
        type: 'previously-rendered',
        view: this,
        element: element
      });
      return;
    }

    this.setElement(element);

    var restoreable = this.$el.attr('data-view-restore') === 'true';
    this.$el.removeAttr('data-view-restore');

    if (!$serverSide && restoreable) {
      // Ensure that our associated template is wired up so that helpers who need to
      // resolve template children are able to do so.
      assignTemplate.call(this, 'template', {
        required: false
      });

      this._renderCount = 1;
      this.trigger('restore', forceRerender);

      var remainingViews = forceRerender ? [] : this.$('[data-view-restore]'),
          rerender = _.filter(remainingViews, function(el) {
            // Ignore views that are deeply nested or views that are under a layout element
            // when checking to see if we need to rerender.
            var parent = $(el).parent();
            return !parent.attr('data-layout-cid') && (parent.view({el: true, helper: true})[0] === element);
          });
      if (rerender.length) {
        this.trigger('restore:fail', {
          type: 'remaining',
          view: this,
          element: element,
          rerendered: rerender
        });

        this.render();
      } else if (forceRerender) {
        // We have an explicit rerender that we wanted to defer until the end of the restore process
        this.render();
      }

      this.trigger('after-restore', forceRerender);

      return true;
    } else {
      this.trigger('restore:fail', {
{'fraction_non_alphanumeric': 0.1256092988376453, 'fraction_numerical': 0.0016247969003874516, 'mean_word_length': 2.6353930031803725, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6108686', 'n_tokens_mistral': 4787, 'n_tokens_neox': 4694, 'n_words': 1364}