<commit_before>/**
 * Backbone-Nested 1.1.2 - An extension of Backbone.js that keeps track of nested attributes
 *
 * http://afeld.github.com/backbone-nested/
 *
 * Copyright (c) 2011-2012 Aidan Feldman
 * MIT Licensed (LICENSE)
 */
/*global $, _, Backbone */
(function(){
  'use strict';

  var _delayedTriggers = [];

  Backbone.NestedModel = Backbone.Model.extend({

    get: function(attrStrOrPath){
      var attrPath = Backbone.NestedModel.attrPath(attrStrOrPath),
        result;

      Backbone.NestedModel.walkPath(this.attributes, attrPath, function(val, path){
        var attr = _.last(path);
        if (path.length === attrPath.length){
          // attribute found
          result = val[attr];
        }
      });

      return result;
    },

    has: function(attr){
      // for some reason this is not how Backbone.Model is implemented - it accesses the attributes object directly
      var result = this.get(attr);
      return !(result === null || _.isUndefined(result));
    },

    set: function(key, value, opts){
      var newAttrs = Backbone.NestedModel.deepClone(this.attributes),
        attrPath;

      if (_.isString(key)){
        // Backbone 0.9.0+ syntax: `model.set(key, val)` - convert the key to an attribute path
        attrPath = Backbone.NestedModel.attrPath(key);
      } else if (_.isArray(key)){
        // attribute path
        attrPath = key;
      }

      if (attrPath){
        opts = opts || {};
        this._setAttr(newAttrs, attrPath, value, opts);
      } else { // it's an Object
        opts = value || {};
        var attrs = key;
        for (var _attrStr in attrs) {
          if (attrs.hasOwnProperty(_attrStr)) {
            this._setAttr(newAttrs,
                          Backbone.NestedModel.attrPath(_attrStr),
                          opts.unset ? null : attrs[_attrStr],
                          opts);
          }
        }
      }

      if (!this._validate(newAttrs, opts)){
        // reset changed attributes
        this.changed = {};
        return false;
      }

      if (opts.unset && attrPath && attrPath.length === 1){ // assume it is a singular attribute being unset
        // unsetting top-level attribute
        var unsetObj = {};
        unsetObj[key] = null;
        Backbone.NestedModel.__super__.set.call(this, unsetObj, opts);
      } else {
        // normal set(), or an unset of nested attribute
        if (opts.unset && attrPath){
          // make sure Backbone.Model won't unset the top-level attribute
          opts = _.extend({}, opts);
          delete opts.unset;
        }
        Backbone.NestedModel.__super__.set.call(this, newAttrs, opts);
      }

      this._runDelayedTriggers();
      return this;
    },

    clear: function(options) {
      // Mostly taken from Backbone.Model.set, modified to work for NestedModel.
      options = options || {};
      if (!options.silent && this.validate && !this.validate({}, options)) {
        return false; // Should maybe return this instead?
      }

      var changed = this.changed = {};
      var model = this;

      var setChanged = function(obj, prefix, options) {
        // obj will be an Array or an Object
        _.each(obj, function(val, attr){
          var changedPath = prefix;
          if (_.isArray(obj)){
            // assume there is a prefix
            changedPath += '[' + attr + ']';
          } else if (prefix){
            changedPath += '.' + attr;
          } else {
            changedPath = attr;
          }

          val = obj[attr];
          if (_.isObject(val)) { // clear child attrs
            setChanged(val, changedPath, options);
          }
          if (!options.silent) model._delayedChange(changedPath, null, options);
          changed[changedPath] = null;
        });
      };
      setChanged(this.attributes, '', options);

      this.attributes = {};

      // Fire the `"change"` events.
      if (!options.silent) this._delayedTrigger('change');

      this._runDelayedTriggers();
      return this;
    },

    add: function(attrStr, value, opts){
      var current = this.get(attrStr);
      if (!_.isArray(current)) throw new Error('current value is not an array');
      return this.set(attrStr + '[' + current.length + ']', value, opts);
    },

    remove: function(attrStr, opts){
      opts = opts || {};

      var attrPath = Backbone.NestedModel.attrPath(attrStr),
        aryPath = _.initial(attrPath),
        val = this.get(aryPath),
        i = _.last(attrPath);

      if (!_.isArray(val)){
        throw new Error("remove() must be called on a nested array");
      }

      // only trigger if an element is actually being removed
      var trigger = !opts.silent && (val.length >= i + 1),
        oldEl = val[i];

      // remove the element from the array
      val.splice(i, 1);
      opts.silent = true; // Triggers should only be fired in trigger section below
      this.set(aryPath, val, opts);

      if (trigger){
        attrStr = Backbone.NestedModel.createAttrStr(aryPath);
        this.trigger('remove:' + attrStr, this, oldEl);
        for (var aryCount = aryPath.length; aryCount >= 1; aryCount--) {
          attrStr = Backbone.NestedModel.createAttrStr(_.first(aryPath, aryCount));
          this.trigger('change:' + attrStr, this, oldEl);
        }
        this.trigger('change', this, oldEl);
      }

      return this;
    },

    toJSON: function(){
      return Backbone.NestedModel.deepClone(this.attributes);
    },

    // private
    _delayedTrigger: function(/* the trigger args */){
      _delayedTriggers.push(arguments);
    },

    _delayedChange: function(attrStr, newVal, options){
      this._delayedTrigger('change:' + attrStr, this, newVal, options);

      // Check if `change` even *exists*, as it won't when the model is
      // freshly created.
      if (!this.changed) {
        this.changed = {};
      }

      this.changed[attrStr] = newVal;
    },

    _runDelayedTriggers: function(){
      while (_delayedTriggers.length > 0){
        this.trigger.apply(this, _delayedTriggers.shift());
      }
    },

    // note: modifies `newAttrs`
    _setAttr: function(newAttrs, attrPath, newValue, opts){
      opts = opts || {};

      var fullPathLength = attrPath.length;
      var model = this;

      Backbone.NestedModel.walkPath(newAttrs, attrPath, function(val, path){
        var attr = _.last(path);
        var attrStr = Backbone.NestedModel.createAttrStr(path);

        // See if this is a new value being set
        var isNewValue = !_.isEqual(val[attr], newValue);

        if (path.length === fullPathLength){
          // reached the attribute to be set

          if (opts.unset){
            // unset the value
            delete val[attr];
          } else {
            // Set the new value
            val[attr] = newValue;
          }

          // Trigger Change Event if new values are being set
          if (!opts.silent && _.isObject(newValue) && isNewValue){
            var visited = [];
            var checkChanges = function(obj, prefix) {
              // Don't choke on circular references
              if(_.indexOf(visited, obj) > -1) {
                return;
              } else {
                visited.push(obj);
              }

              var nestedAttr, nestedVal;
              for (var a in obj){
                if (obj.hasOwnProperty(a)) {
                  nestedAttr = prefix + '.' + a;
                  nestedVal = obj[a];
                  if (!_.isEqual(model.get(nestedAttr), nestedVal)) {
                    model._delayedChange(nestedAttr, nestedVal, opts);
                  }
                  if (_.isObject(nestedVal)) {
                    checkChanges(nestedVal, nestedAttr);
                  }
                }
              }
            };
            checkChanges(newValue, attrStr);

          }

          // Trigger Remove Event if array being set to null
          if (newValue === null){
            var parentPath = Backbone.NestedModel.createAttrStr(_.initial(attrPath));
            model._delayedTrigger('remove:' + parentPath, model, val[attr]);
          }

        } else if (!val[attr]){
          if (_.isNumber(attr)){
            val[attr] = [];
          } else {
            val[attr] = {};
          }
        }

        if (!opts.silent){
          // let the superclass handle change events for top-level attributes
          if (path.length > 1 && isNewValue){
            model._delayedChange(attrStr, val[attr], opts);
          }

          if (_.isArray(val[attr])){
            model._delayedTrigger('add:' + attrStr, model, val[attr]);
          }
        }
      });
    }

  }, {
    // class methods

    attrPath: function(attrStrOrPath){
      var path;

      if (_.isString(attrStrOrPath)){
        // TODO this parsing can probably be more efficient
        path = (attrStrOrPath === '') ? [''] : attrStrOrPath.match(/[^\.\[\]]+/g);
        path = _.map(path, function(val){
          // convert array accessors to numbers
          return val.match(/^\d+$/) ? parseInt(val, 10) : val;
        });
      } else {
        path = attrStrOrPath;
      }

      return path;
    },

    createAttrStr: function(attrPath){
      var attrStr = attrPath[0];
      _.each(_.rest(attrPath), function(attr){
        attrStr += _.isNumber(attr) ? ('[' + attr + ']') : ('.' + attr);
      });

      return attrStr;
    },

    deepClone: function(obj){
      return $.extend(true, {}, obj);
    },

    walkPath: function(obj, attrPath, callback, scope){
      var val = obj,
        childAttr;

      // walk through the child attributes
      for (var i = 0; i < attrPath.length; i++){
        callback.call(scope || this, val, attrPath.slice(0, i + 1));

        childAttr = attrPath[i];
        val = val[childAttr];
        if (!val) break; // at the leaf
      }
    }

  });

}());
<commit_msg>When unsetting an array item, fire remove event.<commit_after>/**
 * Backbone-Nested 1.1.2 - An extension of Backbone.js that keeps track of nested attributes
 *
 * http://afeld.github.com/backbone-nested/
 *
 * Copyright (c) 2011-2012 Aidan Feldman
 * MIT Licensed (LICENSE)
 */
