<commit_before>// ==========================================================================
// Project:   Ember - JavaScript Application Framework
// Copyright: ©2006-2011 Strobe Inc. and contributors.
//            Portions ©2008-2011 Apple Inc. All rights reserved.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================

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

/**
  @class

  An Ember.Application instance serves as the namespace in which you define your
  application's classes. You can also override the configuration of your
  application.

  By default, Ember.Application will begin listening for events on the document.
  If your application is embedded inside a page, instead of controlling the
  entire document, you can specify which DOM element to attach to by setting
  the `rootElement` property:

      MyApp = Ember.Application.create({
        rootElement: $('#my-app')
      });

  The root of an Ember.Application must not be removed during the course of the
  page's lifetime. If you have only a single conceptual application for the
  entire page, and are not embedding any third-party Ember applications
  in your page, use the default document root for your application.

  You only need to specify the root if your page contains multiple instances
  of Ember.Application.

  @extends Ember.Object
*/
Ember.Application = Ember.Namespace.extend(
/** @scope Ember.Application.prototype */{

  /**
    The root DOM element of the Application.

    Can be specified as DOMElement or a selector string.

    @type DOMElement
    @default 'body'
  */
  rootElement: 'body',

  /**
    @type Ember.EventDispatcher
    @default null
  */
  eventDispatcher: null,

  /**
    @type Object
    @default null
  */
  customEvents: null,

  /** @private */
  init: function() {
    var eventDispatcher,
        rootElement = get(this, 'rootElement');
    this._super();

    eventDispatcher = Ember.EventDispatcher.create({
      rootElement: rootElement
    });

    set(this, 'eventDispatcher', eventDispatcher);

    // jQuery 1.7 doesn't call the ready callback if already ready
    if (Ember.$.isReady) {
      Ember.run.once(this, this.didBecomeReady);
    } else {
      var self = this;
      Ember.$(document).ready(function() {
        Ember.run.once(self, self.didBecomeReady);
      });
    }
  },

  /**
    Instantiate all controllers currently available on the namespace
    and inject them onto a router.

    Example:

        App.PostsController = Ember.ArrayController.extend();
        App.CommentsController = Ember.ArrayController.extend();

        var router = Ember.Router.create({
          ...
        });

        App.initialize(router);

        router.get('postsController')     // <App.PostsController:ember1234>
        router.get('commentsController')  // <App.CommentsController:ember1235>

        router.getPath('postsController.router') // router
  */
  initialize: function(router) {
    var properties = Ember.A(Ember.keys(this)),
        injections = get(this.constructor, 'injections'),
        namespace = this, controller, name;

    if (!router && Ember.Router.detect(namespace['Router'])) {
      router = namespace['Router'].create();
      this._createdRouter = router;
    }

    if (router) {
      set(this, 'router', router);

      // By default, the router's namespace is the current application.
      //
      // This allows it to find model classes when a state has a
      // route like `/posts/:post_id`. In that case, it would first
      // convert `post_id` into `Post`, and then look it up on its
      // namespace.
      set(router, 'namespace', this);
    }

    Ember.runLoadHooks('application', this);

    injections.forEach(function(injection) {
      properties.forEach(function(property) {
        injection[1](namespace, router, property);
      });
    });

    if (router && router instanceof Ember.Router) {
      this.startRouting(router);
    }
  },

  /** @private */
  didBecomeReady: function() {
    var eventDispatcher = get(this, 'eventDispatcher'),
        customEvents    = get(this, 'customEvents');

    eventDispatcher.setup(customEvents);

    this.ready();
  },

  /**
    @private

    If the application has a router, use it to route to the current URL, and
    trigger a new call to `route` whenever the URL changes.
  */
  startRouting: function(router) {
    var location = get(router, 'location'),
        rootElement = get(this, 'rootElement'),
        applicationController = get(router, 'applicationController');

    if (this.ApplicationView && applicationController) {
      var applicationView = this.ApplicationView.create({
        controller: applicationController
      });
      this._createdApplicationView = applicationView;

      applicationView.appendTo(rootElement);
    }

    router.route(location.getURL());
    location.onUpdateURL(function(url) {
      router.route(url);
    });
  },

  /**
    Called when the Application has become ready.
    The call will be delayed until the DOM has become ready.
  */
  ready: Ember.K,

  /** @private */
  willDestroy: function() {
    get(this, 'eventDispatcher').destroy();
    if (this._createdRouter)          { this._createdRouter.destroy(); }
    if (this._createdApplicationView) { this._createdApplicationView.destroy(); }
  },

  registerInjection: function(options) {
    this.constructor.registerInjection(options);
  }
});

Ember.Application.reopenClass({
  concatenatedProperties: ['injections'],
  injections: Ember.A(),
  registerInjection: function(options) {
    var injections = get(this, 'injections'),
        before = options.before,
        name = options.name,
        injection = options.injection,
        location;

    if (before) {
      location = injections.find(function(item) {
        if (item[0] === before) { return true; }
      });
      location = injections.indexOf(location);
    } else {
      location = get(injections, 'length');
    }

    injections.splice(location, 0, [name, injection]);
  }
});

Ember.Application.registerInjection({
  name: 'controllers',
  injection: function(app, router, property) {
    if (!/^[A-Z].*Controller$/.test(property)) { return; }

    var name = property[0].toLowerCase() + property.substr(1),
        controller = app[property].create();

    router.set(name, controller);

    controller.setProperties({
      target: router,
      controllers: router,
      namespace: app
    });
  }
});
<commit_msg>switch from String.[] to String.charAt() to make IE8 and IE7 'happy'<commit_after>// ==========================================================================
// Project:   Ember - JavaScript Application Framework
// Copyright: ©2006-2011 Strobe Inc. and contributors.
//            Portions ©2008-2011 Apple Inc. All rights reserved.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================

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

/**
  @class

  An Ember.Application instance serves as the namespace in which you define your
  application's classes. You can also override the configuration of your
  application.

  By default, Ember.Application will begin listening for events on the document.
  If your application is embedded inside a page, instead of controlling the
  entire document, you can specify which DOM element to attach to by setting
  the `rootElement` property:

      MyApp = Ember.Application.create({
        rootElement: $('#my-app')
      });

  The root of an Ember.Application must not be removed during the course of the
  page's lifetime. If you have only a single conceptual application for the
  entire page, and are not embedding any third-party Ember applications
  in your page, use the default document root for your application.

  You only need to specify the root if your page contains multiple instances
  of Ember.Application.

  @extends Ember.Object
*/
Ember.Application = Ember.Namespace.extend(
/** @scope Ember.Application.prototype */{

  /**
    The root DOM element of the Application.

    Can be specified as DOMElement or a selector string.

    @type DOMElement
    @default 'body'
  */
  rootElement: 'body',

  /**
    @type Ember.EventDispatcher
    @default null
  */
  eventDispatcher: null,

  /**
    @type Object
    @default null
  */
  customEvents: null,

  /** @private */
  init: function() {
    var eventDispatcher,
        rootElement = get(this, 'rootElement');
    this._super();

    eventDispatcher = Ember.EventDispatcher.create({
      rootElement: rootElement
    });

    set(this, 'eventDispatcher', eventDispatcher);

    // jQuery 1.7 doesn't call the ready callback if already ready
    if (Ember.$.isReady) {
      Ember.run.once(this, this.didBecomeReady);
    } else {
      var self = this;
      Ember.$(document).ready(function() {
        Ember.run.once(self, self.didBecomeReady);
      });
    }
  },

  /**
    Instantiate all controllers currently available on the namespace
    and inject them onto a router.

    Example:

        App.PostsController = Ember.ArrayController.extend();
        App.CommentsController = Ember.ArrayController.extend();

        var router = Ember.Router.create({
          ...
        });

        App.initialize(router);

        router.get('postsController')     // <App.PostsController:ember1234>
        router.get('commentsController')  // <App.CommentsController:ember1235>

        router.getPath('postsController.router') // router
  */
  initialize: function(router) {
    var properties = Ember.A(Ember.keys(this)),
        injections = get(this.constructor, 'injections'),
        namespace = this, controller, name;

    if (!router && Ember.Router.detect(namespace['Router'])) {
      router = namespace['Router'].create();
      this._createdRouter = router;
    }

    if (router) {
      set(this, 'router', router);

      // By default, the router's namespace is the current application.
      //
      // This allows it to find model classes when a state has a
      // route like `/posts/:post_id`. In that case, it would first
      // convert `post_id` into `Post`, and then look it up on its
      // namespace.
      set(router, 'namespace', this);
    }

    Ember.runLoadHooks('application', this);

    injections.forEach(function(injection) {
      properties.forEach(function(property) {
        injection[1](namespace, router, property);
      });
    });

    if (router && router instanceof Ember.Router) {
      this.startRouting(router);
    }
  },

  /** @private */
  didBecomeReady: function() {
    var eventDispatcher = get(this, 'eventDispatcher'),
        customEvents    = get(this, 'customEvents');

    eventDispatcher.setup(customEvents);

    this.ready();
  },

  /**
    @private

    If the application has a router, use it to route to the current URL, and
    trigger a new call to `route` whenever the URL changes.
  */
  startRouting: function(router) {
    var location = get(router, 'location'),
        rootElement = get(this, 'rootElement'),
        applicationController = get(router, 'applicationController');

    if (this.ApplicationView && applicationController) {
      var applicationView = this.ApplicationView.create({
        controller: applicationController
      });
      this._createdApplicationView = applicationView;

      applicationView.appendTo(rootElement);
    }

    router.route(location.getURL());
    location.onUpdateURL(function(url) {
      router.route(url);
    });
  },

  /**
    Called when the Application has become ready.
    The call will be delayed until the DOM has become ready.
  */
  ready: Ember.K,

  /** @private */
  willDestroy: function() {
    get(this, 'eventDispatcher').destroy();
    if (this._createdRouter)          { this._createdRouter.destroy(); }
    if (this._createdApplicationView) { this._createdApplicationView.destroy(); }
  },

  registerInjection: function(options) {
    this.constructor.registerInjection(options);
  }
});

Ember.Application.reopenClass({
  concatenatedProperties: ['injections'],
  injections: Ember.A(),
  registerInjection: function(options) {
    var injections = get(this, 'injections'),
        before = options.before,
        name = options.name,
        injection = options.injection,
        location;

    if (before) {
      location = injections.find(function(item) {
        if (item[0] === before) { return true; }
      });
      location = injections.indexOf(location);
    } else {
      location = get(injections, 'length');
    }

    injections.splice(location, 0, [name, injection]);
  }
});

Ember.Application.registerInjection({
  name: 'controllers',
  injection: function(app, router, property) {
    if (!/^[A-Z].*Controller$/.test(property)) { return; }

    var name = property.charAt(0).toLowerCase() + property.substr(1),
        controller = app[property].create();

    router.set(name, controller);

    controller.setProperties({
      target: router,
      controllers: router,
      namespace: app
    });
  }
});
<|endoftext|>


<commit_before>const chokidar = require(`chokidar`)
const fs = require(`fs`)
const { Machine } = require(`xstate`)

