<commit_before>require("ember-inflector/system");

var get = Ember.get, set = Ember.set;

/**
  @module ember-data
*/

/*
  This file defines several extensions to the base `DS.Model` class that
  add support for one-to-many relationships.
*/

/**
  @class Model
  @namespace DS
*/
DS.Model.reopen({

  /**
    This Ember.js hook allows an object to be notified when a property
    is defined.

    In this case, we use it to be notified when an Ember Data user defines a
    belongs-to relationship. In that case, we need to set up observers for
    each one, allowing us to track relationship changes and automatically
    reflect changes in the inverse has-many array.

    This hook passes the class being set up, as well as the key and value
    being defined. So, for example, when the user does this:

      DS.Model.extend({
        parent: DS.belongsTo('user')
      });

    This hook would be called with "parent" as the key and the computed
    property returned by `DS.belongsTo` as the value.

    @method didDefineProperty
    @param proto
    @param key
    @param value
  */
  didDefineProperty: function(proto, key, value) {
    // Check if the value being set is a computed property.
    if (value instanceof Ember.Descriptor) {

      // If it is, get the metadata for the relationship. This is
      // populated by the `DS.belongsTo` helper when it is creating
      // the computed property.
      var meta = value.meta();

      if (meta.isRelationship && meta.kind === 'belongsTo') {
        Ember.addObserver(proto, key, null, 'belongsToDidChange');
        Ember.addBeforeObserver(proto, key, null, 'belongsToWillChange');
      }

      meta.parentType = proto.constructor;
    }
  }
});

/*
  These DS.Model extensions add class methods that provide relationship
  introspection abilities about relationships.

  A note about the computed properties contained here:

  **These properties are effectively sealed once called for the first time.**
  To avoid repeatedly doing expensive iteration over a model's fields, these
  values are computed once and then cached for the remainder of the runtime of
  your application.

  If your application needs to modify a class after its initial definition
  (for example, using `reopen()` to add additional attributes), make sure you
  do it before using your model with the store, which uses these properties
  extensively.
*/

DS.Model.reopenClass({
  /**
    For a given relationship name, returns the model type of the relationship.

    For example, if you define a model like this:

        App.Post = DS.Model.extend({
          comments: DS.hasMany('comment')
        });

    Calling `App.Post.typeForRelationship('comments')` will return `App.Comment`.

    @method typeForRelationship
    @static
    @param {String} name the name of the relationship
    @return {subclass of DS.Model} the type of the relationship, or undefined
  */
  typeForRelationship: function(name) {
    var relationship = get(this, 'relationshipsByName').get(name);
    return relationship && relationship.type;
  },

  inverseFor: function(name) {
    var inverseType = this.typeForRelationship(name);

    if (!inverseType) { return null; }

    var options = this.metaForProperty(name).options;

    if (options.inverse === null) { return null; }

    var inverseName, inverseKind;

    if (options.inverse) {
      inverseName = options.inverse;
      inverseKind = Ember.get(inverseType, 'relationshipsByName').get(inverseName).kind;
    } else {
      var possibleRelationships = findPossibleInverses(this, inverseType);

      if (possibleRelationships.length === 0) { return null; }

      Ember.assert("You defined the '" + name + "' relationship on " + this + ", but multiple possible inverse relationships of type " + this + " were found on " + inverseType + ".", possibleRelationships.length === 1);

      inverseName = possibleRelationships[0].name;
      inverseKind = possibleRelationships[0].kind;
    }

    function findPossibleInverses(type, inverseType, possibleRelationships) {
      possibleRelationships = possibleRelationships || [];

      var relationshipMap = get(inverseType, 'relationships');
      if (!relationshipMap) { return; }

      var relationships = relationshipMap.get(type);
      if (relationships) {
        possibleRelationships.push.apply(possibleRelationships, relationshipMap.get(type));
      }

      if (type.superclass) {
        findPossibleInverses(type.superclass, inverseType, possibleRelationships);
      }

      return possibleRelationships;
    }

    return {
      type: inverseType,
      name: inverseName,
      kind: inverseKind
    };
  },

  /**
    The model's relationships as a map, keyed on the type of the
    relationship. The value of each entry is an array containing a descriptor
    for each relationship with that type, describing the name of the relationship
    as well as the type.

    For example, given the following model definition:

        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),
          posts: DS.hasMany('post')
        });

    This computed property would return a map describing these
    relationships, like this:

        var relationships = Ember.get(App.Blog, 'relationships');
        relationships.get(App.User);
        //=> [ { name: 'users', kind: 'hasMany' },
        //     { name: 'owner', kind: 'belongsTo' } ]
        relationships.get(App.Post);
        //=> [ { name: 'posts', kind: 'hasMany' } ]

    @property relationships
    @static
    @type Ember.Map
    @readOnly
  */
  relationships: Ember.computed(function() {
    var map = new Ember.MapWithDefault({
      defaultValue: function() { return []; }
    });

    // Loop through each computed property on the class
    this.eachComputedProperty(function(name, meta) {

      // If the computed property is a relationship, add
      // it to the map.
      if (meta.isRelationship) {
        if (typeof meta.type === 'string') {
          meta.type = this.store.modelFor(meta.type);
        }

        var relationshipsForType = map.get(meta.type);

        relationshipsForType.push({ name: name, kind: meta.kind });
      }
    });

    return map;
  }),

  /**
    A hash containing lists of the model's relationships, grouped
    by the relationship kind. For example, given a model with this
    definition:

        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post')
        });

    This property would contain the following:

       var relationshipNames = Ember.get(App.Blog, 'relationshipNames');
       relationshipNames.hasMany;
       //=> ['users', 'posts']
       relationshipNames.belongsTo;
       //=> ['owner']

    @property relationshipNames
    @static
    @type Object
    @readOnly
  */
  relationshipNames: Ember.computed(function() {
    var names = { hasMany: [], belongsTo: [] };

    this.eachComputedProperty(function(name, meta) {
      if (meta.isRelationship) {
        names[meta.kind].push(name);
      }
    });

    return names;
  }),

  /**
    An array of types directly related to a model. Each type will be
    included once, regardless of the number of relationships it has with
    the model.

    For example, given a model with this definition:

        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post')
        });

    This property would contain the following:

       var relatedTypes = Ember.get(App.Blog, 'relatedTypes');
       //=> [ App.User, App.Post ]

    @property relatedTypes
    @static
    @type Ember.Array
    @readOnly
  */
  relatedTypes: Ember.computed(function() {
    var type,
        types = Ember.A();

    // Loop through each computed property on the class,
    // and create an array of the unique types involved
    // in relationships
    this.eachComputedProperty(function(name, meta) {
      if (meta.isRelationship) {
        type = meta.type;

        if (typeof type === 'string') {
          type = get(this, type, false) || this.store.modelFor(type);
        }

        Ember.assert("You specified a hasMany (" + meta.type + ") on " + meta.parentType + " but " + meta.type + " was not found.",  type);

        if (!types.contains(type)) {
          Ember.assert("Trying to sideload " + name + " on " + this.toString() + " but the type doesn't exist.", !!type);
          types.push(type);
        }
      }
    });

    return types;
  }),

  /**
    A map whose keys are the relationships of a model and whose values are
    relationship descriptors.

    For example, given a model with this
    definition:

        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post')
        });

    This property would contain the following:

       var relationshipsByName = Ember.get(App.Blog, 'relationshipsByName');
       relationshipsByName.get('users');
       //=> { key: 'users', kind: 'hasMany', type: App.User }
       relationshipsByName.get('owner');
       //=> { key: 'owner', kind: 'belongsTo', type: App.User }

    @property relationshipsByName
    @static
    @type Ember.Map
    @readOnly
  */
  relationshipsByName: Ember.computed(function() {
    var map = Ember.Map.create(), type;

    this.eachComputedProperty(function(name, meta) {
      if (meta.isRelationship) {
        meta.key = name;
        type = meta.type;

        if (!type && meta.kind === 'hasMany') {
          type = Ember.String.singularize(name);
        } else if (!type) {
          type = name;
        }

        if (typeof type === 'string') {
          meta.type = this.store.modelFor(type);
        }

        map.set(name, meta);
      }
    });

    return map;
  }),

  /**
    A map whose keys are the fields of the model and whose values are strings
    describing the kind of the field. A model's fields are the union of all of its
    attributes and relationships.

    For example:

        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post'),

          title: DS.attr('string')
        });

        var fields = Ember.get(App.Blog, 'fields');
        fields.forEach(function(field, kind) {
          console.log(field, kind);
        });

        // prints:
        // users, hasMany
        // owner, belongsTo
        // posts, hasMany
        // title, attribute

    @property fields
    @static
    @type Ember.Map
    @readOnly
  */
  fields: Ember.computed(function() {
    var map = Ember.Map.create();

    this.eachComputedProperty(function(name, meta) {
      if (meta.isRelationship) {
        map.set(name, meta.kind);
      } else if (meta.isAttribute) {
        map.set(name, 'attribute');
      }
    });

    return map;
  }),

  /**
    Given a callback, iterates over each of the relationships in the model,
    invoking the callback with the name of each relationship and its relationship
    descriptor.

    @method eachRelationship
    @static
    @param {Function} callback the callback to invoke
    @param {any} binding the value to which the callback's `this` should be bound
  */
  eachRelationship: function(callback, binding) {
    get(this, 'relationshipsByName').forEach(function(name, relationship) {
      callback.call(binding, name, relationship);
    });
  },

  /**
    Given a callback, iterates over each of the types related to a model,
    invoking the callback with the related type's class. Each type will be
    returned just once, regardless of how many different relationships it has
    with a model.

    @method eachRelatedType
    @static
    @param {Function} callback the callback to invoke
    @param {any} binding the value to which the callback's `this` should be bound
  */
  eachRelatedType: function(callback, binding) {
    get(this, 'relatedTypes').forEach(function(type) {
      callback.call(binding, type);
    });
  }
});

DS.Model.reopen({
  /**
    Given a callback, iterates over each of the relationships in the model,
    invoking the callback with the name of each relationship and its relationship
    descriptor.

    @method eachRelationship
    @param {Function} callback the callback to invoke
    @param {any} binding the value to which the callback's `this` should be bound
  */
  eachRelationship: function(callback, binding) {
    this.constructor.eachRelationship(callback, binding);
  }
});
<commit_msg>make inverse error more user friendly<commit_after>require("ember-inflector/system");

var get = Ember.get, set = Ember.set;

/**
  @module ember-data
*/

/*
  This file defines several extensions to the base `DS.Model` class that
  add support for one-to-many relationships.
*/