/*global $, _, Backbone */
(function(){
  'use strict';

  var _delayedTriggers = [];

  Backbone.NestedModel = Backbone.Model.extend({

    get: function(attrStrOrPath){
      var attrPath = Backbone.NestedModel.attrPath(attrStrOrPath),
        result;

      Backbone.NestedModel.walkPath(this.attributes, attrPath, function(val, path){
        var attr = _.last(path);
        if (path.length === attrPath.length){
          // attribute found
          result = val[attr];
        }
      });

      return result;
    },

    has: function(attr){
      // for some reason this is not how Backbone.Model is implemented - it accesses the attributes object directly
      var result = this.get(attr);
      return !(result === null || _.isUndefined(result));
    },

    set: function(key, value, opts){
      var newAttrs = Backbone.NestedModel.deepClone(this.attributes),
        attrPath;

      if (_.isString(key)){
        // Backbone 0.9.0+ syntax: `model.set(key, val)` - convert the key to an attribute path
        attrPath = Backbone.NestedModel.attrPath(key);
      } else if (_.isArray(key)){
        // attribute path
        attrPath = key;
      }

      if (attrPath){
        opts = opts || {};
        this._setAttr(newAttrs, attrPath, value, opts);
      } else { // it's an Object
        opts = value || {};
        var attrs = key;
        for (var _attrStr in attrs) {
          if (attrs.hasOwnProperty(_attrStr)) {
            this._setAttr(newAttrs,
                          Backbone.NestedModel.attrPath(_attrStr),
                          opts.unset ? null : attrs[_attrStr],
                          opts);
          }
        }
      }

      if (!this._validate(newAttrs, opts)){
        // reset changed attributes
        this.changed = {};
        return false;
      }

      if (opts.unset && attrPath && attrPath.length === 1){ // assume it is a singular attribute being unset
        // unsetting top-level attribute
        var unsetObj = {};
        unsetObj[key] = null;
        Backbone.NestedModel.__super__.set.call(this, unsetObj, opts);
      } else {
        // normal set(), or an unset of nested attribute
        if (opts.unset && attrPath){
          // make sure Backbone.Model won't unset the top-level attribute
          opts = _.extend({}, opts);
          delete opts.unset;
        }
        Backbone.NestedModel.__super__.set.call(this, newAttrs, opts);
      }

      this._runDelayedTriggers();
      return this;
    },

    clear: function(options) {
      // Mostly taken from Backbone.Model.set, modified to work for NestedModel.
      options = options || {};
      if (!options.silent && this.validate && !this.validate({}, options)) {
        return false; // Should maybe return this instead?
      }

      var changed = this.changed = {};
      var model = this;

      var setChanged = function(obj, prefix, options) {
        // obj will be an Array or an Object
        _.each(obj, function(val, attr){
          var changedPath = prefix;
          if (_.isArray(obj)){
            // assume there is a prefix
            changedPath += '[' + attr + ']';
          } else if (prefix){
            changedPath += '.' + attr;
          } else {
            changedPath = attr;
          }

          val = obj[attr];
          if (_.isObject(val)) { // clear child attrs
            setChanged(val, changedPath, options);
          }
          if (!options.silent) model._delayedChange(changedPath, null, options);
          changed[changedPath] = null;
        });
      };
      setChanged(this.attributes, '', options);

      this.attributes = {};

      // Fire the `"change"` events.
      if (!options.silent) this._delayedTrigger('change');

      this._runDelayedTriggers();
      return this;
    },

    add: function(attrStr, value, opts){
      var current = this.get(attrStr);
      if (!_.isArray(current)) throw new Error('current value is not an array');
      return this.set(attrStr + '[' + current.length + ']', value, opts);
    },

    remove: function(attrStr, opts){
      opts = opts || {};

      var attrPath = Backbone.NestedModel.attrPath(attrStr),
        aryPath = _.initial(attrPath),
        val = this.get(aryPath),
        i = _.last(attrPath);

      if (!_.isArray(val)){
        throw new Error("remove() must be called on a nested array");
      }

      // only trigger if an element is actually being removed
      var trigger = !opts.silent && (val.length >= i + 1),
        oldEl = val[i];

      // remove the element from the array
      val.splice(i, 1);
      opts.silent = true; // Triggers should only be fired in trigger section below
      this.set(aryPath, val, opts);

      if (trigger){
        attrStr = Backbone.NestedModel.createAttrStr(aryPath);
        this.trigger('remove:' + attrStr, this, oldEl);
        for (var aryCount = aryPath.length; aryCount >= 1; aryCount--) {
          attrStr = Backbone.NestedModel.createAttrStr(_.first(aryPath, aryCount));
          this.trigger('change:' + attrStr, this, oldEl);
        }
        this.trigger('change', this, oldEl);
      }

      return this;
    },

    toJSON: function(){
      return Backbone.NestedModel.deepClone(this.attributes);
    },

    // private
    _delayedTrigger: function(/* the trigger args */){
      _delayedTriggers.push(arguments);
    },

    _delayedChange: function(attrStr, newVal, options){
      this._delayedTrigger('change:' + attrStr, this, newVal, options);

      // Check if `change` even *exists*, as it won't when the model is
      // freshly created.
      if (!this.changed) {
        this.changed = {};
      }

      this.changed[attrStr] = newVal;
    },

    _runDelayedTriggers: function(){
      while (_delayedTriggers.length > 0){
        this.trigger.apply(this, _delayedTriggers.shift());
      }
    },

    // note: modifies `newAttrs`
    _setAttr: function(newAttrs, attrPath, newValue, opts){
      opts = opts || {};

      var fullPathLength = attrPath.length;
      var model = this;

      Backbone.NestedModel.walkPath(newAttrs, attrPath, function(val, path){
        var attr = _.last(path);
        var attrStr = Backbone.NestedModel.createAttrStr(path);

        // See if this is a new value being set
        var isNewValue = !_.isEqual(val[attr], newValue);

        if (path.length === fullPathLength){
          // reached the attribute to be set

          if (opts.unset){
            // unset the value
            delete val[attr];

            // Trigger Remove Event if array being set to null
            if (_.isArray(val)){
              var parentPath = Backbone.NestedModel.createAttrStr(_.initial(attrPath));
              model._delayedTrigger('remove:' + parentPath, model, val[attr]);
            }
          } else {
            // Set the new value
            val[attr] = newValue;
          }

          // Trigger Change Event if new values are being set
          if (!opts.silent && _.isObject(newValue) && isNewValue){
            var visited = [];
            var checkChanges = function(obj, prefix) {
              // Don't choke on circular references
              if(_.indexOf(visited, obj) > -1) {
                return;
              } else {
                visited.push(obj);
              }

              var nestedAttr, nestedVal;
              for (var a in obj){
                if (obj.hasOwnProperty(a)) {
                  nestedAttr = prefix + '.' + a;
                  nestedVal = obj[a];
                  if (!_.isEqual(model.get(nestedAttr), nestedVal)) {
                    model._delayedChange(nestedAttr, nestedVal, opts);
                  }
                  if (_.isObject(nestedVal)) {
                    checkChanges(nestedVal, nestedAttr);
                  }
                }
              }
            };
            checkChanges(newValue, attrStr);

          }

        } else if (!val[attr]){
          if (_.isNumber(attr)){
            val[attr] = [];
          } else {
            val[attr] = {};
          }
        }

        if (!opts.silent){
          // let the superclass handle change events for top-level attributes
          if (path.length > 1 && isNewValue){
            model._delayedChange(attrStr, val[attr], opts);
          }

          if (_.isArray(val[attr])){
            model._delayedTrigger('add:' + attrStr, model, val[attr]);
          }
        }
      });
    }

  }, {
    // class methods

    attrPath: function(attrStrOrPath){
      var path;

      if (_.isString(attrStrOrPath)){
        // TODO this parsing can probably be more efficient
        path = (attrStrOrPath === '') ? [''] : attrStrOrPath.match(/[^\.\[\]]+/g);
        path = _.map(path, function(val){
          // convert array accessors to numbers
          return val.match(/^\d+$/) ? parseInt(val, 10) : val;
        });
      } else {
        path = attrStrOrPath;
      }

      return path;
    },

    createAttrStr: function(attrPath){
      var attrStr = attrPath[0];
      _.each(_.rest(attrPath), function(attr){
        attrStr += _.isNumber(attr) ? ('[' + attr + ']') : ('.' + attr);
      });

      return attrStr;
    },

    deepClone: function(obj){
      return $.extend(true, {}, obj);
    },

    walkPath: function(obj, attrPath, callback, scope){
      var val = obj,
        childAttr;

      // walk through the child attributes
      for (var i = 0; i < attrPath.length; i++){
        callback.call(scope || this, val, attrPath.slice(0, i + 1));

        childAttr = attrPath[i];
        val = val[childAttr];
        if (!val) break; // at the leaf
      }
    }

  });

}());
<|endoftext|>