const { createFileNode } = require(`./create-file-node`)

/**
 * Create a state machine to manage Chokidar's not-ready/ready states and for
 * emitting file system events into Gatsby.
 *
 * On the latter, this solves the problem where if you call createNode for the
 * same File node in quick succession, this can leave Gatsby's internal state
 * in disarray causing queries to fail. The latter state machine tracks when
 * Gatsby is "processing" a node update or when it's "idle". If updates come in
 * while Gatsby is processing, we queue them until the system returns to an
 * "idle" state.
 */
const fsMachine = Machine({
  key: `emitFSEvents`,
  parallel: true,
  strict: true,
  states: {
    CHOKIDAR: {
      initial: `CHOKIDAR_NOT_READY`,
      states: {
        CHOKIDAR_NOT_READY: {
          on: {
            CHOKIDAR_READY: `CHOKIDAR_WATCHING`,
            BOOTSTRAP_FINISHED: `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`,
          },
        },
        CHOKIDAR_WATCHING: {
          on: {
            BOOTSTRAP_FINISHED: `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`,
            CHOKIDAR_READY: `CHOKIDAR_WATCHING`,
          },
        },
        CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED: {
          on: {
            CHOKIDAR_READY: `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`,
          },
        },
      },
    },
    PROCESSING: {
      initial: `BOOTSTRAPPING`,
      states: {
        BOOTSTRAPPING: {
          on: {
            BOOTSTRAP_FINISHED: `IDLE`,
          },
        },
        IDLE: {
          on: {
            EMIT_FS_EVENT: `PROCESSING`,
          },
        },
        PROCESSING: {
          on: {
            QUERY_QUEUE_DRAINED: `IDLE`,
            TOUCH_NODE: `IDLE`,
          },
        },
      },
    },
  },
})

let currentState = fsMachine.initialState

exports.sourceNodes = (
  { actions, getNode, createNodeId, hasNodeChanged, reporter, emitter },
  pluginOptions
) => {
  const { createNode, deleteNode } = actions

  // Validate that the path exists.
  if (!fs.existsSync(pluginOptions.path)) {
    reporter.panic(`
The path passed to gatsby-source-filesystem does not exist on your file system:

${pluginOptions.path}

Please pick a path to an existing directory.

See docs here - https://www.gatsbyjs.org/packages/gatsby-source-filesystem/
      `)
  }
  let fileNodeQueue = new Map()

  // Once bootstrap is finished, we only let one File node update go through
  // the system at a time.
  emitter.on(`BOOTSTRAP_FINISHED`, () => {
    currentState = fsMachine.transition(
      currentState.value,
      `BOOTSTRAP_FINISHED`
    )
  })
  emitter.on(`TOUCH_NODE`, () => {
    // If we create a node which is the same as the previous version, createNode
    // returns TOUCH_NODE and then nothing else happens so we listen to that
    // to return the state back to IDLE.
    currentState = fsMachine.transition(currentState.value, `TOUCH_NODE`)
  })

  emitter.on(`QUERY_QUEUE_DRAINED`, () => {
    currentState = fsMachine.transition(
      currentState.value,
      `QUERY_QUEUE_DRAINED`
    )
    // If we have any updates queued, run one of them now.
    if (fileNodeQueue.size > 0) {
      const toProcess = fileNodeQueue.get(Array.from(fileNodeQueue.keys())[0])
      fileNodeQueue.delete(toProcess.id)
      currentState = fsMachine.transition(currentState.value, `EMIT_FS_EVENT`)
      createNode(toProcess)
    }
  })

  const watcher = chokidar.watch(pluginOptions.path, {
    ignored: [
      `**/*.un~`,
      `**/.gitignore`,
      `**/.npmignore`,
      `**/.babelrc`,
      `**/yarn.lock`,
      `**/node_modules`,
      `../**/dist/**`,
    ],
  })

  const createAndProcessNode = path => {
    const fileNodePromise = createFileNode(
      path,
      createNodeId,
      pluginOptions
    ).then(fileNode => {
      if (currentState.value.PROCESSING === `PROCESSING`) {
        fileNodeQueue.set(fileNode.id, fileNode)
      } else {
        currentState = fsMachine.transition(currentState.value, `EMIT_FS_EVENT`)
        createNode(fileNode)
      }
    })
    return fileNodePromise
  }

  // For every path that is reported before the 'ready' event, we throw them
  // into a queue and then flush the queue when 'ready' event arrives.
  // After 'ready', we handle the 'add' event without putting it into a queue.
  let pathQueue = []
  const flushPathQueue = () => {
    let queue = pathQueue.slice()
    pathQueue = []
    return Promise.all(queue.map(createAndProcessNode))
  }

  watcher.on(`add`, path => {
    if (currentState.value.CHOKIDAR !== `CHOKIDAR_NOT_READY`) {
      if (
        currentState.value.CHOKIDAR === `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`
      ) {
        reporter.info(`added file at ${path}`)
      }
      createAndProcessNode(path).catch(err => reporter.error(err))
    } else {
      pathQueue.push(path)
    }
  })

  watcher.on(`change`, path => {
    if (
      currentState.value.CHOKIDAR === `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`
    ) {
      reporter.info(`changed file at ${path}`)
    }
    createAndProcessNode(path).catch(err => reporter.error(err))
  })

  watcher.on(`unlink`, path => {
    if (
      currentState.value.CHOKIDAR === `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`
    ) {
      reporter.info(`file deleted at ${path}`)
    }
    const node = getNode(createNodeId(path))
    // It's possible the file node was never created as sometimes tools will
    // write and then immediately delete temporary files to the file system.
    if (node) {
      currentState = fsMachine.transition(currentState.value, `EMIT_FS_EVENT`)
      deleteNode({ node })
    }
  })

  watcher.on(`addDir`, path => {
    if (currentState.value.CHOKIDAR !== `CHOKIDAR_NOT_READY`) {
      if (
        currentState.value.CHOKIDAR === `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`
      ) {
        reporter.info(`added directory at ${path}`)
      }
      createAndProcessNode(path).catch(err => reporter.error(err))
    } else {
      pathQueue.push(path)
    }
  })

  watcher.on(`unlinkDir`, path => {
    if (
      currentState.value.CHOKIDAR === `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`
    ) {
      reporter.info(`directory deleted at ${path}`)
    }
    const node = getNode(createNodeId(path))
    deleteNode({ node })
  })

  return new Promise((resolve, reject) => {
    watcher.on(`ready`, () => {
      currentState = fsMachine.transition(currentState.value, `CHOKIDAR_READY`)
      flushPathQueue().then(resolve, reject)
    })
  })
}