/**
  @class Model
  @namespace DS
*/
DS.Model.reopen({

  /**
    This Ember.js hook allows an object to be notified when a property
    is defined.

    In this case, we use it to be notified when an Ember Data user defines a
    belongs-to relationship. In that case, we need to set up observers for
    each one, allowing us to track relationship changes and automatically
    reflect changes in the inverse has-many array.

    This hook passes the class being set up, as well as the key and value
    being defined. So, for example, when the user does this:

      DS.Model.extend({
        parent: DS.belongsTo('user')
      });

    This hook would be called with "parent" as the key and the computed
    property returned by `DS.belongsTo` as the value.

    @method didDefineProperty
    @param proto
    @param key
    @param value
  */
  didDefineProperty: function(proto, key, value) {
    // Check if the value being set is a computed property.
    if (value instanceof Ember.Descriptor) {

      // If it is, get the metadata for the relationship. This is
      // populated by the `DS.belongsTo` helper when it is creating
      // the computed property.
      var meta = value.meta();

      if (meta.isRelationship && meta.kind === 'belongsTo') {
        Ember.addObserver(proto, key, null, 'belongsToDidChange');
        Ember.addBeforeObserver(proto, key, null, 'belongsToWillChange');
      }

      meta.parentType = proto.constructor;
    }
  }
});

/*
  These DS.Model extensions add class methods that provide relationship
  introspection abilities about relationships.

  A note about the computed properties contained here:

  **These properties are effectively sealed once called for the first time.**
  To avoid repeatedly doing expensive iteration over a model's fields, these
  values are computed once and then cached for the remainder of the runtime of
  your application.

  If your application needs to modify a class after its initial definition
  (for example, using `reopen()` to add additional attributes), make sure you
  do it before using your model with the store, which uses these properties
  extensively.
*/

DS.Model.reopenClass({
  /**
    For a given relationship name, returns the model type of the relationship.

    For example, if you define a model like this:

        App.Post = DS.Model.extend({
          comments: DS.hasMany('comment')
        });

    Calling `App.Post.typeForRelationship('comments')` will return `App.Comment`.

    @method typeForRelationship
    @static
    @param {String} name the name of the relationship
    @return {subclass of DS.Model} the type of the relationship, or undefined
  */
  typeForRelationship: function(name) {
    var relationship = get(this, 'relationshipsByName').get(name);
    return relationship && relationship.type;
  },

  inverseFor: function(name) {
    var inverseType = this.typeForRelationship(name);

    if (!inverseType) { return null; }

    var options = this.metaForProperty(name).options;

    if (options.inverse === null) { return null; }

    var inverseName, inverseKind;

    if (options.inverse) {
      inverseName = options.inverse;
      inverseKind = Ember.get(inverseType, 'relationshipsByName').get(inverseName).kind;
    } else {
      var possibleRelationships = findPossibleInverses(this, inverseType);

      if (possibleRelationships.length === 0) { return null; }

      Ember.assert("You defined the '" + name + "' relationship on " + this + ", but multiple possible inverse relationships of type " + this + " were found on " + inverseType + ". Look at http://emberjs.com/guides/models/defining-models/#toc_explicit-inverses for how to explicitly specify inverses", possibleRelationships.length === 1);

      inverseName = possibleRelationships[0].name;
      inverseKind = possibleRelationships[0].kind;
    }

    function findPossibleInverses(type, inverseType, possibleRelationships) {
      possibleRelationships = possibleRelationships || [];

      var relationshipMap = get(inverseType, 'relationships');
      if (!relationshipMap) { return; }

      var relationships = relationshipMap.get(type);
      if (relationships) {
        possibleRelationships.push.apply(possibleRelationships, relationshipMap.get(type));
      }

      if (type.superclass) {
        findPossibleInverses(type.superclass, inverseType, possibleRelationships);
      }

      return possibleRelationships;
    }

    return {
      type: inverseType,
      name: inverseName,
      kind: inverseKind
    };
  },

  /**
    The model's relationships as a map, keyed on the type of the
    relationship. The value of each entry is an array containing a descriptor
    for each relationship with that type, describing the name of the relationship
    as well as the type.

    For example, given the following model definition:

        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),
          posts: DS.hasMany('post')
        });

    This computed property would return a map describing these
    relationships, like this:

        var relationships = Ember.get(App.Blog, 'relationships');
        relationships.get(App.User);
        //=> [ { name: 'users', kind: 'hasMany' },
        //     { name: 'owner', kind: 'belongsTo' } ]
        relationships.get(App.Post);
        //=> [ { name: 'posts', kind: 'hasMany' } ]

    @property relationships
    @static
    @type Ember.Map
    @readOnly
  */
  relationships: Ember.computed(function() {
    var map = new Ember.MapWithDefault({
      defaultValue: function() { return []; }
    });

    // Loop through each computed property on the class
    this.eachComputedProperty(function(name, meta) {

      // If the computed property is a relationship, add
      // it to the map.
      if (meta.isRelationship) {
        if (typeof meta.type === 'string') {
          meta.type = this.store.modelFor(meta.type);
        }

        var relationshipsForType = map.get(meta.type);

        relationshipsForType.push({ name: name, kind: meta.kind });
      }
    });

    return map;
  }),

  /**
    A hash containing lists of the model's relationships, grouped
    by the relationship kind. For example, given a model with this
    definition:

        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post')
        });

    This property would contain the following:

       var relationshipNames = Ember.get(App.Blog, 'relationshipNames');
       relationshipNames.hasMany;
       //=> ['users', 'posts']
       relationshipNames.belongsTo;
       //=> ['owner']

    @property relationshipNames
    @static
    @type Object
    @readOnly
  */
  relationshipNames: Ember.computed(function() {
    var names = { hasMany: [], belongsTo: [] };

    this.eachComputedProperty(function(name, meta) {
      if (meta.isRelationship) {
        names[meta.kind].push(name);
      }
    });

    return names;
  }),

  /**
    An array of types directly related to a model. Each type will be
    included once, regardless of the number of relationships it has with
    the model.

    For example, given a model with this definition:

        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post')
        });

    This property would contain the following:

       var relatedTypes = Ember.get(App.Blog, 'relatedTypes');
       //=> [ App.User, App.Post ]

    @property relatedTypes
    @static
    @type Ember.Array
    @readOnly
  */
  relatedTypes: Ember.computed(function() {
    var type,
        types = Ember.A();

    // Loop through each computed property on the class,
    // and create an array of the unique types involved
    // in relationships
    this.eachComputedProperty(function(name, meta) {
      if (meta.isRelationship) {
        type = meta.type;

        if (typeof type === 'string') {
          type = get(this, type, false) || this.store.modelFor(type);
        }

        Ember.assert("You specified a hasMany (" + meta.type + ") on " + meta.parentType + " but " + meta.type + " was not found.",  type);

        if (!types.contains(type)) {
          Ember.assert("Trying to sideload " + name + " on " + this.toString() + " but the type doesn't exist.", !!type);
          types.push(type);
        }
      }
    });

    return types;
  }),

  /**
    A map whose keys are the relationships of a model and whose values are
    relationship descriptors.

    For example, given a model with this
    definition:

        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post')
        });

    This property would contain the following:

       var relationshipsByName = Ember.get(App.Blog, 'relationshipsByName');
       relationshipsByName.get('users');
       //=> { key: 'users', kind: 'hasMany', type: App.User }
       relationshipsByName.get('owner');
       //=> { key: 'owner', kind: 'belongsTo', type: App.User }

    @property relationshipsByName
    @static
    @type Ember.Map
    @readOnly
  */
  relationshipsByName: Ember.computed(function() {
    var map = Ember.Map.create(), type;

    this.eachComputedProperty(function(name, meta) {
      if (meta.isRelationship) {
        meta.key = name;
        type = meta.type;

        if (!type && meta.kind === 'hasMany') {
          type = Ember.String.singularize(name);
        } else if (!type) {
          type = name;
        }

        if (typeof type === 'string') {
          meta.type = this.store.modelFor(type);
        }

        map.set(name, meta);
      }
    });

    return map;
  }),

  /**
    A map whose keys are the fields of the model and whose values are strings
    describing the kind of the field. A model's fields are the union of all of its
    attributes and relationships.

    For example:

        App.Blog = DS.Model.extend({
          users: DS.hasMany('user'),
          owner: DS.belongsTo('user'),

          posts: DS.hasMany('post'),

          title: DS.attr('string')
        });

        var fields = Ember.get(App.Blog, 'fields');
        fields.forEach(function(field, kind) {
          console.log(field, kind);
        });

        // prints:
        // users, hasMany
        // owner, belongsTo
        // posts, hasMany
        // title, attribute

    @property fields
    @static
    @type Ember.Map
    @readOnly
  */
  fields: Ember.computed(function() {
    var map = Ember.Map.create();

    this.eachComputedProperty(function(name, meta) {
      if (meta.isRelationship) {
        map.set(name, meta.kind);
      } else if (meta.isAttribute) {
        map.set(name, 'attribute');
      }
    });

    return map;
  }),

  /**
    Given a callback, iterates over each of the relationships in the model,
    invoking the callback with the name of each relationship and its relationship
    descriptor.

    @method eachRelationship
    @static
    @param {Function} callback the callback to invoke
    @param {any} binding the value to which the callback's `this` should be bound
  */
  eachRelationship: function(callback, binding) {
    get(this, 'relationshipsByName').forEach(function(name, relationship) {
      callback.call(binding, name, relationship);
    });
  },

  /**
    Given a callback, iterates over each of the types related to a model,
    invoking the callback with the related type's class. Each type will be
    returned just once, regardless of how many different relationships it has
    with a model.

    @method eachRelatedType
    @static
    @param {Function} callback the callback to invoke
    @param {any} binding the value to which the callback's `this` should be bound
  */
  eachRelatedType: function(callback, binding) {
    get(this, 'relatedTypes').forEach(function(type) {
      callback.call(binding, type);
    });
  }
});

DS.Model.reopen({
  /**
    Given a callback, iterates over each of the relationships in the model,
    invoking the callback with the name of each relationship and its relationship
    descriptor.

    @method eachRelationship
    @param {Function} callback the callback to invoke
    @param {any} binding the value to which the callback's `this` should be bound
  */
  eachRelationship: function(callback, binding) {
    this.constructor.eachRelationship(callback, binding);
  }
});
<|endoftext|>


<commit_before>/* eslint-env mocha */
const Graph = require('../../src').DataStructures.Graph;
const assert = require('assert');

