<commit_before>$(document).ready(function() {
  "use strict";
  var GARMENTS = {
    // JavaScript doesn't have ints or else this would be in cents.
    "bathing suit (per piece)": 5,
    "bed sheet": 15,
    "blanket": 15,
    "blazer": 8,
    "blouse": 7,
    "coat": 15,
    "comforter": 30,
    "dress (casual)": 11,
    "dress (formal)": 15,
    "duvet cover": 30,
    "jacket (formal)": 8,
    "napkin": 1,
    "pants": 7,
    "pashmina": 7,
    "pillow": 10,
    "pillowcase": 2,
    "scarf": 7,
    "shawl": 7,
    "shirt": 2.5,
    "skirt": 7,
    "sweater": 7,
    "tablecloth": 30,
    "tie": 5,
    "bath mat": 6,
    "kitchen mat": 6,
    "delicates" : 1,
    "synthetics" : 2.5,
    "wash and fold" : 1.5
  };
  var RUSH_FEE = 3.95;

  var GarmentModel = Backbone.Model.extend({
    defaults: {
      garment_type: '',
      cost: 0,
      quantity: 0,
      total_cost: 0,
    }
  });

  var GarmentCollection = Backbone.Collection.extend({
    model: GarmentModel,
    localStorage: new Backbone.LocalStorage('garments-manager'),

    initialize: function() {
      _.bind(this.sumCosts, this);
    },

    sumCosts: function() {
      return _.reduce(this.models, function(a,x){return a + x.get('total_cost');}, 0);
    }
  });

  var GarmentView = Backbone.View.extend({
    tagName: 'tr',
    className: 'garment',

    events: {
      'click .remove-garment': 'remove'
    },

    initialize: function() {
      _.bindAll(this, 'render', 'unrender', 'remove', 'edit');
      this.model.bind('change', this.render);
      this.model.bind('remove', this.unrender);
    },

    render: function() {
      this.$el.html(
        '<td>' + this.model.get('garment_type') + '</td>' +
        '<td>$' + Math.round10(this.model.get('cost'), -2).toFixed(2) + '</td>' +
        '<td>' + Math.round(this.model.get('quantity')) + '</td>' +
        '<td>$' + Math.round10(this.model.get('total_cost'), -2).toFixed(2) + '</td>' +
        '<td><button class="btn btn-danger remove-garment"><i class="fa fa-times"></i></button></td>'
      );
      return this;
    },

    edit: function() {

    },

    unrender: function() {
      this.$el.remove();
    },

    remove: function() {
      this.model.destroy();
      tableView.updateTotal();
    }
  });

  var TableView = Backbone.View.extend({
    el: $('#calculation-table'),

    initialize: function() {
      var self = this;
      var $garmentType = $('#garment-type');
      var $garmentQuantity = $('#garment-quantity');
      var $rushOrder = $('#rush-order');
      var $addGarment = $('#add-garment');
      _.bindAll(this, 'render');

      this.collection = new GarmentCollection();
      this.collection.bind('add', this.appendGarment);
      // Used to fetch from localStorage
      this.collection.fetch();
      this.updateTotal();
      this.render();

      // Populate garment choices
      var sortedGarments = [];
      for (var garment in GARMENTS) {
        sortedGarments.push(garment);
      }
      sortedGarments.sort();
      for (var i = 0; i < sortedGarments.length; i++) {
        var g = sortedGarments[i];
        $garmentType.append(
          '<option value="' + g + '">' +
            g.toTitleCase() +
          '</option>'
          );
      }

      $garmentType.chosen();

      $addGarment.on('click', function(event) {
        event.preventDefault();
        var garmentType = $garmentType.val();
        var garmentQuantity = parseInt($garmentQuantity.val());
        var garmentCost = parseFloat(GARMENTS[garmentType]);

        self.addGarment.bind(self)({
          garment_type: garmentType.toTitleCase(),
          cost: garmentCost,
          quantity: garmentQuantity,
          total_cost: garmentCost * garmentQuantity,
        });
      });
    },

    updateTotal: function() {
      var totalCost = this.collection.sumCosts().toFixed(2);
      $('#grand-total').html('$' + totalCost);
      $('#total-value').html('$' + totalCost);
    },

    render: function() {
      var self = this;
      _(this.collection.models).each(function(garment){
        self.appendGarment(garment);
      }, this);
    },

    addGarment: function(params) {
      this.collection.create(new GarmentModel(params));
      this.updateTotal();
    },

    appendGarment: function(garment) {
      var garmentView = new GarmentView({
        model: garment
      });
      var garmentEl = garmentView.render().$el;
      $('#calculation-table', this.el).append(garmentEl);
    }
  });

  $('#popover-disclaimer').popover({
    'trigger' : 'hover click',
    'placement' : 'bottom',
    'content' : 'For informational purposes only; check <a href="http://www.rinse.com">rinse.com</a> for the most updated prices. This website is not affiliated with Rinse Inc.',
    'html' : true
  });

  var tableView = new TableView();
});