exports.setFieldsOnGraphQLNodeType = require(`./extend-file-node`)
<commit_msg>[gatsby-source-filesystem] create separate state machines for each instance of plugin (#6044)<commit_after>const chokidar = require(`chokidar`)
const fs = require(`fs`)
const { Machine } = require(`xstate`)

const { createFileNode } = require(`./create-file-node`)

/**
 * Create a state machine to manage Chokidar's not-ready/ready states and for
 * emitting file system events into Gatsby.
 *
 * On the latter, this solves the problem where if you call createNode for the
 * same File node in quick succession, this can leave Gatsby's internal state
 * in disarray causing queries to fail. The latter state machine tracks when
 * Gatsby is "processing" a node update or when it's "idle". If updates come in
 * while Gatsby is processing, we queue them until the system returns to an
 * "idle" state.
 */
const createFSMachine = () =>
  Machine({
    key: `emitFSEvents`,
    parallel: true,
    strict: true,
    states: {
      CHOKIDAR: {
        initial: `CHOKIDAR_NOT_READY`,
        states: {
          CHOKIDAR_NOT_READY: {
            on: {
              CHOKIDAR_READY: `CHOKIDAR_WATCHING`,
              BOOTSTRAP_FINISHED: `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`,
            },
          },
          CHOKIDAR_WATCHING: {
            on: {
              BOOTSTRAP_FINISHED: `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`,
              CHOKIDAR_READY: `CHOKIDAR_WATCHING`,
            },
          },
          CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED: {
            on: {
              CHOKIDAR_READY: `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`,
            },
          },
        },
      },
      PROCESSING: {
        initial: `BOOTSTRAPPING`,
        states: {
          BOOTSTRAPPING: {
            on: {
              BOOTSTRAP_FINISHED: `IDLE`,
            },
          },
          IDLE: {
            on: {
              EMIT_FS_EVENT: `PROCESSING`,
            },
          },
          PROCESSING: {
            on: {
              QUERY_QUEUE_DRAINED: `IDLE`,
              TOUCH_NODE: `IDLE`,
            },
          },
        },
      },
    },
  })

exports.sourceNodes = (
  { actions, getNode, createNodeId, hasNodeChanged, reporter, emitter },
  pluginOptions
) => {
  const { createNode, deleteNode } = actions

  // Validate that the path exists.
  if (!fs.existsSync(pluginOptions.path)) {
    reporter.panic(`
The path passed to gatsby-source-filesystem does not exist on your file system:

${pluginOptions.path}

Please pick a path to an existing directory.

See docs here - https://www.gatsbyjs.org/packages/gatsby-source-filesystem/
      `)
  }

  const fsMachine = createFSMachine()
  let currentState = fsMachine.initialState
  let fileNodeQueue = new Map()

  // Once bootstrap is finished, we only let one File node update go through
  // the system at a time.
  emitter.on(`BOOTSTRAP_FINISHED`, () => {
    currentState = fsMachine.transition(
      currentState.value,
      `BOOTSTRAP_FINISHED`
    )
  })
  emitter.on(`TOUCH_NODE`, () => {
    // If we create a node which is the same as the previous version, createNode
    // returns TOUCH_NODE and then nothing else happens so we listen to that
    // to return the state back to IDLE.
    currentState = fsMachine.transition(currentState.value, `TOUCH_NODE`)
  })

  emitter.on(`QUERY_QUEUE_DRAINED`, () => {
    currentState = fsMachine.transition(
      currentState.value,
      `QUERY_QUEUE_DRAINED`
    )
    // If we have any updates queued, run one of them now.
    if (fileNodeQueue.size > 0) {
      const toProcess = fileNodeQueue.get(Array.from(fileNodeQueue.keys())[0])
      fileNodeQueue.delete(toProcess.id)
      currentState = fsMachine.transition(currentState.value, `EMIT_FS_EVENT`)
      createNode(toProcess)
    }
  })

  const watcher = chokidar.watch(pluginOptions.path, {
    ignored: [
      `**/*.un~`,
      `**/.gitignore`,
      `**/.npmignore`,
      `**/.babelrc`,
      `**/yarn.lock`,
      `**/node_modules`,
      `../**/dist/**`,
    ],
  })

  const createAndProcessNode = path => {
    const fileNodePromise = createFileNode(
      path,
      createNodeId,
      pluginOptions
    ).then(fileNode => {
      if (currentState.value.PROCESSING === `PROCESSING`) {
        fileNodeQueue.set(fileNode.id, fileNode)
      } else {
        currentState = fsMachine.transition(currentState.value, `EMIT_FS_EVENT`)
        createNode(fileNode)
      }
    })
    return fileNodePromise
  }

  // For every path that is reported before the 'ready' event, we throw them
  // into a queue and then flush the queue when 'ready' event arrives.
  // After 'ready', we handle the 'add' event without putting it into a queue.
  let pathQueue = []
  const flushPathQueue = () => {
    let queue = pathQueue.slice()
    pathQueue = []
    return Promise.all(queue.map(createAndProcessNode))
  }

  watcher.on(`add`, path => {
    if (currentState.value.CHOKIDAR !== `CHOKIDAR_NOT_READY`) {
      if (
        currentState.value.CHOKIDAR === `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`
      ) {
        reporter.info(`added file at ${path}`)
      }
      createAndProcessNode(path).catch(err => reporter.error(err))
    } else {
      pathQueue.push(path)
    }
  })

  watcher.on(`change`, path => {
    if (
      currentState.value.CHOKIDAR === `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`
    ) {
      reporter.info(`changed file at ${path}`)
    }
    createAndProcessNode(path).catch(err => reporter.error(err))
  })

  watcher.on(`unlink`, path => {
    if (
      currentState.value.CHOKIDAR === `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`
    ) {
      reporter.info(`file deleted at ${path}`)
    }
    const node = getNode(createNodeId(path))
    // It's possible the file node was never created as sometimes tools will
    // write and then immediately delete temporary files to the file system.
    if (node) {
      currentState = fsMachine.transition(currentState.value, `EMIT_FS_EVENT`)
      deleteNode({ node })
    }
  })

  watcher.on(`addDir`, path => {
    if (currentState.value.CHOKIDAR !== `CHOKIDAR_NOT_READY`) {
      if (
        currentState.value.CHOKIDAR === `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`
      ) {
        reporter.info(`added directory at ${path}`)
      }
      createAndProcessNode(path).catch(err => reporter.error(err))
    } else {
      pathQueue.push(path)
    }
  })

  watcher.on(`unlinkDir`, path => {
    if (
      currentState.value.CHOKIDAR === `CHOKIDAR_WATCHING_BOOTSTRAP_FINISHED`
    ) {
      reporter.info(`directory deleted at ${path}`)
    }
    const node = getNode(createNodeId(path))
    deleteNode({ node })
  })

  return new Promise((resolve, reject) => {
    watcher.on(`ready`, () => {
      currentState = fsMachine.transition(currentState.value, `CHOKIDAR_READY`)
      flushPathQueue().then(resolve, reject)
    })
  })
}

exports.setFieldsOnGraphQLNodeType = require(`./extend-file-node`)
<|endoftext|>


<commit_before>/*!
 * Copyright (c) 2012 Lyconic, LLC.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/***
 * @namespace Convert form fields into nested hashes quickly and painlessly.
 ***/
var Objectify = (function ($) {
  var self;

  /***
   * Because javascript type-checking is something special.
   ***/
  function primitive ( obj ) {
    return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];
  }

  /***
   * Because `hasOwnProperty` can be overwritten.
   ***/
  function hasOwnProperty ( obj, key ) {
    return Object.prototype.hasOwnProperty.call(obj, key);
  }

  /***
   * The secret sauce, as it were. This is what inserts a value into the correct nesting.
   ***/
  function normalize ( key, value, params ) {
    var isArrayValue = key.match( /\[\]$/ ),
        namespace    = self.unpack( key ),
        p = params, k;

    do {
      k = namespace.shift();
      if ( namespace.length > 0 ) {
        p[ k ] || (p[ k ] = {});
        p = p[ k ];
      }
    } while ( namespace.length > 0 );

    if ( isArrayValue ) {
      p[ k ] || (p[ k ] = []);
      if ( !p[ k ].push ) throw("Expected array, got " + typeof(p[k]) + " instead.");
      p[ k ].push( value );
    } else {
      p[ k ] = value;
    }

    return params;
  }

  return self = {
    /***
     * This is the method that does the heavy lifting.
     *
     * @method convert(<selection>)
     * @param selection can be a jQuery selector string, a jQuery instance, or a plain object.
     * @returns {Object}
     * @example
     *
     *   Objectify.convert('form') -> { ... }
     *   Objectify.convert( $('form') ) -> { ... }
     *   Objectify.convert({ ... }) -> { ... }
     ***/
    'convert': function ( selection ) {
      var fields = [], obj = {};

      if ( (primitive(selection) === 'String') || (selection instanceof jQuery) ) {

        if ( $(selection).is('form') ) fields = $(selection).serializeArray();
        else fields = $(selection).find('input, select, textarea').serializeArray();

      } else if ( primitive(selection) == 'Object' ) {

        for (var key in selection) {
          if ( hasOwnProperty(selection, key) ) {
            fields.push({ name: key, value: selection[key] });
          }
        }

      }

      $.each( fields, function ( i, field ) {
        normalize( field.name, field.value, obj );
      });

      return obj;
    },

    /***
     * Takes a packed string and returns and `Array` of parsed tokens.
     *
     * @method unpack(<string>)
     * @returns {Array} tokens
     * @example
     *
     *   Objectify.unpack('user[address][street_address]') -> ['user', 'address', 'street_address']
     ***/
    'unpack': function ( string ) {
      var pattern = /^[\[\]]*([^\[\]]+)\]*/,
          namespace = [], s;

      while ( s = string.match(pattern) ) {
        namespace.push( s[1] );
        string = string.replace( pattern, '' );
      }

      return namespace;
    },

    /***
     * Takes one or more arguments and turns them into a single packed string. Pass in an empty `[]` for an array value.
     *
     * @method pack(<arg1>, <arg2>, ...)
     * @returns {String}
     * @example
     *
     *   Objectify.pack('user', 'address', 'street_address') -> 'user[address][street_address]'
     *   Objectify.pack('user', 'phone_numbers', []) -> 'user[phone_numbers][]'
     ***/
    'pack': function () {
      if ( arguments.length === 0 ) return;

      if ( arguments.length === 1 )
      if ( $.isArray(arguments[0]) ) return self.pack.apply(null, arguments[0]);

      var args      = Array.prototype.slice.call( arguments, 1 ),
          fieldName = arguments[ 0 ];

      $.each( args, function ( i, name ) {
        if ( primitive(name) === 'Array' ) fieldName += '[]';
        else fieldName += '[' + name + ']';
      });

      return fieldName;
    },

    /***
     * Walk into a nested object, to arbitrary depth, and pull out the value
     *
     * @method walk(<obj>, <namespace>)
     * @param {Object} <obj> The nested object
     * @param {Array} <namespace> The chain of keys to walk down
     * @extra If `walk` excounters an `undefined` value it will immediately break and return undefined.
     * @example
     *
     *   var obj = { user: { address: { street_address: '123 Nowhere st.' } } };
     *   Objectify.walk(obj, ['user', 'address', 'street_address']) -> '123 Nowhere st.'
     *   Objectify.walk(obj, ['user', 'address', 'foo', 'bar']) -> undefined
     ***/
    'walk': function ( obj, namespace ) {
      while ( namespace.length > 0 ) {
        if ( obj === undefined ) break;
        obj = obj[ namespace.shift() ];
      }
      return obj;
    }
  };
})(jQuery);

(function ($) {
  /***
   * jQuery plugin to convert the selected nodes. Parameters are treated like `walk` params.
   *
   * @example
   *
   *   $('form').objectify() -> { ... }
   *   $('form').objectify('user', 'address', 'street_address') -> '123 Nowhere st.'
   ***/
  $.fn.objectify = function () {
    return Objectify.walk( Objectify.convert(this), Array.prototype.slice.call(arguments) );
  }
})(jQuery);
<commit_msg>We are in fact doing a check against undefined<commit_after>/*!
 * Copyright (c) 2012 Lyconic, LLC.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/***
 * @namespace Convert form fields into nested hashes quickly and painlessly.
 ***/
var Objectify = (function ($, undefined) {
  var self;

  /***
   * Because javascript type-checking is something special.
   ***/
  function primitive ( obj ) {
    return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];
  }

  /***
   * Because `hasOwnProperty` can be overwritten.
   ***/
  function hasOwnProperty ( obj, key ) {
    return Object.prototype.hasOwnProperty.call(obj, key);
  }

  /***
   * The secret sauce, as it were. This is what inserts a value into the correct nesting.
   ***/
  function normalize ( key, value, params ) {
    var isArrayValue = key.match( /\[\]$/ ),
        namespace    = self.unpack( key ),
        p = params, k;

    // TODO: profile this against a recursive func
    do {
      k = namespace.shift();
      if ( namespace.length > 0 ) {
        p[ k ] || (p[ k ] = {});
        p = p[ k ];
      }
    } while ( namespace.length > 0 );

    if ( isArrayValue ) {
      p[ k ] || (p[ k ] = []);
      if ( !p[ k ].push ) throw("Expected array, got " + typeof(p[k]) + " instead.");
      p[ k ].push( value );
    } else {
      p[ k ] = value;
    }

    return params;
  }

  return self = {
    /***
     * This is the method that does the heavy lifting.
     *
     * @method convert(<selection>)
     * @param selection can be a jQuery selector string, a jQuery instance, or a plain object.
     * @returns {Object}
     * @example
     *
     *   Objectify.convert('form') -> { ... }
     *   Objectify.convert( $('form') ) -> { ... }
     *   Objectify.convert({ ... }) -> { ... }
     ***/
    'convert': function ( selection ) {
      var fields = [], obj = {};

      if ( (primitive(selection) === 'String') || (selection instanceof jQuery) ) {

        if ( $(selection).is('form') ) fields = $(selection).serializeArray();
        else fields = $(selection).find('input, select, textarea').serializeArray();

      } else if ( primitive(selection) == 'Object' ) {

        for (var key in selection) {
          if ( hasOwnProperty(selection, key) ) {
            fields.push({ name: key, value: selection[key] });
          }
        }

      }

      $.each( fields, function ( i, field ) {
        normalize( field.name, field.value, obj );
      });

      return obj;
    },

    /***
     * Takes a packed string and returns an `Array` of parsed tokens.
     *
     * @method unpack(<string>)
     * @returns {Array} tokens
     * @example
     *
     *   Objectify.unpack('user[address][street_address]') -> ['user', 'address', 'street_address']
     ***/
    'unpack': function ( string ) {
      var pattern = /^[\[\]]*([^\[\]]+)\]*/,
          namespace = [], s;

      while ( s = string.match(pattern) ) {
        namespace.push( s[1] );
        string = string.replace( pattern, '' );
      }

      return namespace;
    },

    /***
     * Takes one or more arguments and turns them into a single packed string. Pass in an empty `[]` for an array value.
     *
     * @method pack(<arg1>, <arg2>, ...)
     * @returns {String}
     * @example
     *
     *   Objectify.pack('user', 'address', 'street_address') -> 'user[address][street_address]'
     *   Objectify.pack('user', 'phone_numbers', []) -> 'user[phone_numbers][]'
     ***/
    'pack': function () {
      if ( arguments.length === 0 ) return;

      if ( arguments.length === 1 )
      if ( $.isArray(arguments[0]) ) return self.pack.apply(null, arguments[0]);

      var args      = Array.prototype.slice.call( arguments, 1 ),
          fieldName = arguments[ 0 ];

      $.each( args, function ( i, name ) {
        if ( primitive(name) === 'Array' ) fieldName += '[]';
        else fieldName += '[' + name + ']';
      });

      return fieldName;
    },

    /***
     * Walk into a nested object, to arbitrary depth, and pull out the value
     *
     * @method walk(<obj>, <namespace>)
     * @param {Object} <obj> The nested object
     * @param {Array} <namespace> The chain of keys to walk down
     * @extra If `walk` excounters an `undefined` value it will immediately break and return `undefined`.
     * @example
     *
     *   var obj = { user: { address: { street_address: '123 Nowhere st.' } } };
     *   Objectify.walk(obj, ['user', 'address', 'street_address']) -> '123 Nowhere st.'
     *   Objectify.walk(obj, ['user', 'address', 'foo', 'bar']) -> undefined
     ***/
    'walk': function ( obj, namespace ) {
      while ( namespace.length > 0 ) {
        if ( obj === undefined ) break;
        obj = obj[ namespace.shift() ];
      }
      return obj;
    }
  };
})(jQuery);