describe('Graph', () => {
  it('should be empty when initialized', () => {
    const inst = new Graph();

    assert(inst.isEmpty());
    assert.equal(inst.size, 0);
    assert.deepStrictEqual(inst.vertices, []);
  });
  it('should get neighbours', () => {
    const inst = new Graph();

    inst.addVertex(1);
    inst.addVertex(2);
    inst.addVertex(3);
    inst.addVertex(4);
    inst.addVertex(5);

    inst.addEdge(1, 2, 1);
    inst.addEdge(1, 3, 1);
    inst.addEdge(1, 5, 1);
    inst.addEdge(3, 4, 1);
    inst.addEdge(1, 5, 1);

    assert.deepStrictEqual(inst.getNeighbours(1), ['2', '3', '5']);
  });
});
<commit_msg>Test Graph: Adds test to check for creating Graph<commit_after>/* eslint-env mocha */
const Graph = require('../../src').DataStructures.Graph;
const assert = require('assert');

describe('Graph', () => {
  it('should be empty when initialized', () => {
    const inst = new Graph();

    assert(inst.isEmpty());
    assert.equal(inst.size, 0);
    assert.deepStrictEqual(inst.vertices, []);
  });

  it('should create a graph', () => {
    const inst = new Graph();

    inst.addVertex(1);
    inst.addVertex(2);
    inst.addVertex(3);
    inst.addVertex(4);
    inst.addVertex(5);

    assert.throws(() => inst.addVertex(1));

    inst.addEdge(1, 2, 1);
    inst.addEdge(1, 3, 1);
    inst.addEdge(1, 5, 1);
    inst.addEdge(3, 4, 1);
    inst.addEdge(1, 5, 1);

    assert(!inst.isEmpty());
    assert.equal(inst.size, 5);
    assert.deepStrictEqual(inst.vertices, ['1', '2', '3', '4', '5']);
  });

  it('should get neighbours', () => {
    const inst = new Graph();

    inst.addVertex(1);
    inst.addVertex(2);
    inst.addVertex(3);
    inst.addVertex(4);
    inst.addVertex(5);

    inst.addEdge(1, 2, 1);
    inst.addEdge(1, 3, 1);
    inst.addEdge(1, 5, 1);
    inst.addEdge(3, 4, 1);
    inst.addEdge(1, 5, 1);

    assert.deepStrictEqual(inst.getNeighbours(1), ['2', '3', '5']);
  });
});
<|endoftext|>


<commit_before>// Node.js API.
var fs = require('fs')
var assert = require('assert')

// Control-flow utilities.
var cadence = require('cadence')
var Turnstile = require('turnstile')
Turnstile.Check = require('turnstile/check')

// Pipeline processing and filtering.
var Pipeline = require('prolific.pipeline')
var Acceptor = require('prolific.acceptor')

var interrupt = require('interrupt').createInterrupter('prolific')
var logger = require('prolific.logger').createLogger('prolific.supervisor')

// Construct a processor that will reload it's configuration from the given
// configuration and call the given function with the new in-process Acceptor
// configuration. The in-process Acceptor configuration will be routed to the
// child process we're monitoring and injected into it so that the first round
// of filtering will happen in-process saving copying time.
//
// The given destructible is used to manage the lifecycle of the pipeline and
// its processors.

//
function Processor (destructible, configuration, reloaded) {
    var turnstile = new Turnstile
    turnstile.listen(destructible.monitor('reopen'))
    destructible.destruct.wait(turnstile, 'close')
    this.destroyed = false
    this._configuration = configuration
    this._reloaded = reloaded
    this._check = new Turnstile.Check(this, '_reload', turnstile)
    this._destructible = destructible
    this._destructible.markDestroyed(this)
    this._version = 0
    this._versions = []
}

// This is like the problem of the Chaperon in Compassion that gets an event to
// peform a meta-consensus action, but while it performing service discovery the
// participant it is trying to place shuts down. Not the easiest race to test.
//
// We encountered this already here in testing. We shutdown the monitor in the
// middle of it's first reload and it hung because `Destructible.monitor` is
// called and it has some convoluted logic where if it is destroyed, it wants to
// wait for the destruction to complete, but it won't because our Turnstile is
// waiting for this function to complete, and our Destructible is waiting on the
// Turnstile.
//
// What is the nature of this problem? In the case of Compassion is is
// Happenstance and Destructible interacting, in this case it is Turnstile and
// Destructible interacting. Events that generate new stacks?

//
Processor.prototype._pipeline = cadence(function (async) {
    async(function () {
        fs.readFile(this._configuration, 'utf8', async())
    }, function (configuration) {
        interrupt.assert(!this.destroyed, 'destroyed')
        configuration = JSON.parse(configuration)
        async(function () {
            this._destructible.monitor([ 'pipeline', this._version ], true, Pipeline, configuration.pipeline, async())
        }, function (pipeline, destructible) {
            return [ configuration, pipeline, destructible ]
        })
    })
})

Processor.prototype.load = cadence(function (async) {
    async(function () {
        this._pipeline(async())
    }, function (configuration, pipeline, destructible) {
        this._pipelineDestructible = destructible
        var acceptor = new Acceptor(configuration.accept, configuration.chain)
        this._processor = {
            process: function (entry) {
                if (acceptor.acceptByContext(entry)) {
                    pipeline.process(entry)
                }
            }
        }
    })
})

Processor.prototype.updated = cadence(function (async, version) {
    var configuration = this._versions.shift()
    assert(version == configuration.version)
    this._processor = configuration.processor
    configuration.destructible.completed.wait(async())
    configuration.destructible.destroy()
})

Processor.prototype.process = cadence(function (async, envelope) {
    var lines = envelope.body.buffer.toString().split('\n')
    if (lines[lines.length - 1].length == 0) {
        lines.pop()
    }
    var entries = lines.map(JSON.parse)
    var loop = async(function () {
        while (entries.length && !Array.isArray(entries[0])) {
            console.log(entries)
            this._processor.process(entries.shift())
        }
        if (entries.length == 0) {
            return [ loop.break ]
        } else {
            this.updated(entries.shift()[0].version, async())
        }
    })()
})

Processor.prototype._reload = cadence(function (async, configuration) {
    async([function () {
        this._pipeline(async())
    }, function (error) {
        // TODO Logging with the notion of a separate log for the monitor.
        logger.error('pipeline', { configuration: configuration, error: error.stack })
        return [ async.break, null ]
    }], function (configuration, pipeline, destructible) {
        var version = this._version++
        this._versions.push({
            destructible: this._pipelineDestructible,
            version: version,
            processor: pipeline
        })
        this._pipelineDestructible = destructible
        this._reloaded({ version: version, accept: configuration.accept, chain: configuration.chain })
        return [ configuration ]
    })
})

Processor.prototype.reload = function (callback) {
    this._check.check(callback)
}

module.exports = cadence(function (async, destructible, configuration, reloaded) {
    var processor = new Processor(destructible, configuration, reloaded)
    async(function () {
        processor.load(async())
    }, function () {
        return [ processor ]
    })
})
<commit_msg>Remove debugging message.<commit_after>// Node.js API.
var fs = require('fs')
var assert = require('assert')

// Control-flow utilities.
var cadence = require('cadence')
var Turnstile = require('turnstile')
Turnstile.Check = require('turnstile/check')

// Pipeline processing and filtering.
var Pipeline = require('prolific.pipeline')
var Acceptor = require('prolific.acceptor')

var interrupt = require('interrupt').createInterrupter('prolific')
var logger = require('prolific.logger').createLogger('prolific.supervisor')

// Construct a processor that will reload it's configuration from the given
// configuration and call the given function with the new in-process Acceptor
// configuration. The in-process Acceptor configuration will be routed to the
// child process we're monitoring and injected into it so that the first round
// of filtering will happen in-process saving copying time.
//
// The given destructible is used to manage the lifecycle of the pipeline and
// its processors.

//
function Processor (destructible, configuration, reloaded) {
    var turnstile = new Turnstile
    turnstile.listen(destructible.monitor('reopen'))
    destructible.destruct.wait(turnstile, 'close')
    this.destroyed = false
    this._configuration = configuration
    this._reloaded = reloaded
    this._check = new Turnstile.Check(this, '_reload', turnstile)
    this._destructible = destructible
    this._destructible.markDestroyed(this)
    this._version = 0
    this._versions = []
}

// This is like the problem of the Chaperon in Compassion that gets an event to
// peform a meta-consensus action, but while it performing service discovery the
// participant it is trying to place shuts down. Not the easiest race to test.
//
// We encountered this already here in testing. We shutdown the monitor in the
// middle of it's first reload and it hung because `Destructible.monitor` is
// called and it has some convoluted logic where if it is destroyed, it wants to
// wait for the destruction to complete, but it won't because our Turnstile is
// waiting for this function to complete, and our Destructible is waiting on the
// Turnstile.
//
// What is the nature of this problem? In the case of Compassion is is
// Happenstance and Destructible interacting, in this case it is Turnstile and
// Destructible interacting. Events that generate new stacks?

//
Processor.prototype._pipeline = cadence(function (async) {
    async(function () {
        fs.readFile(this._configuration, 'utf8', async())
    }, function (configuration) {
        interrupt.assert(!this.destroyed, 'destroyed')
        configuration = JSON.parse(configuration)
        async(function () {
            this._destructible.monitor([ 'pipeline', this._version ], true, Pipeline, configuration.pipeline, async())
        }, function (pipeline, destructible) {
            return [ configuration, pipeline, destructible ]
        })
    })
})

Processor.prototype.load = cadence(function (async) {
    async(function () {
        this._pipeline(async())
    }, function (configuration, pipeline, destructible) {
        this._pipelineDestructible = destructible
        var acceptor = new Acceptor(configuration.accept, configuration.chain)
        this._processor = {
            process: function (entry) {
                if (acceptor.acceptByContext(entry)) {
                    pipeline.process(entry)
                }
            }
        }
    })
})

Processor.prototype.updated = cadence(function (async, version) {
    var configuration = this._versions.shift()
    assert(version == configuration.version)
    this._processor = configuration.processor
    configuration.destructible.completed.wait(async())
    configuration.destructible.destroy()
})

Processor.prototype.process = cadence(function (async, envelope) {
    var lines = envelope.body.buffer.toString().split('\n')
    if (lines[lines.length - 1].length == 0) {
        lines.pop()
    }
    var entries = lines.map(JSON.parse)
    var loop = async(function () {
        while (entries.length && !Array.isArray(entries[0])) {
            this._processor.process(entries.shift())
        }
        if (entries.length == 0) {
            return [ loop.break ]
        } else {
            this.updated(entries.shift()[0].version, async())
        }
    })()
})

