<commit_before>/*jshint indent:2, curly:true eqeqeq:true, immed:true, latedef:true,
newcap:true, noarg:true, regexp:true, undef:true, strict:true, trailing:true
white:true*/
/*global XT:true, XM:true, Backbone:true, _:true, console:true */

(function () {
  "use strict";

  /**
    @class

    @extends XM.Model
  */
  XM.Country = XM.Model.extend({
    /** @scope XM.Country.prototype */

    recordType: 'XM.Country',

    requiredAttributes: [
      "abbreviation",
      "currencyAbbreviation",
      "name"
    ],

    // ..........................................................
    // METHODS
    //

    validateEdit: function (attributes) {
      var params = {};

      if (attributes.abbreviation &&
          attributes.abbreviation.length !== 2) {
        params.attr = "_abbreviation".loc();
        params.length = "2";
        return XT.Error.clone('xt1006', { params: params });
      }

      if (attributes.currencyAbbreviation &&
          attributes.currencyAbbreviation.length !== 3) {
        params.attr = "_currencyAbbreviation".loc();
        params.length = "3";
        return XT.Error.clone('xt1006', { params: params });
      }
    }

  });

  /**
    @class

    @extends XM.Model
  */
  XM.State = XM.Model.extend({
    /** @scope XM.State.prototype */

    recordType: 'XM.State',

    requiredAttributes: [
      "abbreviation",
      "country",
      "name"
    ]

  });

  /**
    @class

    @extends XM.Document
  */
  XM.Address = XM.Document.extend({
    /** @scope XM.Address.prototype */

    recordType: 'XM.Address',

    numberPolicy: XM.Document.AUTO_NUMBER,

    // ..........................................................
    // METHODS
    //

    /**
      Formats the multiple lines of an address into a
      text block separating the elements of the address by line breaks.

      @params {Boolean} Is HTML
      @return {String}
    */
    format: function (isHtml) {
      return XM.Address.format(this, isHtml);
    },

    /**
      A formatted address that includes city, state and country.

      @return {String}
    */
    formatShort: function () {
      return XM.Address.formatShort(this);
    },

    /**
      Success response returns an integer from the server indicating how many times the address
      is used by other records.

      @param {Object} Options
      @returns Receiver
    */
    useCount: function (options) {
      console.log("XM.Address.useCount for: " + this.id);
      XT.dataSource.dispatch('XM.Address', 'useCount', this.id, options);
      return this;
    }

  });

  // ..........................................................
  // CLASS METHODS
  //

  _.extend(XM.Address, {

    /**
      Success response returns an address id for an address with the same fields
      as those passed.

      @param {String} Line1
      @param {String} Line2
      @param {String} Line3
      @param {String} City
      @param {String} State
      @param {String} Postal Code
      @param {String} Country
      @param {Object} Options
      @returns Receiver
    */
    findExisting: function (line1, line2, line3, city, state, postalcode, country, options) {
      var params = {
          type: 'Address',
          line1: line1,
          line2: line2,
          line3: line3,
          city: city,
          state: state,
          postalcode: postalcode,
          country: country
        };
      XT.dataSource.dispatch('XM.Address', 'findExisting', params, options);
      console.log("XM.Address.findExisting");
      return this;
    },

    /**
      This function formats the multiple lines of an address into a
      text block separating the elements of the address by line breaks.

      Address format accepts multiple argument formats:
        XM.Address.format(address);
        XM.Address.format(address, isHtml);
        XM.Address.format(name, line1, line2, line3, city, state, postalcode, country);
        XM.Address.format(name, line1, line2, line3, city, state, postalcode, country, isHtml);

      Where address is an XM.Address and isHtml determines whether to
      use HTML line breaks instead of ASCII new line characters. The
      default for isHtml is false. The longer signatures accept string
      components of an address.

      @return {String}
    */
    format: function () {
      var fmtlines   = [],
        name, line1, line2, line3,
        city, state, postalcode, country,
        breaks, result = '', csz;

      if (typeof arguments[0] === 'object') {
        name = '';
        line1 = arguments[0].get('line1');
        line2 = arguments[0].get('line2');
        line3 = arguments[0].get('line3');
        city = arguments[0].get('city');
        state = arguments[0].get('state');
        postalcode = arguments[0].get('postalcode');
        country = arguments[0].get('country');
        breaks = (arguments[1] === undefined ? false : arguments[1]) ? '
' : '\n';
      } else if (typeof arguments[0] === 'string')  {
        name = arguments[0];
        line1 = arguments[1];
        line2 = arguments[2];
        line3 = arguments[3];
        city = arguments[4];
        state = arguments[5];
        postalcode = arguments[6];
        country = arguments[7];
        breaks = (arguments[8] === undefined ? false : arguments[8]) ? '
' : '\n';
      } else { return false; }

      if (name) { fmtlines.push(name); }
      if (line1) { fmtlines.push(line1); }
      if (line2) { fmtlines.push(line2); }
      if (line3) { fmtlines.push(line3); }
      if (city || state || postalcode) {
        csz = (city || '') +
              (city && (state || postalcode) ? ', '  : '') +
              (state || '') +
              (state && postalcode ? ' '  : '') +
              (postalcode || '');
        fmtlines.push(csz);
      }
      if (country) { fmtlines.push(country); }

      if (fmtlines.length) { result = fmtlines.join(breaks); }

      return result;
    },

    /**
      A formatted address that includes city, state and country.

      @return {String}
    */
    formatShort: function (address) {
      var ret,
        city = address.get('city') || '',
        state = address.get('state') || '',
        country = address.get('country') || '';
      ret = city + (city && state ? ', ' : '') + state;
      ret += (ret ? ' ' : '') + country;
      return ret;
    },

    // ..........................................................
    // CONSTANTS
    //

    /**
      Option to convert the existing address into a new one.

      @static
      @constant
      @type Number
      @default 0
    */
    CHANGE_ONE: 0,

    /**
      Option to change the existing address so all users of the
      address are affected.

      @static
      @constant
      @type Number
      @default 1
    */
    CHANGE_ALL: 1

  });

  /**
    @class

    @extends XM.Model
  */
  XM.AddressComment = XM.Model.extend({
    /** @scope XM.AddressComment.prototype */

    recordType: 'XM.AddressComment'

  });

  /**
    @class

    @extends XM.Model
  */
  XM.AddressCharacteristic = XM.Model.extend({
    /** @scope XM.AddressCharacteristic.prototype */

    recordType: 'XM.AddressCharacteristic'

  });

  /**
    @class

    @extends XM.Model
  */
  XM.AddressInfo = XM.Document.extend({
    /** @scope XM.AddressInfo.prototype */

    recordType: 'XM.AddressInfo',

    numberPolicy: XM.Document.AUTO_NUMBER,

    // ..........................................................
    // METHODS
    //

    /**
     Return a copy of this address.

     @return {XM.Address} copy of the address
    */
    copy: function () {
      var attrs = _.clone(this.attributes);
      delete attrs.id;
      delete attrs.dataState;
      delete attrs.number;
      delete attrs.type;
      delete attrs.isActive;
      return new XM.AddressInfo(attrs, {isNew: true});
    },

    /**
      Formats the multiple lines of an address into a
      text block separating the elements of the address by line breaks.

      @params {Boolean} Is HTML
      @return {String}
    */
    format: function (isHtml) {
      return XM.Address.format(this, isHtml);
    },

    /**
      A formatted address that includes city, state and country.

      @return {String}
    */
    formatShort: function () {
      return XM.Address.formatShort(this);
    },

    isEmpty: function () {
      return (_.isEmpty(this.get('line1')) &&
              _.isEmpty(this.get('line2')) &&
              _.isEmpty(this.get('line3')) &&
              _.isEmpty(this.get('city')) &&
              _.isEmpty(this.get('state')) &&
              _.isEmpty(this.get('postalCode')) &&
              _.isEmpty(this.get('country')));
    },

    /**
      Success response returns an integer from the server indicating how many times the address
      is used by other records.

      @param {Object} Options
      @returns Receiver
    */
    useCount: function (options) {
      console.log("XM.Address.useCount for: " + this.id);
      XT.dataSource.dispatch('XM.Address', 'useCount', this.id, options);
      return this;
    }

  });

  // ..........................................................
  // MIXINS
  //

  /**
    Use this mixin on models that include an editable address. It will set the
    parent model status appropriately if the address is edited, and will
    perform address processing on the parent including:
      * Initialize: A new address will be created with each new parent.
      * Save first: The address will be saved first, and only on successful save
        will the parent save.
      * Check Empty: Address will set to null if empty on save.
      * Find Existing: Search for an identical address on the server.
        If found it will be used automatically.
      * Check Use Count: Check if the address is used elsewhere.

    If it is determined the address on a parent model has been edited and is being
    used by other records an error will be thrown unless the appropriate option is
    passed to instruct the model how to handle it. The options are:
      * XM.Address.CHANGE_ONE: Create a new address for the parent model so only it
        is affected by the edits.
      * XM.Address.CHANGE_ALL: Save changes to the original address so all
        records that reference that address are affected.

    Example:
      m.save(null, {address: XM.Address.CHANGE_ONE});
  */
  XM.AddressCheckMixin = {
    addressChanged: function () {
      var address = this.get('address'),
        addressStatus = address ? address.getStatus() : false,
        status = this.getStatus(),
        K = XM.Model;
      if (addressStatus === K.READY_DIRTY &&
          status === K.READY_CLEAN) {
        this.setStatus(K.READY_DIRTY);
      }
    },

    didChange: function () {
      var address,
        that = this;
      XM.Document.prototype.didChange.apply(this, arguments);
      if (this.changed.address) {
        address = this.previous('address');
        if (address) {
          address.off('change', this.addressChanged, that);
        }
        address = this.get('address');
        if (address) {
          address.on('change', this.addressChanged, that);
        }
      }
    },

    destroy: function () {
      var address = this.get('address');
      if (address.isNew()) { address.releaseNumber(); }
      XM.Document.prototype.destroy.apply(this, arguments);
    },

    initialize: function (attributes, options) {
      XM.Document.prototype.initialize.apply(this, arguments);
      if (options && options.isNew && this.get('address') === null) {
        this.set('address', new XM.AddressInfo(null, {isNew: true}));
      }
    },

    save: function (key, value, options) {
      var model = this,
        address = this.get("address"),
        addressStatus = address ? address.getStatus() : false,
        maxUse = this.isNew() ? 0 : 1,
        addressOptions = {},
        findExistingOptions = {},
        useCountOptions = {},
        isValid = this.isValid(),
        K = XM.Model;

      // Perform address checks if warranted
      if (isValid && address && addressStatus !== K.READY_CLEAN) {
        // Handle both `"key", value` and `{key: value}` -style arguments.
        if (_.isObject(key) || _.isEmpty(key)) {
          options = value ? _.clone(value) : {};
        } else {
          options = options ? _.clone(options) : {};
        }

        // Callback: call save on the original again
        addressOptions.success = function (resp) {
          XM.Document.prototype.save.call(model, key, value, options);
        };

        // If the address is empty set it to null
        if (address.isEmpty()) {
          if (address.isNew()) { address.releaseNumber(); }
          this.set('address', null);

        // If dirty, see if this address already exists
        } else if (address.isDirty() && !options.existingChecked) {
          // Callback: call save on the original again
          findExistingOptions.success = function (resp) {
            // If found, set the address with found id
            if (resp) {
              address.set('id', resp, {force: true}); // Id is all that matters...
              address.status = K.READY_CLEAN; // So we don't come back here
            }

            // Try saving again
            options.existingChecked = true;
            if (_.isObject(key) || _.isEmpty(key)) { value = options; }
            model.save(key, value, options);
          };
          XM.Address.findExisting(address.get('line1'),
                                  address.get('line2'),
                                  address.get('line3'),
                                  address.get('city'),
                                  address.get('state'),
                                  address.get('postalCode'),
                                  address.get('country'),
                                  findExistingOptions);
          return;

        // If it is new, save it first
        } else if (address.isNew()) {
          address.save(null, addressOptions);
          return;

        // If it has changed, check to see if used elsewhere
        } else if (address.isDirty()) {
          // Callback: define what to do after use count check
          useCountOptions.success = function (resp) {
            var error,
              K = XM.Address,
              callback,
              newAddress;
            // If address is used then we need to handle that
            if (resp > maxUse) {
              // If no address option passed, then error
              if (!_.isNumber(options.address)) {
                error = XT.Error.clone('xt2007');
                model.trigger('error', model, error, options);
                return;

              // `CHANGE_ONE` is always the fallback as it's the safest
              } else if (options.address !== K.CHANGE_ALL) {
                // Callback after successfull copy
                // Only proceed when we have both an id and number from the server
                callback = function () {
                  var id = newAddress.id,
                    number = newAddress.get('number');
                  if (id && number) {
                    newAddress.off('change:id change:number', callback);
                    model.set('address', newAddress);
                    newAddress.save(null, addressOptions);
                  }
                };
                newAddress = address.copy();
                newAddress.on('change:id change:number', callback);
                callback(); // In case the data was here before event handlers could respond
                return;
              }
            }

            // No problem so save the address and original model after that
            address.save(null, addressOptions);
          };

          // Perform the check: find out how many places this address is used
          address.useCount(useCountOptions);
          return;
        }
      }

      // No problem with address, just save the record
      // If record was invalid, this will bubble up the error
      XM.Document.prototype.save.call(model, key, value, options);
    }
  };

  // ..........................................................
  // COLLECTIONS
  //

  /**
    @class

    @extends XM.Collection
  */
  XM.AddressInfoCollection = XM.Collection.extend({
    /** @scope XM.AddressInfoCollection.prototype */

    model: XM.AddressInfo

  });

  /**
    @class

    @extends XM.Collection
  */
  XM.CountryCollection = XM.Collection.extend({
    /** @scope XM.CountryCollection.prototype */

    model: XM.Country

  });

  /**
    @class

    @extends XM.Collection
  */
  XM.StateCollection = XM.Collection.extend({
    /** @scope XM.StateCollection.prototype */

    model: XM.State

  });

}());
<commit_msg>tweak address docs.<commit_after>/*jshint indent:2, curly:true eqeqeq:true, immed:true, latedef:true,
newcap:true, noarg:true, regexp:true, undef:true, strict:true, trailing:true
white:true*/
/*global XT:true, XM:true, Backbone:true, _:true, console:true */