(function ($) {
  /***
   * jQuery plugin to convert the selected nodes. Parameters are treated like `walk` params.
   *
   * @example
   *
   *   $('form').objectify() -> { ... }
   *   $('form').objectify('user', 'address', 'street_address') -> '123 Nowhere st.'
   ***/
  $.fn.objectify = function () {
    return Objectify.walk( Objectify.convert(this), Array.prototype.slice.call(arguments) );
  }
})(jQuery);
<|endoftext|>


<commit_before>exports.notify = {
  notify: function(eventName) {
    this.dispatchEvent(eventName, this[eventName]);
  }
};

exports.autoProperty = {
  createAutoProperty: function(propertyName, defaultValue, readonly) {
    if (!readonly) {
      Object.defineProperty(this, propertyName, {
        get: function() {
          if (!this["_" + propertyName])
            this["_" + propertyName] = defaultValue;
          return this["_" + propertyName];
        },
        set: function(val) {
          if (val != this["_" + propertyName]) {
            this["_" + propertyName] = val;
            if (this.notify)
              this.notify(propertyName, val);
          }
        },
        configurable: false,
        enumerable: true
      });
    } else {
      Object.defineProperty(this, "_" + propertyName, {
        get: function() {
          if (!this["__" + propertyName])
            this["__" + propertyName] = defaultValue;
          return this["__" + propertyName];
        },
        set: function(val) {
          if (val != this["__" + propertyName]) {
            this["__" + propertyName] = val;
            if (this.notify)
              this.notify(propertyName, val);
          }
        },
        configurable: false,
        enumerable: false
      });
      Object.defineProperty(this, propertyName, {
        get: function() {
          return this["__" + propertyName];
        },
        configurable: false,
        enumerable: true
      });
    }
  }
};

exports.managedEvents = {
  addManagedEventListener: function(subject, property, handler) {
    if (subject && property && handler) {
      var binding = handler.bind(this);
      this._managedEvents = this._managedEvents || [];
      this._managedEvents.push({
        subject: subject,
        property: property,
        handler: handler,
        binding: binding
      });
      subject.addEventListener(property, binding);
    }
  },

  removeAllManagedEventListeners : function() {
    if (this._managedEvents) {
      this._managedEvents.forEach(function(ctx) {
        if (ctx.subject && ctx.property && ctx.binding)
          ctx.subject.removeEventListener(ctx.property, ctx.binding);
      });
      this._managedEvents = null;
    }
  }
};
<commit_msg>BugFix for null reference for some frameworks on core view dipose<commit_after>exports.notify = {
  notify: function(eventName) {
    this.dispatchEvent(eventName, this[eventName]);
  }
};

exports.autoProperty = {
  createAutoProperty: function(propertyName, defaultValue, readonly) {
    if (!readonly) {
      Object.defineProperty(this, propertyName, {
        get: function() {
          if (!this["_" + propertyName])
            this["_" + propertyName] = defaultValue;
          return this["_" + propertyName];
        },
        set: function(val) {
          if (val != this["_" + propertyName]) {
            this["_" + propertyName] = val;
            if (this.notify)
              this.notify(propertyName, val);
          }
        },
        configurable: false,
        enumerable: true
      });
    } else {
      Object.defineProperty(this, "_" + propertyName, {
        get: function() {
          if (!this["__" + propertyName])
            this["__" + propertyName] = defaultValue;
          return this["__" + propertyName];
        },
        set: function(val) {
          if (val != this["__" + propertyName]) {
            this["__" + propertyName] = val;
            if (this.notify)
              this.notify(propertyName, val);
          }
        },
        configurable: false,
        enumerable: false
      });
      Object.defineProperty(this, propertyName, {
        get: function() {
          return this["__" + propertyName];
        },
        configurable: false,
        enumerable: true
      });
    }
  }
};

exports.managedEvents = {
  addManagedEventListener: function(subject, property, handler) {
    if (subject && property && handler) {
      var binding = handler.bind(this);
      this._managedEvents = this._managedEvents || [];
      this._managedEvents.push({
        subject: subject,
        property: property,
        handler: handler,
        binding: binding
      });
      subject.addEventListener(property, binding);
    }
  },

  removeAllManagedEventListeners : function() {
    if (this._managedEvents) {
      this._managedEvents.forEach(function(ctx) {
        if (ctx.subject && ctx.property && ctx.binding && ctx.subject.removeEventListener)
          ctx.subject.removeEventListener(ctx.property, ctx.binding);
      });
      this._managedEvents = null;
    }
  }
};
<|endoftext|>