Processor.prototype._reload = cadence(function (async, configuration) {
    async([function () {
        this._pipeline(async())
    }, function (error) {
        // TODO Logging with the notion of a separate log for the monitor.
        logger.error('pipeline', { configuration: configuration, error: error.stack })
        return [ async.break, null ]
    }], function (configuration, pipeline, destructible) {
        var version = this._version++
        this._versions.push({
            destructible: this._pipelineDestructible,
            version: version,
            processor: pipeline
        })
        this._pipelineDestructible = destructible
        this._reloaded({ version: version, accept: configuration.accept, chain: configuration.chain })
        return [ configuration ]
    })
})

Processor.prototype.reload = function (callback) {
    this._check.check(callback)
}

module.exports = cadence(function (async, destructible, configuration, reloaded) {
    var processor = new Processor(destructible, configuration, reloaded)
    async(function () {
        processor.load(async())
    }, function () {
        return [ processor ]
    })
})
<|endoftext|>


<commit_before>'use strict';

angular.module('metadatamanagementApp')
  .config(function($stateProvider) {
    $stateProvider
      .state('variable', {
        parent: 'entity',
        url: '/variables?{page, query}',
        data: {
          authorities: ['ROLE_USER'],
          pageTitle: 'metadatamanagementApp.variable.home.title'
        },
        views: {
          'content@': {
            templateUrl: 'scripts/variablemanagement/' +
            'views/variables.html.tmpl',
            controller: 'VariableController'
          }
        },
        resolve: {
          translatePartialLoader: ['$translate', '$translatePartialLoader',
            function($translate, $translatePartialLoader) {
              $translatePartialLoader.addPart('variablesearch');
              $translatePartialLoader.addPart('pagination');
              $translatePartialLoader.addPart('variable');
              $translatePartialLoader.addPart('global');
              return $translate.refresh();
            }
          ]
        },
        reloadOnSearch: false
      })
      .state('variable.new', {
        parent: 'variable',
        url: '/new',
        data: {
          authorities: ['ROLE_USER'],
        },
        onEnter: ['$stateParams', '$state', '$uibModal', function(
          $stateParams,
          $state, $uibModal) {
          $uibModal.open({
              templateUrl: 'scripts/variablemanagement/views/' +
              'variable-dialog.html.tmpl',
              controller: 'VariableDialogController',
              size: 'lg',
              resolve: {
                entity: ['Variable', function(Variable) {
                  return new Variable();
                }],
                isCreateMode: true
              }
            }).result.then(function() {
              $state.go('variable', null, {
                reload: true
              });
            }, function() {
              $state.go('variable');
            });
        }]
      })
      .state('variable.detail', {
        parent: 'entity',
        url: '/variables/{id}',
        data: {
          authorities: ['ROLE_USER'],
          pageTitle: 'metadatamanagementApp.variable.detail.title'
        },
        views: {
          'content@': {
            templateUrl: 'scripts/variablemanagement/views/' +
              'variable-detail.html.tmpl',
            controller: 'VariableDetailController'
          }
        },
        resolve: {
          translatePartialLoader: ['$translate', '$translatePartialLoader',
            function($translate, $translatePartialLoader) {
              $translatePartialLoader.addPart('variable');
              return $translate.refresh();
            }
          ],
          entity: ['$stateParams', 'Variable', '$q', '$state',
          function($stateParams, Variable, $q, $state) {
            var deferred = $q.defer();
            Variable.get({
                id: $stateParams.id
              }).$promise.
              then(function(data) {
                deferred.resolve(data);
              },
                function() {
                  $state.go('error');});
            return deferred.promise;
          }]
        },
      })
      .state('variable.edit', {
        parent: 'variable',
        url: '/{id}/edit',
        data: {
          authorities: ['ROLE_USER'],
        },
        onEnter: ['$stateParams', '$state', '$uibModal', function(
          $stateParams,
          $state, $uibModal) {
          $uibModal.open({
            templateUrl: 'scripts/variablemanagement/views/' +
              'variable-dialog.html.tmpl',
            controller: 'VariableDialogController',
            size: 'lg',
            resolve: {
              entity: ['Variable', function(Variable) {
                return Variable.get({
                  id: $stateParams.id
                });
              }],
              isCreateMode: false
            }
          }).result.then(function() {
            $state.go('variable', null, {
              reload: true
            });
          }, function() {
            $state.go('^');
          });
        }]
      });
  });
<commit_msg>#396 changed fix to return an angular resource again<commit_after>'use strict';

angular.module('metadatamanagementApp')
  .config(function($stateProvider) {
    $stateProvider
      .state('variable', {
        parent: 'entity',
        url: '/variables?{page, query}',
        data: {
          authorities: ['ROLE_USER'],
          pageTitle: 'metadatamanagementApp.variable.home.title'
        },
        views: {
          'content@': {
            templateUrl: 'scripts/variablemanagement/' +
            'views/variables.html.tmpl',
            controller: 'VariableController'
          }
        },
        resolve: {
          translatePartialLoader: ['$translate', '$translatePartialLoader',
            function($translate, $translatePartialLoader) {
              $translatePartialLoader.addPart('variablesearch');
              $translatePartialLoader.addPart('pagination');
              $translatePartialLoader.addPart('variable');
              $translatePartialLoader.addPart('global');
              return $translate.refresh();
            }
          ]
        },
        reloadOnSearch: false
      })
      .state('variable.new', {
        parent: 'variable',
        url: '/new',
        data: {
          authorities: ['ROLE_USER'],
        },
        onEnter: ['$stateParams', '$state', '$uibModal', function(
          $stateParams,
          $state, $uibModal) {
          $uibModal.open({
              templateUrl: 'scripts/variablemanagement/views/' +
              'variable-dialog.html.tmpl',
              controller: 'VariableDialogController',
              size: 'lg',
              resolve: {
                entity: ['Variable', function(Variable) {
                  return new Variable();
                }],
                isCreateMode: true
              }
            }).result.then(function() {
              $state.go('variable', null, {
                reload: true
              });
            }, function() {
              $state.go('variable');
            });
        }]
      })
      .state('variable.detail', {
        parent: 'entity',
        url: '/variables/{id}',
        data: {
          authorities: ['ROLE_USER'],
          pageTitle: 'metadatamanagementApp.variable.detail.title'
        },
        views: {
          'content@': {
            templateUrl: 'scripts/variablemanagement/views/' +
              'variable-detail.html.tmpl',
            controller: 'VariableDetailController'
          }
        },
        resolve: {
          translatePartialLoader: ['$translate', '$translatePartialLoader',
            function($translate, $translatePartialLoader) {
              $translatePartialLoader.addPart('variable');
              return $translate.refresh();
            }
          ],
          entity: ['$stateParams', 'Variable', '$q', '$state',
          function($stateParams, Variable, $q, $state) {
            return Variable.get({
                id: $stateParams.id
              }).$promise.
              then(function() {
              },
                function() {
                  $state.go('error');});
          }]
        },
      })
      .state('variable.edit', {
        parent: 'variable',
        url: '/{id}/edit',
        data: {
          authorities: ['ROLE_USER'],
        },
        onEnter: ['$stateParams', '$state', '$uibModal', function(
          $stateParams,
          $state, $uibModal) {
          $uibModal.open({
            templateUrl: 'scripts/variablemanagement/views/' +
              'variable-dialog.html.tmpl',
            controller: 'VariableDialogController',
            size: 'lg',
            resolve: {
              entity: ['Variable', function(Variable) {
                return Variable.get({
                  id: $stateParams.id
                });
              }],
              isCreateMode: false
            }
          }).result.then(function() {
            $state.go('variable', null, {
              reload: true
            });
          }, function() {
            $state.go('^');
          });
        }]
      });
  });
<|endoftext|>


<commit_before>require(["require", "view/ui", "data/namer"], function(require, ui, Namer) {
    // find view target
    var target = document.getElementById("tacdom")
            || document.getElementsByClassName("tacdom")[0]
            || document.getElementsByTagName("body")[0];

    // create a Portal view for the game
    var portal = ui.Portal.create(target);

    // create interface to get commander name from user
    var name = Namer.commander(),
        input = ui.TextBox.create("Who leads your warrior band?", name);

    // display the user prompt
    portal.show(input.elem);
});<commit_msg>remove reference to unused dependency<commit_after>require(["view/ui", "data/namer"], function(ui, Namer) {
    // find view target
    var target = document.getElementById("tacdom")
            || document.getElementsByClassName("tacdom")[0]
            || document.getElementsByTagName("body")[0];

    // create a Portal view for the game
    var portal = ui.Portal.create(target);

    // create interface to get commander name from user
    var name = Namer.commander(),
        input = ui.TextBox.create("Who leads your warrior band?", name);

    // display the user prompt
    portal.show(input.elem);
});<|endoftext|>


<commit_before>/*! CCTray Dashboard
 *
 * web-cctray.js
 *
 * @category   Dashboards
 * @author     Nicola Asuni <nicola.asuni@tecnick.com>
 * @copyright  2013-2017 Nicola Asuni - Tecnick.com LTD
 * @license    MIT (see LICENSE)
 * @link       https://github.com/tecnickcom/web-cctray
 */