<commit_before>(function (module) {
    module.factory("measurements", measurementsService);

    function measurementsService() {
        var self = this;
        self.activeTemplate = {};
        self.copy = [];
        self.touchedProperties = {};
        self.activeProperty = {};
        self.copySample = {};
        self.modal = {sample: {}};
        self.measurements = [
            {
                name: "Composition",
                attribute: "composition",
                description: "Composition of sample",
                category: "scalar",
                fn: Composition
            },
            {
                name: "Area Fraction",
                attribute: "area_fraction",
                description: "",
                category: "scalar",
                fn: AreaFraction
            },
            {
                name: "Volume Fraction",
                attribute: "volume_fraction",
                description: "",
                category: "scalar",
                fn: VolumeFraction
            },
            {
                name: "Dislocation Density",
                attribute: "dislocation_density",
                description: "",
                category: "scalar",
                fn: DislocationDensity
            },
            {
                name: "Length",
                attribute: "length",
                description: "",
                category: "scalar",
                fn: Length
            },
            {
                name: "Width",
                attribute: "width",
                description: "",
                category: "scalar",
                fn: Width
            },
            {
                name: "Height",
                attribute: "height",
                description: "",
                category: "scalar",
                fn: Height
            },
            {
                name: "Density",
                attribute: "density",
                description: "",
                category: "scalar",
                fn: Density
            },
            {
                name: "Volume",
                attribute: "volume",
                description: "",
                category: "scalar",
                fn: Volume
            },
            {
                name: "Young's Modulus",
                attribute: "youngs_modulus",
                description: "",
                category: "scalar",
                fn: YoungsModulus
            },
            {
                name: "Tensile Yield Strength",
                attribute: "tensile_yield_strength",
                description: "",
                category: "scalar",
                fn: TensileYieldStrength
            },
            {
                name: "Ultimate Tensile Strength",
                attribute: "ultimate_tensile_strength",
                description: "",
                category: "scalar",
                fn: UltimateTensileStrength
            },
            {
                name: "Strain To Fracture",
                attribute: "strain_to_fracture",
                description: "",
                category: "scalar",
                fn: StrainToFracture
            },
            {
                name: "Space Group",
                attribute: "space_group",
                description: "",
                category: "scalar",
                fn: SpaceGroup
            },
            {
                name: "Point Group",
                attribute: "point_group",
                description: "",
                category: "scalar",
                fn: PointGroup
            },
            {
                name: "Crystal System",
                attribute: "crystal_system",
                description: "",
                category: "scalar",
                fn: CrystalSystem
            },
            {
                name: "Band Gap",
                attribute: "band_gap",
                description: "",
                category: "scalar",
                fn: BandGap
            },
            //{
            //    name: "Fatigue Life",
            //    attribute: "fatigue_life",
            //    description: "",
            //    category: "pairs",
            //    fn: FatigueLife
            //},
            //{
            //    name: "Crack Growth",
            //    attribute: "crack_growth",
            //    description: "",
            //    category: "pairs",
            //    fn: CrackGrowth
            //},
            {
                name: "Particle Size Distribution",
                attribute: "particle_size_distribution",
                description: "",
                category: "chart",
                fn: ParticleSizeDistribution
            },
            {
                name: "Particle Shape Distribution",
                attribute: "particle_shape_distribution",
                description: "",
                category: "chart",
                fn: ParticleShapeDistribution
            },
            {
                name: "Grain Size Distribution",
                attribute: "grain_size_distribution",
                description: "",
                category: "chart",
                fn: GrainSizeDistribution
            },
            {
                name: "Grain Orientation Distribution",
                attribute: "grain_orientation_distribution",
                description: "",
                category: "chart",
                fn: GrainOrientationDistribution
            },
            {
                name: "Stress Strain",
                attribute: "stress_strain",
                description: "",
                category: "chart",
                fn: StressStrain
            },
            {
                name: "Stress Displacement",
                attribute: "stress_displacement",
                description: "",
                category: "chart",
                fn: StressDisplacement
            },
            //{
            //    name: "Phases Present",
            //    attribute: "phases_present",
            //    description: "",
            //    category: "list",
            //    fn: PhasesPresent
            //} ,
            {
                name: "Shape",
                attribute: "shape",
                description: "",
                category: "scalar",
                fn: Shape
            },
            {
                name: "Gauge Length",
                attribute: "gauge_length",
                description: "",
                category: "scalar",
                fn: GaugeLength
            },
            {
                name: "Gauge Thickness",
                attribute: "gauge_thickness",
                description: "",
                category: "scalar",
                fn: GaugeThickness
            },
            {
                name: "Area",
                attribute: "area",
                description: "",
                category: "scalar",
                fn: Area
            }
        ];

        return {
            templates: function () {
                self.copy = angular.copy(self.measurements);
            },

            newInstance: function (m) {
                return new m.fn();
            },

            templatesCopy: function () {
                return self.copy
            },

            verifyAndSave: function (property) {
                if (('value' in property) && property.value !== null) {
                    if (this.isExistingPropertyValid(property)) {
                        //check for the sample touchedProperties
                        var key = self.modal.sample.name;
                        if (self.touchedProperties.hasOwnProperty(key)) {
                            self.touchedProperties[key].push(property);
                        } else {
                            self.touchedProperties[key] = [];
                            self.touchedProperties[key].push(property);
                        }
                        this.processMeasurments(property);
                        return self.modal.sample;
                    }
                    else {
                        return false;
                    }
                } else {
                    return true;
                }
            },

            processMeasurments: function (property) {
                var type = property._type;
                var values = [];
                switch (type) {
                case 'number':
                    values = property.value.split("\n");
                    property.measurements = [];
                    values.forEach(function (v) {
                        property.measurements.push({
                            value: v,
                            _type: type,
                            unit: property.unit,
                            attribute: property.attribute
                        });
                    });
                    this.saveToSample(property);
                    break;
                case 'fraction':
                    values = property.value.split("\n");
                    property.measurements = [];
                    values.forEach(function (v) {
                        property.measurements.push({
                            value: v,
                            _type: type,
                            unit: property.unit,
                            attribute: property.attribute
                        });
                    });
                    this.saveToSample(property);
                    break;
                case 'histogram':
                    property.measurements = [];
                    property.measurements.push({
                        value: property.value,
                        _type: type,
                        unit: property.unit,
                        attribute: property.attribute
                    });
                    this.saveToSample(property);
                    break;
                case 'line':
                    property.measurements = [];
                    property.measurements.push({
                        value: property.value,
                        _type: type,
                        unit: property.unit,
                        attribute: property.attribute
                    });
                    this.saveToSample(property);
                    break;
                case 'selection':
                    property.measurements = [];
                    property.measurements.push({
                        value: property.value,
                        _type: type,
                        unit: property.unit,
                        attribute: property.attribute
                    });
                    this.saveToSample(property);
                    break;
                case 'composition':
                    var elements = property.value.elements.split("\n");
                    values = property.value.values.split("\n");
                    property.measurements = [];
                    for (var i = 0; i < elements.length - 1; i++) {
                        property.measurements.push({
                            value: values[i],
                            element: elements[i],
                            _type: property._type,
                            unit: property.unit,
                            attribute: property.attribute
                        });
                    }
                    if (elements.length > 1) {
                        this.saveToSample(property);
                    }
                    break;
                }
            },

            isExistingPropertyValid: function (property) {
                var type = property._type;
                var values = [];
                switch (type) {
                case 'number':
                    values = property.value.split("\n");
                    return this.isNumberValid(values);
                    break;
                case 'fraction':
                    values = property.value.split("\n");
                    return this.isFractionValid(values);
                    break;
                case 'histogram':
                    var values = [];
                    values = property.value.values.split("\n");
                    return this.isNumberValid(values);
                    break;
                case 'line':
                    var values = [];
                    values = property.value.values.split("\n");
                    return this.isNumberValid(values);
                    break;
                case 'selection':
                    return true;
                    break;
                case 'composition':
                    var values = [];
                    values = property.value.values.split("\n");
                    return this.isNumberValid(values);
                    break;
                }
            },

            isNumberValid: function (values) {
                var isNumeric = true;
                values.forEach(function (v) {
                    if (isNaN(v)) {
                        isNumeric = false;
                    }
                });
                return isNumeric;
            },

            isFractionValid: function (values) {
                var isNumeric = true;
                var fraction = [];
                values.forEach(function (v) {
                    fraction = v.split("/");
                    if (isNaN(fraction[0]) || isNaN(fraction[1])) {
                        isNumeric = false;
                    }
                });
                return isNumeric;
            },

            saveToSample: function (property) {
                var i, j, k;
                i = _.indexOf(self.copySample.properties, function (entry) {
                    return property.name === entry.name;
                });
                if (i < 0) {
                    j = _.indexOf(self.modal.sample.new_properties, function (prop) {
                        return property.name === prop.name;
                    });
                    if (j < 0) {
                        self.modal.sample.new_properties.push(property);
                    } else {
                        self.modal.sample.new_properties[j] = property;
                    }
                } else {
                    var old_prop = self.copySample.properties[i];
                    property.property_set_id = old_prop.property_set_id;
                    property.property_id = old_prop.property_id;
                    k = _.indexOf(self.modal.sample.old_properties, function (entry) {
                        return property.name === entry.name;
                    });
                    if (k > 0) {
                        self.modal.sample.old_properties[k] = property;

                    } else {
                        self.modal.sample.old_properties.push(property);
                    }
                }
            },

            getTouchedProperties: function (key) {
                if (self.touchedProperties.hasOwnProperty(key)) {
                    return self.touchedProperties[key]
                } else {
                    return [];
                }
            },

            copySample: function (sample) {
                self.copySample = angular.copy(sample);
                self.modal.sample = sample;
            },

            reset: function () {
                self.touchedProperties = {};
            }
        };
    }
}(angular.module('materialscommons')));<commit_msg>Add $inject reference.<commit_after>(function (module) {
    module.factory("measurements", measurementsService);
    measurementsService.$inject = [];

    function measurementsService() {
        var self = this;
        self.activeTemplate = {};
        self.copy = [];
        self.touchedProperties = {};
        self.activeProperty = {};
        self.copySample = {};
        self.modal = {sample: {}};
        self.measurements = [
            {
                name: "Composition",
                attribute: "composition",
                description: "Composition of sample",
                category: "scalar",
                fn: Composition
            },
            {
                name: "Area Fraction",
                attribute: "area_fraction",
                description: "",
                category: "scalar",
                fn: AreaFraction
            },
            {
                name: "Volume Fraction",
                attribute: "volume_fraction",
                description: "",
                category: "scalar",
                fn: VolumeFraction
            },
            {
                name: "Dislocation Density",
                attribute: "dislocation_density",
                description: "",
                category: "scalar",
                fn: DislocationDensity
            },
            {
                name: "Length",
                attribute: "length",
                description: "",
                category: "scalar",
                fn: Length
            },
            {
                name: "Width",
                attribute: "width",
                description: "",
                category: "scalar",
                fn: Width
            },
            {
                name: "Height",
                attribute: "height",
                description: "",
                category: "scalar",
                fn: Height
            },
            {
                name: "Density",
                attribute: "density",
                description: "",
                category: "scalar",
                fn: Density
            },
            {
                name: "Volume",
                attribute: "volume",
                description: "",
                category: "scalar",
                fn: Volume
            },
            {
                name: "Young's Modulus",
                attribute: "youngs_modulus",
                description: "",
                category: "scalar",
                fn: YoungsModulus
            },
            {
                name: "Tensile Yield Strength",
                attribute: "tensile_yield_strength",
                description: "",
                category: "scalar",
                fn: TensileYieldStrength
            },
            {
                name: "Ultimate Tensile Strength",
                attribute: "ultimate_tensile_strength",
                description: "",
                category: "scalar",
                fn: UltimateTensileStrength
            },
            {
                name: "Strain To Fracture",
                attribute: "strain_to_fracture",
                description: "",
                category: "scalar",
                fn: StrainToFracture
            },
            {
                name: "Space Group",
                attribute: "space_group",
                description: "",
                category: "scalar",
                fn: SpaceGroup
            },
            {
                name: "Point Group",
                attribute: "point_group",
                description: "",
                category: "scalar",
                fn: PointGroup
            },
            {
                name: "Crystal System",
                attribute: "crystal_system",
                description: "",
                category: "scalar",
                fn: CrystalSystem
            },
            {
                name: "Band Gap",
                attribute: "band_gap",
                description: "",
                category: "scalar",
                fn: BandGap
            },
            //{
            //    name: "Fatigue Life",
            //    attribute: "fatigue_life",
            //    description: "",
            //    category: "pairs",
            //    fn: FatigueLife
            //},
            //{
            //    name: "Crack Growth",
            //    attribute: "crack_growth",
            //    description: "",
            //    category: "pairs",
            //    fn: CrackGrowth
            //},
            {
                name: "Particle Size Distribution",
                attribute: "particle_size_distribution",
                description: "",
                category: "chart",
                fn: ParticleSizeDistribution
            },
            {
                name: "Particle Shape Distribution",
                attribute: "particle_shape_distribution",
                description: "",
                category: "chart",
                fn: ParticleShapeDistribution
            },
            {
                name: "Grain Size Distribution",
                attribute: "grain_size_distribution",
                description: "",
                category: "chart",
                fn: GrainSizeDistribution
            },
            {
                name: "Grain Orientation Distribution",
                attribute: "grain_orientation_distribution",
                description: "",
                category: "chart",
                fn: GrainOrientationDistribution
            },
            {
                name: "Stress Strain",
                attribute: "stress_strain",
                description: "",
                category: "chart",
                fn: StressStrain
            },
            {
                name: "Stress Displacement",
                attribute: "stress_displacement",
                description: "",
                category: "chart",
                fn: StressDisplacement
            },
            //{
            //    name: "Phases Present",
            //    attribute: "phases_present",
            //    description: "",
            //    category: "list",
            //    fn: PhasesPresent
            //} ,
            {
                name: "Shape",
                attribute: "shape",
                description: "",
                category: "scalar",
                fn: Shape
            },
            {
                name: "Gauge Length",
                attribute: "gauge_length",
                description: "",
                category: "scalar",
                fn: GaugeLength
            },
            {
                name: "Gauge Thickness",
                attribute: "gauge_thickness",
                description: "",
                category: "scalar",
                fn: GaugeThickness
            },
            {
                name: "Area",
                attribute: "area",
                description: "",
                category: "scalar",
                fn: Area
            }
        ];

        return {
            templates: function () {
                self.copy = angular.copy(self.measurements);
            },

            newInstance: function (m) {
                return new m.fn();
            },

            templatesCopy: function () {
                return self.copy
            },

            verifyAndSave: function (property) {
                if (('value' in property) && property.value !== null) {
                    if (this.isExistingPropertyValid(property)) {
                        //check for the sample touchedProperties
                        var key = self.modal.sample.name;
                        if (self.touchedProperties.hasOwnProperty(key)) {
                            self.touchedProperties[key].push(property);
                        } else {
                            self.touchedProperties[key] = [];
                            self.touchedProperties[key].push(property);
                        }
                        this.processMeasurments(property);
                        return self.modal.sample;
                    }
                    else {
                        return false;
                    }
                } else {
                    return true;
                }
            },

            processMeasurments: function (property) {
                var type = property._type;
                var values = [];
                switch (type) {
                case 'number':
                    values = property.value.split("\n");
                    property.measurements = [];
                    values.forEach(function (v) {
                        property.measurements.push({
                            value: v,
                            _type: type,
                            unit: property.unit,
                            attribute: property.attribute
                        });
                    });
                    this.saveToSample(property);
                    break;
                case 'fraction':
                    values = property.value.split("\n");
                    property.measurements = [];
                    values.forEach(function (v) {
                        property.measurements.push({
                            value: v,
                            _type: type,
                            unit: property.unit,
                            attribute: property.attribute
                        });
                    });
                    this.saveToSample(property);
                    break;
                case 'histogram':
                    property.measurements = [];
                    property.measurements.push({
                        value: property.value,
                        _type: type,
                        unit: property.unit,
                        attribute: property.attribute
                    });
                    this.saveToSample(property);
                    break;
                case 'line':
                    property.measurements = [];
                    property.measurements.push({
                        value: property.value,
                        _type: type,
                        unit: property.unit,
                        attribute: property.attribute
                    });
                    this.saveToSample(property);
                    break;
                case 'selection':
                    property.measurements = [];
                    property.measurements.push({
                        value: property.value,
                        _type: type,
                        unit: property.unit,
                        attribute: property.attribute
                    });
                    this.saveToSample(property);
                    break;
                case 'composition':
                    var elements = property.value.elements.split("\n");
                    values = property.value.values.split("\n");
                    property.measurements = [];
                    for (var i = 0; i < elements.length - 1; i++) {
                        property.measurements.push({
                            value: values[i],
                            element: elements[i],
                            _type: property._type,
                            unit: property.unit,
                            attribute: property.attribute
                        });
                    }
                    if (elements.length > 1) {
                        this.saveToSample(property);
                    }
                    break;
                }
            },

            isExistingPropertyValid: function (property) {
                var type = property._type;
                var values = [];
                switch (type) {
                case 'number':
                    values = property.value.split("\n");
                    return this.isNumberValid(values);
                    break;
                case 'fraction':
                    values = property.value.split("\n");
                    return this.isFractionValid(values);
                    break;
                case 'histogram':
                    values = property.value.values.split("\n");
                    return this.isNumberValid(values);
                    break;
                case 'line':
                    values = property.value.values.split("\n");
                    return this.isNumberValid(values);
                    break;
                case 'selection':
                    return true;
                    break;
                case 'composition':
                    values = property.value.values.split("\n");
                    return this.isNumberValid(values);
                    break;
                }
            },

            isNumberValid: function (values) {
                var isNumeric = true;
                values.forEach(function (v) {
                    if (isNaN(v)) {
                        isNumeric = false;
                    }
                });
                return isNumeric;
            },

            isFractionValid: function (values) {
                var isNumeric = true;
                var fraction = [];
                values.forEach(function (v) {
                    fraction = v.split("/");
                    if (isNaN(fraction[0]) || isNaN(fraction[1])) {
                        isNumeric = false;
                    }
                });
                return isNumeric;
            },

            saveToSample: function (property) {
                var i, j, k;
                i = _.indexOf(self.copySample.properties, function (entry) {
                    return property.name === entry.name;
                });
                if (i < 0) {
                    j = _.indexOf(self.modal.sample.new_properties, function (prop) {
                        return property.name === prop.name;
                    });
                    if (j < 0) {
                        self.modal.sample.new_properties.push(property);
                    } else {
                        self.modal.sample.new_properties[j] = property;
                    }
                } else {
                    var old_prop = self.copySample.properties[i];
                    property.property_set_id = old_prop.property_set_id;
                    property.property_id = old_prop.property_id;
                    k = _.indexOf(self.modal.sample.old_properties, function (entry) {
                        return property.name === entry.name;
                    });
                    if (k > 0) {
                        self.modal.sample.old_properties[k] = property;

                    } else {
                        self.modal.sample.old_properties.push(property);
                    }
                }
            },

            getTouchedProperties: function (key) {
                if (self.touchedProperties.hasOwnProperty(key)) {
                    return self.touchedProperties[key]
                } else {
                    return [];
                }
            },

            copySample: function (sample) {
                self.copySample = angular.copy(sample);
                self.modal.sample = sample;
            },

            reset: function () {
                self.touchedProperties = {};
            }
        };
    }
}(angular.module('materialscommons')));<|endoftext|>