<commit_before>/*
Contains:
	Sandbox
	ParticleEmitter
*/
function Sandbox(attrs){
	var self = this;
	attrs = defaultTo({}, attrs);
	this.bin = {};
	this.drawCanvas = defaultTo(c, attrs.drawCanvas);
	this.rate = defaultTo(.15, attrs.rate);
	this.wallInfo = defaultTo(0, attrs.wallInfo);
	this.wall = walls[this.wallInfo];
	this.massMax = defaultTo(75, attrs.massMax);
	this.massMin = defaultTo(10, attrs.massMin);
	this.mass = defaultTo(10, attrs.massInit);
	this.buttonAdd = defaultTo('buttonAddMass', attrs.addButtonId);
	this.buttonRemove = defaultTo('buttonRemoveMass', attrs.removeButtonId);

	this.makeButtons();

	this.massChunkName = 'sandMass' + defaultTo('', attrs.handle);
	this.wall.setMass(this.massChunkName, this.mass);
	this.wall.recordPExt();
	this.wall.recordWork();
	this.wallHandler = defaultTo('cPAdiabaticDamped', attrs.compMode) + compAdj;
	walls.setSubWallHandler(this.wallInfo, 0, this.wallHandler);

	this.emitters = new Array();
	this.spcVol = 70; //specific volume
	this.sand.col = defaultTo(Col(224, 165, 75), attrs.sandCol);
	this.sand.pts = this.getLiquidPts();

	this.binX = (this.wall[1].x+this.wall[0].x)/2;
	this.pistonPt = this.wall[0].y;

	this.addCleanUp();

	return this.init();
}
_.extend(Sandbox.prototype, compressorFuncs, objectFuncs,
{
	init: function(){
		this.drawListenerName = unique('drawSand' + this.handle, curLevel.updateListeners.listeners);
		this.cleanUpEmittersListenerName = unique('cleanUpSandEmitters' + this.handle, curLevel.updateListener.listeners);
		addListener(curLevel, 'update', this.drawListenerName, this.draw, this);
		addListener(curLevel, 'data', this.cleanUpEmittersListenerName, this.cleanUpEmitters, this);
		this.wall.moveInit();
		return this.displayMass().displayPressure();
	},
	makeButtons: function(){
		addButton(this.buttonAddId, 'Add mass');
		addButton(this.buttonRemoveId, 'Remove mass');
		var self = this;
		$('#'+this.buttonAddId).mousedown(function(){self.buttonAddDown()});
		$('#'+this.buttonAddId).mouseup(function(){self.buttonAddUp()});

		$('#'+this.buttonRemoveId).mousedown(function(){self.buttonRemoveDown()});
		$('#'+this.buttonRemoveId).mouseup(function(){self.buttonRemoveUp()});
	},
	draw: function(){
		this.drawCanvas.save();
		this.drawCanvas.translate(this.binX, this.pistonY());
		draw.fillPts(this.bin.pts, this.bin.col, this.drawCanvas);
		draw.fillPts(this.sand.pts, this.liquid.col, this.drawCanvas);
		this.drawCanvas.restore();
	},
	cleanUpEmitters: function(){
		for(var emitterIdx=this.emitters.length-1; emitterIdx>=0; emitterIdx-=1){
			if(this.emitters[emitterIdx].removed){
				this.emitters.slice(emitterIdx, 1);
			}
		}
	},
	getSandPts: function(){
		var dWidth = this.bin.widthUpper - this.bin.width;
		this.liquid.height = this.mass*this.spcVol/(this.bin.width + (dWidth)/this.bin.height);
		var height = this.liquid.height;
		var pts = new Array(4);
		var liquidDWidth = dWidth*height/this.bin.height;
		pts[0] = P(-this.bin.width/2, -this.bin.thickness);
		pts[1] = P(this.bin.width/2, -this.bin.thickness);
		pts[2] = P((this.bin.width + liquidDWidth)/2, -height-this.bin.thickness);
		pts[3] = P((-this.bin.width - liquidDWidth)/2, -height-this.bin.thickness);
		return pts;
	},
	buttonAddDown: function(){
		this.addMass();
	},
	buttonAddUp: function(){
		this.addMassStop();
	},
	buttonRemoveDown: function(){
		this.removeMass();
	},
	buttonRemoveUp: function(){
		this.removeMassStop();
	},
	changeMassFunc: function(sign){
		return function(){
			this.mass  = Math.min(this.massMax, Math.max(this.mass + sign*this.rate, this.massMin));
			this.sand.pts = this.getSandPts();
			this.wall.setMass(this.massChunkName, this.mass);
		}
	},
	addMass: function(){
		addListener(curLevel, 'update', 'changeMassSand' + this.handle, this.changeMassFunc(1), this);
		this.emitters.push(this.makeDownEmitter())
	},
	addMassStop: function(){
		removeListener(curLevel, 'update', 'changeMassSand' + this.handle);
		this.emitters[this.emitters.length-1].stopFlow();
	},
	removeMass: function(){
		addListener(curLevel, 'update', 'changeMassSand' + this.handle, this.changeMassFunc(-1), this);
	},
	removeMassStop: function(){
		addListener(curLevel, 'update', 'changeMassSand' + this.handle);
		this.emitters[this.emitters.length-1].stopFlow();
	},
	remove: function(){
		removeListener(curLevel, 'update', this.drawListenerName);
		removeListener(curLevel, 'data', this.cleanUpEmittersListenerName);
		this.wall.moveStop();
		//this.stops.remove();
	},

}
)
function testPart(){
	sillyParticles = new ParticleEmitter({pos:P(300,50), dir:0, width:100, dist:300, col:Col(0,0,255)});
}
function ParticleEmitter(attrs){
	this.pos = attrs.pos;
	this.handle = unique('emitter' + defaultTo('', attrs.handle), curLevel.updateListeners.listeners);
	this.dir = attrs.dir;
	this.width = attrs.width;
	this.col = attrs.col;
	this.dist = attrs.dist;
	this.rate = defaultTo(Math.round(.1*this.width), attrs.rate);
	this.speed = defaultTo(5, attrs.speed);
	this.speedSpread = defaultTo(1, attrs.speedSpread);
	if(2*this.speedSpread>this.speed){
		console.log('Uh-oh.  Making particle emitter with handle ' + this.handle + ' with speed spread such that particles will hit ~0 speed');
	}
	this.accel = defaultTo(.5, attrs.accel);
	this.accelSpread = defaultTo(1, attrs.accelSpread);
	this.dirSpread = defaultTo(0, attrs.dirSpread);
	this.drawCanvas = defaultTo(c, attrs.drawCanvas);
	this.makeBounds();
	this.addCleanUp();
	this.particles = [];
	return this.init();
}
_.extend(ParticleEmitter.prototype, objectFuncs, {
	init: function(){
		this.runListenerName = unique('particle' + this.handle, curLevel.updateListeners.listeners);
		addListener(curLevel, 'update', this.runListenerName, this.run, this);
		return this;
	},
	adjust: function(attrs){
		if(attrs.angle){
			this.dir+=attrs.angle;
		}
		if(attrs.v){
			this.pos.movePt(attrs.v);
		}
		if(attrs.col){
			this.col = attrs.col.copy();
		}
		this.makeBounds();
	},
	makeBounds: function(){
		this.UV = angleToUV(this.dir);
		//var dir1 = UV.rotate(-Math.PI/2);
		//var dir2 = UV.rotate(Math.PI/2);
		var edgePt1 = this.pos.copy().movePt(this.UV.copy().rotate(-Math.PI/2).mult(this.width/2));
		var edgePt2 = this.pos.copy().movePt(this.UV.copy().rotate(Math.PI/2).mult(this.width/2));
		this.prodPt = edgePt1;
		this.prodV = edgePt1.VTo(edgePt2);
		this.finishPt = edgePt1.copy().movePt(this.UV.copy().mult(this.dist))
		this.finishV = this.finishPt.VTo(this.prodPt);
	},
	run: function(){
		this.generateNew();
		this.updateParticles();
		this.draw();
	},
	trickleOut: function(){
		this.updateParticles();
		this.draw();
		if(this.particles.length==0){
			this.remove();
		}
	},
	generateNew: function(){
		var numNew = Math.round(Math.random()*this.rate);
		for(var newIdx=0; newIdx<numNew; newIdx++){
			this.particles.push(this.newParticle());
		}
	},
	newParticle: function(){
		var initPos = this.prodPt.copy().movePt(this.prodV.copy().mult(Math.random()));
		var initSpeed = Math.max(.01, this.speed + this.speedSpread*(Math.random()-.5));
		var accel = Math.max(0, this.accel + this.accelSpread*(Math.random()-.5));
		var UV = angleToUV(this.dir + this.dirSpread*(Math.random()-.5));
		var lifetime = this.getLifetime(initPos, initSpeed, accel, UV);
		return {pos:initPos, V:UV.copy().mult(initSpeed), accelV:UV.copy().mult(accel), age:0, lifetime:lifetime};
	},
	getLifetime: function(initPos, initSpeed, accel, UV){
		var coLinRatio = UV.dotProd(this.UV);
		var coLinAccel = accel*coLinRatio;
		var coLinSpeed = initSpeed*coLinRatio;
		var a = .5*coLinAccel;
		var b = coLinSpeed;
		var c = -this.dist;
		return (-b + Math.sqrt(b*b - 4*a*c))/(2*a);
	},
	updateParticles: function(){
		for (var particleIdx=this.particles.length-1; particleIdx>=0; particleIdx-=1){
			var particle = this.particles[particleIdx];
			particle.pos.movePt(particle.V);
			particle.V.add(particle.accelV);
			particle.age++;
			if(particle.age>particle.lifetime){
				this.particles.splice(particleIdx, 1);
			}
		}
	},
	/*
	isFinished: function(particle){
		var particleV = this.finishPt.VTo(particle.pos);
		if(particleV.dotProd(this.finishV)<0){
			return true;
		}
		return false;
	},
	*/
	draw: function(){
		this.drawCanvas.strokeStyle = this.col.hex;
		for (var particleIdx = 0; particleIdx<this.particles.length; particleIdx++){
			var particle = this.particles[particleIdx];
			//c.globalAlpha = dotsLocal[dotIdx].col.a;
			c.beginPath();
			c.moveTo(particle.pos.x, particle.pos.y);
			c.lineTo(particle.pos.x+1, particle.pos.y+1);
			c.closePath();
			//perhaps can more stroke outside of this function?  I think I can, actually.
			c.stroke();

		}
	},
	stopFlow: function(){
		removeListener(curLevel, 'update', this.runListenerName);
		addListener(curLevel, 'update', this.runListenerName, this.trickleOut, this)
	},
	remove: function(){
		removeListener(curLevel, 'update', this.runListenerName);
		removeListener(curLevel, 'cleanUp', this.cleanUpListenerName);
		this.removed = true;
	},

}
)<commit_msg>working on sandbox.  Added onGenerate, onFinish<commit_after>/*
Contains:
	Sandbox
	ParticleEmitter
*/
function Sandbox(attrs){
	var self = this;
	attrs = defaultTo({}, attrs);
	this.bin = {};
	this.drawCanvas = defaultTo(c, attrs.drawCanvas);
	this.rate = defaultTo(.15, attrs.rate);
	this.wallInfo = defaultTo(0, attrs.wallInfo);
	this.wall = walls[this.wallInfo];
	this.massMax = defaultTo(75, attrs.massMax);
	this.massMin = defaultTo(10, attrs.massMin);
	this.mass = defaultTo(10, attrs.massInit);
	this.buttonAdd = defaultTo('buttonAddMass', attrs.addButtonId);
	this.buttonRemove = defaultTo('buttonRemoveMass', attrs.removeButtonId);
	this.particleMass = .05;
	this.makeButtons();

	this.massChunkName = 'sandMass' + defaultTo('', attrs.handle);
	this.wall.setMass(this.massChunkName, this.mass);
	this.wall.recordPExt();
	this.wall.recordWork();
	this.wallHandler = defaultTo('cPAdiabaticDamped', attrs.compMode) + compAdj;
	walls.setSubWallHandler(this.wallInfo, 0, this.wallHandler);

	this.emitters = new Array();
	this.spcVol = 70; //specific volume
	this.sand.col = defaultTo(Col(224, 165, 75), attrs.sandCol);
	this.sand.pts = this.getLiquidPts();

	this.binX = (this.wall[1].x+this.wall[0].x)/2;
	this.pistonPt = this.wall[0].y;

	this.addCleanUp();

	return this.init();
}
_.extend(Sandbox.prototype, compressorFuncs, objectFuncs,
{
	init: function(){
		this.drawListenerName = unique('drawSand' + this.handle, curLevel.updateListeners.listeners);
		this.cleanUpEmittersListenerName = unique('cleanUpSandEmitters' + this.handle, curLevel.updateListener.listeners);
		addListener(curLevel, 'update', this.drawListenerName, this.draw, this);
		addListener(curLevel, 'data', this.cleanUpEmittersListenerName, this.cleanUpEmitters, this);
		this.wall.moveInit();
		return this.displayMass().displayPressure();
	},
	makeButtons: function(){
		addButton(this.buttonAddId, 'Add mass');
		addButton(this.buttonRemoveId, 'Remove mass');
		var self = this;
		$('#'+this.buttonAddId).mousedown(function(){self.buttonAddDown()});
		$('#'+this.buttonAddId).mouseup(function(){self.buttonAddUp()});

		$('#'+this.buttonRemoveId).mousedown(function(){self.buttonRemoveDown()});
		$('#'+this.buttonRemoveId).mouseup(function(){self.buttonRemoveUp()});
	},
	draw: function(){
		this.drawCanvas.save();
		this.drawCanvas.translate(this.binX, this.pistonY());
		draw.fillPts(this.bin.pts, this.bin.col, this.drawCanvas);
		draw.fillPts(this.sand.pts, this.liquid.col, this.drawCanvas);
		this.drawCanvas.restore();
	},
	cleanUpEmitters: function(){
		for(var emitterIdx=this.emitters.length-1; emitterIdx>=0; emitterIdx-=1){
			if(this.emitters[emitterIdx].removed){
				this.emitters.slice(emitterIdx, 1);
			}
		}
	},
	getSandPts: function(){
		var dWidth = this.bin.widthUpper - this.bin.width;
		this.liquid.height = this.mass*this.spcVol/(this.bin.width + (dWidth)/this.bin.height);
		var height = this.liquid.height;
		var pts = new Array(4);
		var liquidDWidth = dWidth*height/this.bin.height;
		pts[0] = P(-this.bin.width/2, -this.bin.thickness);
		pts[1] = P(this.bin.width/2, -this.bin.thickness);
		pts[2] = P((this.bin.width + liquidDWidth)/2, -height-this.bin.thickness);
		pts[3] = P((-this.bin.width - liquidDWidth)/2, -height-this.bin.thickness);
		return pts;
	},
	buttonAddDown: function(){
		this.addMass();
	},
	buttonAddUp: function(){
		this.addMassStop();
	},
	buttonRemoveDown: function(){
		this.removeMass();
	},
	buttonRemoveUp: function(){
		this.removeMassStop();
	},

	addMass: function(){
		this.emitters.push(this.makeAddEmitter())
	},
	addMassStop: function(){
		this.emitters[this.emitters.length-1].stopFlow();
	},
	removeMass: function(){
		this.emitters.push(this.madeRemoveEmitter());
	},
	removeMassStop: function(){
		this.emitters[this.emitters.length-1].stopFlow();
	},
	makeAddEmitter: function(){
		var onFinish = {func:this.onFinishAdd, obj:this};
		var emitterIdx = this.emitters.length-1;
		addListener(curLevel, 'update',
		//You were here.  Need to make a listener that adjusts dist of emitter and then removes when emitter is done
		//Maybe give the emitter an onRemove func (OH YEAH, DO THAT)
	},
	onGenerateRemove: function(){
		this.mass-=this.particleMass;
		this.wall.setMass(this.massChunkName, this.mass);
	},
	onFinishAdd: function(){
		this.mass+=this.particleMass;
		this.wall.setMass(this.massChunkName, this.mass);
	},
	remove: function(){
		for(var emitterIdx=0; emitterIdx<this.emitters.length; emitterIdx++){
			this.emitters[emitterIdx].remove();
		}
		this.emitters = [];
		removeListener(curLevel, 'update', this.drawListenerName);
		removeListener(curLevel, 'data', this.cleanUpEmittersListenerName);
		this.wall.moveStop();
	},

}
)
function testPart(){
	sillyParticles = new ParticleEmitter({pos:P(300,50), dir:0, width:100, dist:300, col:Col(0,0,255)});
}
function ParticleEmitter(attrs){
	this.pos = attrs.pos;
	this.handle = unique('emitter' + defaultTo('', attrs.handle), curLevel.updateListeners.listeners);
	this.dir = attrs.dir;
	this.width = attrs.width;
	this.col = attrs.col;
	this.dist = attrs.dist;
	this.onGenerate = attrs.onGenerate;
	this.onFinish = attrs.onFinish;
	this.rate = defaultTo(Math.round(.1*this.width), attrs.rate);
	this.speed = defaultTo(5, attrs.speed);
	this.speedSpread = defaultTo(1, attrs.speedSpread);
	if(2*this.speedSpread>this.speed){
		console.log('Uh-oh.  Making particle emitter with handle ' + this.handle + ' with speed spread such that particles will hit ~0 speed');
	}
	this.accel = defaultTo(.5, attrs.accel);
	this.accelSpread = defaultTo(1, attrs.accelSpread);
	this.dirSpread = defaultTo(0, attrs.dirSpread);
	this.drawCanvas = defaultTo(c, attrs.drawCanvas);
	this.makeBounds();
	this.addCleanUp();
	this.particles = [];
	return this.init();
}
_.extend(ParticleEmitter.prototype, objectFuncs, {
	init: function(){
		this.runListenerName = unique('particle' + this.handle, curLevel.updateListeners.listeners);
		addListener(curLevel, 'update', this.runListenerName, this.run, this);
		return this;
	},
	adjust: function(attrs){
		for(var attr in attrs){
			this[attr] = attrs[attr];
		}
		this.makeBounds();
	},
	makeBounds: function(){
		this.UV = angleToUV(this.dir);
		var edgePt1 = this.pos.copy().movePt(this.UV.copy().rotate(-Math.PI/2).mult(this.width/2));
		var edgePt2 = this.pos.copy().movePt(this.UV.copy().rotate(Math.PI/2).mult(this.width/2));
		this.prodPt = edgePt1;
		this.prodV = edgePt1.VTo(edgePt2);
		this.finishPt = edgePt1.copy().movePt(this.UV.copy().mult(this.dist))
		this.finishV = this.finishPt.VTo(this.prodPt);
	},
	run: function(){
		this.generateNew();
		this.updateParticles();
		this.draw();
	},
	trickleOut: function(){
		this.updateParticles();
		this.draw();
		if(this.particles.length==0){
			this.remove();
		}
	},
	generateNew: function(){
		var numNew = Math.round(Math.random()*this.rate);
		for(var newIdx=0; newIdx<numNew; newIdx++){
			this.particles.push(this.newParticle());
			if(this.onGenerate){
				this.onGenerate.func.apply(this.onGenerate.obj);
			}
		}
	},
	newParticle: function(){
		var initPos = this.prodPt.copy().movePt(this.prodV.copy().mult(Math.random()));
		var initSpeed = Math.max(.01, this.speed + this.speedSpread*(Math.random()-.5));
		var accel = Math.max(0, this.accel + this.accelSpread*(Math.random()-.5));
		var UV = angleToUV(this.dir + this.dirSpread*(Math.random()-.5));
		var lifetime = this.getLifetime(initPos, initSpeed, accel, UV);
		return {pos:initPos, V:UV.copy().mult(initSpeed), accelV:UV.copy().mult(accel), age:0, lifetime:lifetime};
	},
	getLifetime: function(initPos, initSpeed, accel, UV){
		var coLinRatio = UV.dotProd(this.UV);
		var coLinAccel = accel*coLinRatio;
		var coLinSpeed = initSpeed*coLinRatio;
		var a = .5*coLinAccel;
		var b = coLinSpeed;
		var c = -this.dist;
		return (-b + Math.sqrt(b*b - 4*a*c))/(2*a);
	},
	updateParticles: function(){
		for (var particleIdx=this.particles.length-1; particleIdx>=0; particleIdx-=1){
			var particle = this.particles[particleIdx];
			particle.pos.movePt(particle.V);
			particle.V.add(particle.accelV);
			particle.age++;
			if(particle.age>particle.lifetime){
				this.particles.splice(particleIdx, 1);
				if(this.onFinish){
					this.onFinish.func.apply(this.onFinish.obj);
				}
			}
		}
	},
	/*
	isFinished: function(particle){
		var particleV = this.finishPt.VTo(particle.pos);
		if(particleV.dotProd(this.finishV)<0){
			return true;
		}
		return false;
	},
	*/
	draw: function(){
		this.drawCanvas.strokeStyle = this.col.hex;
		for (var particleIdx = 0; particleIdx<this.particles.length; particleIdx++){
			var particle = this.particles[particleIdx];
			c.beginPath();
			c.moveTo(particle.pos.x, particle.pos.y);
			c.lineTo(particle.pos.x+2, particle.pos.y+2);
			//if lines start behaving strangely, not closing the path here may have something to do with it
			c.stroke();
		}
	},
	stopFlow: function(){
		removeListener(curLevel, 'update', this.runListenerName);
		addListener(curLevel, 'update', this.runListenerName, this.trickleOut, this)
	},
	remove: function(){
		removeListener(curLevel, 'update', this.runListenerName);
		removeListener(curLevel, 'cleanUp', this.cleanUpListenerName);
		this.removed = true;
	},

}
)<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { HOC as FormsyHOC } from 'formsy-react';
import { styleClassNames } from '../components/prop-types';

// Component HOC
// -------------
//
// This HOC provides shared code for our form components.
//
// We use this to merge props set using our OptionsProvider, so that
// we can set commonly used props on an enclosing component.
//
// This allows us to set these properties 'as a whole' for each component in the
// the form, while retaining the ability to override the prop on a per-component
// basis.
const FormsyReactComponent = (ComposedComponent) => {
    class ComponentHOC extends Component {

        // Use the following value for layout:
        // 1. layout prop (if supplied)
        // 2. [else] layout context (if defined)
        // 3. [else] 'horizontal' (default value)
        getLayout = () => {
            return this.props.layout || (this.context.layout || 'horizontal');
        }

        // Use the following value for validatePristine:
        // 1. validatePristine prop (if supplied)
        // 2. [else] validatePristine context (if defined)
        // 3. [else] false (default value)
        getValidatePristine = () => {
            if (typeof this.props.validatePristine === 'boolean') {
                return this.props.validatePristine;
            }
            return this.context.validatePristine || false;
        }

        // Use the following value for validateOnSubmit:
        // 1. validateOnSubmit prop (if supplied)
        // 2. [else] validateOnSubmit context (if defined)
        // 3. [else] false (default value)
        getValidateOnSubmit = () => {
            if (typeof this.props.validateOnSubmit === 'boolean') {
                return this.props.validateOnSubmit;
            }
            return this.context.validateOnSubmit || false;
        }

        // Combine a parent context value with a component prop value.
        // This is used for CSS classnames, where the value is passed to `JedWatson/classnames`.
        combineContextWithProp = (key) => {
            return [this.context[key], this.props[key]];
        }

        // getId
        // -----
        //
        // The ID is used as an attribute on the form control, and is used to allow
        // associating the label element with the form control.
        //
        // If we don't explicitly pass an `id` prop, we generate one based on the
        // `name` and `label` properties.
        getId = () => {
            let { id, label, name } = this.props;
            if (id !== '') {
                return id;
            }
            return [
                'frc',
                name.split('[').join('_').replace(']', ''),
                this.hashString(JSON.stringify(label))
            ].join('-');
        }

        hashString = (string) => {
            var hash = 0;
            for (var i = 0; i < string.length; i++) {
                hash = (((hash << 5) - hash) + string.charCodeAt(i)) & 0xFFFFFFFF;
            }
            return hash;
        }

        // Determine whether to show errors, or not.
        shouldShowErrors = () => {
            if (this.props.isPristine() === true) {
                if (this.getValidatePristine() === false) {
                    return false;
                }
            }
            if (this.getValidateOnSubmit() === true) {
                if (this.props.isFormSubmitted() === false) {
                    return false;
                }
            }
            return (this.props.isValid() === false);
        }

        // We pass through all unknown props, but delete some formsy HOC props that we know we don't need.
        render() {

            let cssProps = {
                elementWrapperClassName: this.combineContextWithProp('elementWrapperClassName'),
                labelClassName:          this.combineContextWithProp('labelClassName'),
                rowClassName:            this.combineContextWithProp('rowClassName'),
            };

            let props = {
                ...this.props,
                ...cssProps,
                disabled:      this.props.isFormDisabled() || this.props.disabled,
                errorMessages: this.props.getErrorMessages(),
                id:            this.getId(),
                layout:        this.getLayout(),
                ref:           this.props.componentRef,
                required:      this.props.isRequired(),
                showErrors:    this.shouldShowErrors(),
                value:         this.props.getValue(),
                onSetValue:    this.props.setValue
            };

            // Formsy HOC props we don't use.
            delete props.getErrorMessage;
            delete props.getErrorMessages;
            delete props.getValue;
            delete props.hasValue;
            delete props.isFormDisabled;
            delete props.isFormSubmitted;
            delete props.isPristine;
            delete props.isRequired;
            delete props.isValid;
            delete props.isValidValue;
            delete props.resetValue;
            delete props.setValidations;
            delete props.setValue;
            delete props.showError;
            delete props.showRequired;

            // Formsy props we don't use
            delete props.validationError;
            delete props.validationErrors;
            delete props.validations;

            // HOC refs
            delete props.innerRef;
            delete props.componentRef;

            return (
                <ComposedComponent
                    {...props}
                />
            );
        }
    }

    // These are the props that we require from the formsy-react HOC.
    // There are others, but as we don't use them, we don't need to define their PropTypes.
    const formsyPropTypes = {
        getErrorMessages: PropTypes.func.isRequired,
        getValue: PropTypes.func.isRequired,
        isFormDisabled: PropTypes.func.isRequired,
        isPristine: PropTypes.func.isRequired,
        isRequired: PropTypes.func.isRequired,
        isValid: PropTypes.func.isRequired,
        setValue: PropTypes.func.isRequired
    };

    ComponentHOC.propTypes = {

        ...formsyPropTypes,
        ...styleClassNames,

        name: PropTypes.string.isRequired,
        disabled: PropTypes.bool,

        // Not used here, but composed components expect this to be a string.
        help: PropTypes.string,

        id: PropTypes.string,
        label: PropTypes.string,
        layout: PropTypes.string,

        // * validateOnSubmit
        // * validatePristine
        //
        // Neither of these props actually stop the validations from running,
        // they just determine whether the error messages should be shown on
        // components or not.

        // Whether to hide validation errors on components before the form is
        // submitted.
        validateOnSubmit: PropTypes.bool,

        // Whether to show validation errors on pristine (untouched) components.
        validatePristine: PropTypes.bool,
    };

    ComponentHOC.contextTypes = {
        ...styleClassNames,
        layout: PropTypes.string,
        validateOnSubmit: PropTypes.bool,
        validatePristine: PropTypes.bool
    };

    // TODO: Should we add default props for the following?:
    // * elementWrapperClassName
    // * labelClassName
    // * rowClassName

    // The following props get their default values by first looking for props in the parent context.
    // * layout (See getLayout, defaults to 'horizontal')
    // * validatePristine: (See getValidatePristine, defaults to 'false'),
    // * validateOnSubmit: (See getValidateOnSubmit, defaults to 'false'),
    ComponentHOC.defaultProps = {
        disabled: false,
        id: '',
        label: ''
    };

    return FormsyHOC(ComponentHOC);

};

export default FormsyReactComponent;
<commit_msg>Tweak displayname, and update for forthcoming formsy-react 1.0.<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Wrapper as FormsyHOC } from 'formsy-react';
import { styleClassNames } from '../components/prop-types';