(function() {

	// get selected dashboard looking at the "d" URL query value
	var urlquery = getUrlQueryParams();
	var mode = urlquery['d'] === undefined ? 'rotate' : urlquery['d'];

	function decodeComp(s) {
		return decodeURIComponent(s.replace(/\+/g, ' '));
	};

	function getUrlQueryParams() {
		var map  = {};
		var query = location.search.substring(1);
		var kv = query.split('&');
		for(var i in kv) {
			var key = kv[i].split('=');
			if (key.length > 1) {
				map[decodeComp(key[0])] = decodeComp(key[1]);
			}
		}
		return map;
	}

	function loadRemoteURL(url, access, mime, callback){
		var xhr = new XMLHttpRequest();
		xhr.onreadystatechange = function(){
			if(xhr.readyState === 4 && xhr.status === 200){
				callback(xhr.responseText);
			}
		}
		xhr.overrideMimeType(mime);
		xhr.open('GET', url, true);
		xhr.withCredentials = true;
		if (access) {
			xhr.setRequestHeaders('Authorization', 'Basic '+btoa(access));
		}
		xhr.send();
	}

	function parseCctray(xml) {
		var obj = {};
		parser = new DOMParser();
		xmlDoc = parser.parseFromString(xml, 'text/xml');
		var xtag = xmlDoc.getElementsByTagName('Project');
		for (var i = 0; i < xtag.length; i++) {
			elem = xtag[i].attributes;
			var attr = {};
			for (var j = 0; j < elem.length; j++) {
				var attribute = elem.item(j);
				attr[attribute.nodeName] = attribute.nodeValue;
			}
			obj[attr['name']] = attr;
		}
		return obj;
	}

	function loadDashboard(config, dlist, idx, max, delay) {
		dashboard = config.dashboard[dlist[idx]];
		loadRemoteURL(dashboard.url, dashboard.access, 'application/xml', function(ctx) {
			xitem = parseCctray(ctx);

			var mainDiv = document.createElement('div');
			mainDiv.id = 'main';
			mainDiv.className = 'main';

			var numRows = dashboard.grid.length;
			for (var r = 0; r < numRows; r++) {

				var rowDiv = document.createElement('div');
				rowDiv.id = 'row_' + r;
				rowDiv.className = 'row';
				rowDiv.style.height = ''+(100 / numRows)+'%';

				row = dashboard.grid[r];
				var numCols = row.length;
				for (var c = 0; c < numCols; c++) {
					var name = row[c];

					var colDiv = document.createElement('div');
					colDiv.style.width = ''+(100 / numCols)+'%';
					colDiv.id = 'col_' + xitem[name].activity;
					colDiv.className = 'status_'+xitem[name].lastBuildStatus;
					colDiv.innerHTML = ''+name+'
'+xitem[name].lastBuildLabel+' - '+xitem[name].lastBuildTime+'';
					rowDiv.appendChild(colDiv);
				}

				mainDiv.appendChild(rowDiv);
			}

			document.body.removeChild(document.body.childNodes[0]);
			document.body.appendChild(mainDiv);
			document.body.style.fontSize = 'calc(1px + '+(dashboard.fontratio / numRows)+'vh';
		});
		// load next dashboard
		idx++;
		if (idx > max) {
			idx = 0;
		}
		setTimeout(loadDashboard, delay, config, dlist, idx, max, delay);
	}

	loadRemoteURL('config/config.json', '', 'application/json', function(cfg) {
		var config = JSON.parse(cfg);
		var numDashboards = config.dashboard.length;
		// select dashboards to display
		var dlist = [];
		for (var i = 0; i < numDashboards; i++) {
			if ((mode == 'rotate') || (config.dashboard[i]['name'] == mode)) {
				dlist.push(i);
			}
		}
		loadDashboard(config, dlist, 0, (dlist.length - 1), (config.refresh * 1000))
	});

})();

<commit_msg>Fix typo<commit_after>/*! CCTray Dashboard
 *
 * web-cctray.js
 *
 * @category   Dashboards
 * @author     Nicola Asuni <nicola.asuni@tecnick.com>
 * @copyright  2013-2017 Nicola Asuni - Tecnick.com LTD
 * @license    MIT (see LICENSE)
 * @link       https://github.com/tecnickcom/web-cctray
 */

(function() {

	// get selected dashboard looking at the "d" URL query value
	var urlquery = getUrlQueryParams();
	var mode = urlquery['d'] === undefined ? 'rotate' : urlquery['d'];

	function decodeComp(s) {
		return decodeURIComponent(s.replace(/\+/g, ' '));
	};

	function getUrlQueryParams() {
		var map  = {};
		var query = location.search.substring(1);
		var kv = query.split('&');
		for(var i in kv) {
			var key = kv[i].split('=');
			if (key.length > 1) {
				map[decodeComp(key[0])] = decodeComp(key[1]);
			}
		}
		return map;
	}

	function loadRemoteURL(url, access, mime, callback){
		var xhr = new XMLHttpRequest();
		xhr.onreadystatechange = function(){
			if(xhr.readyState === 4 && xhr.status === 200){
				callback(xhr.responseText);
			}
		}
		xhr.overrideMimeType(mime);
		xhr.open('GET', url, true);
		xhr.withCredentials = true;
		if (access) {
			xhr.setRequestHeader('Authorization', 'Basic '+btoa(access));
		}
		xhr.send();
	}

	function parseCctray(xml) {
		var obj = {};
		parser = new DOMParser();
		xmlDoc = parser.parseFromString(xml, 'text/xml');
		var xtag = xmlDoc.getElementsByTagName('Project');
		for (var i = 0; i < xtag.length; i++) {
			elem = xtag[i].attributes;
			var attr = {};
			for (var j = 0; j < elem.length; j++) {
				var attribute = elem.item(j);
				attr[attribute.nodeName] = attribute.nodeValue;
			}
			obj[attr['name']] = attr;
		}
		return obj;
	}

	function loadDashboard(config, dlist, idx, max, delay) {
		dashboard = config.dashboard[dlist[idx]];
		loadRemoteURL(dashboard.url, dashboard.access, 'application/xml', function(ctx) {
			xitem = parseCctray(ctx);

			var mainDiv = document.createElement('div');
			mainDiv.id = 'main';
			mainDiv.className = 'main';

			var numRows = dashboard.grid.length;
			for (var r = 0; r < numRows; r++) {

				var rowDiv = document.createElement('div');
				rowDiv.id = 'row_' + r;
				rowDiv.className = 'row';
				rowDiv.style.height = ''+(100 / numRows)+'%';

				row = dashboard.grid[r];
				var numCols = row.length;
				for (var c = 0; c < numCols; c++) {
					var name = row[c];

					var colDiv = document.createElement('div');
					colDiv.style.width = ''+(100 / numCols)+'%';
					colDiv.id = 'col_' + xitem[name].activity;
					colDiv.className = 'status_'+xitem[name].lastBuildStatus;
					colDiv.innerHTML = ''+name+'
'+xitem[name].lastBuildLabel+' - '+xitem[name].lastBuildTime+'';
					rowDiv.appendChild(colDiv);
				}

				mainDiv.appendChild(rowDiv);
			}

			document.body.removeChild(document.body.childNodes[0]);
			document.body.appendChild(mainDiv);
			document.body.style.fontSize = 'calc(1px + '+(dashboard.fontratio / numRows)+'vh';
		});
		// load next dashboard
		idx++;
		if (idx > max) {
			idx = 0;
		}
		setTimeout(loadDashboard, delay, config, dlist, idx, max, delay);
	}

	loadRemoteURL('config/config.json', '', 'application/json', function(cfg) {
		var config = JSON.parse(cfg);
		var numDashboards = config.dashboard.length;
		// select dashboards to display
		var dlist = [];
		for (var i = 0; i < numDashboards; i++) {
			if ((mode == 'rotate') || (config.dashboard[i]['name'] == mode)) {
				dlist.push(i);
			}
		}
		loadDashboard(config, dlist, 0, (dlist.length - 1), (config.refresh * 1000))
	});

})();

<|endoftext|>


<commit_before>module.exports = function (config) {
  config.set({
    browsers: ['PhantomJS'],
    frameworks: ['mocha', 'sinon', 'chai'],
    files: ['./src/**/*Spec.js'],
    preprocessors: {
      './src/**/*.js': ['webpack']
    },
    webpack: {
      module: {
        loaders: [
          {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/
          },
          {
            test: /\.vue$/,
            loader: 'vue-loader'
          }
        ]
      }
    },

    webpackMiddleware: {
      noInfo: true
    }
  });
};<commit_msg>Fix unit tests<commit_after>var path = require('path')

module.exports = function (config) {
  config.set({
    browsers: ['PhantomJS'],
    frameworks: ['mocha', 'sinon', 'chai'],
    files: ['./src/**/*Spec.js'],
    preprocessors: {
      './src/**/*.js': ['webpack']
    },
    webpack: {
      resolve: {
        modules: [
          path.resolve('./src'),
          path.resolve('./node_modules')
        ]
      },
      module: {
        loaders: [
          {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/
          },
          {
            test: /\.vue$/,
            loader: 'vue-loader'
          }
        ]
      }
    },

    webpackMiddleware: {
      noInfo: true
    }
  });
};
<|endoftext|>


<commit_before>goog.provide('lime.animation.Loop');

goog.require('goog.math.Coordinate');
goog.require('lime.Sprite');
goog.require('lime.animation.Animation');

/**
 * Loop animation again after it has finished
 * @constructor
 * @param {lime.animation.Animation} action Animation to loop.
 * @extends lime.animation.Animation
 */
lime.animation.Loop = function(action) {

    lime.animation.Animation.call(this);

    this.action_ = action;
    goog.events.listen(action, lime.animation.Event.STOP,
        this.handleActionEnd_, false, this);

    this.setLimit(0);

    this.timesRun_ = 0;

    this.playing_ = 0;

    this.setDuration(action.duration_);

};
goog.inherits(lime.animation.Loop, lime.animation.Animation);

/**
 * @inheritDoc
 * @see lime.animation.Animation#makeTargetProp
 */
lime.animation.Loop.prototype.initTarget = function(target) {
    lime.animation.Animation.prototype.initTarget.call(this, target);

    this.setDuration(this.action_.duration_);
};

/**
 * Return the run limit value for animation. 0 means no limit.
 * @return {number} Limit.
 */
lime.animation.Loop.prototype.getLimit = function() {
    return this.limit_;
};

/**
 * Set new run limit for animation. 0 means no limit/infinity.
 * @param {number} value New limit value.
 * @return {lime.animation.Loop} object itself.
 */
lime.animation.Loop.prototype.setLimit = function(value) {
    this.limit_ = value;
    this.timesRun_ = 0;
    return this;
};

/**
 * @inheritDoc
 * @see lime.animation.Animation#play
 */
lime.animation.Loop.prototype.play = function() {
    this.action_.play();
    this.playing_ = 1;
    this.dispatchEvent({type: lime.animation.Event.START});
};

/**
 * @inheritDoc
 * @see lime.animation.Animation#stop
 */
lime.animation.Loop.prototype.stop = function() {
    this.playing_ = 0;
    this.action_.stop();
    this.dispatchEvent({type: lime.animation.Event.STOP});

};

/**
 * Handle action end. Start new action or stop if limit reached.
 * @private
 */
lime.animation.Loop.prototype.handleActionEnd_ = function() {
    this.timesRun_++;
    if (this.playing_ && (!this.limit_ || this.timesRun_ < this.limit_)) {
        this.action_.play();
    }
};

/**
 * @inheritDoc
 * @see lime.animation.Animation#addTarget
 */
lime.animation.Loop.prototype.addTarget = function(target) {
    this.action_.addTarget(target);
};

/**
 * @inheritDoc
 * @see lime.animation.Animation#removeTarget
 */