<commit_before>// Unit test the search_suggestion.js module.
//
// These tests are framework-free and run sequentially; they are invoked
// immediately after being defined.  The contract here is that tests should
// clean up after themselves, and they should explicitly stub all
// dependencies.

var assert = require('assert');
var clean_up;

function set_up_dependencies() {
    var _ = global._ = require('third/underscore/underscore.js');
    global.Handlebars = require('handlebars');

    var actual_narrow = require('js/narrow.js');
    var search = require('js/search_suggestion.js');
    global.narrow = require('js/narrow.js');

    global.page_params = {
        email: 'bob@zulip.com'
    };

    global.typeahead_helper = require('js/typeahead_helper.js');

    global.util = require('js/util.js');
    global.Dict = require('js/dict.js');
    global.recent_subjects = new global.Dict();

    global.Filter = require('js/filter.js');
    global.stream_data = require('js/stream_data.js');

    var narrow_stream = global.narrow.stream;
    var stream_data_subscribed_streams = global.stream_data.subscribed_streams;
    clean_up = function () {
        global.narrow.stream = narrow_stream;
        global.stream_data.subscribed_streams = stream_data_subscribed_streams;
    };

    return search;
}

var search = set_up_dependencies();

(function test_basic_get_suggestions() {
    var query = 'fred';

    global.stream_data.subscribed_streams = function () {
        return [];
    };

    global.narrow.stream = function () {
        return 'office';
    };

    var suggestions = search.get_suggestions(query);

    var expected = [
        'fred'
    ];
    assert.deepEqual(suggestions.strings, expected);
}());

(function test_empty_query_suggestions() {
    var query = '';

    global.stream_data.subscribed_streams = function () {
        return ['devel', 'office'];
    };

    global.narrow.stream = function () {
        return undefined;
    };

    var suggestions = search.get_suggestions(query);

    var expected = [
        "",
        "in:all",
        "is:private",
        "is:starred",
        "is:mentioned",
        "sender:bob@zulip.com",
        "stream:devel",
        "stream:office"
    ];

    assert.deepEqual(suggestions.strings, expected);

    function describe(q) {
        return suggestions.lookup_table[q].description;
    }
    assert.equal(describe('in:all'), 'All messages');
    assert.equal(describe('is:private'), 'Private messages');
    assert.equal(describe('is:starred'), 'Starred messages');
    assert.equal(describe('is:mentioned'), '@-mentions');
    assert.equal(describe('sender:bob@zulip.com'), 'Sent by me');
    assert.equal(describe('stream:devel'), 'Narrow to stream devel');
}());

(function test_topic_suggestions() {
    var query = 'te';

    global.stream_data.subscribed_streams = function () {
        return ['office'];
    };

    global.narrow.stream = function () {
        return 'office';
    };

    global.recent_subjects = new global.Dict({
        office: [
            {subject: 'team'},
            {subject: 'ignore'},
            {subject: 'test'}
        ]
    });

    var suggestions = search.get_suggestions(query);

    var expected = [
        "te",
        "stream:office topic:team",
        "stream:office topic:test"
    ];

    assert.deepEqual(suggestions.strings, expected);

    function describe(q) {
        return suggestions.lookup_table[q].description;
    }
    assert.equal(describe('te'), "Search for te");
    assert.equal(describe('stream:office topic:team'), "Narrow to office > team");

}());