function getDisplayName(component) {
    return (
        component.displayName ||
        component.name ||
        (typeof component === 'string' ? component : 'Component')
    );
}

// Component HOC
// -------------
//
// This HOC provides shared code for our form components.
//
// We use this to merge props set using our OptionsProvider, so that
// we can set commonly used props on an enclosing component.
//
// This allows us to set these properties 'as a whole' for each component in the
// the form, while retaining the ability to override the prop on a per-component
// basis.
const FormsyReactComponent = (ComposedComponent) => {
    class ComponentHOC extends Component {

        // Use the following value for layout:
        // 1. layout prop (if supplied)
        // 2. [else] layout context (if defined)
        // 3. [else] 'horizontal' (default value)
        getLayout = () => {
            return this.props.layout || (this.context.layout || 'horizontal');
        }

        // Use the following value for validatePristine:
        // 1. validatePristine prop (if supplied)
        // 2. [else] validatePristine context (if defined)
        // 3. [else] false (default value)
        getValidatePristine = () => {
            if (typeof this.props.validatePristine === 'boolean') {
                return this.props.validatePristine;
            }
            return this.context.validatePristine || false;
        }

        // Use the following value for validateOnSubmit:
        // 1. validateOnSubmit prop (if supplied)
        // 2. [else] validateOnSubmit context (if defined)
        // 3. [else] false (default value)
        getValidateOnSubmit = () => {
            if (typeof this.props.validateOnSubmit === 'boolean') {
                return this.props.validateOnSubmit;
            }
            return this.context.validateOnSubmit || false;
        }

        // Combine a parent context value with a component prop value.
        // This is used for CSS classnames, where the value is passed to `JedWatson/classnames`.
        combineContextWithProp = (key) => {
            return [this.context[key], this.props[key]];
        }

        // getId
        // -----
        //
        // The ID is used as an attribute on the form control, and is used to allow
        // associating the label element with the form control.
        //
        // If we don't explicitly pass an `id` prop, we generate one based on the
        // `name` and `label` properties.
        getId = () => {
            let { id, label, name } = this.props;
            if (id !== '') {
                return id;
            }
            return [
                'frc',
                name.split('[').join('_').replace(']', ''),
                this.hashString(JSON.stringify(label))
            ].join('-');
        }

        hashString = (string) => {
            var hash = 0;
            for (var i = 0; i < string.length; i++) {
                hash = (((hash << 5) - hash) + string.charCodeAt(i)) & 0xFFFFFFFF;
            }
            return hash;
        }

        // Determine whether to show errors, or not.
        shouldShowErrors = () => {
            if (this.props.isPristine() === true) {
                if (this.getValidatePristine() === false) {
                    return false;
                }
            }
            if (this.getValidateOnSubmit() === true) {
                if (this.props.isFormSubmitted() === false) {
                    return false;
                }
            }
            return (this.props.isValid() === false);
        }

        // We pass through all unknown props, but delete some formsy HOC props that we know we don't need.
        render() {

            let cssProps = {
                elementWrapperClassName: this.combineContextWithProp('elementWrapperClassName'),
                labelClassName:          this.combineContextWithProp('labelClassName'),
                rowClassName:            this.combineContextWithProp('rowClassName'),
            };

            let props = {
                ...this.props,
                ...cssProps,
                disabled:      this.props.isFormDisabled() || this.props.disabled,
                errorMessages: this.props.getErrorMessages(),
                id:            this.getId(),
                layout:        this.getLayout(),
                ref:           this.props.componentRef,
                required:      this.props.isRequired(),
                showErrors:    this.shouldShowErrors(),
                value:         this.props.getValue(),
                onSetValue:    this.props.setValue
            };

            // Formsy HOC props we don't use.
            delete props.getErrorMessage;
            delete props.getErrorMessages;
            delete props.getValue;
            delete props.hasValue;
            delete props.isFormDisabled;
            delete props.isFormSubmitted;
            delete props.isPristine;
            delete props.isRequired;
            delete props.isValid;
            delete props.isValidValue;
            delete props.resetValue;
            delete props.setValidations;
            delete props.setValue;
            delete props.showError;
            delete props.showRequired;

            // Formsy props we don't use
            delete props.validationError;
            delete props.validationErrors;
            delete props.validations;

            // HOC refs
            delete props.innerRef;
            delete props.componentRef;

            return (
                <ComposedComponent
                    {...props}
                />
            );
        }
    }

    // These are the props that we require from the formsy-react HOC.
    // There are others, but as we don't use them, we don't need to define their PropTypes.
    const formsyPropTypes = {
        getErrorMessages: PropTypes.func.isRequired,
        getValue: PropTypes.func.isRequired,
        isFormDisabled: PropTypes.func.isRequired,
        isPristine: PropTypes.func.isRequired,
        isRequired: PropTypes.func.isRequired,
        isValid: PropTypes.func.isRequired,
        setValue: PropTypes.func.isRequired
    };

    ComponentHOC.propTypes = {

        ...formsyPropTypes,
        ...styleClassNames,

        name: PropTypes.string.isRequired,
        disabled: PropTypes.bool,

        // Not used here, but composed components expect this to be a string.
        help: PropTypes.string,

        id: PropTypes.string,
        label: PropTypes.string,
        layout: PropTypes.string,

        // * validateOnSubmit
        // * validatePristine
        //
        // Neither of these props actually stop the validations from running,
        // they just determine whether the error messages should be shown on
        // components or not.

        // Whether to hide validation errors on components before the form is
        // submitted.
        validateOnSubmit: PropTypes.bool,

        // Whether to show validation errors on pristine (untouched) components.
        validatePristine: PropTypes.bool,
    };

    ComponentHOC.contextTypes = {
        ...styleClassNames,
        layout: PropTypes.string,
        validateOnSubmit: PropTypes.bool,
        validatePristine: PropTypes.bool
    };

    // TODO: Should we add default props for the following?:
    // * elementWrapperClassName
    // * labelClassName
    // * rowClassName

    // The following props get their default values by first looking for props in the parent context.
    // * layout (See getLayout, defaults to 'horizontal')
    // * validatePristine: (See getValidatePristine, defaults to 'false'),
    // * validateOnSubmit: (See getValidateOnSubmit, defaults to 'false'),
    ComponentHOC.defaultProps = {
        disabled: false,
        id: '',
        label: ''
    };

    ComponentHOC.displayName = `FRC(${getDisplayName(ComposedComponent)})`;

    return FormsyHOC(ComponentHOC);

};