// Decimal rounding from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
(function() {
  /**
   * Decimal adjustment of a number.
   *
   * @param {String}  type  The type of adjustment.
   * @param {Number}  value The number.
   * @param {Integer} exp   The exponent (the 10 logarithm of the adjustment base).
   * @returns {Number} The adjusted value.
   */
  function decimalAdjust(type, value, exp) {
    // If the exp is undefined or zero...
    if (typeof exp === 'undefined' || +exp === 0) {
      return Math[type](value);
    }
    value = +value;
    exp = +exp;
    // If the value is not a number or the exp is not an integer...<commit_msg>Clear all items from the collection<commit_after>$(document).ready(function() {
  "use strict";
  var GARMENTS = {
    // JavaScript doesn't have ints or else this would be in cents.
    "bathing suit (per piece)": 5,
    "bed sheet": 15,
    "blanket": 15,
    "blazer": 8,
    "blouse": 7,
    "coat": 15,
    "comforter": 30,
    "dress (casual)": 11,
    "dress (formal)": 15,
    "duvet cover": 30,
    "jacket (formal)": 8,
    "napkin": 1,
    "pants": 7,
    "pashmina": 7,
    "pillow": 10,
    "pillowcase": 2,
    "scarf": 7,
    "shawl": 7,
    "shirt": 2.5,
    "skirt": 7,
    "sweater": 7,
    "tablecloth": 30,
    "tie": 5,
    "bath mat": 6,
    "kitchen mat": 6,
    "delicates" : 1,
    "synthetics" : 2.5,
    "wash and fold" : 1.5
  };
  var RUSH_FEE = 3.95;

  var GarmentModel = Backbone.Model.extend({
    defaults: {
      garment_type: '',
      cost: 0,
      quantity: 0,
      total_cost: 0,
    }
  });

  var GarmentCollection = Backbone.Collection.extend({
    model: GarmentModel,
    localStorage: new Backbone.LocalStorage('garments-manager'),

    initialize: function() {
      _.bind(this.sumCosts, this);
    },

    sumCosts: function() {
      return _.reduce(this.models, function(a,x){return a + x.get('total_cost');}, 0);
    }
  });

  var GarmentView = Backbone.View.extend({
    tagName: 'tr',
    className: 'garment',

    events: {
      'click .remove-garment': 'remove'
    },

    initialize: function() {
      _.bindAll(this, 'render', 'unrender', 'remove', 'edit');
      this.model.bind('change', this.render);
      this.model.bind('remove', this.unrender);
    },

    render: function() {
      this.$el.html(
        '<td>' + this.model.get('garment_type') + '</td>' +
        '<td>$' + Math.round10(this.model.get('cost'), -2).toFixed(2) + '</td>' +
        '<td>' + Math.round(this.model.get('quantity')) + '</td>' +
        '<td>$' + Math.round10(this.model.get('total_cost'), -2).toFixed(2) + '</td>' +
        '<td><button class="btn btn-danger remove-garment"><i class="fa fa-times"></i></button></td>'
      );
      return this;
    },

    edit: function() {

    },

    unrender: function() {
      this.$el.remove();
    },

    remove: function() {
      this.model.destroy();
      tableView.updateTotal();
    }
  });

  var TableView = Backbone.View.extend({
    el: $('#calculation-table'),

    initialize: function() {
      var self = this;
      var $garmentType = $('#garment-type');
      var $garmentQuantity = $('#garment-quantity');
      var $rushOrder = $('#rush-order');
      var $addGarment = $('#add-garment');
      var $clearAll = $('#clear-items');
      _.bindAll(this, 'render');

      this.collection = new GarmentCollection();
      this.collection.bind('add', this.appendGarment);
      // Used to fetch from localStorage
      this.collection.fetch();
      this.updateTotal();
      this.render();

      // Populate garment choices
      var sortedGarments = [];
      for (var garment in GARMENTS) {
        sortedGarments.push(garment);
      }
      sortedGarments.sort();
      for (var i = 0; i < sortedGarments.length; i++) {
        var g = sortedGarments[i];
        $garmentType.append(
          '<option value="' + g + '">' +
            g.toTitleCase() +
          '</option>'
          );
      }

      $garmentType.chosen();

      // TODO: Refactor this into an AppView to preserve the local scope
      //       and events of $el.
      $addGarment.on('click', function(event) {
        event.preventDefault();
        var garmentType = $garmentType.val();
        var garmentQuantity = parseInt($garmentQuantity.val());
        var garmentCost = parseFloat(GARMENTS[garmentType]);

        self.addGarment.bind(self)({
          garment_type: garmentType.toTitleCase(),
          cost: garmentCost,
          quantity: garmentQuantity,
          total_cost: garmentCost * garmentQuantity,
        });
      });

      $clearAll.on('click', function(event) {
        event.preventDefault();
        self.removeAll.bind(self)();
        self.unrenderAll.bind(self)();
        self.updateTotal();
      });
    },

    updateTotal: function() {
      var totalCost = this.collection.sumCosts().toFixed(2);
      $('#grand-total').html('$' + totalCost);
      $('#total-value').html('$' + totalCost);
    },

    render: function() {
      var self = this;
      _(this.collection.models).each(function(garment){
        self.appendGarment(garment);
      }, this);
    },

    unrenderAll: function() {
      this.$el.html('');
    },

    addGarment: function(params) {
      this.collection.create(new GarmentModel(params));
      this.updateTotal();
    },

    appendGarment: function(garment) {
      var garmentView = new GarmentView({
        model: garment
      });
      var garmentEl = garmentView.render().$el;
      $('#calculation-table', this.el).append(garmentEl);
    },

    removeAll: function() {
      this.collection.reset();
    }
  });

  $('#popover-disclaimer').popover({
    'trigger' : 'hover click',
    'placement' : 'bottom',
    'content' : 'For informational purposes only; check <a href="http://www.rinse.com">rinse.com</a> for the most updated prices. This website is not affiliated with Rinse Inc.',
    'html' : true
  });

  var tableView = new TableView();
});

// Decimal rounding from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
(function() {
  /**
   * Decimal adjustment of a number.
   *
   * @param {String}  type  The type of adjustment.
   * @param {Number}  value The number.
   * @param {Integer} exp   The exponent (the 10 logarithm of the adjustment base).
   * @returns {Number} The adjusted value.
   */
  function decimalAdjust(type, value, exp) {
    // If the exp is undefined or zero...
    if (typeof exp === 'undefined' || +exp === 0) {
      return Math[type](value);
    }
    value = +value;
    exp = +exp;
    // If the value is not a number or the exp is not an integer...
{'fraction_non_alphanumeric': 0.17032728535463149, 'fraction_numerical': 0.010417570969702231, 'mean_word_length': 2.475113122171946, 'pattern_counts': {'":': 50, '<': 41, '<?xml version=': 0, '>': 39, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, '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': '1506266', 'n_tokens_mistral': 3942, 'n_tokens_neox': 3687, 'n_words': 846}