(function test_whitespace_glitch() {
    var query = 'stream:office '; // note trailing space

    global.stream_data.subscribed_streams = function () {
        return ['office'];
    };

    global.narrow.stream = function () {
        return;
    };

    global.recent_subjects = new global.Dict();

    var suggestions = search.get_suggestions(query);

    var expected = [
        "stream:office"
    ];

    assert.deepEqual(suggestions.strings, expected);
}());

(function test_people_suggestions() {
    var query = 'te';

    global.stream_data.subscribed_streams = function () {
        return [];
    };

    global.narrow.stream = function () {
        return;
    };

    global.page_params.people_list = [
        {
            email: 'ted@zulip.com',
            full_name: 'Ted Smith'
        },
        {
            email: 'alice@zulip.com',
            full_name: 'Alice Ignore'
        }
    ];

    global.recent_subjects = new global.Dict({
        office: [
            {subject: 'team'},
            {subject: 'ignore'},
            {subject: 'test'}
        ]
    });

    var suggestions = search.get_suggestions(query);

    var expected = [
        "te",
        "pm-with:ted@zulip.com",
        "sender:ted@zulip.com"
    ];

    assert.deepEqual(suggestions.strings, expected);
    function describe(q) {
        return suggestions.lookup_table[q].description;
    }
    assert.equal(describe('pm-with:ted@zulip.com'),
        "Narrow to private messages with Ted Smith <ted@zulip.com>");
    assert.equal(describe('sender:ted@zulip.com'),
        "Narrow to messages sent by Ted Smith <ted@zulip.com>");

    suggestions = search.get_suggestions('Ted '); // note space

    expected = [
        "Ted",
        "pm-with:ted@zulip.com",
        "sender:ted@zulip.com"
    ];

    assert.deepEqual(suggestions.strings, expected);
}());

clean_up();

<commit_msg>Remove unused var in search_suggestion.js test<commit_after>// Unit test the search_suggestion.js module.
//
// These tests are framework-free and run sequentially; they are invoked
// immediately after being defined.  The contract here is that tests should
// clean up after themselves, and they should explicitly stub all
// dependencies.

var assert = require('assert');
var clean_up;

function set_up_dependencies() {
    var _ = global._ = require('third/underscore/underscore.js');
    global.Handlebars = require('handlebars');

    var search = require('js/search_suggestion.js');
    global.narrow = require('js/narrow.js');

    global.page_params = {
        email: 'bob@zulip.com'
    };

    global.typeahead_helper = require('js/typeahead_helper.js');

    global.util = require('js/util.js');
    global.Dict = require('js/dict.js');
    global.recent_subjects = new global.Dict();

    global.Filter = require('js/filter.js');
    global.stream_data = require('js/stream_data.js');

    var narrow_stream = global.narrow.stream;
    var stream_data_subscribed_streams = global.stream_data.subscribed_streams;
    clean_up = function () {
        global.narrow.stream = narrow_stream;
        global.stream_data.subscribed_streams = stream_data_subscribed_streams;
    };

    return search;
}

var search = set_up_dependencies();

(function test_basic_get_suggestions() {
    var query = 'fred';

    global.stream_data.subscribed_streams = function () {
        return [];
    };

    global.narrow.stream = function () {
        return 'office';
    };

    var suggestions = search.get_suggestions(query);

    var expected = [
        'fred'
    ];
    assert.deepEqual(suggestions.strings, expected);
}());

(function test_empty_query_suggestions() {
    var query = '';

    global.stream_data.subscribed_streams = function () {
        return ['devel', 'office'];
    };

    global.narrow.stream = function () {
        return undefined;
    };

    var suggestions = search.get_suggestions(query);

    var expected = [
        "",
        "in:all",
        "is:private",
        "is:starred",
        "is:mentioned",
        "sender:bob@zulip.com",
        "stream:devel",
        "stream:office"
    ];

    assert.deepEqual(suggestions.strings, expected);

    function describe(q) {
        return suggestions.lookup_table[q].description;
    }
    assert.equal(describe('in:all'), 'All messages');
    assert.equal(describe('is:private'), 'Private messages');
    assert.equal(describe('is:starred'), 'Starred messages');
    assert.equal(describe('is:mentioned'), '@-mentions');
    assert.equal(describe('sender:bob@zulip.com'), 'Sent by me');
    assert.equal(describe('stream:devel'), 'Narrow to stream devel');
}());

(function test_topic_suggestions() {
    var query = 'te';

    global.stream_data.subscribed_streams = function () {
        return ['office'];
    };

    global.narrow.stream = function () {
        return 'office';
    };

    global.recent_subjects = new global.Dict({
        office: [
            {subject: 'team'},
            {subject: 'ignore'},
            {subject: 'test'}
        ]
    });

    var suggestions = search.get_suggestions(query);

    var expected = [
        "te",
        "stream:office topic:team",
        "stream:office topic:test"
    ];

    assert.deepEqual(suggestions.strings, expected);

    function describe(q) {
        return suggestions.lookup_table[q].description;
    }
    assert.equal(describe('te'), "Search for te");
    assert.equal(describe('stream:office topic:team'), "Narrow to office > team");

}());

(function test_whitespace_glitch() {
    var query = 'stream:office '; // note trailing space

    global.stream_data.subscribed_streams = function () {
        return ['office'];
    };

    global.narrow.stream = function () {
        return;
    };

    global.recent_subjects = new global.Dict();

    var suggestions = search.get_suggestions(query);

    var expected = [
        "stream:office"
    ];

    assert.deepEqual(suggestions.strings, expected);
}());

(function test_people_suggestions() {
    var query = 'te';

    global.stream_data.subscribed_streams = function () {
        return [];
    };

    global.narrow.stream = function () {
        return;
    };

    global.page_params.people_list = [
        {
            email: 'ted@zulip.com',
            full_name: 'Ted Smith'
        },
        {
            email: 'alice@zulip.com',
            full_name: 'Alice Ignore'
        }
    ];

    global.recent_subjects = new global.Dict({
        office: [
            {subject: 'team'},
            {subject: 'ignore'},
            {subject: 'test'}
        ]
    });

    var suggestions = search.get_suggestions(query);

    var expected = [
        "te",
        "pm-with:ted@zulip.com",
        "sender:ted@zulip.com"
    ];

    assert.deepEqual(suggestions.strings, expected);
    function describe(q) {
        return suggestions.lookup_table[q].description;
    }
    assert.equal(describe('pm-with:ted@zulip.com'),
        "Narrow to private messages with Ted Smith <ted@zulip.com>");
    assert.equal(describe('sender:ted@zulip.com'),
        "Narrow to messages sent by Ted Smith <ted@zulip.com>");

    suggestions = search.get_suggestions('Ted '); // note space

    expected = [
        "Ted",
        "pm-with:ted@zulip.com",
        "sender:ted@zulip.com"
    ];

    assert.deepEqual(suggestions.strings, expected);
}());

clean_up();

<|endoftext|>


<commit_before>'use strict';
var gulp = require('gulp');
var requireDir = require('require-dir');
var helpers = require('./gulp/helpers');
requireDir('./gulp/tasks', {
  recurse: true
});

gulp.task('test', ['eslint-build', 'esdoc', 'mocha-server'], function () {
  console.log('checking for error');
  if (helpers.getError()) {
    throw helpers.getError();
  }
});
gulp.task('default', function () {
  return gulp.start('eslint-build', 'esdoc',
    'mocha-server');
});

gulp.task('build', ['transpile', 'webpack'])
<commit_msg>remove webpack task<commit_after>'use strict';
var gulp = require('gulp');
var requireDir = require('require-dir');
var helpers = require('./gulp/helpers');
requireDir('./gulp/tasks', {
  recurse: true
});

gulp.task('test', ['eslint-build', 'esdoc', 'mocha-server'], function () {
  console.log('checking for error');
  if (helpers.getError()) {
    throw helpers.getError();
  }
});
gulp.task('default', function () {
  return gulp.start('eslint-build', 'esdoc',
    'mocha-server');
});

gulp.task('build', ['transpile'])
<|endoftext|>


<commit_before>/**
 * Backbone Global Events
 * A simple way to listen to global triggers in Backbone.js applications.
 * Version 0.1.0
 *
 * https://github.com/DarrylD/Backbone.global
 */
(function(){

  //By default, Use the built-in Backbone global event bus
  Backbone.View.prototype.globalEventBus = Backbone;

  var originalDelegateEvents = Backbone.View.prototype.delegateEvents; //cache the original prototype to chain after new logic
  Backbone.View.prototype.delegateEvents = function(events) {
      // incase events comes from this.events opposed to the arg
      // _(this).result('events') grabs the propery when when its a function, involke and return
      // in our case we are looking for this.events
      if(!( events || ( events = _(this).result('events') ) ) )
          return;

      var seperatedEvents = _.pairs(events), //turn obj into an array of key/values
          that = this;

      _.each(seperatedEvents, function( event ){
        var isGlobal = event[0].split(' ')[0] === 'global', //check for global event
            channel = event[0].split(' ')[1], //example: "someStuff/todo"
             method = event[1];

        if(isGlobal){
          //do awesomeness here with mediator
          that.globalEventBus.on( channel, that[method] );
        }
      });

      // chain the original method, it will ignore the global events natrually
      originalDelegateEvents.call(this, events);
  };
})()
<commit_msg>Update backbone.global.js<commit_after>/**
 * Backbone Global Events
 * A simple way to listen to global triggers in Backbone.js applications.
 * Version 0.1.0
 *
 * https://github.com/DarrylD/Backbone.global
 */
(function(){

  //By default, Use the built-in Backbone global event bus
  Backbone.View.prototype.globalEventBus = Backbone;

  var originalDelegateEvents = Backbone.View.prototype.delegateEvents; //cache the original prototype to chain after new logic
  Backbone.View.prototype.delegateEvents = function(events) {
      // incase events comes from this.events opposed to the arg
      // _(this).result('events') grabs the propery when when its a function, involke and return
      // in our case we are looking for this.events
      if(!( events || ( events = _(this).result('events') ) ) )
          return;

      var seperatedEvents = _.pairs(events), //turn obj into an array of key/values
          that = this;

      _.each(seperatedEvents, function( event ){
        var isGlobal = event[0].split(' ')[0] === 'global', //check for global event
            channel = event[0].split(' ')[1], //example: "someStuff/todo"
             method = event[1];

        if(isGlobal){
          //do awesomeness here with mediator
          that.globalEventBus.on( channel, that[method], that );
        }
      });

      // chain the original method, it will ignore the global events natrually
      originalDelegateEvents.call(this, events);
  };
})()
<|endoftext|>