lime.animation.Loop.prototype.removeTarget = function(target) {
    this.action_.removeTarget(target);
};
<commit_msg>Fix: Return this for addTarget/removeTarget in Loop<commit_after>goog.provide('lime.animation.Loop');

goog.require('goog.math.Coordinate');
goog.require('lime.Sprite');
goog.require('lime.animation.Animation');

/**
 * Loop animation again after it has finished
 * @constructor
 * @param {lime.animation.Animation} action Animation to loop.
 * @extends lime.animation.Animation
 */
lime.animation.Loop = function(action) {

    lime.animation.Animation.call(this);

    this.action_ = action;
    goog.events.listen(action, lime.animation.Event.STOP,
        this.handleActionEnd_, false, this);

    this.setLimit(0);

    this.timesRun_ = 0;

    this.playing_ = 0;

    this.setDuration(action.duration_);

};
goog.inherits(lime.animation.Loop, lime.animation.Animation);

/**
 * @inheritDoc
 * @see lime.animation.Animation#makeTargetProp
 */
lime.animation.Loop.prototype.initTarget = function(target) {
    lime.animation.Animation.prototype.initTarget.call(this, target);

    this.setDuration(this.action_.duration_);
};

/**
 * Return the run limit value for animation. 0 means no limit.
 * @return {number} Limit.
 */
lime.animation.Loop.prototype.getLimit = function() {
    return this.limit_;
};

/**
 * Set new run limit for animation. 0 means no limit/infinity.
 * @param {number} value New limit value.
 * @return {lime.animation.Loop} object itself.
 */
lime.animation.Loop.prototype.setLimit = function(value) {
    this.limit_ = value;
    this.timesRun_ = 0;
    return this;
};

/**
 * @inheritDoc
 * @see lime.animation.Animation#play
 */
lime.animation.Loop.prototype.play = function() {
    this.action_.play();
    this.playing_ = 1;
    this.dispatchEvent({type: lime.animation.Event.START});
};

/**
 * @inheritDoc
 * @see lime.animation.Animation#stop
 */
lime.animation.Loop.prototype.stop = function() {
    this.playing_ = 0;
    this.action_.stop();
    this.dispatchEvent({type: lime.animation.Event.STOP});

};

/**
 * Handle action end. Start new action or stop if limit reached.
 * @private
 */
lime.animation.Loop.prototype.handleActionEnd_ = function() {
    this.timesRun_++;
    if (this.playing_ && (!this.limit_ || this.timesRun_ < this.limit_)) {
        this.action_.play();
    }
};

/**
 * @inheritDoc
 * @see lime.animation.Animation#addTarget
 */
lime.animation.Loop.prototype.addTarget = function(target) {
    this.action_.addTarget(target);
    return this;
};

/**
 * @inheritDoc
 * @see lime.animation.Animation#removeTarget
 */
lime.animation.Loop.prototype.removeTarget = function(target) {
    this.action_.removeTarget(target);
    return this;
};
<|endoftext|>


<commit_before>function leapYear(year) {
  return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
}