(function () {
  "use strict";

  /**
    @class

    @extends XM.Model
  */
  XM.Country = XM.Model.extend({
    /** @scope XM.Country.prototype */

    recordType: 'XM.Country',

    requiredAttributes: [
      "abbreviation",
      "currencyAbbreviation",
      "name"
    ],

    // ..........................................................
    // METHODS
    //

    validateEdit: function (attributes) {
      var params = {};

      if (attributes.abbreviation &&
          attributes.abbreviation.length !== 2) {
        params.attr = "_abbreviation".loc();
        params.length = "2";
        return XT.Error.clone('xt1006', { params: params });
      }

      if (attributes.currencyAbbreviation &&
          attributes.currencyAbbreviation.length !== 3) {
        params.attr = "_currencyAbbreviation".loc();
        params.length = "3";
        return XT.Error.clone('xt1006', { params: params });
      }
    }

  });

  /**
    @class

    @extends XM.Model
  */
  XM.State = XM.Model.extend({
    /** @scope XM.State.prototype */

    recordType: 'XM.State',

    requiredAttributes: [
      "abbreviation",
      "country",
      "name"
    ]

  });

  /**
    @class

    @extends XM.Document
  */
  XM.Address = XM.Document.extend({
    /** @scope XM.Address.prototype */

    recordType: 'XM.Address',

    numberPolicy: XM.Document.AUTO_NUMBER,

    // ..........................................................
    // METHODS
    //

    /**
      Formats the multiple lines of an address into a
      text block separating the elements of the address by line breaks.

      @params {Boolean} Is HTML
      @return {String}
    */
    format: function (isHtml) {
      return XM.Address.format(this, isHtml);
    },

    /**
      A formatted address that includes city, state and country.

      @return {String}
    */
    formatShort: function () {
      return XM.Address.formatShort(this);
    },

    /**
      Success response returns an integer from the server indicating how many times the address
      is used by other records.

      @param {Object} Options
      @returns Receiver
    */
    useCount: function (options) {
      console.log("XM.Address.useCount for: " + this.id);
      XT.dataSource.dispatch('XM.Address', 'useCount', this.id, options);
      return this;
    }

  });

  // ..........................................................
  // CLASS METHODS
  //

  _.extend(XM.Address, {

    /**
      Success response returns an address id for an address with the same fields
      as those passed.

      @param {String} Line1
      @param {String} Line2
      @param {String} Line3
      @param {String} City
      @param {String} State
      @param {String} Postal Code
      @param {String} Country
      @param {Object} Options
      @returns Receiver
    */
    findExisting: function (line1, line2, line3, city, state, postalcode, country, options) {
      var params = {
          type: 'Address',
          line1: line1,
          line2: line2,
          line3: line3,
          city: city,
          state: state,
          postalcode: postalcode,
          country: country
        };
      XT.dataSource.dispatch('XM.Address', 'findExisting', params, options);
      console.log("XM.Address.findExisting");
      return this;
    },

    /**
      This function formats the multiple lines of an address into a
      text block separating the elements of the address by line breaks.

      Address format accepts multiple argument formats:
        XM.Address.format(address);
        XM.Address.format(address, isHtml);
        XM.Address.format(name, line1, line2, line3, city, state, postalcode, country);
        XM.Address.format(name, line1, line2, line3, city, state, postalcode, country, isHtml);

      Where address is an XM.Address and isHtml determines whether to
      use HTML line breaks instead of ASCII new line characters. The
      default for isHtml is false. The longer signatures accept string
      components of an address.

      @return {String}
    */
    format: function () {
      var fmtlines   = [],
        name, line1, line2, line3,
        city, state, postalcode, country,
        breaks, result = '', csz;

      if (typeof arguments[0] === 'object') {
        name = '';
        line1 = arguments[0].get('line1');
        line2 = arguments[0].get('line2');
        line3 = arguments[0].get('line3');
        city = arguments[0].get('city');
        state = arguments[0].get('state');
        postalcode = arguments[0].get('postalcode');
        country = arguments[0].get('country');
        breaks = (arguments[1] === undefined ? false : arguments[1]) ? '
' : '\n';
      } else if (typeof arguments[0] === 'string')  {
        name = arguments[0];
        line1 = arguments[1];
        line2 = arguments[2];
        line3 = arguments[3];
        city = arguments[4];
        state = arguments[5];
        postalcode = arguments[6];
        country = arguments[7];
        breaks = (arguments[8] === undefined ? false : arguments[8]) ? '
' : '\n';
      } else { return false; }

      if (name) { fmtlines.push(name); }
      if (line1) { fmtlines.push(line1); }
      if (line2) { fmtlines.push(line2); }
      if (line3) { fmtlines.push(line3); }
      if (city || state || postalcode) {
        csz = (city || '') +
              (city && (state || postalcode) ? ', '  : '') +
              (state || '') +
              (state && postalcode ? ' '  : '') +
              (postalcode || '');
        fmtlines.push(csz);
      }
      if (country) { fmtlines.push(country); }

      if (fmtlines.length) { result = fmtlines.join(breaks); }

      return result;
    },

    /**
      A formatted address that includes city, state and country.

      @return {String}
    */
    formatShort: function (address) {
      var ret,
        city = address.get('city') || '',
        state = address.get('state') || '',
        country = address.get('country') || '';
      ret = city + (city && state ? ', ' : '') + state;
      ret += (ret ? ' ' : '') + country;
      return ret;
    },

    // ..........................................................
    // CONSTANTS
    //

    /**
      Option to convert the existing address into a new one.

      @static
      @constant
      @type Number
      @default 0
    */
    CHANGE_ONE: 0,

    /**
      Option to change the existing address so all users of the
      address are affected.

      @static
      @constant
      @type Number
      @default 1
    */
    CHANGE_ALL: 1

  });

  /**
    @class

    @extends XM.Model
  */
  XM.AddressComment = XM.Model.extend({
    /** @scope XM.AddressComment.prototype */

    recordType: 'XM.AddressComment'

  });

  /**
    @class

    @extends XM.Model
  */
  XM.AddressCharacteristic = XM.Model.extend({
    /** @scope XM.AddressCharacteristic.prototype */

    recordType: 'XM.AddressCharacteristic'

  });

  /**
    @class

    @extends XM.Model
  */
  XM.AddressInfo = XM.Document.extend({
    /** @scope XM.AddressInfo.prototype */

    recordType: 'XM.AddressInfo',

    numberPolicy: XM.Document.AUTO_NUMBER,

    // ..........................................................
    // METHODS
    //

    /**
     Return a copy of this address.

     @return {XM.Address} copy of the address
    */
    copy: function () {
      var attrs = _.clone(this.attributes);
      delete attrs.id;
      delete attrs.dataState;
      delete attrs.number;
      delete attrs.type;
      delete attrs.isActive;
      return new XM.AddressInfo(attrs, {isNew: true});
    },

    /**
      Formats the multiple lines of an address into a
      text block separating the elements of the address by line breaks.

      @params {Boolean} Is HTML
      @return {String}
    */
    format: function (isHtml) {
      return XM.Address.format(this, isHtml);
    },

    /**
      A formatted address that includes city, state and country.

      @return {String}
    */
    formatShort: function () {
      return XM.Address.formatShort(this);
    },

    isEmpty: function () {
      return (_.isEmpty(this.get('line1')) &&
              _.isEmpty(this.get('line2')) &&
              _.isEmpty(this.get('line3')) &&
              _.isEmpty(this.get('city')) &&
              _.isEmpty(this.get('state')) &&
              _.isEmpty(this.get('postalCode')) &&
              _.isEmpty(this.get('country')));
    },

    /**
      Success response returns an integer from the server indicating how many times the address
      is used by other records.

      @param {Object} Options
      @returns Receiver
    */
    useCount: function (options) {
      console.log("XM.Address.useCount for: " + this.id);
      XT.dataSource.dispatch('XM.Address', 'useCount', this.id, options);
      return this;
    }

  });

  // ..........................................................
  // MIXINS
  //

  /**
    @class

    Use this mixin on models that include an editable address. It will set the
    parent model status appropriately if the address is edited, and will
    perform address processing on the parent including:
      * Initialize: A new address will be created with each new parent.
      * Save first: The address will be saved first, and only on successful save
        will the parent save.
      * Check Empty: Address will set to null if empty on save.
      * Find Existing: Search for an identical address on the server.
        If found it will be used automatically.
      * Check Use Count: Check if the address is used elsewhere.

    If it is determined the address on a parent model has been edited and is being
    used by other records an error will be thrown unless the appropriate option is
    passed to instruct the model how to handle it. The options are:
      * XM.Address.CHANGE_ONE: Create a new address for the parent model so only it
        is affected by the edits.
      * XM.Address.CHANGE_ALL: Save changes to the original address so all
        records that reference that address are affected.

    Example:
      m.save(null, {address: XM.Address.CHANGE_ONE});
  */
  XM.AddressCheckMixin = {
    addressChanged: function () {
      var address = this.get('address'),
        addressStatus = address ? address.getStatus() : false,
        status = this.getStatus(),
        K = XM.Model;
      if (addressStatus === K.READY_DIRTY &&
          status === K.READY_CLEAN) {
        this.setStatus(K.READY_DIRTY);
      }
    },

    didChange: function () {
      var address,
        that = this;
      XM.Document.prototype.didChange.apply(this, arguments);
      if (this.changed.address) {
        address = this.previous('address');
        if (address) {
          address.off('change', this.addressChanged, that);
        }
        address = this.get('address');
        if (address) {
          address.on('change', this.addressChanged, that);
        }
      }
    },

    destroy: function () {
      var address = this.get('address');
      if (address.isNew()) { address.releaseNumber(); }
      XM.Document.prototype.destroy.apply(this, arguments);
    },

    initialize: function (attributes, options) {
      XM.Document.prototype.initialize.apply(this, arguments);
      if (options && options.isNew && this.get('address') === null) {
        this.set('address', new XM.AddressInfo(null, {isNew: true}));
      }
    },

    save: function (key, value, options) {
      var model = this,
        address = this.get("address"),
        addressStatus = address ? address.getStatus() : false,
        maxUse = this.isNew() ? 0 : 1,
        addressOptions = {},
        findExistingOptions = {},
        useCountOptions = {},
        isValid = this.isValid(),
        K = XM.Model;

      // Perform address checks if warranted
      if (isValid && address && addressStatus !== K.READY_CLEAN) {
        // Handle both `"key", value` and `{key: value}` -style arguments.
        if (_.isObject(key) || _.isEmpty(key)) {
          options = value ? _.clone(value) : {};
        } else {
          options = options ? _.clone(options) : {};
        }

        // Callback: call save on the original again
        addressOptions.success = function (resp) {
          XM.Document.prototype.save.call(model, key, value, options);
        };

        // If the address is empty set it to null
        if (address.isEmpty()) {
          if (address.isNew()) { address.releaseNumber(); }
          this.set('address', null);

        // If dirty, see if this address already exists
        } else if (address.isDirty() && !options.existingChecked) {
          // Callback: call save on the original again
          findExistingOptions.success = function (resp) {
            // If found, set the address with found id
            if (resp) {
              address.set('id', resp, {force: true}); // Id is all that matters...
              address.status = K.READY_CLEAN; // So we don't come back here
            }

            // Try saving again
            options.existingChecked = true;
            if (_.isObject(key) || _.isEmpty(key)) { value = options; }
            model.save(key, value, options);
          };
          XM.Address.findExisting(address.get('line1'),
                                  address.get('line2'),
                                  address.get('line3'),
                                  address.get('city'),
                                  address.get('state'),
                                  address.get('postalCode'),
                                  address.get('country'),
                                  findExistingOptions);
          return;

        // If it is new, save it first
        } else if (address.isNew()) {
          address.save(null, addressOptions);
          return;

        // If it has changed, check to see if used elsewhere
        } else if (address.isDirty()) {
          // Callback: define what to do after use count check
          useCountOptions.success = function (resp) {
            var error,
              K = XM.Address,
              callback,
              newAddress;
            // If address is used then we need to handle that
            if (resp > maxUse) {
              // If no address option passed, then error
              if (!_.isNumber(options.address)) {
                error = XT.Error.clone('xt2007');
                model.trigger('error', model, error, options);
                return;

              // `CHANGE_ONE` is always the fallback as it's the safest
              } else if (options.address !== K.CHANGE_ALL) {
                // Callback after successfull copy
                // Only proceed when we have both an id and number from the server
                callback = function () {
                  var id = newAddress.id,
                    number = newAddress.get('number');
                  if (id && number) {
                    newAddress.off('change:id change:number', callback);
                    model.set('address', newAddress);
                    newAddress.save(null, addressOptions);
                  }
                };
                newAddress = address.copy();
                newAddress.on('change:id change:number', callback);
                callback(); // In case the data was here before event handlers could respond
                return;
              }
            }

            // No problem so save the address and original model after that
            address.save(null, addressOptions);
          };

          // Perform the check: find out how many places this address is used
          address.useCount(useCountOptions);
          return;
        }
      }

      // No problem with address, just save the record
      // If record was invalid, this will bubble up the error
      XM.Document.prototype.save.call(model, key, value, options);
    }
  };

  // ..........................................................
  // COLLECTIONS
  //

  /**
    @class

    @extends XM.Collection
  */
  XM.AddressInfoCollection = XM.Collection.extend({
    /** @scope XM.AddressInfoCollection.prototype */

    model: XM.AddressInfo

  });

  /**
    @class

    @extends XM.Collection
  */
  XM.CountryCollection = XM.Collection.extend({
    /** @scope XM.CountryCollection.prototype */

    model: XM.Country

  });

  /**
    @class

    @extends XM.Collection
  */
  XM.StateCollection = XM.Collection.extend({
    /** @scope XM.StateCollection.prototype */

    model: XM.State

  });

}());
<|endoftext|>