<commit_before>import { getWindowTop, deepAccess, logMessage } from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';

const BIDDER_CODE = 'colossusssp';
const G_URL = 'https://colossusssp.com/?c=o&m=multi';
const G_URL_SYNC = 'https://colossusssp.com/?c=o&m=cookie';

function isBidResponseValid(bid) {
  if (!bid.requestId || !bid.cpm || !bid.creativeId || !bid.ttl || !bid.currency) {
    return false;
  }

  switch (bid.mediaType) {
    case BANNER:
      return Boolean(bid.width && bid.height && bid.ad);
    case VIDEO:
      return Boolean(bid.vastUrl);
    case NATIVE:
      return Boolean(bid.native);
    default:
      return false;
  }
}

function getUserId(eids, id, source, uidExt) {
  if (id) {
    var uid = { id };
    if (uidExt) {
      uid.ext = uidExt;
    }
    eids.push({
      source,
      uids: [ uid ]
    });
  }
}

export const spec = {
  code: BIDDER_CODE,
  supportedMediaTypes: [BANNER, VIDEO, NATIVE],
  /**
   * Determines whether or not the given bid request is valid.
   *
   * @param {object} bid The bid to validate.
   * @return boolean True if this is a valid bid, and false otherwise.
   */
  isBidRequestValid: (bid) => {
    return Boolean(bid.bidId && bid.params && !isNaN(bid.params.placement_id));
  },

  /**
   * Make a server request from the list of BidRequests.
   *
   * @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the Server.
   * @return ServerRequest Info describing the request to the server.
   */
  buildRequests: (validBidRequests, bidderRequest) => {
    const winTop = getWindowTop();
    const location = winTop.location;
    let placements = [];
    let request = {
      'deviceWidth': winTop.screen.width,
      'deviceHeight': winTop.screen.height,
      'language': (navigator && navigator.language) ? navigator.language : '',
      'secure': location.protocol === 'https:' ? 1 : 0,
      'host': location.host,
      'page': location.pathname,
      'placements': placements,
    };

    if (bidderRequest) {
      if (bidderRequest.uspConsent) {
        request.ccpa = bidderRequest.uspConsent;
      }
      if (bidderRequest.gdprConsent) {
        request.gdpr_consent = bidderRequest.gdprConsent.consentString || 'ALL'
        request.gdpr_require = bidderRequest.gdprConsent.gdprApplies ? 1 : 0
      }
    }

    for (let i = 0; i < validBidRequests.length; i++) {
      let bid = validBidRequests[i];
      let traff = bid.params.traffic || BANNER
      let placement = {
        placementId: bid.params.placement_id,
        bidId: bid.bidId,
        sizes: bid.mediaTypes[traff].sizes,
        traffic: traff,
        eids: [],
        floor: {}
      };
      if (typeof bid.getFloor === 'function') {
        let tmpFloor = {};
        for (let size of placement.sizes) {
          tmpFloor = bid.getFloor({
            currency: 'USD',
            mediaType: traff,
            size: size
          });
          if (tmpFloor) {
            placement.floor[`${size[0]}x${size[1]}`] = tmpFloor.floor;
          }
        }
      }
      if (bid.schain) {
        placement.schain = bid.schain;
      }
      let gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot');
      if (gpid) {
        placement.gpid = gpid;
      }
      if (bid.userId) {
        getUserId(placement.eids, bid.userId.britepoolid, 'britepool.com');
        getUserId(placement.eids, bid.userId.idl_env, 'identityLink');
        getUserId(placement.eids, bid.userId.id5id, 'id5-sync.com');
        getUserId(placement.eids, bid.userId.uid2 && bid.userId.uid2.id, 'uidapi.com');
        getUserId(placement.eids, bid.userId.tdid, 'adserver.org', {
          rtiPartner: 'TDID'
        });
      }
      if (traff === VIDEO) {
        placement.playerSize = bid.mediaTypes[VIDEO].playerSize;
        placement.minduration = bid.mediaTypes[VIDEO].minduration;
        placement.maxduration = bid.mediaTypes[VIDEO].maxduration;
        placement.mimes = bid.mediaTypes[VIDEO].mimes;
        placement.protocols = bid.mediaTypes[VIDEO].protocols;
        placement.startdelay = bid.mediaTypes[VIDEO].startdelay;
        placement.placement = bid.mediaTypes[VIDEO].placement;
        placement.skip = bid.mediaTypes[VIDEO].skip;
        placement.skipafter = bid.mediaTypes[VIDEO].skipafter;
        placement.minbitrate = bid.mediaTypes[VIDEO].minbitrate;
        placement.maxbitrate = bid.mediaTypes[VIDEO].maxbitrate;
        placement.delivery = bid.mediaTypes[VIDEO].delivery;
        placement.playbackmethod = bid.mediaTypes[VIDEO].playbackmethod;
        placement.api = bid.mediaTypes[VIDEO].api;
        placement.linearity = bid.mediaTypes[VIDEO].linearity;
      }
      placements.push(placement);
    }
    return {
      method: 'POST',
      url: G_URL,
      data: request
    };
  },

  /**
   * Unpack the response from the server into a list of bids.
   *
   * @param {*} serverResponse A successful response from the server.
   * @return {Bid[]} An array of bids which were nested inside the server.
   */
  interpretResponse: (serverResponse) => {
    let response = [];
    try {
      serverResponse = serverResponse.body;
      for (let i = 0; i < serverResponse.length; i++) {
        let resItem = serverResponse[i];
        if (isBidResponseValid(resItem)) {
          const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : [];
          resItem.meta = { ...resItem.meta, advertiserDomains };

          response.push(resItem);
        }
      }
    } catch (e) {
      logMessage(e);
    };
    return response;
  },

  getUserSyncs: () => {
    return [{
      type: 'image',
      url: G_URL_SYNC
    }];
  }
};

registerBidder(spec);
<commit_msg>add onBidWon<commit_after>import { getWindowTop, deepAccess, logMessage } from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
import { ajax } from '../src/ajax.js';

const BIDDER_CODE = 'colossusssp';
const G_URL = 'https://colossusssp.com/?c=o&m=multi';
const G_URL_SYNC = 'https://colossusssp.com/?c=o&m=cookie';

function isBidResponseValid(bid) {
  if (!bid.requestId || !bid.cpm || !bid.creativeId || !bid.ttl || !bid.currency) {
    return false;
  }

  switch (bid.mediaType) {
    case BANNER:
      return Boolean(bid.width && bid.height && bid.ad);
    case VIDEO:
      return Boolean(bid.vastUrl);
    case NATIVE:
      return Boolean(bid.native);
    default:
      return false;
  }
}

function getUserId(eids, id, source, uidExt) {
  if (id) {
    var uid = { id };
    if (uidExt) {
      uid.ext = uidExt;
    }
    eids.push({
      source,
      uids: [ uid ]
    });
  }
}

export const spec = {
  code: BIDDER_CODE,
  supportedMediaTypes: [BANNER, VIDEO, NATIVE],
  /**
   * Determines whether or not the given bid request is valid.
   *
   * @param {object} bid The bid to validate.
   * @return boolean True if this is a valid bid, and false otherwise.
   */
  isBidRequestValid: (bid) => {
    return Boolean(bid.bidId && bid.params && !isNaN(bid.params.placement_id));
  },

  /**
   * Make a server request from the list of BidRequests.
   *
   * @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the Server.
   * @return ServerRequest Info describing the request to the server.
   */
  buildRequests: (validBidRequests, bidderRequest) => {
    const winTop = getWindowTop();
    const location = winTop.location;
    let placements = [];
    let request = {
      'deviceWidth': winTop.screen.width,
      'deviceHeight': winTop.screen.height,
      'language': (navigator && navigator.language) ? navigator.language : '',
      'secure': location.protocol === 'https:' ? 1 : 0,
      'host': location.host,
      'page': location.pathname,
      'placements': placements,
    };

    if (bidderRequest) {
      if (bidderRequest.uspConsent) {
        request.ccpa = bidderRequest.uspConsent;
      }
      if (bidderRequest.gdprConsent) {
        request.gdpr_consent = bidderRequest.gdprConsent.consentString || 'ALL'
        request.gdpr_require = bidderRequest.gdprConsent.gdprApplies ? 1 : 0
      }
    }

    for (let i = 0; i < validBidRequests.length; i++) {
      let bid = validBidRequests[i];
      let traff = bid.params.traffic || BANNER
      let placement = {
        placementId: bid.params.placement_id,
        bidId: bid.bidId,
        sizes: bid.mediaTypes[traff].sizes,
        traffic: traff,
        eids: [],
        floor: {}
      };
      if (typeof bid.getFloor === 'function') {
        let tmpFloor = {};
        for (let size of placement.sizes) {
          tmpFloor = bid.getFloor({
            currency: 'USD',
            mediaType: traff,
            size: size
          });
          if (tmpFloor) {
            placement.floor[`${size[0]}x${size[1]}`] = tmpFloor.floor;
          }
        }
      }
      if (bid.schain) {
        placement.schain = bid.schain;
      }
      let gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot');
      if (gpid) {
        placement.gpid = gpid;
      }
      if (bid.userId) {
        getUserId(placement.eids, bid.userId.britepoolid, 'britepool.com');
        getUserId(placement.eids, bid.userId.idl_env, 'identityLink');
        getUserId(placement.eids, bid.userId.id5id, 'id5-sync.com');
        getUserId(placement.eids, bid.userId.uid2 && bid.userId.uid2.id, 'uidapi.com');
        getUserId(placement.eids, bid.userId.tdid, 'adserver.org', {
          rtiPartner: 'TDID'
        });
      }
      if (traff === VIDEO) {
        placement.playerSize = bid.mediaTypes[VIDEO].playerSize;
        placement.minduration = bid.mediaTypes[VIDEO].minduration;
        placement.maxduration = bid.mediaTypes[VIDEO].maxduration;
        placement.mimes = bid.mediaTypes[VIDEO].mimes;
        placement.protocols = bid.mediaTypes[VIDEO].protocols;
        placement.startdelay = bid.mediaTypes[VIDEO].startdelay;
        placement.placement = bid.mediaTypes[VIDEO].placement;
        placement.skip = bid.mediaTypes[VIDEO].skip;
        placement.skipafter = bid.mediaTypes[VIDEO].skipafter;
        placement.minbitrate = bid.mediaTypes[VIDEO].minbitrate;
        placement.maxbitrate = bid.mediaTypes[VIDEO].maxbitrate;
        placement.delivery = bid.mediaTypes[VIDEO].delivery;
        placement.playbackmethod = bid.mediaTypes[VIDEO].playbackmethod;
        placement.api = bid.mediaTypes[VIDEO].api;
        placement.linearity = bid.mediaTypes[VIDEO].linearity;
      }
      placements.push(placement);
    }
    return {
      method: 'POST',
      url: G_URL,
      data: request
    };
  },

  /**
   * Unpack the response from the server into a list of bids.
   *
   * @param {*} serverResponse A successful response from the server.
   * @return {Bid[]} An array of bids which were nested inside the server.
   */
  interpretResponse: (serverResponse) => {
    let response = [];
    try {
      serverResponse = serverResponse.body;
      for (let i = 0; i < serverResponse.length; i++) {
        let resItem = serverResponse[i];
        if (isBidResponseValid(resItem)) {
          const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : [];
          resItem.meta = { ...resItem.meta, advertiserDomains };

          response.push(resItem);
        }
      }
    } catch (e) {
      logMessage(e);
    };
    return response;
  },

  getUserSyncs: () => {
    return [{
      type: 'image',
      url: G_URL_SYNC
    }];
  },

  onBidWon: function(bid) {
    if (bid.nurl) {
      ajax(bid.nurl, null);
    }
  }
};