function isValidDate(inDate) {
    var valid = true;

    // reformat if supplied as mm.dd.yyyy (period delimiter)
    if (typeof inDate === 'string') {
      var pos = inDate.indexOf('.');
      if ((pos > 0 && pos <= 6)) {
        inDate = inDate.replace(/\./g, '-');
      }
    }

    var testDate = new Date(inDate);
    var yr = testDate.getFullYear();
    var mo = testDate.getMonth() + 1;
    var day = testDate.getDate();

    var daysInMonth = [31, (leapYear(yr) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

    if (yr < 1000) { return false; }
    if (isNaN(mo)) { return false; }
    if (mo > 12) { return false; }
    if (isNaN(day)) { return false; }
    if (day > daysInMonth[mo]) { return false; }

    return valid;
}

var rules = {

  required: function(val) {
    var str;

    if (val === undefined || val === null) {
      return false;
    }

    str = String(val).replace(/\s/g, "");
    return str.length > 0 ? true : false;
  },

  required_if: function(val, req, attribute) {
    req = this.getParameters();
    if (this.validator._objectPath(this.validator.input, req[0]) === req[1]) {
      return this.validator.getRule('required').validate(val);
    }

    return true;
  },

  required_unless: function(val, req, attribute) {
    req = this.getParameters();
    if (this.validator._objectPath(this.validator.input, req[0]) !== req[1]) {
      return this.validator.getRule('required').validate(val);
    }

    return true;
  },

  required_with: function(val, req, attribute) {
    if (this.validator._objectPath(this.validator.input, req)) {
      return this.validator.getRule('required').validate(val);
    }

    return true;
  },

  required_with_all: function(val, req, attribute) {

    req = this.getParameters();

    for(var i = 0; i < req.length; i++) {
      if (!this.validator._objectPath(this.validator.input, req[i])) {
        return true;
      }
    }

    return this.validator.getRule('required').validate(val);
  },

  required_without: function(val, req, attribute) {

    if (this.validator._objectPath(this.validator.input, req)) {
      return true;
    }

    return this.validator.getRule('required').validate(val);
  },

  required_without_all: function(val, req, attribute) {

    req = this.getParameters();

    for(var i = 0; i < req.length; i++) {
      if (this.validator._objectPath(this.validator.input, req[i])) {
        return true;
      }
    }

    return this.validator.getRule('required').validate(val);
  },

  'boolean': function (val) {
    return (
      val === true ||
      val === false ||
      val === 0 ||
      val === 1 ||
      val === '0' ||
      val === '1' ||
      val === 'true' ||
      val === 'false'
    );
  },

  // compares the size of strings
  // with numbers, compares the value
  size: function(val, req, attribute) {
    if (val) {
      req = parseFloat(req);

      var size = this.getSize();

      return size === req;
    }

    return true;
  },

  string: function(val, req, attribute) {
    return typeof val === 'string';
  },

  sometimes: function(val) {
    return true;
  },

  /**
   * Compares the size of strings or the value of numbers if there is a truthy value
   */
  min: function(val, req, attribute) {
    var size = this.getSize();
    return size >= req;
  },

  /**
   * Compares the size of strings or the value of numbers if there is a truthy value
   */
  max: function(val, req, attribute) {
    var size = this.getSize();
    return size <= req;
  },

  between: function(val, req, attribute) {
    req = this.getParameters();
    var size = this.getSize();
    var min = parseFloat(req[0], 10);
    var max = parseFloat(req[1], 10);
    return size >= min && size <= max;
  },

  email: function(val) {
    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(val);
  },

  numeric: function(val) {
    var num;

    num = Number(val); // tries to convert value to a number. useful if value is coming from form element

    if (typeof num === 'number' && !isNaN(num) && typeof val !== 'boolean') {
      return true;
    } else {
      return false;
    }
  },

  array: function(val) {
    return val instanceof Array;
  },

  url: function(url) {
    return (/^https?:\/\/\S+/).test(url);
  },

  alpha: function(val) {
    return (/^[a-zA-Z]+$/).test(val);
  },

  alpha_dash: function(val) {
    return (/^[a-zA-Z0-9_\-]+$/).test(val);
  },

  alpha_num: function(val) {
    return (/^[a-zA-Z0-9]+$/).test(val);
  },

  same: function(val, req) {
    var val1 = this.validator.input[req];
    var val2 = val;

    if (val1 === val2) {
      return true;
    }

    return false;
  },

  different: function(val, req) {
    var val1 = this.validator.input[req];
    var val2 = val;

    if (val1 !== val2) {
      return true;
    }

    return false;
  },

  "in": function(val, req) {
    var list, i;

    if (val) {
      list = req.split(',');
    }

    if (val && !(val instanceof Array)) {
      val = String(val); // if it is a number

      for (i = 0; i < list.length; i++) {
        if (val === list[i]) {
          return true;
        }
      }

      return false;
    }

    if (val && val instanceof Array) {
      for (i = 0; i < val.length; i++) {
        if (list.indexOf(val[i]) < 0) {
          return false;
        }
      }
    }

    return true;
  },

  not_in: function(val, req) {
    var list = req.split(',');
    var len = list.length;
    var returnVal = true;

    val = String(val); // convert val to a string if it is a number

    for (var i = 0; i < len; i++) {
      if (val === list[i]) {
        returnVal = false;
        break;
      }
    }

    return returnVal;
  },

  accepted: function(val) {
    if (val === 'on' || val === 'yes' || val === 1 || val === '1' || val === true) {
      return true;
    }

    return false;
  },

  confirmed: function(val, req, key) {
    var confirmedKey = key + '_confirmation';

    if (this.validator.input[confirmedKey] === val) {
      return true;
    }

    return false;
  },

  integer: function(val) {
    return String(parseInt(val, 10)) === String(val);
  },

  digits: function(val, req) {
    var numericRule = this.validator.getRule('numeric');
    if (numericRule.validate(val) && String(val).length === parseInt(req)) {
      return true;
    }

    return false;
  },

  regex: function(val, req) {
    var mod = /[g|i|m]{1,3}$/;
    var flag = req.match(mod);
    flag = flag ? flag[0] : "";
    req = req.replace(mod, "").slice(1, -1);
    req = new RegExp(req, flag);
    return !!val.match(req);
  },

  date: function(val, format) {
    return isValidDate(val);
  },

  present: function(val) {
    return typeof val !== 'undefined';
  },

  after: function(val, req){
    var val1 = this.validator.input[req];
    var val2 = val;

    if(!isValidDate(val1)){ return false;}
    if(!isValidDate(val2)){ return false;}

    if (new Date(val1).getTime() < new Date(val2).getTime()) {
      return true;
    }

    return false;
  },

   after_or_equal: function(val, req){
    var val1 = this.validator.input[req];
    var val2 = val;

    if(!isValidDate(val1)){ return false;}
    if(!isValidDate(val2)){ return false;}

    if (new Date(val1).getTime() <= new Date(val2).getTime()) {
      return true;
    }

    return false;
  },

  before: function(val, req){
    var val1 = this.validator.input[req];
    var val2 = val;

    if(!isValidDate(val1)){ return false;}
    if(!isValidDate(val2)){ return false;}

    if (new Date(val1).getTime() > new Date(val2).getTime()) {
      return true;
    }

    return false;
  },

   before_or_equal: function(val, req){
    var val1 = this.validator.input[req];
    var val2 = val;

    if(!isValidDate(val1)){ return false;}
    if(!isValidDate(val2)){ return false;}

    if (new Date(val1).getTime() >= new Date(val2).getTime()) {
      return true;
    }

    return false;
  }

};

function Rule(name, fn, async) {
  this.name = name;
  this.fn = fn;
  this.passes = null;
  this.customMessage = undefined;
  this.async = async;
}

Rule.prototype = {

  /**
   * Validate rule
   *
   * @param  {mixed} inputValue
   * @param  {mixed} ruleValue
   * @param  {string} attribute
   * @param  {function} callback
   * @return {boolean|undefined}
   */
  validate: function(inputValue, ruleValue, attribute, callback) {
    var _this = this;
    this._setValidatingData(attribute, inputValue, ruleValue);
    if (typeof callback === 'function') {
      this.callback = callback;
      var handleResponse = function(passes, message) {
        _this.response(passes, message);
      };

      if (this.async) {
        return this.fn.apply(this, [inputValue, ruleValue, attribute, handleResponse]);
      } else {
        return handleResponse(this.fn.apply(this, [inputValue, ruleValue, attribute]));
      }
    }
    return this.fn.apply(this, [inputValue, ruleValue, attribute]);
  },

  /**
   * Set validating data
   *
   * @param {string} attribute
   * @param {mixed} inputValue
   * @param {mixed} ruleValue
   * @return {void}
   */
  _setValidatingData: function(attribute, inputValue, ruleValue) {
    this.attribute = attribute;
    this.inputValue = inputValue;
    this.ruleValue = ruleValue;
  },

  /**
   * Get parameters
   *
   * @return {array}
   */
  getParameters: function() {
    return this.ruleValue ? this.ruleValue.split(',') : [];
  },

  /**
   * Get true size of value
   *
   * @return {integer|float}
   */
  getSize: function() {
    var value = this.inputValue;

    if (value instanceof Array) {
      return value.length;
    }

    if (typeof value === 'number') {
      return value;
    }

    if (this.validator._hasNumericRule(this.attribute)) {
      return parseFloat(value, 10);
    }

    return value.length;
  },

  /**
   * Get the type of value being checked; numeric or string.
   *
   * @return {string}
   */
  _getValueType: function() {

    if (typeof this.inputValue === 'number' || this.validator._hasNumericRule(this.attribute)) {
      return 'numeric';
    }

    return 'string';
  },

  /**
   * Set the async callback response
   *
   * @param  {boolean|undefined} passes  Whether validation passed
   * @param  {string|undefined} message Custom error message
   * @return {void}
   */
  response: function(passes, message) {
    this.passes = (passes === undefined || passes === true);
    this.customMessage = message;
    this.callback(this.passes, message);
  },

  /**
   * Set validator instance
   *
   * @param {Validator} validator
   * @return {void}
   */
  setValidator: function(validator) {
    this.validator = validator;
  }

};

var manager = {

  /**
   * List of async rule names
   *
   * @type {Array}
   */
  asyncRules: [],

  /**
   * Implicit rules (rules to always validate)
   *
   * @type {Array}
   */
  implicitRules: ['required', 'required_if', 'required_unless', 'required_with', 'required_with_all', 'required_without', 'required_without_all', 'accepted', 'present'],

  /**
   * Get rule by name
   *
   * @param  {string} name
   * @param {Validator}
   * @return {Rule}
   */
  make: function(name, validator) {
    var async = this.isAsync(name);
    var rule = new Rule(name, rules[name], async);
    rule.setValidator(validator);
    return rule;
  },

  /**
   * Determine if given rule is async
   *
   * @param  {string}  name
   * @return {boolean}
   */
  isAsync: function(name) {
    for (var i = 0, len = this.asyncRules.length; i < len; i++) {
      if (this.asyncRules[i] === name) {
        return true;
      }
    }
    return false;
  },

  /**
   * Determine if rule is implicit (should always validate)
   *
   * @param {string} name
   * @return {boolean}
   */
  isImplicit: function(name) {
    return this.implicitRules.indexOf(name) > -1;
  },

  /**
   * Register new rule
   *
   * @param  {string}   name
   * @param  {function} fn
   * @return {void}
   */
  register: function(name, fn) {
    rules[name] = fn;
  },

    /**
   * Register new implicit rule
   *
   * @param  {string}   name
   * @param  {function} fn
   * @return {void}
   */
  registerImplicit: function(name, fn) {
    rules[name] = fn;
    this.implicitRules.push(name);
  },

  /**
   * Register async rule
   *
   * @param  {string}   name
   * @param  {function} fn
   * @return {void}
   */
  registerAsync: function(name, fn) {
    this.register(name, fn);
    this.asyncRules.push(name);
  },

  /**
   * Register implicit async rule
   *
   * @param  {string}   name
   * @param  {function} fn
   * @return {void}
   */
  registerAsyncImplicit: function(name, fn) {
    this.registerImplicit(name, fn);
    this.asyncRules.push(name);
  }

};

module.exports = manager;
<commit_msg>Refactored registerImplicit to call default register function.<commit_after>function leapYear(year) {
  return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
}

function isValidDate(inDate) {
    var valid = true;

    // reformat if supplied as mm.dd.yyyy (period delimiter)
    if (typeof inDate === 'string') {
      var pos = inDate.indexOf('.');
      if ((pos > 0 && pos <= 6)) {
        inDate = inDate.replace(/\./g, '-');
      }
    }

    var testDate = new Date(inDate);
    var yr = testDate.getFullYear();
    var mo = testDate.getMonth() + 1;
    var day = testDate.getDate();

    var daysInMonth = [31, (leapYear(yr) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

    if (yr < 1000) { return false; }
    if (isNaN(mo)) { return false; }
    if (mo > 12) { return false; }
    if (isNaN(day)) { return false; }
    if (day > daysInMonth[mo]) { return false; }

    return valid;
}

var rules = {

  required: function(val) {
    var str;

    if (val === undefined || val === null) {
      return false;
    }

    str = String(val).replace(/\s/g, "");
    return str.length > 0 ? true : false;
  },

  required_if: function(val, req, attribute) {
    req = this.getParameters();
    if (this.validator._objectPath(this.validator.input, req[0]) === req[1]) {
      return this.validator.getRule('required').validate(val);
    }

    return true;
  },

  required_unless: function(val, req, attribute) {
    req = this.getParameters();
    if (this.validator._objectPath(this.validator.input, req[0]) !== req[1]) {
      return this.validator.getRule('required').validate(val);
    }

    return true;
  },

  required_with: function(val, req, attribute) {
    if (this.validator._objectPath(this.validator.input, req)) {
      return this.validator.getRule('required').validate(val);
    }

    return true;
  },

  required_with_all: function(val, req, attribute) {

    req = this.getParameters();

    for(var i = 0; i < req.length; i++) {
      if (!this.validator._objectPath(this.validator.input, req[i])) {
        return true;
      }
    }

    return this.validator.getRule('required').validate(val);
  },

  required_without: function(val, req, attribute) {

    if (this.validator._objectPath(this.validator.input, req)) {
      return true;
    }

    return this.validator.getRule('required').validate(val);
  },

  required_without_all: function(val, req, attribute) {

    req = this.getParameters();

    for(var i = 0; i < req.length; i++) {
      if (this.validator._objectPath(this.validator.input, req[i])) {
        return true;
      }
    }

    return this.validator.getRule('required').validate(val);
  },

  'boolean': function (val) {
    return (
      val === true ||
      val === false ||
      val === 0 ||
      val === 1 ||
      val === '0' ||
      val === '1' ||
      val === 'true' ||
      val === 'false'
    );
  },

  // compares the size of strings
  // with numbers, compares the value
  size: function(val, req, attribute) {
    if (val) {
      req = parseFloat(req);

      var size = this.getSize();

      return size === req;
    }

    return true;
  },

  string: function(val, req, attribute) {
    return typeof val === 'string';
  },

  sometimes: function(val) {
    return true;
  },

  /**
   * Compares the size of strings or the value of numbers if there is a truthy value
   */
  min: function(val, req, attribute) {
    var size = this.getSize();
    return size >= req;
  },

  /**
   * Compares the size of strings or the value of numbers if there is a truthy value
   */
  max: function(val, req, attribute) {
    var size = this.getSize();
    return size <= req;
  },

  between: function(val, req, attribute) {
    req = this.getParameters();
    var size = this.getSize();
    var min = parseFloat(req[0], 10);
    var max = parseFloat(req[1], 10);
    return size >= min && size <= max;
  },

  email: function(val) {
    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(val);
  },

  numeric: function(val) {
    var num;

    num = Number(val); // tries to convert value to a number. useful if value is coming from form element

    if (typeof num === 'number' && !isNaN(num) && typeof val !== 'boolean') {
      return true;
    } else {
      return false;
    }
  },

  array: function(val) {
    return val instanceof Array;
  },

  url: function(url) {
    return (/^https?:\/\/\S+/).test(url);
  },

  alpha: function(val) {
    return (/^[a-zA-Z]+$/).test(val);
  },

  alpha_dash: function(val) {
    return (/^[a-zA-Z0-9_\-]+$/).test(val);
  },

  alpha_num: function(val) {
    return (/^[a-zA-Z0-9]+$/).test(val);
  },

  same: function(val, req) {
    var val1 = this.validator.input[req];
    var val2 = val;

    if (val1 === val2) {
      return true;
    }

    return false;
  },

  different: function(val, req) {
    var val1 = this.validator.input[req];
    var val2 = val;

    if (val1 !== val2) {
      return true;
    }

    return false;
  },

  "in": function(val, req) {
    var list, i;

    if (val) {
      list = req.split(',');
    }

    if (val && !(val instanceof Array)) {
      val = String(val); // if it is a number

      for (i = 0; i < list.length; i++) {
        if (val === list[i]) {
          return true;
        }
      }

      return false;
    }

    if (val && val instanceof Array) {
      for (i = 0; i < val.length; i++) {
        if (list.indexOf(val[i]) < 0) {
          return false;
        }
      }
    }

    return true;
  },

  not_in: function(val, req) {
    var list = req.split(',');
    var len = list.length;
    var returnVal = true;

    val = String(val); // convert val to a string if it is a number

    for (var i = 0; i < len; i++) {
      if (val === list[i]) {
        returnVal = false;
        break;
      }
    }

    return returnVal;
  },

  accepted: function(val) {
    if (val === 'on' || val === 'yes' || val === 1 || val === '1' || val === true) {
      return true;
    }

    return false;
  },

  confirmed: function(val, req, key) {
    var confirmedKey = key + '_confirmation';

    if (this.validator.input[confirmedKey] === val) {
      return true;
    }

    return false;
  },

  integer: function(val) {
    return String(parseInt(val, 10)) === String(val);
  },

  digits: function(val, req) {
    var numericRule = this.validator.getRule('numeric');
    if (numericRule.validate(val) && String(val).length === parseInt(req)) {
      return true;
    }

    return false;
  },

  regex: function(val, req) {
    var mod = /[g|i|m]{1,3}$/;
    var flag = req.match(mod);
    flag = flag ? flag[0] : "";
    req = req.replace(mod, "").slice(1, -1);
    req = new RegExp(req, flag);
    return !!val.match(req);
  },

  date: function(val, format) {
    return isValidDate(val);
  },

  present: function(val) {
    return typeof val !== 'undefined';
  },

  after: function(val, req){
    var val1 = this.validator.input[req];
    var val2 = val;

    if(!isValidDate(val1)){ return false;}
    if(!isValidDate(val2)){ return false;}

    if (new Date(val1).getTime() < new Date(val2).getTime()) {
      return true;
    }

    return false;
  },

   after_or_equal: function(val, req){
    var val1 = this.validator.input[req];
    var val2 = val;

    if(!isValidDate(val1)){ return false;}
    if(!isValidDate(val2)){ return false;}

    if (new Date(val1).getTime() <= new Date(val2).getTime()) {
      return true;
    }

    return false;
  },

  before: function(val, req){
    var val1 = this.validator.input[req];
    var val2 = val;

    if(!isValidDate(val1)){ return false;}
    if(!isValidDate(val2)){ return false;}

    if (new Date(val1).getTime() > new Date(val2).getTime()) {
      return true;
    }

    return false;
  },

   before_or_equal: function(val, req){
    var val1 = this.validator.input[req];
    var val2 = val;

    if(!isValidDate(val1)){ return false;}
    if(!isValidDate(val2)){ return false;}

    if (new Date(val1).getTime() >= new Date(val2).getTime()) {
      return true;
    }

    return false;
  }

};

function Rule(name, fn, async) {
  this.name = name;
  this.fn = fn;
  this.passes = null;
  this.customMessage = undefined;
  this.async = async;
}

Rule.prototype = {

  /**
   * Validate rule
   *
   * @param  {mixed} inputValue
   * @param  {mixed} ruleValue
   * @param  {string} attribute
   * @param  {function} callback
   * @return {boolean|undefined}
   */
  validate: function(inputValue, ruleValue, attribute, callback) {
    var _this = this;
    this._setValidatingData(attribute, inputValue, ruleValue);
    if (typeof callback === 'function') {
      this.callback = callback;
      var handleResponse = function(passes, message) {
        _this.response(passes, message);
      };

      if (this.async) {
        return this.fn.apply(this, [inputValue, ruleValue, attribute, handleResponse]);
      } else {
        return handleResponse(this.fn.apply(this, [inputValue, ruleValue, attribute]));
      }
    }
    return this.fn.apply(this, [inputValue, ruleValue, attribute]);
  },

  /**
   * Set validating data
   *
   * @param {string} attribute
   * @param {mixed} inputValue
   * @param {mixed} ruleValue
   * @return {void}
   */
  _setValidatingData: function(attribute, inputValue, ruleValue) {
    this.attribute = attribute;
    this.inputValue = inputValue;
    this.ruleValue = ruleValue;
  },

  /**
   * Get parameters
   *
   * @return {array}
   */
  getParameters: function() {
    return this.ruleValue ? this.ruleValue.split(',') : [];
  },

  /**
   * Get true size of value
   *
   * @return {integer|float}
   */
  getSize: function() {
    var value = this.inputValue;

    if (value instanceof Array) {
      return value.length;
    }

    if (typeof value === 'number') {
      return value;
    }

    if (this.validator._hasNumericRule(this.attribute)) {
      return parseFloat(value, 10);
    }

    return value.length;
  },

  /**
   * Get the type of value being checked; numeric or string.
   *
   * @return {string}
   */
  _getValueType: function() {

    if (typeof this.inputValue === 'number' || this.validator._hasNumericRule(this.attribute)) {
      return 'numeric';
    }

    return 'string';
  },

  /**
   * Set the async callback response
   *
   * @param  {boolean|undefined} passes  Whether validation passed
   * @param  {string|undefined} message Custom error message
   * @return {void}
   */
  response: function(passes, message) {
    this.passes = (passes === undefined || passes === true);
    this.customMessage = message;
    this.callback(this.passes, message);
  },

  /**
   * Set validator instance
   *
   * @param {Validator} validator
   * @return {void}
   */
  setValidator: function(validator) {
    this.validator = validator;
  }

};

var manager = {

  /**
   * List of async rule names
   *
   * @type {Array}
   */
  asyncRules: [],

  /**
   * Implicit rules (rules to always validate)
   *
   * @type {Array}
   */
  implicitRules: ['required', 'required_if', 'required_unless', 'required_with', 'required_with_all', 'required_without', 'required_without_all', 'accepted', 'present'],

  /**
   * Get rule by name
   *
   * @param  {string} name
   * @param {Validator}
   * @return {Rule}
   */
  make: function(name, validator) {
    var async = this.isAsync(name);
    var rule = new Rule(name, rules[name], async);
    rule.setValidator(validator);
    return rule;
  },

  /**
   * Determine if given rule is async
   *
   * @param  {string}  name
   * @return {boolean}
   */
  isAsync: function(name) {
    for (var i = 0, len = this.asyncRules.length; i < len; i++) {
      if (this.asyncRules[i] === name) {
        return true;
      }
    }
    return false;
  },

  /**
   * Determine if rule is implicit (should always validate)
   *
   * @param {string} name
   * @return {boolean}
   */
  isImplicit: function(name) {
    return this.implicitRules.indexOf(name) > -1;
  },

  /**
   * Register new rule
   *
   * @param  {string}   name
   * @param  {function} fn
   * @return {void}
   */
  register: function(name, fn) {
    rules[name] = fn;
  },

    /**
   * Register new implicit rule
   *
   * @param  {string}   name
   * @param  {function} fn
   * @return {void}
   */
  registerImplicit: function(name, fn) {
    this.register(name, fn);
    this.implicitRules.push(name);
  },

  /**
   * Register async rule
   *
   * @param  {string}   name
   * @param  {function} fn
   * @return {void}
   */
  registerAsync: function(name, fn) {
    this.register(name, fn);
    this.asyncRules.push(name);
  },

  /**
   * Register implicit async rule
   *
   * @param  {string}   name
   * @param  {function} fn
   * @return {void}
   */
  registerAsyncImplicit: function(name, fn) {
    this.registerImplicit(name, fn);
    this.asyncRules.push(name);
  }

};

module.exports = manager;
<|endoftext|>


<commit_before>import { listenOpts } from '../utils/event.js'
import Platform from '../plugins/Platform.js'

let
  registered = 0,
  needReposition = false,
  scrollPosition,
  bodyTop

function onIOSScroll (e) {
  const target = e.target

  if (target === document) {
    document.scrollingElement.scrollTop = 0
    return
  }

  const { scrollTop, scrollHeight, offsetHeight } = target

  if (scrollTop <= 0 || scrollTop >= scrollHeight - offsetHeight) {
    needReposition = true
    target.classList.add('q-ios-overflow-scroll-auto')
    target.scrollTop = scrollTop <= 0 ? 1 : target.scrollHeight - target.offsetHeight - 1

    setTimeout(() => {
      target.classList.remove('q-ios-overflow-scroll-auto')
      if (needReposition === true) {
        target.scrollTop = scrollTop <= 0 ? 0 : target.scrollHeight - target.offsetHeight
        needReposition = false
      }
    }, 0)
  }
  else {
    needReposition = false
  }
}

function prevent (register) {
  let action = 'add'

  if (register === true) {
    registered++
    if (registered > 1) {
      return
    }
  }
  else {
    if (registered < 1) {
      return
    }
    registered--
    action = 'remove'
  }

  const body = document.body

  if (register === true && typeof window !== 'undefined') {
    scrollPosition = window.pageYOffset || window.scrollY || body.scrollTop || 0
    bodyTop = body.style.top

    body.style.top = `-${scrollPosition}px`
    body.scrollHeight > window.innerHeight && body.classList.add('q-body--force-scrollbar')

    Platform.is.ios === true && window.addEventListener('scroll', onIOSScroll, listenOpts.passiveCapture)
  }

  body.classList[action]('q-body--prevent-scroll')

  if (register !== true && typeof window !== 'undefined') {
    Platform.is.ios === true && window.removeEventListener('scroll', onIOSScroll, listenOpts.passiveCapture)

    body.classList.remove('q-body--force-scrollbar')
    body.style.top = bodyTop
    window.scrollTo(0, scrollPosition)
  }
}

export default {
  methods: {
    __preventScroll (state) {
      if (this.preventedScroll === void 0 && state !== true) {
        return
      }

      if (state !== this.preventedScroll) {
        this.preventedScroll = state
        prevent(state)
      }
    }
  }
}
<commit_msg>Update prevent-scroll.js<commit_after>import { listenOpts } from '../utils/event.js'
import Platform from '../plugins/Platform.js'

let
  registered = 0,
  needReposition = false,
  scrollPosition,
  bodyTop

function onAppleScroll (e) {
  if (e.target === document) {
    document.scrollingElement.scrollTop = 0
  }
}

function prevent (register) {
  let action = 'add'

  if (register === true) {
    registered++
    if (registered > 1) {
      return
    }
  }
  else {
    if (registered < 1) {
      return
    }
    registered--
    action = 'remove'
  }

  const body = document.body

  if (register === true && typeof window !== 'undefined') {
    scrollPosition = window.pageYOffset || window.scrollY || body.scrollTop || 0
    bodyTop = body.style.top

    body.style.top = `-${scrollPosition}px`
    body.scrollHeight > window.innerHeight && body.classList.add('q-body--force-scrollbar')

    Platform.is.ios === true && window.addEventListener('scroll', onAppleScroll, listenOpts.passiveCapture)
  }

  body.classList[action]('q-body--prevent-scroll')

  if (register !== true && typeof window !== 'undefined') {
    Platform.is.ios === true && window.removeEventListener('scroll', onAppleScroll, listenOpts.passiveCapture)

    body.classList.remove('q-body--force-scrollbar')
    body.style.top = bodyTop
    window.scrollTo(0, scrollPosition)
  }
}

export default {
  methods: {
    __preventScroll (state) {
      if (this.preventedScroll === void 0 && state !== true) {
        return
      }

      if (state !== this.preventedScroll) {
        this.preventedScroll = state
        prevent(state)
      }
    }
  }
}
<|endoftext|>