<commit_before>// dependencies
//
import React from 'react';
import update from 'react-addons-update';
import uniqueId from 'lodash/uniqueId';
import classnames from 'classnames';

import Alert from './Alert';
import CheckboxGroup from './form/CheckboxGroup';
import Dropdown from './form/Dropdown';
import RadioButtonGroup from './form/RadioButtonGroup';
import SubmitButton from './form/SubmitButton';
import TextInput from './form/TextInput';

// @TODO added labelColumns, inputColumns to Form

/**
 * The Form component
 */
class Form extends React.Component {
    /**
     * Construct the Form component instance
     * @param  {Object} props The component properties
     */
    constructor(props) {
        super(props);

        // initialize the state, which consists of the validation messages for
        // any children. This is just an empty object now, but as child
        // components are mounted, they will "call in" via the
        // `onChildValidationEvent` handler, at which time this state will
        // become populated with values
        //
        this.state = {
            validation:   {},
            hasValidated: {},
        };

        // bind `this` to the `isValid` method
        //
        this.isValid = this.isValid.bind(this);

        // bind `this` to the onChildValidationEvent handler
        //
        this.onChildValidationEvent = this.onChildValidationEvent.bind(this);
    }

    /**
     * Get the child context values
     *
     * These  values are availabe for use by children of the Form component.
     *
     * @return {Object} The child context values
     */
    getChildContext() {
        return {
            isValid:                this.isValid(),
            onChildValidationEvent: this.onChildValidationEvent,
        };
    }

    /**
     * Handle a validation event from one of the children of this Form
     * @param  {String} validationKey     A unique key identifying the child
     *                                    component
     * @param  {[type]} childHasValidated A flag to indicate whether the
     *                                    component has validated in response to
     *                                    user input
     * @param  {String|null} message      The validation error message, or null
     *                                    if the component is valid
     */
    onChildValidationEvent(validationKey, childHasValidated, message) {
        // build a change event to update the `validation` and `hasValidated`
        // state
        //
        const validation = {};
        validation[validationKey] = { $set: message };

        const hasValidated = {};
        hasValidated[validationKey] = { $set: !!childHasValidated };

        const delta = { validation, hasValidated };

        // update the Form component state
        //
        this.setState((state) => update(state, delta));
    }