registerBidder(spec);
<|endoftext|>


<commit_before>/*
 * PurePO2JSON v3.1.0
 * by André Zanghelini (An_dz)
 *
 * with previous contributions by Roland Reck (QuHno)
 * IBM i18n idea and formula from Roland Reck (QuHno)
 */
"use strict";

/**
 * @brief Convert special characters to their unicode number
 *
 * Used by the `replace` method to convert the characters to
 * their unicode values between underlines.
 */
function specialChars(match, linefeed, special) {
	// get rid of new lines
	if (linefeed === "n") {
		return "_10_";
	}
	if (linefeed === "r") {
		return "_13_";
	}
	// convert special chars to their code
	if (special !== undefined) {
		return "_" + match.charCodeAt(0) + "_";
	}
	return match;
}

/**
 * @brief Class representing a message
 *
 * This class is a construction for one message, it holds all
 * the data about the message, including original text, context
 * and all possible translations (if there are plurals)
 *
 * @warning: The setters append and don't replace
 */
class Message {
	/**
	 * @brief Construct a new message
	 *
	 * @param lf         {string}  The linefeed for each line,
	 * minimised JSON if left as an empty string
	 * @param ibmi18n    {boolean} Expand string by IBM guideline
	 * @param showReview {boolean} Add # around strings marked for review
	 */
	constructor(lf, ibmi18n, showReview) {
		this.linefeed = lf;
		this.ibmi18n  = ibmi18n;
		this.toReview = showReview;
		this.tab      = (lf === "" ? "" : "\t");
		this.space    = (lf === "" ? "" : " ");
		this.str      = [];
		this.id       = "";
		this.ctxt     = "";
		this.lastUsed = null;
		this.reviewed = true;
	}
	/**
	 * @brief Set or amend msgid
	 *
	 * @param text {string} The text to set
	 */
	set msgid(text) {
		this.id = text;
		this.lastUsed = this.id;
	}
	get msgid() {
		return this.id;
	}
	/**
	 * @brief Set the context
	 *
	 * @param context {string} The text to set
	 */
	set msgctxt(context) {
		this.ctxt = context;
		this.lastUsed = this.ctxt;
	}
	get msgctxt() {
		return this.ctxt;
	}
	/**
	 * @brief Set or amend msgid
	 *
	 * @param string {string} The text to set
	 */
	set msgstr(string) {
		const index = this.str.push(string) - 1;
		this.lastUsed = this.str[index];
	}
	get msgstr() {
		return this.str;
	}
	/**
	 * @brief Appends text to the last defined property
	 *
	 * @param string {string} The text to append
	 */
	set amend(string) {
		this.lastUsed += string;
	}
	/**
	 * @brief Increase string to safe length if enabled
	 *
	 * Applies the IBM algorithm that increases the length of the
	 * string to test screen space in multiple languages.
	 *
	 * @param string {string} the text to apply IBM algorithm
	 *
	 * @return {string} String with increase length or same string
	 */
	getIBM(string) {
		if (this.ibmi18n !== true) {
			return string;
		}

		const length = string.length;

		return `${string}${"-".repeat(
			(3 / Math.log(length) + 0.7) * length - length
		)}`;
	}
	/**
	 * @brief Return a constructed JSON as a string
	 *
	 * @return {string} JSON of the message
	 */
	toString() {
		const lf = this.linefeed;
		const tab = this.tab;
		const space = this.space;

		const msgctxt = (this.msgctxt.length > 0 ? "\x04" : "");

		const id = `${this.msgctxt}${msgctxt}${this.msgid}`.replace(
			/\\(n|r)|([^a-z0-9])/g, specialChars
		);

		const json = [];

		this.msgstr.forEach((string, index) => {
			if (string.length === 0) {
				string = this.msgid;
				this.reviewed = false;
			}

			if (this.toReview === true && this.reviewed === false) {
				string = `# ${string} #`;
			}

			json.push(
				`"${id}${index}":${space}{${lf}` +
					`${tab}"message":${space}"${this.getIBM(string)}"${lf}` +
				"}"
			);
		});

		return json.join(`,${lf}`);
	}
}

/**
 * @brief Gets a PO file and converts to JSON
 *
 * Gets a PO file as a `String` and returns a `String`
 * with the contents of a JSON file.
 *
 * @param[in] file       {String}  The PO file to convert
 * @param[in] minify     {Boolean} If the result must be minified (optional)
 * @param[in] showReview {boolean} Add # around strings marked for review
 * @param[in] ibmi18n    {Boolean} If the result expands strings to match W3C
 * Internationalisation guideline. @see https://www.w3.org/International/articles/article-text-size
 *
 * @return {String} JSON file
 *
 * @info The W3C formula comes from a simplification of the following formula:
 * X = (((3 * ln(length) + 0.7) * length) - length)
 * Where:
 * p = (300 * ln(length) + 70) <-- This returns the percentage of expansion
 * p = (  3 * ln(length) + 0.7) <-- This returns the same but divided by 100
 * e = (p * length) <-- This returns the final expanded length
 * f = (e - length) <-- This returns the amount of chars to add
 */
function purePO2JSON(file, minify, ibmi18n, showReview) {
	// Check line feed
	const linefeed = file.match(/\r\n?|\n/)[0];
	file = file.split(linefeed);

	const lf = (minify ? "" : linefeed);

	const messages = [];
	let ignoreline = true;

	file.forEach(function choose(line) {
		// if the line has no text or begins with '#' (comment)
		if (line === "#, fuzzy") {
			const length = messages.push(
				new Message(lf, ibmi18n, showReview)
			);
			messages[length - 1].reviewed = false;
			return;
		}

		if (line.length === 0 || line[0] === "#") {
			if (line[1] === "~") {
				const currentMessage = messages[messages.length - 1];

				if (currentMessage.msgid.length === 0) {
					messages.pop();
				}
			}

			return;
		}

		const msg = line.match(
			/^msg(?:(id)(_plural)?|(str)(?:\[\d\])?|(ctxt))\s"(.*)"$/
		);
		const currentMessage = messages[messages.length - 1];

		// line is continuation of a string
		if (msg === null) {
			// only amend if there's anything to amend
			if (currentMessage !== undefined) {
				currentMessage.amend = line.substring(1, line.length - 1);
			}

			return;
		}

		const msgid        = Boolean(msg[1]);
		const msgid_plural = Boolean(msg[2]);
		const msgstr       = Boolean(msg[3]);
		const msgctxt      = Boolean(msg[4]);
		const text         = msg[5];

		// ignore the first msgid/msgstr pair
		if (ignoreline === true) {
			// stop ignoring after the first msgid
			if (msgstr === true) {
				ignoreline = false;
			}

			return;
		}

		if (msgctxt) {
			if (
				currentMessage === undefined ||
				currentMessage.msgid.length > 0
			) {
				const length = messages.push(
					new Message(lf, ibmi18n, showReview)
				);
				messages[length - 1].msgctxt = text;
				return;
			}

			currentMessage.msgctxt = text;
			return;
		}

		if (msgid_plural) {
			return;
		}

		if (msgid) {
			if (
				currentMessage === undefined ||
				currentMessage.msgid.length > 0
			) {
				const length = messages.push(
					new Message(lf, ibmi18n, showReview)
				);
				messages[length - 1].msgid = text;
				return;
			}

			currentMessage.msgid = text;
			return;
		}

		if (msgstr) {
			currentMessage.msgstr = text;
		}
	});

	console.info("All done, just copy the content of the page now. ;D");

	// Join all lines again with the original line feed
	return `{${lf}${messages.join(`,${lf}`)}${lf}}`;
}
<commit_msg>Fix strings not being correctly amended<commit_after>/*
 * PurePO2JSON v3.1.0
 * by André Zanghelini (An_dz)
 *
 * with previous contributions by Roland Reck (QuHno)
 * IBM i18n idea and formula from Roland Reck (QuHno)
 */
"use strict";

/**
 * @brief Convert special characters to their unicode number
 *
 * Used by the `replace` method to convert the characters to
 * their unicode values between underlines.
 */
function specialChars(match, linefeed, special) {
	// get rid of new lines
	if (linefeed === "n") {
		return "_10_";
	}
	if (linefeed === "r") {
		return "_13_";
	}
	// convert special chars to their code
	if (special !== undefined) {
		return "_" + match.charCodeAt(0) + "_";
	}
	return match;
}

/**
 * @brief Class representing a message
 *
 * This class is a construction for one message, it holds all
 * the data about the message, including original text, context
 * and all possible translations (if there are plurals)
 *
 * @warning: The setters append and don't replace
 */