export default FormsyReactComponent;
<|endoftext|>


<commit_before>function createObstacle(options){
    let boxes = [];

	let obstacle = {
		spriteSheets: options.spriteSheets,
        spriteSheet: options.spriteSheets[0],
		context: options.context,
		width: options.width,
		height: options.height,
		obstacleCrateYLine: options.obstacleCrateYLine,
		numberOfFrames: options.numberOfFrames,
		loopTicksPerFrame: options.loopTicksPerFrame,
		frameIndex: 0,
		loopTicksCount: 0,
		render: render,
		update: update,
		boxes: boxes,
		spawnBoxHurdle: spawnBoxHurdle,
		iterateBoxesArray: iterateBoxesArray
    };

	let clearOffset = 0;

    function render(drawCoordinates, clearCoordinates) {
		this.context.clearRect(
			clearCoordinates.x - clearOffset,
			clearCoordinates.y - clearOffset,
			this.width + clearOffset * 2,
			this.height + clearOffset * 2
		);

		this.context.drawImage(
			this.spriteSheet,
			this.frameIndex * this.width,
			0,
			this.width,
			this.height,
			drawCoordinates.x,
			drawCoordinates.y,
			this.width,
			this.height
		);
	}

	function update() {
		this.loopTicksCount += 1;

		if (this.loopTicksCount >= this.loopTicksPerFrame) {
			this.loopTicksCount = 0;
			this.frameIndex += 1;

			if (this.frameIndex >= this.numberOfFrames) {
				this.frameIndex = 0;
			}
		}
	}

	function spawnBoxHurdle() {
		let spawnChance = 0.01,
			spawnOffsetX = 200;

		if (Math.random() < spawnChance) {
			if (boxes.length) {
				var lastBox = boxes[boxes.length - 1];
				var newBox = createPhysicalBody({
					coordinates: { x: 1000, y: this.obstacleCrateYLine},
					speed: { x: -3, y: 0 },
					height: this.height,
					width: this.width
				});
				boxes.push(newBox);

			} else {
				boxes.push(createPhysicalBody({
					coordinates: { x: 1000, y: this.obstacleCrateYLine},
					speed: { x: -3, y: 0 },
					height: this.height,
					width: this.width
				}));
			}
		}
	}

	function iterateBoxesArray(){
		for (i = 0; i < this.boxes.length; i += 1) {

			box = this.boxes[i];

			// if out of game field, remove pokeball
			if (box.coordinates.x < -box.width) {
				this.boxes.splice(i, 1);
				i -= 1;
				continue;
			}

			let lastObstacleCrateCoordinates = box.move();
			this.render(box.coordinates, lastObstacleCrateCoordinates);
			this.update();

			// if (ninjaPhysicalBody.collidesWith(box.body)) {
			// 	alert("Game over!");
			// }
		}
	}

    return obstacle;
}<commit_msg>Fixed overlaping obstacles<commit_after>function createObstacle(options){
    let boxes = [];

	let obstacle = {
		spriteSheets: options.spriteSheets,
        spriteSheet: options.spriteSheets[0],
		context: options.context,
		width: options.width,
		height: options.height,
		obstacleCrateYLine: options.obstacleCrateYLine,
		numberOfFrames: options.numberOfFrames,
		loopTicksPerFrame: options.loopTicksPerFrame,
		frameIndex: 0,
		loopTicksCount: 0,
		render: render,
		update: update,
		boxes: boxes,
		spawnBoxHurdle: spawnBoxHurdle,
		iterateBoxesArray: iterateBoxesArray
    };

	let clearOffset = 0;

    function render(drawCoordinates, clearCoordinates) {
		this.context.clearRect(
			clearCoordinates.x - clearOffset,
			clearCoordinates.y - clearOffset,
			this.width + clearOffset * 2,
			this.height + clearOffset * 2
		);

		this.context.drawImage(
			this.spriteSheet,
			this.frameIndex * this.width,
			0,
			this.width,
			this.height,
			drawCoordinates.x,
			drawCoordinates.y,
			this.width,
			this.height
		);
	}

	function update() {
		this.loopTicksCount += 1;

		if (this.loopTicksCount >= this.loopTicksPerFrame) {
			this.loopTicksCount = 0;
			this.frameIndex += 1;

			if (this.frameIndex >= this.numberOfFrames) {
				this.frameIndex = 0;
			}
		}
	}

	function spawnBoxHurdle() {
		var spawnChance = 0.01,
			spawnOffsetX = 200;
		var newBox = createPhysicalBody({
					coordinates: { x: 1000, y: this.obstacleCrateYLine},
					speed: { x: -3, y: 0 },
					height: this.height,
					width: this.width
				});

		if (Math.random() < spawnChance) {
			if (this.boxes.length) {
				if (this.boxes[boxes.length-1].coordinates.x < 700){
					var lastBox = boxes[boxes.length - 1];
					boxes.push(newBox);
				}
			} else {
				boxes.push(newBox);
			}
		}
	}

	function iterateBoxesArray(){
		for (i = 0; i < this.boxes.length; i += 1) {

			box = this.boxes[i];

			if (box.coordinates.x < -box.width) {
				this.boxes.splice(i, 1);
				i -= 1;
				continue;
			}

			let lastObstacleCrateCoordinates = box.move();
			this.render(box.coordinates, lastObstacleCrateCoordinates);
			this.update();

			// if (ninjaPhysicalBody.collidesWith(box.body)) {
			// 	alert("Game over!");
			// }
		}
	}

    return obstacle;
}
<|endoftext|>