    /**
     * Determine if the form is valid
     * @return {Boolean} If true, then all form components are valid
     */
    isValid() {
        // get the list of keys from the validation state
        //
        const keys = Object.keys(this.state.validation);

        // iterate over the list of keys
        //
        for (let idx = 0; idx < keys.length; idx++) {
            // do we have a validation error message for the current item? if
            // so, return false, since we have at least one component which has
            // failed validation
            //
            if (this.state.validation[keys[idx]]) {
                return false;
            }
        }

        // if we get here, then none of the children have failed validation.
        // Return true
        //
        return true;
    }

    /**
     * Build a list of validation errors for the Form
     * @return {Array} An array of validation errors (possibly empty, if all
     *                 components are valid)
     */
    validationErrors() {
        // declare an array to hold the error messages
        //
        const errors = [];

        // iterate through the keys of the validation state and add non-null
        // messages for children which have validated to the array
        //
        Object.keys(this.state.validation).forEach((key) => {
            if (this.state.hasValidated[key] && this.state.validation[key]) {
                errors.push(this.state.validation[key]);
            }
        });

        // return the list of error messages
        //
        return errors;
    }

    /**
     * Render the component
     * @return {React.Element} The React element describing the component
     */
    render() {
        // get the list of validation error messages for the form
        //
        const errors = this.validationErrors();

        // if we have errors, then add an Alert component describing the
        // problems
        //
        const alert = errors.length > 0
            ? <Alert style="error">

Please correct the following problems:

                    {errors.map((err) =>
{err}
)}

            </Alert>
            : '';

        // render the component and return it
        //
        return (

                {alert}
                {this.props.children}

        );
    }
}

// set the property types for the component
//
Form.propTypes = {
    inline:     React.PropTypes.bool,
    horizontal: React.PropTypes.bool,
    children:   React.PropTypes.oneOfType([
        React.PropTypes.arrayOf(React.PropTypes.node),
        React.PropTypes.node,
    ]).isRequired,
};

// set the child context types to propagate to the children
//
Form.childContextTypes = {
    isValid:                React.PropTypes.bool,
    onChildValidationEvent: React.PropTypes.func,
};

// add the "sub-components" so that they can be imported as part of the same
// package
//
Form.CheckboxGroup = CheckboxGroup;
Form.Dropdown = Dropdown;
Form.RadioButtonGroup = RadioButtonGroup;
Form.SubmitButton = SubmitButton;
Form.TextInput = TextInput;

// export the component
//
export default Form;
<commit_msg>comment cleanup<commit_after>// dependencies
//
import React from 'react';
import update from 'react-addons-update';
import uniqueId from 'lodash/uniqueId';
import classnames from 'classnames';

import Alert from './Alert';
import CheckboxGroup from './form/CheckboxGroup';
import Dropdown from './form/Dropdown';
import RadioButtonGroup from './form/RadioButtonGroup';
import SubmitButton from './form/SubmitButton';
import TextInput from './form/TextInput';

// @TODO added labelColumns, inputColumns to Form
// @TODO changing values of children via props should trigger re-validation

/**
 * The Form component
 */
class Form extends React.Component {
    /**
     * Construct the Form component instance
     * @param  {Object} props The component properties
     */
    constructor(props) {
        super(props);

        // initialize the state, which consists of the validation messages for
        // any children. This is just an empty object now, but as child
        // components are mounted, they will "call in" via the
        // `onChildValidationEvent` handler, at which time this state will
        // become populated with values
        //
        this.state = {
            validation:   {},
            hasValidated: {},
        };

        // bind `this` to the `isValid` method
        //
        this.isValid = this.isValid.bind(this);

        // bind `this` to the onChildValidationEvent handler
        //
        this.onChildValidationEvent = this.onChildValidationEvent.bind(this);
    }

    /**
     * Get the child context values
     *
     * These  values are availabe for use by children of the Form component.
     *
     * @return {Object} The child context values
     */
    getChildContext() {
        return {
            isValid:                this.isValid(),
            onChildValidationEvent: this.onChildValidationEvent,
        };
    }

    /**
     * Handle a validation event from one of the children of this Form
     * @param  {String} validationKey     A unique key identifying the child
     *                                    component
     * @param  {[type]} childHasValidated A flag to indicate whether the
     *                                    component has validated in response to
     *                                    user input
     * @param  {String|null} message      The validation error message, or null
     *                                    if the component is valid
     */
    onChildValidationEvent(validationKey, childHasValidated, message) {
        // build a change event to update the `validation` and `hasValidated`
        // state
        //
        const validation = {};
        validation[validationKey] = { $set: message };

        const hasValidated = {};
        hasValidated[validationKey] = { $set: !!childHasValidated };

        const delta = { validation, hasValidated };

        // update the Form component state
        //
        this.setState((state) => update(state, delta));
    }

    /**
     * Determine if the form is valid
     * @return {Boolean} If true, then all form components are valid
     */
    isValid() {
        // get the list of keys from the validation state
        //
        const keys = Object.keys(this.state.validation);

        // iterate over the list of keys
        //
        for (let idx = 0; idx < keys.length; idx++) {
            // do we have a validation error message for the current item? if
            // so, return false, since we have at least one component which has
            // failed validation
            //
            if (this.state.validation[keys[idx]]) {
                return false;
            }
        }

        // if we get here, then none of the children have failed validation.
        // Return true
        //
        return true;
    }

    /**
     * Build a list of validation errors for the Form
     * @return {Array} An array of validation errors (possibly empty, if all
     *                 components are valid)
     */
    validationErrors() {
        // declare an array to hold the error messages
        //
        const errors = [];

        // iterate through the keys of the validation state and add non-null
        // messages for children which have validated to the array
        //
        Object.keys(this.state.validation).forEach((key) => {
            if (this.state.hasValidated[key] && this.state.validation[key]) {
                errors.push(this.state.validation[key]);
            }
        });

        // return the list of error messages
        //
        return errors;
    }

    /**
     * Render the component
     * @return {React.Element} The React element describing the component
     */
    render() {
        // get the list of validation error messages for the form
        //
        const errors = this.validationErrors();

        // if we have errors, then add an Alert component describing the
        // problems
        //
        const alert = errors.length > 0
            ? <Alert style="error">

Please correct the following problems:

                    {errors.map((err) =>
{err}
)}

            </Alert>
            : '';

        // render the component and return it
        //
        return (

                {alert}
                {this.props.children}

        );
    }
}

// set the property types for the component
//
Form.propTypes = {
    inline:     React.PropTypes.bool,
    horizontal: React.PropTypes.bool,
    children:   React.PropTypes.oneOfType([
        React.PropTypes.arrayOf(React.PropTypes.node),
        React.PropTypes.node,
    ]).isRequired,
};

// set the child context types to propagate to the children
//
Form.childContextTypes = {
    isValid:                React.PropTypes.bool,
    onChildValidationEvent: React.PropTypes.func,
};

// add the "sub-components" so that they can be imported as part of the same
// package
//
Form.CheckboxGroup = CheckboxGroup;
Form.Dropdown = Dropdown;
Form.RadioButtonGroup = RadioButtonGroup;
Form.SubmitButton = SubmitButton;
Form.TextInput = TextInput;

// export the component
//
export default Form;
<|endoftext|>


<commit_before>var settings = {
    format: 'a4',
    sizeMultiplier: 4,
    activeBorderColor: 'gray'
};

var formats = {
    a4: [210, 297]
};