class Message {
	/**
	 * @brief Construct a new message
	 *
	 * @param lf         {string}  The linefeed for each line,
	 * minimised JSON if left as an empty string
	 * @param ibmi18n    {boolean} Expand string by IBM guideline
	 * @param showReview {boolean} Add # around strings marked for review
	 */
	constructor(lf, ibmi18n, showReview) {
		this.linefeed = lf;
		this.ibmi18n  = ibmi18n;
		this.toReview = showReview;
		this.tab      = (lf === "" ? "" : "\t");
		this.space    = (lf === "" ? "" : " ");
		this.str      = [];
		this.id       = "";
		this.ctxt     = "";
		this.lastUsed = null;
		this.reviewed = true;
	}
	/**
	 * @brief Set or amend msgid
	 *
	 * @param text {string} The text to set
	 */
	set msgid(text) {
		this.id = text;
		this.lastUsed = "id";
	}
	get msgid() {
		return this.id;
	}
	/**
	 * @brief Set the context
	 *
	 * @param context {string} The text to set
	 */
	set msgctxt(context) {
		this.ctxt = context;
		this.lastUsed = "ctxt";
	}
	get msgctxt() {
		return this.ctxt;
	}
	/**
	 * @brief Set or amend msgid
	 *
	 * @param string {string} The text to set
	 */
	set msgstr(string) {
		this.str.push(string);
		this.lastUsed = "str";
	}
	get msgstr() {
		return this.str;
	}
	/**
	 * @brief Appends text to the last defined property
	 *
	 * @param string {string} The text to append
	 */
	set amend(string) {
		if (this.lastUsed === "str") {
			this.str[this.str.length - 1] += string;
			return;
		}

		this[this.lastUsed] += string;
	}
	/**
	 * @brief Increase string to safe length if enabled
	 *
	 * Applies the IBM algorithm that increases the length of the
	 * string to test screen space in multiple languages.
	 *
	 * @param string {string} the text to apply IBM algorithm
	 *
	 * @return {string} String with increase length or same string
	 */
	getIBM(string) {
		if (this.ibmi18n !== true) {
			return string;
		}

		const length = string.length;

		return `${string}${"-".repeat(
			(3 / Math.log(length) + 0.7) * length - length
		)}`;
	}
	/**
	 * @brief Return a constructed JSON as a string
	 *
	 * @return {string} JSON of the message
	 */
	toString() {
		const lf = this.linefeed;
		const tab = this.tab;
		const space = this.space;

		const msgctxt = (this.msgctxt.length > 0 ? "\x04" : "");

		const id = `${this.msgctxt}${msgctxt}${this.msgid}`.replace(
			/\\(n|r)|([^a-z0-9])/g, specialChars
		);

		const json = [];

		this.msgstr.forEach((string, index) => {
			if (string.length === 0) {
				string = this.msgid;
				this.reviewed = false;
			}

			if (this.toReview === true && this.reviewed === false) {
				string = `# ${string} #`;
			}

			json.push(
				`"${id}${index}":${space}{${lf}` +
					`${tab}"message":${space}"${this.getIBM(string)}"${lf}` +
				"}"
			);
		});

		return json.join(`,${lf}`);
	}
}

/**
 * @brief Gets a PO file and converts to JSON
 *
 * Gets a PO file as a `String` and returns a `String`
 * with the contents of a JSON file.
 *
 * @param[in] file       {String}  The PO file to convert
 * @param[in] minify     {Boolean} If the result must be minified (optional)
 * @param[in] showReview {boolean} Add # around strings marked for review
 * @param[in] ibmi18n    {Boolean} If the result expands strings to match W3C
 * Internationalisation guideline. @see https://www.w3.org/International/articles/article-text-size
 *
 * @return {String} JSON file
 *
 * @info The W3C formula comes from a simplification of the following formula:
 * X = (((3 * ln(length) + 0.7) * length) - length)
 * Where:
 * p = (300 * ln(length) + 70) <-- This returns the percentage of expansion
 * p = (  3 * ln(length) + 0.7) <-- This returns the same but divided by 100
 * e = (p * length) <-- This returns the final expanded length
 * f = (e - length) <-- This returns the amount of chars to add
 */
function purePO2JSON(file, minify, ibmi18n, showReview) {
	// Check line feed
	const linefeed = file.match(/\r\n?|\n/)[0];
	file = file.split(linefeed);

	const lf = (minify ? "" : linefeed);

	const messages = [];
	let ignoreline = true;

	file.forEach(function choose(line) {
		// if the line has no text or begins with '#' (comment)
		if (line === "#, fuzzy") {
			const length = messages.push(
				new Message(lf, ibmi18n, showReview)
			);
			messages[length - 1].reviewed = false;
			return;
		}

		if (line.length === 0 || line[0] === "#") {
			if (line[1] === "~") {
				const currentMessage = messages[messages.length - 1];

				if (currentMessage.msgid.length === 0) {
					messages.pop();
				}
			}

			return;
		}

		const msg = line.match(
			/^msg(?:(id)(_plural)?|(str)(?:\[\d\])?|(ctxt))\s"(.*)"$/
		);
		const currentMessage = messages[messages.length - 1];

		// line is continuation of a string
		if (msg === null) {
			// only amend if there's anything to amend
			if (currentMessage !== undefined) {
				currentMessage.amend = line.substring(1, line.length - 1);
			}

			return;
		}

		const msgid        = Boolean(msg[1]);
		const msgid_plural = Boolean(msg[2]);
		const msgstr       = Boolean(msg[3]);
		const msgctxt      = Boolean(msg[4]);
		const text         = msg[5];

		// ignore the first msgid/msgstr pair
		if (ignoreline === true) {
			// stop ignoring after the first msgid
			if (msgstr === true) {
				ignoreline = false;
			}

			return;
		}

		if (msgctxt) {
			if (
				currentMessage === undefined ||
				currentMessage.msgid.length > 0
			) {
				const length = messages.push(
					new Message(lf, ibmi18n, showReview)
				);
				messages[length - 1].msgctxt = text;
				return;
			}

			currentMessage.msgctxt = text;
			return;
		}

		if (msgid_plural) {
			return;
		}

		if (msgid) {
			if (
				currentMessage === undefined ||
				currentMessage.msgid.length > 0
			) {
				const length = messages.push(
					new Message(lf, ibmi18n, showReview)
				);
				messages[length - 1].msgid = text;
				return;
			}

			currentMessage.msgid = text;
			return;
		}

		if (msgstr) {
			currentMessage.msgstr = text;
		}
	});

	console.info("All done, just copy the content of the page now. ;D");

	// Join all lines again with the original line feed
	return `{${lf}${messages.join(`,${lf}`)}${lf}}`;
}
<|endoftext|>


<commit_before>"use strict";

var assert = require('assert');
var markov = require('./markov.js');

describe('Markov chain', function() {
    describe('building model', function() {

	var model = null;

	beforeEach(function() {
	    model = markov.buildModel(2, [
		'the',
		'quick',
		'brown',
		'fox',
		'the',
		'quick'
	    ]);
	});

	it('should provide entries', function() {
	    assert.equal(6, model.entryCount());
	});

	it('should provide frequency analysis', function() {
	    assert.equal(2, model.frequencyOf('the','quick'));
	    assert.equal(1, model.frequencyOf('brown','fox'));
	});
    });

    describe('generating data', function() {

	var createModel = function(predictionContext) {
	    return markov.buildModel(predictionContext, [
		'the',
		'quick',
		'brown',
		'fox',
		'the',
		'quick'
	    ]);
	};

	it('length of sequence', function() {
	    var run = createModel(2).generate(['the'],10);
	    assert.equal(10, run.length);
	});

	it('has appropriate first index', function() {
	    var run = createModel(2).generate(['the'],1);
	    assert.deepEqual(['the'],run);
	});

	it('generates words', function() {
	    var run = createModel(2).generate(['the'],2);
	    assert.deepEqual(['the','quick'],run);
	});

	it('requires the right prime', function() {
	    assert.throws(function() {
		createModel(2).generate([],2);
	    });
	});

	it.only('generates words with wider window', function() {
	    var run = createModel(3).generate(['the','quick'],3);
	    assert.deepEqual(['the','quick','brown'], run);
	});
    });

    describe('larger prediction context', function() {
	it('should count the frequency of n', function() {
	    var model = markov.buildModel(3, ['a','b','c','d','e']);
	    assert.equal(1, model.frequencyOf('a','b','c'));
	});

	it('should have a wide window', function() {
	    var model = markov.buildModel(4, ['a','b','c','d','e']);
	    assert.equal(1, model.frequencyOf('a','b','c','d'));
	});
    });
});
<commit_msg>now all tests pass<commit_after>"use strict";

var assert = require('assert');
var markov = require('./markov.js');

describe('Markov chain', function() {
    describe('building model', function() {

	var model = null;

	beforeEach(function() {
	    model = markov.buildModel(2, [
		'the',
		'quick',
		'brown',
		'fox',
		'the',
		'quick'
	    ]);
	});

	it('should provide entries', function() {
	    assert.equal(6, model.entryCount());
	});

	it('should provide frequency analysis', function() {
	    assert.equal(2, model.frequencyOf('the','quick'));
	    assert.equal(1, model.frequencyOf('brown','fox'));
	});
    });

    describe('generating data', function() {

	var createModel = function(predictionContext) {
	    return markov.buildModel(predictionContext, [
		'the',
		'quick',
		'brown',
		'fox',
		'the',
		'quick'
	    ]);
	};

	it('length of sequence', function() {
	    var run = createModel(2).generate(['the'],10);
	    assert.equal(10, run.length);
	});

	it('has appropriate first index', function() {
	    var run = createModel(2).generate(['the'],1);
	    assert.deepEqual(['the'],run);
	});

	it('generates words', function() {
	    var run = createModel(2).generate(['the'],2);
	    assert.deepEqual(['the','quick'],run);
	});

	it('requires the right prime', function() {
	    assert.throws(function() {
		createModel(2).generate([],2);
	    });
	});

	it('generates words with wider window', function() {
	    var run = createModel(3).generate(['the','quick'],3);
	    assert.deepEqual(['the','quick','brown'], run);
	});
    });

    describe('larger prediction context', function() {
	it('should count the frequency of n', function() {
	    var model = markov.buildModel(3, ['a','b','c','d','e']);
	    assert.equal(1, model.frequencyOf('a','b','c'));
	});

	it('should have a wide window', function() {
	    var model = markov.buildModel(4, ['a','b','c','d','e']);
	    assert.equal(1, model.frequencyOf('a','b','c','d'));
	});
    });
});
<|endoftext|>