<commit_before>'use strict';

module.exports = {
  tests: {
    client: ['modules/*/tests/client/**/*.js'],
    server: ['modules/*/tests/server/**/*.js'],
    e2e: ['modules/*/tests/e2e/**/*.js']
  }
};
<commit_msg> read tests for audio model<commit_after>'use strict';

module.exports = {
  tests: {
    //client: ['modules/*/tests/client/**/*.js'],
    server: ['modules/audioFiles/tests/server/**/*.js']//,
    //e2e: ['modules/*/tests/e2e/**/*.js']
  }
};
<|endoftext|>


<commit_before>'use strict'

var angular = require('angular')
var objectKeys = require('object-keys')
var arrayMap = require('array-map')

module.exports = httpEtagHttpDecorator

httpEtagHttpDecorator.$inject = ['$delegate', 'httpEtag']

function httpEtagHttpDecorator ($delegate, httpEtag) {
  var $http = $delegate
  var cachableHttpMethods = [
    'GET',
    'JSONP'
  ]
  var $httpShortcutMethods = [
    'get',
    'head',
    'post',
    'put',
    'delete',
    'jsonp',
    'patch'
  ]

  function $httpDecorator (httpConfig) {
    var isCachable = httpConfig.etagCache && cachableHttpMethods.indexOf(httpConfig.method) >= 0
    var httpPromise

    if (isCachable) {
      var etagCacheConfig = processHttpConfigEtagValue(httpConfig)
      if (etagCacheConfig) {
        var itemCache = httpEtag.getItemCache(etagCacheConfig.id, etagCacheConfig.itemKey)
        var cacheInfo = itemCache.info()
        var cachedData = itemCache.get()
        var cachedEtag = cachedData && cachedData.etagHeader
        var cachedResponse = cachedEtag && cachedData.responseData

        // Allow easy access to cache in interceptor
        httpConfig.$$_itemCache = itemCache

        if (cachedEtag) {
          httpConfig.headers = angular.extend({}, httpConfig.headers, {
            'If-None-Match': cachedEtag
          })
        }
      }
    }

    httpPromise = $http.apply($http, arguments)

    httpPromise.cached = function (callback) {
      if (isCachable && cachedData && cacheInfo.cacheResponseData) callback(cachedResponse, undefined, undefined, httpConfig, itemCache)
      return httpPromise
    }

    return httpPromise
  }

  // Decorate the shortcut methods, too
  angular.forEach($httpShortcutMethods, function (method) {
    var httpMethod = method.toUpperCase()
    var isCachable = cachableHttpMethods.indexOf(httpMethod) >= 0
    var shortcutMethod

    if (!isCachable) shortcutMethod = $http[method]
    else {
      shortcutMethod = function httpEtagHttpShortcutWrapper (url, config) {
        config = angular.extend({}, config, {
          method: httpMethod,
          url: url
        })

        return $httpDecorator.call($http, config)
      }
    }
    $httpDecorator[method] = shortcutMethod
  })

  /**
   * HELPERS
   */

  function processHttpConfigEtagValue (httpConfig) {
    var etagValue = httpConfig.etagCache
    var etagValueType = typeof etagValue
    var etagCacheConfig = {}

    // Evaluate function first
    if (etagValueType === 'function') {
      etagValue = etagValue(httpConfig)
      etagValueType = typeof etagValue
    }

    if (etagValueType === 'object') {
      etagCacheConfig.id = etagValue.id
      etagCacheConfig.itemKey = etagValue.itemKey || generateCacheItemKey(httpConfig)
    } else if (etagValueType === 'string') {
      etagCacheConfig.id = etagValue
      etagCacheConfig.itemKey = generateCacheItemKey(httpConfig)
    } else if (etagValue === true) {
      // Undefined cacheId will use the default cacheId as defined in provider
      etagCacheConfig.itemKey = generateCacheItemKey(httpConfig)
    } else return
    return etagCacheConfig
  }

  function generateCacheItemKey (httpConfig) {
    var url = httpConfig.url
    var params = stringifyParams(httpConfig.params)
    return url + ((params && url.indexOf('?') > 0) ? '&' : '?') + params
  }

  // Based on npm package "query-string"
  function stringifyParams (obj) {
    return obj ? arrayMap(objectKeys(obj).sort(), function (key) {
      var val = obj[key]

      if (angular.isArray(val)) {
        return arrayMap(val.sort(), function (val2) {
          return encodeURIComponent(key) + '=' + encodeURIComponent(val2)
        }).join('&')
      }

      return encodeURIComponent(key) + '=' + encodeURIComponent(val)
    }).join('&') : ''
  }

  return $httpDecorator
}
<commit_msg>Cached callback now has status of 'cached', add itemCache to success<commit_after>'use strict'

var angular = require('angular')
var objectKeys = require('object-keys')
var arrayMap = require('array-map')

module.exports = httpEtagHttpDecorator

httpEtagHttpDecorator.$inject = ['$delegate', 'httpEtag']

function httpEtagHttpDecorator ($delegate, httpEtag) {
  var $http = $delegate
  var cachableHttpMethods = [
    'GET',
    'JSONP'
  ]
  var $httpShortcutMethods = [
    'get',
    'head',
    'post',
    'put',
    'delete',
    'jsonp',
    'patch'
  ]

  function $httpDecorator (httpConfig) {
    var isCachable = httpConfig.etagCache && cachableHttpMethods.indexOf(httpConfig.method) >= 0
    var httpPromise

    if (isCachable) {
      var etagCacheConfig = processHttpConfigEtagValue(httpConfig)
      if (etagCacheConfig) {
        var itemCache = httpEtag.getItemCache(etagCacheConfig.id, etagCacheConfig.itemKey)
        var cacheInfo = itemCache.info()
        var cachedData = itemCache.get()
        var cachedEtag = cachedData && cachedData.etagHeader
        var cachedResponse = cachedEtag && cachedData.responseData

        // Allow easy access to cache in interceptor
        httpConfig.$$_itemCache = itemCache

        if (cachedEtag) {
          httpConfig.headers = angular.extend({}, httpConfig.headers, {
            'If-None-Match': cachedEtag
          })
        }
      }
    }

    httpPromise = $http.apply($http, arguments)

    httpPromise.cached = function (callback) {
      if (isCachable && cachedData && cacheInfo.cacheResponseData) callback(cachedResponse, 'cached', undefined, httpConfig, itemCache)
      return httpPromise
    }

    if (itemCache) {
      var onSuccess = httpPromise.success
      httpPromise.success = function (callback) {
        var partialCallback = partial(callback, undefined, undefined, undefined, undefined, itemCache)
        return onSuccess(partialCallback)
      }
    }

    return httpPromise
  }

  // Decorate the shortcut methods, too
  angular.forEach($httpShortcutMethods, function (method) {
    var httpMethod = method.toUpperCase()
    var isCachable = cachableHttpMethods.indexOf(httpMethod) >= 0
    var shortcutMethod

    if (!isCachable) shortcutMethod = $http[method]
    else {
      shortcutMethod = function httpEtagHttpShortcutWrapper (url, config) {
        config = angular.extend({}, config, {
          method: httpMethod,
          url: url
        })

        return $httpDecorator.call($http, config)
      }
    }
    $httpDecorator[method] = shortcutMethod
  })

  /**
   * HELPERS
   */

  function processHttpConfigEtagValue (httpConfig) {
    var etagValue = httpConfig.etagCache
    var etagValueType = typeof etagValue
    var etagCacheConfig = {}

    // Evaluate function first
    if (etagValueType === 'function') {
      etagValue = etagValue(httpConfig)
      etagValueType = typeof etagValue
    }

    if (etagValueType === 'object') {
      etagCacheConfig.id = etagValue.id
      etagCacheConfig.itemKey = etagValue.itemKey || generateCacheItemKey(httpConfig)
    } else if (etagValueType === 'string') {
      etagCacheConfig.id = etagValue
      etagCacheConfig.itemKey = generateCacheItemKey(httpConfig)
    } else if (etagValue === true) {
      // Undefined cacheId will use the default cacheId as defined in provider
      etagCacheConfig.itemKey = generateCacheItemKey(httpConfig)
    } else return
    return etagCacheConfig
  }

  function generateCacheItemKey (httpConfig) {
    var url = httpConfig.url
    var params = stringifyParams(httpConfig.params)
    return url + ((params && url.indexOf('?') > 0) ? '&' : '?') + params
  }

  // Based on npm package "query-string"
  function stringifyParams (obj) {
    return obj ? arrayMap(objectKeys(obj).sort(), function (key) {
      var val = obj[key]

      if (angular.isArray(val)) {
        return arrayMap(val.sort(), function (val2) {
          return encodeURIComponent(key) + '=' + encodeURIComponent(val2)
        }).join('&')
      }

      return encodeURIComponent(key) + '=' + encodeURIComponent(val)
    }).join('&') : ''
  }

  // http://ejohn.org/blog/partial-functions-in-javascript/
  function partial (fn) {
    var args = Array.prototype.slice.call(arguments, 1)
    return function () {
      var arg = 0
      for (var i = 0; i < args.length && arg < arguments.length; i++) {
        if (args[i] === undefined) args[i] = arguments[arg++]
      }
      return fn.apply(this, args)
    }
  }

  return $httpDecorator
}
<|endoftext|>