var Markup = function(markupField, markupTools) {
    this.MarkupField = markupField;
    this.MarkupTools = markupTools;
    this.Elements = [];
    var plugins = [];
    var objectHandleId = 0;
    var activeElement = -1;

    var initMarkupField = function() {
        $(markupField)
            .on('click', function(){ ResetActiveElement(); })
            .css({
                width: SizeCalculator.ToPixels(formats[settings.format][0]) + 'px',
                height: SizeCalculator.ToPixels(formats[settings.format][1]) + 'px'
            });
    };

    var AddObjects = function() {
        for (var i in this.Elements) {
            var elementObject = this.Elements[i];

            if (elementObject.Handle) {
                $('#' + elementObject.Handle).remove();
            }

            elementObject.Handle = "PDFMARKUP-" + ++objectHandleId;
            $(this.MarkupField).prepend('

');
            $('#' + elementObject.Handle)
                .addClass('pdfmarkup-editable')
                .on('click', ActivateElementEvent)
                .css({
                    position: 'absolute',
                    border: '1px solid transparent',
                    top: elementObject.y,
                    left: elementObject.x,
                });

            if (plugins.length > 0) {
                for (var i in plugins) {
                    if (plugins[i].HandlesType(elementObject.type)) {
                        plugins[i].Paint(elementObject);
                    }
                }
            }
        }
    };

    var UpdatePositions = function() {
        if (this.Elements.length > 0) {
            for (var i in this.Elements) {
                this.Elements[i].x = Math.round(SizeCalculator.ToMM($('#' + this.Elements[i].Handle).position().left));
                this.Elements[i].y = Math.round(SizeCalculator.ToMM($('#' + this.Elements[i].Handle).position().top));
            }
        }
    };

    var MakeObjectsDraggable = function() {
        $(this.MarkupField).children().draggable({
            stop: function(event, ui) {
                UpdatePositions();
                SendUpdateEvent();
            }
        });
    };

    var ActivateElementByIndex = function(index) {
        if (activeElement != index) {
            ResetActiveElement();
            activeElement = index;

            if (this.Elements[activeElement]) {
                $('#' + this.Elements[activeElement].Handle).css({border: '1px solid ' + settings.activeBorderColor});
                SendActivateEvent();
            }
        }
    };

    var SendUpdateEvent = function() {
        if (this.Elements[activeElement]) {
            for (var i in plugins) {
                if (plugins[i].HandlesType(this.Elements[activeElement].type)) {
                    plugins[i].Update(this.Elements[activeElement]);
                    markupTools.Activate(this.Elements[activeElement], plugins[i]);
                }
            }
        }

        $(this).trigger('update');
    };

    var SendActivateEvent = function() {
        if (this.Elements[activeElement]) {
            for (var i in plugins) {
                if (plugins[i].HandlesType(this.Elements[activeElement].type)) {
                    plugins[i].Activate(this.Elements[activeElement]);
                    markupTools.Activate(this.Elements[activeElement], plugins[i]);
                }
            }
        }
    };

    this.AddPlugin = function(plugin) {
        plugins.push(plugin);
    };

    this.Refresh = function() {
        if (this.Elements.length > 0) {
            AddObjects();
            MakeObjectsDraggable();
        }
    };

    this.ActivateElement = function(handle) {
        if (this.Elements.length > 0) {
            for (var i in this.Elements) {
                if (this.Elements[i].Handle == handle) {
                    return ActivateElementByIndex(i);
                }
            }
        }
    };

    this.ActivateElementEvent = function(event) {
        event.stopPropagation();
        ActivateElement($(this).attr('id'));
    };

    this.ResetActiveElement = function() {
        if (this.Elements[activeElement]) {
            $('#' + this.Elements[activeElement].Handle).css({border: '1px solid transparent'});
        }

        activeElement = -1;
        markupTools.Deactivate();
    };

    this.AddElement = function(elementObject) {
        this.Elements.push(elementObject);
        this.Refresh();
        ActivateElementByIndex(this.Elements.length - 1);
        $(this).trigger('add');
    };

    this.GetActiveElement = function() {
        if (activeElement >= 0) {
            return this.Elements[activeElement];
        }

        return null;
    };

    this.Serialize = function() {
        var result = JSON.parse(JSON.stringify(this.Elements));

        for (var i in result) {
            if (result[i].Handle) {
                delete result[i].Handle;
            }
        }

        return result;
    };

    initMarkupField();
    return this;
};

<commit_msg>Remove the properties from the serialized output<commit_after>var settings = {
    format: 'a4',
    sizeMultiplier: 4,
    activeBorderColor: 'gray'
};

var formats = {
    a4: [210, 297]
};

var Markup = function(markupField, markupTools) {
    this.MarkupField = markupField;
    this.MarkupTools = markupTools;
    this.Elements = [];
    var plugins = [];
    var objectHandleId = 0;
    var activeElement = -1;

    var initMarkupField = function() {
        $(markupField)
            .on('click', function(){ ResetActiveElement(); })
            .css({
                width: SizeCalculator.ToPixels(formats[settings.format][0]) + 'px',
                height: SizeCalculator.ToPixels(formats[settings.format][1]) + 'px'
            });
    };

    var AddObjects = function() {
        for (var i in this.Elements) {
            var elementObject = this.Elements[i];

            if (elementObject.Handle) {
                $('#' + elementObject.Handle).remove();
            }

            elementObject.Handle = "PDFMARKUP-" + ++objectHandleId;
            $(this.MarkupField).prepend('

');
            $('#' + elementObject.Handle)
                .addClass('pdfmarkup-editable')
                .on('click', ActivateElementEvent)
                .css({
                    position: 'absolute',
                    border: '1px solid transparent',
                    top: elementObject.y,
                    left: elementObject.x,
                });

            if (plugins.length > 0) {
                for (var i in plugins) {
                    if (plugins[i].HandlesType(elementObject.type)) {
                        plugins[i].Paint(elementObject);
                    }
                }
            }
        }
    };

    var UpdatePositions = function() {
        if (this.Elements.length > 0) {
            for (var i in this.Elements) {
                this.Elements[i].x = Math.round(SizeCalculator.ToMM($('#' + this.Elements[i].Handle).position().left));
                this.Elements[i].y = Math.round(SizeCalculator.ToMM($('#' + this.Elements[i].Handle).position().top));
            }
        }
    };

    var MakeObjectsDraggable = function() {
        $(this.MarkupField).children().draggable({
            stop: function(event, ui) {
                UpdatePositions();
                SendUpdateEvent();
            }
        });
    };

    var ActivateElementByIndex = function(index) {
        if (activeElement != index) {
            ResetActiveElement();
            activeElement = index;

            if (this.Elements[activeElement]) {
                $('#' + this.Elements[activeElement].Handle).css({border: '1px solid ' + settings.activeBorderColor});
                SendActivateEvent();
            }
        }
    };

    var SendUpdateEvent = function() {
        if (this.Elements[activeElement]) {
            for (var i in plugins) {
                if (plugins[i].HandlesType(this.Elements[activeElement].type)) {
                    plugins[i].Update(this.Elements[activeElement]);
                    markupTools.Activate(this.Elements[activeElement], plugins[i]);
                }
            }
        }

        $(this).trigger('update');
    };

    var SendActivateEvent = function() {
        if (this.Elements[activeElement]) {
            for (var i in plugins) {
                if (plugins[i].HandlesType(this.Elements[activeElement].type)) {
                    plugins[i].Activate(this.Elements[activeElement]);
                    markupTools.Activate(this.Elements[activeElement], plugins[i]);
                }
            }
        }
    };

    this.AddPlugin = function(plugin) {
        plugins.push(plugin);
    };

    this.Refresh = function() {
        if (this.Elements.length > 0) {
            AddObjects();
            MakeObjectsDraggable();
        }
    };

    this.ActivateElement = function(handle) {
        if (this.Elements.length > 0) {
            for (var i in this.Elements) {
                if (this.Elements[i].Handle == handle) {
                    return ActivateElementByIndex(i);
                }
            }
        }
    };

    this.ActivateElementEvent = function(event) {
        event.stopPropagation();
        ActivateElement($(this).attr('id'));
    };

    this.ResetActiveElement = function() {
        if (this.Elements[activeElement]) {
            $('#' + this.Elements[activeElement].Handle).css({border: '1px solid transparent'});
        }

        activeElement = -1;
        markupTools.Deactivate();
    };

    this.AddElement = function(elementObject) {
        this.Elements.push(elementObject);
        this.Refresh();
        ActivateElementByIndex(this.Elements.length - 1);
        $(this).trigger('add');
    };

    this.GetActiveElement = function() {
        if (activeElement >= 0) {
            return this.Elements[activeElement];
        }

        return null;
    };

    this.Serialize = function() {
        var result = JSON.parse(JSON.stringify(this.Elements));

        for (var i in result) {
            if (result[i].Handle) {
                delete result[i].Handle;
            }

            if (result[i].properties) {
                delete result[i].properties;
            }
        }

        return result;
    };

    initMarkupField();
    return this;
};

<|endoftext|>


<commit_before>var BOARD_SIZE = 12;
var SQUARE_SIZE = 48;

// state constants
var STATE_LOADING = 0;
var STATE_READY = 1;
var STATE_ANIMATING = 2;
var STATE_CLEARED = 3;
var STATE_FAILED = 4;

// key constants
var KEY_LEFT = 37;
var KEY_UP = 38;
var KEY_RIGHT = 39;
var KEY_DOWN = 40;

var state;

var step, stepLimit;

var level = 0;

function getLevelString(){
	return (Math.floor(level / 10) + 1) + '-' + (level % 10 + 1);
}

$(document).ready(function() {
	state = STATE_LOADING;
	$(document).keyup(keyPressed);
	$(".arrow").mousedown(arrowPressed);
	initialize();
	loadLevel(level);
});

var board;
var codeDivs;
var step, stepLimit;

function initialize() {
    // initialize board
	board = [];
	for (var i = 0; i < BOARD_SIZE; ++i)
	{
		board[i] = [];
	}

	// initialize code map
	codeDivs = [];
	$(".palette").each(function() {
		codeDivs[$(this).data('code')] = this;
	});
}

function loadLevel(name) {
	$.ajax({
		url : "levels/" + getLevelString() + ".txt",
		dataType: "text",
		success : function (data) {
			// read and parse level file
			data = data.replace(/\s/g, "");
			for (var i = 0; i < BOARD_SIZE * BOARD_SIZE; ++i) {
				board[Math.floor(i / BOARD_SIZE)][i % BOARD_SIZE] = data.charAt(i);
			}
			stepLimit = parseInt(data.slice(-2));
			step = stepLimit;

			// setup board
			$(".inBoard").remove();
			for (var i = 0; i < board.length; ++i) {
				for (var j = 0; j < board.length; ++j){
					if (typeof codeDivs[board[i][j]] !== 'undefined'){
						$(codeDivs[board[i][j]]).clone()
							.removeClass("palette").addClass("inBoard").addClass("r" + i + "c" + j)
							.offset({top: SQUARE_SIZE * i, left: SQUARE_SIZE * j}).appendTo("#board");
					}
				}
			}

			// setup info
			$("#level .content").html(getLevelString);
			$("#steps .content").html(step + "/" + stepLimit);
			$(".arrow").removeClass("lastDir");

			// ready
			state = STATE_READY;
		}
	});
}

function markMoved(dir) {
	$(".arrow").removeClass("lastDir");
	$("." + dir).addClass("lastDir");
}

function keyPressed(e) {
	if (state != STATE_READY) return;
	switch (e.which) {
		case KEY_UP:
			if ($(".up").hasClass("lastDir")) return;
			makeStep(-1, 0);
			markMoved("up");
			break;
		case KEY_DOWN:
			if ($(".down").hasClass("lastDir")) return;
			makeStep(1, 0);
			markMoved("down");
			break;
		case KEY_LEFT:
			if ($(".left").hasClass("lastDir")) return;
			makeStep(0, -1);
			markMoved("left");
			break;
		case KEY_RIGHT:
			if ($(".right").hasClass("lastDir")) return;
			makeStep(0, 1);
			markMoved("right");
			break;
	}
}

function arrowPressed(e) {
	if (state != STATE_READY) return;
	var $this = $(this);
	if ($this.hasClass("lastDir")) return;
	if ($this.hasClass("up")) {
		makeStep(-1, 0);
		markMoved("up");
	} else if ($this.hasClass("down")) {
		makeStep(1, 0);
		markMoved("down");
	} else if ($this.hasClass("left")) {
		makeStep(0, -1);
		markMoved("left");
	} else if ($this.hasClass("right")) {
		makeStep(0, 1);
		markMoved("right");
	}
}

function makeStep(dirX, dirY) {
	var steps = [];
	do {
		var moved = moveBlocks(dirX, dirY);
		steps.push(moved);
		var eliminated = eliminateBlocks();
		steps.push(eliminated);
	} while (eliminated.length > 0);
	animateBlocks(steps);
	--step;
	$("#steps .content").html(step + "/" + stepLimit);
}

function moveBlock(startR, startC, endR, endC) {
	var start = [startR, startC];
	var end = [endR, endC];

	if (startR != endR || startC != endC) {
		board[end[0]][end[1]] = board[start[0]][start[1]];
		board[start[0]][start[1]] = ".";
	}

	return {start: start, end: end};
}

function moveBlocks(dirR, dirC) {
	var changeSet = [];

	if (dirC < 0) {
		for (var i = 0; i < BOARD_SIZE; ++i) {
			for (var j = 0; j < BOARD_SIZE; ++j) {
				if ($.inArray(board[i][j], ['1', '2', '3', '4']) >= 0) {
					for (var k = j - 1; k >= 0; --k)
					{
						if ($.inArray(board[i][k], ['X', '1', '2', '3', '4']) >= 0) {
							var elem = moveBlock(i, j, i, k + 1);
							if (elem) {
								changeSet.push(elem);
							}
							break;
						}
					}
				}
			}
		}
	}

	if (dirC > 0) {
		for (var i = 0; i < BOARD_SIZE; ++i) {
			for (var j = BOARD_SIZE - 1; j > 0 ; --j) {
				if ($.inArray(board[i][j], ['1', '2', '3', '4']) >= 0) {
					for (var k = j + 1; k >= 0; ++k)
					{
						if ($.inArray(board[i][k], ['X', '1', '2', '3', '4']) >= 0) {
							var elem = moveBlock(i, j, i, k - 1);
							if (elem) {
								changeSet.push(elem);
							}
							break;
						}
					}
				}
			}
		}
	}

	if (dirR < 0) {
		for (var i = 0; i < BOARD_SIZE; ++i) {
			for (var j = 0; j < BOARD_SIZE; ++j) {
				if ($.inArray(board[j][i], ['1', '2', '3', '4']) >= 0) {
					for (var k = j - 1; k >= 0; --k)
					{
						if ($.inArray(board[k][i], ['X', '1', '2', '3', '4']) >= 0) {
							var elem = moveBlock(j, i, k + 1, i);
							if (elem) {
								changeSet.push(elem);
							}
							break;
						}
					}
				}
			}
		}
	}

	if (dirR > 0) {
		for (var i = 0; i < BOARD_SIZE; ++i) {
			for (var j = BOARD_SIZE - 1; j > 0 ; --j) {
				if ($.inArray(board[j][i], ['1', '2', '3', '4']) >= 0) {
					for (var k = j + 1; k >= 0; ++k)
					{
						if ($.inArray(board[k][i], ['X', '1', '2', '3', '4']) >= 0) {
							var elem = moveBlock(j, i, k - 1, i);
							if (elem) {
								changeSet.push(elem);
							}
							break;
						}
					}
				}
			}
		}
	}

	return changeSet;
}

function eliminateBlocks() {
	var eliminateSet = [];
	for (var i = 0; i < BOARD_SIZE; ++i){
		for (var j = 0; j < BOARD_SIZE; ++j) {
			if ($.inArray(board[i][j], ['1', '2', '3', '4']) >= 0) {
				var color = board[i][j];
				var visited = [];
				for (var k = 0; k < BOARD_SIZE; ++k)
				{
					visited[k] = [];
					for (var l = 0; l < BOARD_SIZE; ++l)
					{
						visited[k][l] = false;
					}
				}
				var eliminated = [];

				(function dfs(startR, startC){
					visited[startR][startC] = true;
					eliminated.push([startR, startC]);
					if (startR > 0 && !visited[startR - 1][startC] && board[startR - 1][startC] == color) {
						dfs(startR - 1, startC);
					}
					if (startR < BOARD_SIZE && !visited[startR + 1][startC] && board[startR + 1][startC] == color) {
						dfs(startR + 1, startC);
					}
					if (startC > 0 && !visited[startR][startC - 1] && board[startR][startC - 1] == color) {
						dfs(startR, startC - 1);
					}
					if (startC < BOARD_SIZE && !visited[startR][startC + 1] && board[startR][startC + 1] == color) {
						dfs(startR, startC + 1);
					}
				})(i, j);

				if (eliminated.length > 1) {
					for (var i in eliminated) {
						board[eliminated[i][0]][eliminated[i][1]] = ".";
						eliminateSet.push(eliminated[i]);
					}
				}
			}
		}
	}
	return eliminateSet;
}

var MOVING_SPEED = 100;
var ELIMINATE_SPEED = 400;
function animateBlocks(steps) {
	state = STATE_ANIMATING;

	var animationTime = 0;
	for (var i = 0; i < steps.length; i += 2) {
		// move
		var maxDistance = -1;
		for (var j in steps[i]) {
			var start = steps[i][j].start;
			var end = steps[i][j].end;
			var distance = Math.abs(start[0] - end[0]) + Math.abs(start[1] - end[1]);
			if (distance > maxDistance) {
				maxDistance = distance;
			}
		}

		for (var j in steps[i]) {
			var start = steps[i][j].start;
			var end = steps[i][j].end;
			var distance = Math.abs(start[0] - end[0]) + Math.abs(start[1] - end[1]);

			$(".r" + start[0] + "c" + start[1]).animate({top: SQUARE_SIZE * end[0], left: SQUARE_SIZE * end[1]}, distance * MOVING_SPEED, "linear")
				.removeClass("r" + start[0] + "c" + start[1]).addClass("r" + end[0] + "c" + end[1]).delay(maxDistance * MOVING_SPEED - distance * MOVING_SPEED);
		}
		animationTime += maxDistance * MOVING_SPEED;

		// eliminate
		for (var j in steps[i+1]) {
			$(".r" + steps[i+1][j][0] + "c" + steps[i+1][j][1]).fadeOut(ELIMINATE_SPEED, function(){$(this).remove();});
		}

		if (steps[i+1].length > 0){
			animationTime += ELIMINATE_SPEED;
			for (var j in steps[i]) {
				var end = steps[i][j].end;
				$(".r" + end[0] + "c" + end[1]).delay(ELIMINATE_SPEED);
			}
		}
	}

	setTimeout(function(){
		state = STATE_READY;
		checkComplete();
		checkFail();
	}, animationTime);
}

function checkComplete() {
	var completed = true;
	for (var i = 0; i < BOARD_SIZE; ++i){
		for (var j = 0; j < BOARD_SIZE; ++j) {
			if ($.inArray(board[i][j], ['1', '2', '3', '4']) >= 0) {
				completed = false;
			}
		}
	}
	if (completed) {
		$(".level-cleared .content").html("Steps remain: " + step);
		//$("#popup-layer").show();
		$(".level-cleared").show();
		state = STATE_CLEARED;
		$(".retry").one("click", function() {
			loadLevel(level);
			//$("#popup-layer").hide();
			$(".level-cleared").hide();
		});
		$(".next").one("click", function() {
			loadLevel(++level);
			//$("#popup-layer").hide();
			$(".level-cleared").hide();
		});
	}
}

function checkFail() {
	if (step <= 0 && state == STATE_READY) {
		//$("#popup-layer").show();
		$(".level-failed").show();
		state = STATE_FAILED;
		$(".retry").one("click", function() {
			loadLevel(level);
			//$("#popup-layer").hide();
			$(".level-failed").hide();
		});
	}
}<commit_msg>tweak animate function<commit_after>var BOARD_SIZE = 12;
var SQUARE_SIZE = 48;

// state constants
var STATE_LOADING = 0;
var STATE_READY = 1;
var STATE_ANIMATING = 2;
var STATE_CLEARED = 3;
var STATE_FAILED = 4;

// key constants
var KEY_LEFT = 37;
var KEY_UP = 38;
var KEY_RIGHT = 39;
var KEY_DOWN = 40;

var state;

var step, stepLimit;

var level = 0;

function getLevelString(){
	return (Math.floor(level / 10) + 1) + '-' + (level % 10 + 1);
}

$(document).ready(function() {
	state = STATE_LOADING;
	$(document).keyup(keyPressed);
	$(".arrow").mousedown(arrowPressed);
	initialize();
	loadLevel(level);
});

var board;
var codeDivs;
var step, stepLimit;

function initialize() {
    // initialize board
	board = [];
	for (var i = 0; i < BOARD_SIZE; ++i)
	{
		board[i] = [];
	}

	// initialize code map
	codeDivs = [];
	$(".palette").each(function() {
		codeDivs[$(this).data('code')] = this;
	});
}

function loadLevel(name) {
	$.ajax({
		url : "levels/" + getLevelString() + ".txt",
		dataType: "text",
		success : function (data) {
			// read and parse level file
			data = data.replace(/\s/g, "");
			for (var i = 0; i < BOARD_SIZE * BOARD_SIZE; ++i) {
				board[Math.floor(i / BOARD_SIZE)][i % BOARD_SIZE] = data.charAt(i);
			}
			stepLimit = parseInt(data.slice(-2));
			step = stepLimit;

			// setup board
			$(".inBoard").remove();
			for (var i = 0; i < board.length; ++i) {
				for (var j = 0; j < board.length; ++j){
					if (typeof codeDivs[board[i][j]] !== 'undefined'){
						$(codeDivs[board[i][j]]).clone()
							.removeClass("palette").addClass("inBoard").addClass("r" + i + "c" + j)
							.offset({top: SQUARE_SIZE * i, left: SQUARE_SIZE * j}).appendTo("#board");
					}
				}
			}

			// setup info
			$("#level .content").html(getLevelString);
			$("#steps .content").html(step + "/" + stepLimit);
			$(".arrow").removeClass("lastDir");

			// ready
			state = STATE_READY;
		}
	});
}

function markMoved(dir) {
	$(".arrow").removeClass("lastDir");
	$("." + dir).addClass("lastDir");
}

function keyPressed(e) {
	if (state != STATE_READY) return;
	switch (e.which) {
		case KEY_UP:
			if ($(".up").hasClass("lastDir")) return;
			makeStep(-1, 0);
			markMoved("up");
			break;
		case KEY_DOWN:
			if ($(".down").hasClass("lastDir")) return;
			makeStep(1, 0);
			markMoved("down");
			break;
		case KEY_LEFT:
			if ($(".left").hasClass("lastDir")) return;
			makeStep(0, -1);
			markMoved("left");
			break;
		case KEY_RIGHT:
			if ($(".right").hasClass("lastDir")) return;
			makeStep(0, 1);
			markMoved("right");
			break;
	}
}

function arrowPressed(e) {
	if (state != STATE_READY) return;
	var $this = $(this);
	if ($this.hasClass("lastDir")) return;
	if ($this.hasClass("up")) {
		makeStep(-1, 0);
		markMoved("up");
	} else if ($this.hasClass("down")) {
		makeStep(1, 0);
		markMoved("down");
	} else if ($this.hasClass("left")) {
		makeStep(0, -1);
		markMoved("left");
	} else if ($this.hasClass("right")) {
		makeStep(0, 1);
		markMoved("right");
	}
}

function makeStep(dirX, dirY) {
	var steps = [];
	do {
		var moved = moveBlocks(dirX, dirY);
		steps.push(moved);
		var eliminated = eliminateBlocks();
		steps.push(eliminated);
	} while (eliminated.length > 0);
	--step;
	$("#steps .content").html(step + "/" + stepLimit);
	animateBlocks(steps, function(){
		state = STATE_READY;
		checkComplete();
		checkFail();
	});
}

function moveBlock(startR, startC, endR, endC) {
	var start = [startR, startC];
	var end = [endR, endC];

	if (startR != endR || startC != endC) {
		board[end[0]][end[1]] = board[start[0]][start[1]];
		board[start[0]][start[1]] = ".";
	}

	return {start: start, end: end};
}

function moveBlocks(dirR, dirC) {
	var changeSet = [];

	if (dirC < 0) {
		for (var i = 0; i < BOARD_SIZE; ++i) {
			for (var j = 0; j < BOARD_SIZE; ++j) {
				if ($.inArray(board[i][j], ['1', '2', '3', '4']) >= 0) {
					for (var k = j - 1; k >= 0; --k)
					{
						if ($.inArray(board[i][k], ['X', '1', '2', '3', '4']) >= 0) {
							var elem = moveBlock(i, j, i, k + 1);
							if (elem) {
								changeSet.push(elem);
							}
							break;
						}
					}
				}
			}
		}
	}

	if (dirC > 0) {
		for (var i = 0; i < BOARD_SIZE; ++i) {
			for (var j = BOARD_SIZE - 1; j > 0 ; --j) {
				if ($.inArray(board[i][j], ['1', '2', '3', '4']) >= 0) {
					for (var k = j + 1; k >= 0; ++k)
					{
						if ($.inArray(board[i][k], ['X', '1', '2', '3', '4']) >= 0) {
							var elem = moveBlock(i, j, i, k - 1);
							if (elem) {
								changeSet.push(elem);
							}
							break;
						}
					}
				}
			}
		}
	}

	if (dirR < 0) {
		for (var i = 0; i < BOARD_SIZE; ++i) {
			for (var j = 0; j < BOARD_SIZE; ++j) {
				if ($.inArray(board[j][i], ['1', '2', '3', '4']) >= 0) {
					for (var k = j - 1; k >= 0; --k)
					{
						if ($.inArray(board[k][i], ['X', '1', '2', '3', '4']) >= 0) {
							var elem = moveBlock(j, i, k + 1, i);
							if (elem) {
								changeSet.push(elem);
							}
							break;
						}
					}
				}
			}
		}
	}

	if (dirR > 0) {
		for (var i = 0; i < BOARD_SIZE; ++i) {
			for (var j = BOARD_SIZE - 1; j > 0 ; --j) {
				if ($.inArray(board[j][i], ['1', '2', '3', '4']) >= 0) {
					for (var k = j + 1; k >= 0; ++k)
					{
						if ($.inArray(board[k][i], ['X', '1', '2', '3', '4']) >= 0) {
							var elem = moveBlock(j, i, k - 1, i);
							if (elem) {
								changeSet.push(elem);
							}
							break;
						}
					}
				}
			}
		}
	}

	return changeSet;
}

function eliminateBlocks() {
	var eliminateSet = [];
	for (var i = 0; i < BOARD_SIZE; ++i){
		for (var j = 0; j < BOARD_SIZE; ++j) {
			if ($.inArray(board[i][j], ['1', '2', '3', '4']) >= 0) {
				var color = board[i][j];
				var visited = [];
				for (var k = 0; k < BOARD_SIZE; ++k)
				{
					visited[k] = [];
					for (var l = 0; l < BOARD_SIZE; ++l)
					{
						visited[k][l] = false;
					}
				}
				var eliminated = [];

				(function dfs(startR, startC){
					visited[startR][startC] = true;
					eliminated.push([startR, startC]);
					if (startR > 0 && !visited[startR - 1][startC] && board[startR - 1][startC] == color) {
						dfs(startR - 1, startC);
					}
					if (startR < BOARD_SIZE && !visited[startR + 1][startC] && board[startR + 1][startC] == color) {
						dfs(startR + 1, startC);
					}
					if (startC > 0 && !visited[startR][startC - 1] && board[startR][startC - 1] == color) {
						dfs(startR, startC - 1);
					}
					if (startC < BOARD_SIZE && !visited[startR][startC + 1] && board[startR][startC + 1] == color) {
						dfs(startR, startC + 1);
					}
				})(i, j);

				if (eliminated.length > 1) {
					for (var i in eliminated) {
						board[eliminated[i][0]][eliminated[i][1]] = ".";
						eliminateSet.push(eliminated[i]);
					}
				}
			}
		}
	}
	return eliminateSet;
}

var MOVING_SPEED = 100;
var ELIMINATE_SPEED = 400;
function animateBlocks(steps, callback) {
	state = STATE_ANIMATING;

	var animationTime = 0;
	for (var i = 0; i < steps.length; i += 2) {
		// move
		var maxDistance = -1;
		for (var j in steps[i]) {
			var start = steps[i][j].start;
			var end = steps[i][j].end;
			var distance = Math.abs(start[0] - end[0]) + Math.abs(start[1] - end[1]);
			if (distance > maxDistance) {
				maxDistance = distance;
			}
		}

		for (var j in steps[i]) {
			var start = steps[i][j].start;
			var end = steps[i][j].end;
			var distance = Math.abs(start[0] - end[0]) + Math.abs(start[1] - end[1]);

			$(".r" + start[0] + "c" + start[1]).animate({top: SQUARE_SIZE * end[0], left: SQUARE_SIZE * end[1]}, distance * MOVING_SPEED, "linear")
				.removeClass("r" + start[0] + "c" + start[1]).addClass("r" + end[0] + "c" + end[1]).delay(maxDistance * MOVING_SPEED - distance * MOVING_SPEED);
		}
		animationTime += maxDistance * MOVING_SPEED;

		// eliminate
		for (var j in steps[i+1]) {
			$(".r" + steps[i+1][j][0] + "c" + steps[i+1][j][1]).fadeOut(ELIMINATE_SPEED, function(){$(this).remove();});
		}

		if (steps[i+1].length > 0){
			animationTime += ELIMINATE_SPEED;
			for (var j in steps[i]) {
				var end = steps[i][j].end;
				$(".r" + end[0] + "c" + end[1]).delay(ELIMINATE_SPEED);
			}
		}
	}

	setTimeout(callback, animationTime);
}

function checkComplete() {
	var completed = true;
	for (var i = 0; i < BOARD_SIZE; ++i){
		for (var j = 0; j < BOARD_SIZE; ++j) {
			if ($.inArray(board[i][j], ['1', '2', '3', '4']) >= 0) {
				completed = false;
			}
		}
	}
	if (completed) {
		$(".level-cleared .content").html("Steps remain: " + step);
		//$("#popup-layer").show();
		$(".level-cleared").show();
		state = STATE_CLEARED;
		$(".retry").one("click", function() {
			loadLevel(level);
			//$("#popup-layer").hide();
			$(".level-cleared").hide();
		});
		$(".next").one("click", function() {
			loadLevel(++level);
			//$("#popup-layer").hide();
			$(".level-cleared").hide();
		});
	}
}

function checkFail() {
	if (step <= 0 && state == STATE_READY) {
		//$("#popup-layer").show();
		$(".level-failed").show();
		state = STATE_FAILED;
		$(".retry").one("click", function() {
			loadLevel(level);
			//$("#popup-layer").hide();
			$(".level-failed").hide();
		});
	}
}<|endoftext|>


<commit_before>import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import {
    Router,
    Route,
    Link,
    IndexRoute,
    hashHistory,
    browserHistory
} from 'react-router';
import Dashboard from './Dashboard/Dashboard';
import CaptureReportTemplate from './CaptureReportTemplate/CaptureReportTemplate';
import DashboardIndex from './Dashboard/DashBoardIndex';
import MaintainBusinessRules from './MaintainBusinessRules/MaintainBusinessRules';
import AddBusinessRule from './MaintainBusinessRules/AddBusinessRule/AddBusinessRule';
import custom from '../../js/custom';
import RegOpzDataGrid from './RegOpzDataGrid/RegOpzDataGrid';
import ViewDataComponentV2 from './ViewData/ViewDataComponentV2';
import ViewDataComponent from './ViewData/ViewDataComponent';
import ViewReport from './ViewReport/ViewReport';
import DrillDown from './DrillDown/DrillDown';
import MaintainReportRules from './MaintainReportRules/MaintainReportRules';
import AddReportRules from './MaintainReportRules/AddReportRules/AddReportRules';
import AddReportAggRules from './MaintainReportRules/AddReportAggRules';
import MaintainSources from './MaintainSources/MaintainSources';
import AddSources from './MaintainSources/AddSources/AddSources';
import VarianceAnalysisForm from './VarianceAnalysis/VarianceAnalysis';
import VarianceAnalysisGrid from './VarianceAnalysis/VarianceAnalysisGrid';
import VarianceAnalysisChart from './VarianceAnalysis/VarianceAnalysisChart';
import CreateReport from './CreateReport/CreateReport';
import ManageDefChange from './ManageDefChange/ManageDefChange';
import ManageRoles from './ManageRoles/ManageRoles';
import AddRoles from './ManageRoles/AddRoles/AddRoles';
import ManageUsers from './ManageUsers/ManageUsers';

class HomeIndex extends Component {
    render() {
        return (
            <Router history={hashHistory}>
                <Route path="dashboard" component={Dashboard} >
                    <IndexRoute component={DashboardIndex} />
                    <Route path="capture-report-template" component={CaptureReportTemplate} />
                    <Route path="data-grid" component={RegOpzDataGrid} />
                    <Route path="maintain-business-rules" component={MaintainBusinessRules} />
                    <Route path="maintain-business-rules/add-business-rule" component={AddBusinessRule} />
                    <Route path="view-data" component={ViewDataComponentV2} />
                    <Route path="view-data-on-grid" component={ViewDataComponent} />
                    <Route path="view-report" component={ViewReport} />
                    <Route path="create-report" component={CreateReport} />
                    <Route path="drill-down" component={DrillDown} />
                    <Route path="maintain-report-rules" component={MaintainReportRules} />
                    <Route path="maintain-report-rules/add-report-rules" component={AddReportRules} />
                    <Route path="maintain-report-rules/add-report-agg-rules" component={AddReportAggRules} />
                    <Route path="maintain-sources" component={MaintainSources} />
                    <Route path="maintain-sources/add-sources" component={AddSources} />
                    <Route path="variance-analysis" component={VarianceAnalysisForm} />
                    <Route path="variance-analysis/variance-data-grid" component={VarianceAnalysisGrid} />
                    <Route path="variance-analysis/variance-chart" component={VarianceAnalysisChart}/>
                    <Route path="workflow/manage-def-change" component={ManageDefChange} />
                    <Route path="manage-roles" component={ManageRoles}/>
                    <Route path="manage-roles/add-roles" component={AddRoles}/>
                    <Route path="manage-users" component={ManageUsers}/>
                </Route>
            </Router>
        );
    }
}

export default HomeIndex;

/*
<Route path="/dashboard" name="Dashboard" component={Dashboard} >
                    <IndexRoute component={DashboardIndex} />
                    <Route path="capture-report-template" name="Capture Report Template" component={CaptureReportTemplate} />
                    <Route path="maintain-business-rules" name="Maintain Business Rules" component={MaintainBusinessRules} />
                    <Route path="data-grid" name="Data Grid" component={RegOpzDataGrid} />
                    <Route path="view-data-on-grid" name="View Data Grid" component={ViewDataComponent} />
                    <Route path="view-data" name="View Data">
                      <IndexRoute component={ViewDataComponentV2} />
                      <Route path="view-data-on-grid" name="View Data Grid" component={ViewDataComponent} />
                    </Route>
                    <Route path="view-report" name="View Report">
                      <IndexRoute component={ViewReport} />
                      <Route path="data-grid" component={RegOpzDataGrid} />
                    </Route>
                    <Route path="create-report" name="Create Report" component={CreateReport} />
                    <Route path="drill-down" name="DrillDown" component={DrillDown} />
                    <Route path="maintain-report-rules" name="Maintain Report Rules" component={MaintainReportRules} />
                    <Route path="maintain-report-rules/add-report-rules" name="Add Report Rules" component={AddReportRules} />
                    <Route path="maintain-sources" name="Maintain Sources" component={MaintainSources} />
                    <Route path="maintain-sources/add-sources" name="Add Sources" component={AddSources} />
                    <Route path="variance-analysis" name="Variance Analysis" component={VarianceAnalysisForm} />
                    <Route path="variance-analysis/variance-data-grid" name="Variance Analysis Grid" component={VarianceAnalysisGrid} />
                    <Route path="variance-analysis/variance-chart" name="Variance Analysis Chart" component={VarianceAnalysisChart}/>
                </Route>
*/
<commit_msg>Removed Home.js file<commit_after><|endoftext|>


<commit_before>import React from 'react';
import { Link } from 'react-router';
import CircularProgressbar from 'react-circular-progressbar';
import userSettings from '../containers/userSettings';
import helpers from './helpers'

class Home extends React.Component {
  constructor() {
    super();
    this.state = {
      events: helpers,
      pushEvents: null,
    }
}

goToRepos() {
  this.context.router.push('/repos');
}

grabUserInfo() {
  fetch(`https://api.github.com/users/bcgodfrey91/events?page=0&callback`, {
    method: 'GET'
  })
  .then((res) => {return res.json(); })
  .then((response) => { this.setState({events: response}) })
  .catch(() => { alert('Please try again.')})
}

getPushEvent() {
  const { events } = this.state
  const pushEv = events.filter((ghEvent) => ghEvent.type==='PushEvent')
  this.setState({ pushEvents: pushEv})
}

getOpenedPullRequests() {
  const { events } = this.state
  const pullReq = events.filter((ghEvent) => ghEvent.type==='PullRequestEvent')
  const openedPullRequests = pullReq.filter((obj) => obj.payload.action==='opened')
  return openedPullRequests.length
}

getCommits() {
  const { pushEvents } = this.state
  const commitLengths = pushEvents.map((obj) => obj.payload.commits.length)
  const reducedCommits = commitLengths.reduce((a, b) => a + b, 0)
  return reducedCommits
}

  render(){
    return(

Mod 1 Repost:

22

Mod 1 Commits:

134

You VS Last Mod:

            <CircularProgressbar
              percentage={60}
              strokeWidth={20} />

14

Followers

            <button
            onClick={() => this.getPushEvent()}
            >fetch</button>
            <button
            onClick={() => console.log(this.state.pushEvents) }
            >log</button>
            <button
            onClick={() => this.getIssuesClosed() }
            >commits</button>

        <Link to='/repos'
          className='back back-right'>

        </Link>

    );
  }
};

export default userSettings(Home);
<commit_msg>Get issues opened<commit_after>import React from 'react';
import { Link } from 'react-router';
import CircularProgressbar from 'react-circular-progressbar';
import userSettings from '../containers/userSettings';
import helpers from './helpers'

class Home extends React.Component {
  constructor() {
    super();
    this.state = {
      events: helpers,
      pushEvents: null,
    }
}

goToRepos() {
  this.context.router.push('/repos');
}

grabUserInfo() {
  fetch(`https://api.github.com/users/bcgodfrey91/events?page=0&callback`, {
    method: 'GET'
  })
  .then((res) => {return res.json(); })
  .then((response) => { this.setState({events: response}) })
  .catch(() => { alert('Please try again.')})
}

getPushEvent() {
  const { events } = this.state
  const pushEv = events.filter((ghEvent) => ghEvent.type==='PushEvent')
  this.setState({ pushEvents: pushEv})
}

getOpenedPullRequests() {
  const { events } = this.state
  const pullReq = events.filter((ghEvent) => ghEvent.type==='PullRequestEvent')
  const openedPullRequests = pullReq.filter((obj) => obj.payload.action==='opened')
  return openedPullRequests.length
}

getIssuesCreated() {
  const { events } = this.state
  const issues = events.filter((ghEvent) => ghEvent.type==='IssuesEvent')
  const openedIssues = issues.filter((obj) => obj.payload.action==='opened')
  return openedIssues.length
}

getCommits() {
  const { pushEvents } = this.state
  const commitLengths = pushEvents.map((obj) => obj.payload.commits.length)
  const reducedCommits = commitLengths.reduce((a, b) => a + b, 0)
  return reducedCommits
}

  render(){
    return(

Mod 1 Repost:

22

Mod 1 Commits:

134

You VS Last Mod:

            <CircularProgressbar
              percentage={60}
              strokeWidth={20} />

14

Followers

            <button
            onClick={() => this.getPushEvent()}
            >fetch</button>
            <button
            onClick={() => console.log(this.state.pushEvents) }
            >log</button>
            <button
            onClick={() => this.getIssuesClosed() }
            >commits</button>

        <Link to='/repos'
          className='back back-right'>

        </Link>

    );
  }
};

export default userSettings(Home);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';

import styles from '../utils/styles';

class Item extends Component {
  static propTypes = {
    children: PropTypes.node.isRequired,
    className: PropTypes.string,
    style: PropTypes.object,
    nativeEvent: PropTypes.object,
    propsFromTrigger: PropTypes.object,
    disabled: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
    onClick: PropTypes.func
  };

  static defaultProps = {
    className: null,
    style: {},
    disabled: false,
    onClick: () => {},
    nativeEvent: {},
    propsFromTrigger: {}
  };

  disabled = false;

  handleClick = e => {
    this.disabled
      ? e.stopPropagation()
      : this.props.onClick({
          event: this.props.nativeEvent,
          props: this.props.propsFromTrigger
        });
  };

  render() {
    const {
      className,
      disabled,
      style,
      children,
      nativeEvent,
      propsFromTrigger
    } = this.props;

    this.disabled =
      typeof disabled === 'function'
        ? disabled({
            event: nativeEvent,
            props: propsFromTrigger,
          })
        : disabled;

    const cssClasses = cx(styles.item, className, {
      [`${styles.itemDisabled}`]: this.disabled
    });

    return (

{children}

    );
  }
}

export default Item;
<commit_msg>Update Item component<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';

import styles from '../utils/styles';

class Item extends Component {
  static propTypes = {
    children: PropTypes.node.isRequired,
    className: PropTypes.string,
    style: PropTypes.object,
    nativeEvent: PropTypes.object,
    propsFromTrigger: PropTypes.object,
    disable: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
    onClick: PropTypes.func,
    data: PropTypes.object
  };

  static defaultProps = {
    className: null,
    style: {},
    disable: false,
    onClick: () => {},
    nativeEvent: {},
    propsFromTrigger: {},
    data: {}
  };

  isDisabled = false;

  handleClick = e => {
    this.isDisabled
      ? e.stopPropagation()
      : this.props.onClick({
          event: this.props.nativeEvent,
          props: { ...this.props.propsFromTrigger, ...this.props.data }
        });
  };

  render() {
    const {
      className,
      disable,
      style,
      children,
      nativeEvent,
      propsFromTrigger,
      data
    } = this.props;

    this.isDisabled =
      typeof disable === 'function'
        ? disable({
            event: nativeEvent,
            props: { ...propsFromTrigger, ...data }
          })
        : disable;

    const cssClasses = cx(styles.item, className, {
      [`${styles.itemDisabled}`]: this.isDisabled
    });

    return (

{children}

    );
  }
}

export default Item;
<|endoftext|>