<commit_before>//////////////////////////////////////////////////////////////////////////////
/**
 * @module geo
 */
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * Layer options object specification
 *
 * @class geo.layerOptions
 */
//////////////////////////////////////////////////////////////////////////////
geo.layerOptions = function () {
  "use strict";

  if (!(this instanceof geo.layerOptions)) {
    return new geo.layerOptions();
  }

  this.opacity = 0.5;
  this.showAttribution = true;
  this.visible = true;
  this.binNumber = vgl.material.RenderBin.Default;

  return this;
};

geo.newLayerId = (function () {
    "use strict";
    var currentId = 1;
    return function () {
      var id = currentId;
      currentId += 1;
      return id;
    };
  }()
);

//////////////////////////////////////////////////////////////////////////////
/**
 * Base class for all layer types geo.layer represents any object that be
 * rendered on top of the map base. This could include image, points, line, and
 * polygons.
 *
 * @class geo.layer
 * @returns {geo.layer}
 */
//////////////////////////////////////////////////////////////////////////////
geo.layer = function (arg) {
  "use strict";

  if (!(this instanceof geo.layer)) {
    return new geo.layer(arg);
  }
  arg = arg || {};
  geo.sceneObject.call(this, arg);

  //////////////////////////////////////////////////////////////////////////////
  /**
   * @private
   */
  //////////////////////////////////////////////////////////////////////////////
  var m_this = this,
      m_style = arg.style === undefined ? {"opacity" : 0.5,
                                           "color" : [0.8, 0.8, 0.8],
                                           "visible" : true,
                                           "bin" : 100} : arg.style,
      m_id = arg.id === undefined ? geo.newLayerId() : arg.id,
      m_name = "",
      m_gcs = "EPSG:4326",
      m_timeRange = null,
      m_source = arg.source || null,
      m_map = arg.map === undefined ? null : arg.map,
      m_isReference = false,
      m_x = 0,
      m_y = 0,
      m_width = 0,
      m_height = 0,
      m_node = null,
      m_canvas = null,
      m_renderer = null,
      m_initialized = false,
      m_rendererName = arg.renderer  === undefined ? "vglRenderer" : arg.renderer,
      m_dataTime = geo.timestamp(),
      m_updateTime = geo.timestamp(),
      m_drawTime = geo.timestamp(),
      m_sticky = arg.sticky === undefined ? true : arg.sticky;

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get whether or not the layer is sticky (navigates with the map).
   *
   * @returns {Boolean}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.sticky = function () {
    return m_sticky;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set root node of the layer
   *
   * @returns {div}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.node = function () {
    return m_node;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set id of the layer
   *
   * @returns {String}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.id = function (val) {
    if (val === undefined) {
      return m_id;
    }
    m_id = geo.newLayerId();
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set name of the layer
   *
   * @returns {String}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.name = function (val) {
    if (val === undefined) {
      return m_name;
    }
    m_name = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set opacity of the layer
   *
   * @returns {Number}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.opacity = function (val) {
    if (val === undefined) {
      return m_style.opacity;
    }
    m_style.opacity = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set visibility of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.visible = function (val) {
    if (val === undefined) {
      return m_style.visible;
    }
    m_style.visible = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set bin of the layer
   *
   * @returns {Number}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.bin = function (val) {
    if (val === undefined) {
      return m_style.bin;
    }
    m_style.bin = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set projection of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.gcs = function (val) {
    if (val === undefined) {
      return m_gcs;
    }
    m_gcs = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Transform layer to the reference layer gcs
   */
  ////////////////////////////////////////////////////////////////////////////
  this.transform = function (val) {
    geo.transform.transformLayer(val, m_this, m_map.baseLayer());
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set time range of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.timeRange = function (val) {
    if (val === undefined) {
      return m_timeRange;
    }
    m_timeRange = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set source of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.source = function (val) {
    if (val === undefined) {
      return m_source;
    }
    m_source = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set map of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.map = function (val) {
    if (val === undefined) {
      return m_map;
    }
    m_map = val;
    m_map.node().append(m_node);
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get renderer for the layer if any
   */
  ////////////////////////////////////////////////////////////////////////////
  this.renderer = function () {
    return m_renderer;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get canvas of the layer
   *
   */
  ////////////////////////////////////////////////////////////////////////////
  this.canvas = function () {
    return m_canvas;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get viewport of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.viewport = function () {
    return [m_x, m_y, m_width, m_height];
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return last time data got changed
   */
  ////////////////////////////////////////////////////////////////////////////
  this.dataTime = function () {
    return m_dataTime;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return the modified time for the last update that did something
   */
  ////////////////////////////////////////////////////////////////////////////
  this.updateTime = function () {
    return m_updateTime;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return the modified time for the last draw call that did something
   */
  ////////////////////////////////////////////////////////////////////////////
  this.drawTime = function () {
    return m_drawTime;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Run query and return results for it
   */
  ////////////////////////////////////////////////////////////////////////////
  this.query = function () {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set layer as the reference layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.referenceLayer = function (val) {
    if (val !== undefined) {
      m_isReference = val;
      m_this.modified();
      return m_this;
    }
    return m_isReference;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set if the layer has been initialized
   */
  ////////////////////////////////////////////////////////////////////////////
  this.initialized = function (val) {
    if (val !== undefined) {
      m_initialized = val;
      return m_this;
    }
    return m_initialized;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Transform a point or array of points in GCS space to
   * local space of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.toLocal = function (input) {
    return input;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Transform a point or array of points in local space to
   * latitude-longitude space
   */
  ////////////////////////////////////////////////////////////////////////////
  this.fromLocal = function (input) {
    return input;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Init layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this._init = function () {
    if (m_initialized) {
      return m_this;
    }

    // Create top level div for the layer
    m_node = $(document.createElement("div"));
    m_node.attr("id", m_name);
    // TODO: need to position according to offsets from the map element
    //       and maybe respond to events in case the map element moves
    //       around the page.
    m_node.css("position", "absolute");

    if (m_map) {
      m_map.node().append(m_node);

    }

    // Share context if have valid one
    if (m_canvas) {
      m_renderer = geo.createRenderer(m_rendererName, m_this, m_canvas);
    } else {
      m_renderer = geo.createRenderer(m_rendererName, m_this);
      m_canvas = m_renderer.canvas();
    }

    m_initialized = true;

    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Clean up resouces
   */
  ////////////////////////////////////////////////////////////////////////////
  this._exit = function () {
    m_node.remove();
    m_node = null;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Update layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this._update = function () {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Respond to resize event
   */
  ////////////////////////////////////////////////////////////////////////////
  this._resize = function (x, y, w, h) {
    m_x = x;
    m_y = y;
    m_width = w;
    m_height = h;
    m_node.width(w);
    m_node.height(h);

    m_this.modified();
    m_this.geoTrigger(geo.event.resize,
      {x: x, y: y, width: m_width, height: m_height});

    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return the width of the layer in pixels
   */
  ////////////////////////////////////////////////////////////////////////////
  this.width = function () {
    return m_width;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return the height of the layer in pixels
   */
  ////////////////////////////////////////////////////////////////////////////
  this.height = function () {
    return m_height;
  };

  return this;
};

inherit(geo.layer, geo.sceneObject);
<commit_msg>Implemented active vs. non-active layers<commit_after>//////////////////////////////////////////////////////////////////////////////
/**
 * @module geo
 */
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * Layer options object specification
 *
 * @class geo.layerOptions
 */
//////////////////////////////////////////////////////////////////////////////
geo.layerOptions = function () {
  "use strict";

  if (!(this instanceof geo.layerOptions)) {
    return new geo.layerOptions();
  }

  this.opacity = 0.5;
  this.showAttribution = true;
  this.visible = true;
  this.binNumber = vgl.material.RenderBin.Default;

  return this;
};

geo.newLayerId = (function () {
    "use strict";
    var currentId = 1;
    return function () {
      var id = currentId;
      currentId += 1;
      return id;
    };
  }()
);

//////////////////////////////////////////////////////////////////////////////
/**
 * Base class for all layer types geo.layer represents any object that be
 * rendered on top of the map base. This could include image, points, line, and
 * polygons.
 *
 * @class geo.layer
 * @returns {geo.layer}
 */
//////////////////////////////////////////////////////////////////////////////
geo.layer = function (arg) {
  "use strict";

  if (!(this instanceof geo.layer)) {
    return new geo.layer(arg);
  }
  arg = arg || {};
  geo.sceneObject.call(this, arg);

  //////////////////////////////////////////////////////////////////////////////
  /**
   * @private
   */
  //////////////////////////////////////////////////////////////////////////////
  var m_this = this,
      m_style = arg.style === undefined ? {"opacity" : 0.5,
                                           "color" : [0.8, 0.8, 0.8],
                                           "visible" : true,
                                           "bin" : 100} : arg.style,
      m_id = arg.id === undefined ? geo.newLayerId() : arg.id,
      m_name = "",
      m_gcs = "EPSG:4326",
      m_timeRange = null,
      m_source = arg.source || null,
      m_map = arg.map === undefined ? null : arg.map,
      m_isReference = false,
      m_x = 0,
      m_y = 0,
      m_width = 0,
      m_height = 0,
      m_node = null,
      m_canvas = null,
      m_renderer = null,
      m_initialized = false,
      m_rendererName = arg.renderer  === undefined ? "vglRenderer" : arg.renderer,
      m_dataTime = geo.timestamp(),
      m_updateTime = geo.timestamp(),
      m_drawTime = geo.timestamp(),
      m_sticky = arg.sticky === undefined ? true : arg.sticky,
      m_active = arg.active === undefined ? true : arg.active;

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get whether or not the layer is sticky (navigates with the map).
   *
   * @returns {Boolean}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.sticky = function () {
    return m_sticky;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get whether or not the layer is active.  An active layer will receive
   * native mouse when the layer is on top.  Non-active layers will never
   * receive native mouse events.
   *
   * @returns {Boolean}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.active = function () {
    return m_active;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set root node of the layer
   *
   * @returns {div}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.node = function () {
    return m_node;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set id of the layer
   *
   * @returns {String}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.id = function (val) {
    if (val === undefined) {
      return m_id;
    }
    m_id = geo.newLayerId();
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set name of the layer
   *
   * @returns {String}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.name = function (val) {
    if (val === undefined) {
      return m_name;
    }
    m_name = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set opacity of the layer
   *
   * @returns {Number}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.opacity = function (val) {
    if (val === undefined) {
      return m_style.opacity;
    }
    m_style.opacity = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set visibility of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.visible = function (val) {
    if (val === undefined) {
      return m_style.visible;
    }
    m_style.visible = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set bin of the layer
   *
   * @returns {Number}
   */
  ////////////////////////////////////////////////////////////////////////////
  this.bin = function (val) {
    if (val === undefined) {
      return m_style.bin;
    }
    m_style.bin = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set projection of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.gcs = function (val) {
    if (val === undefined) {
      return m_gcs;
    }
    m_gcs = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Transform layer to the reference layer gcs
   */
  ////////////////////////////////////////////////////////////////////////////
  this.transform = function (val) {
    geo.transform.transformLayer(val, m_this, m_map.baseLayer());
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set time range of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.timeRange = function (val) {
    if (val === undefined) {
      return m_timeRange;
    }
    m_timeRange = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set source of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.source = function (val) {
    if (val === undefined) {
      return m_source;
    }
    m_source = val;
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set map of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.map = function (val) {
    if (val === undefined) {
      return m_map;
    }
    m_map = val;
    m_map.node().append(m_node);
    m_this.modified();
    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get renderer for the layer if any
   */
  ////////////////////////////////////////////////////////////////////////////
  this.renderer = function () {
    return m_renderer;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get canvas of the layer
   *
   */
  ////////////////////////////////////////////////////////////////////////////
  this.canvas = function () {
    return m_canvas;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get viewport of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.viewport = function () {
    return [m_x, m_y, m_width, m_height];
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return last time data got changed
   */
  ////////////////////////////////////////////////////////////////////////////
  this.dataTime = function () {
    return m_dataTime;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return the modified time for the last update that did something
   */
  ////////////////////////////////////////////////////////////////////////////
  this.updateTime = function () {
    return m_updateTime;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return the modified time for the last draw call that did something
   */
  ////////////////////////////////////////////////////////////////////////////
  this.drawTime = function () {
    return m_drawTime;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Run query and return results for it
   */
  ////////////////////////////////////////////////////////////////////////////
  this.query = function () {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set layer as the reference layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.referenceLayer = function (val) {
    if (val !== undefined) {
      m_isReference = val;
      m_this.modified();
      return m_this;
    }
    return m_isReference;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Get/Set if the layer has been initialized
   */
  ////////////////////////////////////////////////////////////////////////////
  this.initialized = function (val) {
    if (val !== undefined) {
      m_initialized = val;
      return m_this;
    }
    return m_initialized;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Transform a point or array of points in GCS space to
   * local space of the layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this.toLocal = function (input) {
    return input;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Transform a point or array of points in local space to
   * latitude-longitude space
   */
  ////////////////////////////////////////////////////////////////////////////
  this.fromLocal = function (input) {
    return input;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Init layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this._init = function () {
    if (m_initialized) {
      return m_this;
    }

    // Create top level div for the layer
    m_node = $(document.createElement("div"));
    m_node.attr("id", m_name);
    // TODO: need to position according to offsets from the map element
    //       and maybe respond to events in case the map element moves
    //       around the page.
    m_node.css("position", "absolute");

    if (m_map) {
      m_map.node().append(m_node);

    }

    // Share context if have valid one
    if (m_canvas) {
      m_renderer = geo.createRenderer(m_rendererName, m_this, m_canvas);
    } else {
      m_renderer = geo.createRenderer(m_rendererName, m_this);
      m_canvas = m_renderer.canvas();
    }

    if (!m_this.active()) {
      m_node.css("pointerEvents", "none");
    }

    m_initialized = true;

    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Clean up resouces
   */
  ////////////////////////////////////////////////////////////////////////////
  this._exit = function () {
    m_node.remove();
    m_node = null;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Update layer
   */
  ////////////////////////////////////////////////////////////////////////////
  this._update = function () {
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Respond to resize event
   */
  ////////////////////////////////////////////////////////////////////////////
  this._resize = function (x, y, w, h) {
    m_x = x;
    m_y = y;
    m_width = w;
    m_height = h;
    m_node.width(w);
    m_node.height(h);

    m_this.modified();
    m_this.geoTrigger(geo.event.resize,
      {x: x, y: y, width: m_width, height: m_height});

    return m_this;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return the width of the layer in pixels
   */
  ////////////////////////////////////////////////////////////////////////////
  this.width = function () {
    return m_width;
  };

  ////////////////////////////////////////////////////////////////////////////
  /**
   * Return the height of the layer in pixels
   */
  ////////////////////////////////////////////////////////////////////////////
  this.height = function () {
    return m_height;
  };

  return this;
};

inherit(geo.layer, geo.sceneObject);
<|endoftext|>


<commit_before>'use strict';
const fs = require('fs');
const fpath = require('path');
const utils = require('./utils.js');

function writeTestToFile(path, content) {
  fs.writeFileSync(path, content, 'utf8');
  console.log('Test written to ' + path); // eslint-disable-line
}

function test2Str(type, transformerName, raw, transformed) {

  return ['  it(\'Testing output of ' + type + 'Transformer "' + transformerName + '"\', (done) => {',
          '',
          '    let ' + type + 'TransformerInput = ' + JSON.stringify(raw) + ';',
          '    let ' + type + 'TransformerOutput = ' + JSON.stringify(transformed) + ';',
          '',
          '    expect(' + transformerName + '(' + type + 'TransformerInput)).to.equal(' + type + 'TransformerOutput);',
          '    done();',
          '  });',
          '',
          ''].join('\n');

}

export default function createTest(clientFunction, requestTransformer, responseTransformer,
                                   request, transformedRequest, response, transformedResponse, path, description) {

  if (utils.isDir(fpath.dirname(path)) === false) {
    utils.die('Test directory ' + fpath.dirname(path) + ' dosn\'t exist');
  }

  var cf_name = utils.functionName(clientFunction);
  var reqt_name = utils.functionName(requestTransformer);
  var rept_name = utils.functionName(responseTransformer);

  if (!fs.existsSync(path)) {

    if (description === 'undefined') {
      description = 'Test Transformers (' + reqt_name + ' and ' + rept_name + ') used with client "' + cf_name + '"';
    }

    let content = ['\'use strict\';',
                   'import {expect} from \'chai\';',
                   '',
                   '// PLEASE INSERT NECESSARY REQUIRES FOR THE FOLLOWING FUNCTIONS: ',
                   '// ' + cf_name,
                   '// ' + reqt_name,
                   '// ' + rept_name,
                   '',
                   'describe(\'' + description + '\', () => {',
                   '',
                   ''].join('\n') +
                   test2Str('request', reqt_name, request, transformedRequest) +
                   test2Str('response', rept_name, response, transformedResponse) +
                   ['});'].join('\n');

    writeTestToFile(path, content);
  }
  else {

    let newContent = fs.readFileSync(path, 'utf8');
    let contentSplit = newContent.split(/(\/\/(\/|[\s\S])*\/\/.*)/);
    contentSplit[1] += '\n// ' + cf_name + '\n// ' + reqt_name +'\n// ' + rept_name;
    newContent = contentSplit.join('');

    contentSplit = newContent.split('\n');
    contentSplit[contentSplit.length - 2] += '\n' +
      test2Str('request', reqt_name, request, transformedRequest) +
      test2Str('response', rept_name, response, transformedResponse);

    newContent = contentSplit.join('\n');
    writeTestToFile(path, newContent);
  }
}
<commit_msg>fixed regex<commit_after>'use strict';
const fs = require('fs');
const fpath = require('path');
const utils = require('./utils.js');

function writeTestToFile(path, content) {
  fs.writeFileSync(path, content, 'utf8');
  console.log('Test written to ' + path); // eslint-disable-line
}

function test2Str(type, transformerName, raw, transformed) {

  return ['  it(\'Testing output of ' + type + 'Transformer "' + transformerName + '"\', (done) => {',
          '',
          '    let ' + type + 'TransformerInput = ' + JSON.stringify(raw) + ';',
          '    let ' + type + 'TransformerOutput = ' + JSON.stringify(transformed) + ';',
          '',
          '    expect(' + transformerName + '(' + type + 'TransformerInput)).to.equal(' + type + 'TransformerOutput);',
          '    done();',
          '  });',
          '',
          ''].join('\n');

}

export default function createTest(clientFunction, requestTransformer, responseTransformer,
                                   request, transformedRequest, response, transformedResponse, path, description) {

  if (utils.isDir(fpath.dirname(path)) === false) {
    utils.die('Test directory ' + fpath.dirname(path) + ' dosn\'t exist');
  }

  var cf_name = utils.functionName(clientFunction);
  var reqt_name = utils.functionName(requestTransformer);
  var rept_name = utils.functionName(responseTransformer);

  if (!fs.existsSync(path)) {

    if (description === 'undefined') {
      description = 'Test Transformers (' + reqt_name + ' and ' + rept_name + ') used with client "' + cf_name + '"';
    }

    let content = ['\'use strict\';',
                   'import {expect} from \'chai\';',
                   '',
                   '// PLEASE INSERT NECESSARY REQUIRES FOR THE FOLLOWING FUNCTIONS: ',
                   '// ' + cf_name,
                   '// ' + reqt_name,
                   '// ' + rept_name,
                   '',
                   'describe(\'' + description + '\', () => {',
                   '',
                   ''].join('\n') +
                   test2Str('request', reqt_name, request, transformedRequest) +
                   test2Str('response', rept_name, response, transformedResponse) +
                   ['});'].join('\n');

    writeTestToFile(path, content);
  }
  else {

    let newContent = fs.readFileSync(path, 'utf8');
    let contentSplit = newContent.split(/(\/\/(\/|[\s\S])*\/\/.*)\n\n/);

    contentSplit[1] += '\n// ' + cf_name + '\n// ' + reqt_name +'\n// ' + rept_name + '\n';
    newContent = contentSplit.join('');

    contentSplit = newContent.split('\n');
    contentSplit[contentSplit.length - 2] += '\n' +
      test2Str('request', reqt_name, request, transformedRequest) +
      test2Str('response', rept_name, response, transformedResponse);

    newContent = contentSplit.join('\n');
    writeTestToFile(path, newContent);
  }
}
<|endoftext|>


<commit_before>import noVelocity from './noVelocity';
import hasReachedStyle from './hasReachedStyle';
import mergeDiff from './mergeDiff';
import configAnimation from './animationLoop';
import zero from './zero';
import {interpolateValue, updateCurrentStyle, updateCurrentVelocity} from './updateTree';
import deprecatedSprings from './deprecatedSprings';
import stripStyle from './stripStyle';

const startAnimation = configAnimation();

function mapObject(f, obj) {
  let ret = {};
  for (const key in obj) {
    if (!obj.hasOwnProperty(key)) {
      continue;
    }
    ret[key] = f(obj[key], key);
  }
  return ret;
}

function everyObj(f, obj) {
  for (const key in obj) {
    if (!obj.hasOwnProperty(key)) {
      continue;
    }
    if (!f(obj[key], key)) {
      return false;
    }
  }
  return true;
}

export default function components(React: Object): Object {
  const {PropTypes} = React;

  type CurrentStyles = Array<CurrentStyle>;
  type Styles = Array<Style>;
  type Velocities = Array<Velocity>;

  type StaggerMotionState = {
    currentStyles: CurrentStyles,
    currentVelocities: Velocities,
    previousIdealStyles: CurrentStyles,
    previousIdealVelocities: Velocities,
    nextIdealStyles: CurrentStyles,
    nextIdealVelocities: Velocities,
  };

  type DestStylesFunc = (_: ?CurrentStyles) => Styles;

  const StaggeredMotion = React.createClass({
    propTypes: {
      defaultStyle: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'You forgot the "s" for `StaggeredMotion`\'s `defaultStyles`.'
          );
        }
      },
      style: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'You forgot the "s" for `StaggeredMotion`\'s `styles`.'
          );
        }
      },
      // TOOD: warn against putting configs in here
      defaultStyles: PropTypes.arrayOf(PropTypes.object),
      styles: PropTypes.func.isRequired,
      children: PropTypes.func.isRequired,
    },

    getInitialState() {
      const {styles, defaultStyles} = this.props;
      const currentStyles = defaultStyles ? defaultStyles : styles();
      return {
        currentStyles: currentStyles,
        currentVelocities: currentStyles.map(s => mapObject(zero, s)),
      };
    },

    componentDidMount() {
      this.startAnimating();
    },

    componentWillReceiveProps() {
      this.startAnimating();
    },

    animationStep(timestep, state) {
      const {currentStyles, currentVelocities} = state;
      const styles = this.props.styles(currentStyles.map(stripStyle));

      const newCurrentStyles = currentStyles.map((currentStyle, i) => {
        return updateCurrentStyle(timestep, currentStyle, currentVelocities[i], styles[i]);
      });
      const newCurrentVelocities = currentStyles.map((currentStyle, i) => {
        return updateCurrentVelocity(timestep, currentStyle, currentVelocities[i], styles[i]);
      });

      // TODO: is this right?
      if (currentVelocities.every((v, k) => noVelocity(v, currentStyles[k])) &&
          newCurrentVelocities.every((v, k) => noVelocity(v, newCurrentStyles[k]))) {
        this.stopAnimation();
      }

      return {
        currentStyles: newCurrentStyles,
        currentVelocities: newCurrentVelocities,
      };
    },

    stopAnimation: null,

    // used in animationRender
    hasUnmounted: false,

    componentWillUnmount() {
      this.stopAnimation();
      this.hasUnmounted = true;
    },

    startAnimating() {
      this.stopAnimation = startAnimation(
        this.state,
        this.animationStep,
        this.animationRender,
      );
    },

    animationRender(alpha, nextState, prevState) {
      // See comment in Motion.
      if (!this.hasUnmounted) {
        const currentStyles = nextState.currentStyles.map((style, i) => {
          return interpolateValue(alpha, style, prevState.currentStyles[i]);
        });
        this.setState({
          currentStyles,
          currentVelocities: nextState.currentVelocities,
        });
      }
    },

    render() {
      const strippedStyle = this.state.currentStyles.map(stripStyle);
      const renderedChildren = this.props.children(strippedStyle);
      return renderedChildren && React.Children.only(renderedChildren);
    },
  });

  const TransitionMotion = React.createClass({
    propTypes: {
      defaultValue: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'TransitionSpring\'s `defaultValue` has been changed to ' +
            '`defaultStyles`. Its format received a few (easy to update!) ' +
            'changes as well.'
          );
        }
      },
      endValue: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'TransitionSpring\'s `endValue` has been changed to `styles`. ' +
            'Its format received a few (easy to update!) changes as well.'
          );
        }
      },
      defaultStyle: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'You forgot the "s" for `TransitionMotion`\'s `defaultStyles`.'
          );
        }
      },
      style: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'You forgot the "s" for `TransitionMotion`\'s `styles`.'
          );
        }
      },
      // TOOD: warn against putting configs in here
      defaultStyles: PropTypes.objectOf(PropTypes.any),
      styles: PropTypes.oneOfType([
        PropTypes.func,
        PropTypes.objectOf(PropTypes.any.isRequired),
      ]).isRequired,
      willLeave: PropTypes.oneOfType([
        PropTypes.func,
      ]),
      // TOOD: warn against putting configs in here
      willEnter: PropTypes.oneOfType([
        PropTypes.func,
      ]),
      children: PropTypes.func.isRequired,
    },

    getDefaultProps() {
      return {
        willEnter: (key, value) => value,
        willLeave: () => null,
      };
    },

    getInitialState() {
      const {styles, defaultStyles} = this.props;
      let currentStyles;
      if (defaultStyles == null) {
        if (typeof styles === 'function') {
          currentStyles = styles();
        } else {
          currentStyles = styles;
        }
      } else {
        currentStyles = defaultStyles;
      }
      return {
        currentStyles: currentStyles,
        currentVelocities: mapObject(s => mapObject(zero, s), currentStyles),
      };
    },

    componentDidMount() {
      this.startAnimating();
    },

    componentWillReceiveProps() {
      this.startAnimating();
    },

    animationStep(timestep, state) {
      let {currentStyles, currentVelocities} = state;
      const {willEnter, willLeave} = this.props;

      let styles = this.props.styles;
      if (typeof styles === 'function') {
        styles = styles(currentStyles);
      }

      // TODO: huh?
      let mergedStyles = styles; // set mergedStyles to styles as the default
      let hasNewKey = false;

      mergedStyles = mergeDiff(
        currentStyles,
        styles,
        // TODO: stop allocating like crazy in this whole code path
        key => {
          const res = willLeave(key, currentStyles[key], styles, currentStyles, currentVelocities);
          if (res == null) {
            // For legacy reason. We won't allow returning null soon
            // TODO: remove, after next release
            return null;
          }

          if (noVelocity(currentVelocities[key], currentStyles[key]) &&
              hasReachedStyle(currentStyles[key], res)) {
            return null;
          }
          return res;
        }
      );

      Object.keys(mergedStyles)
        .filter(key => !currentStyles.hasOwnProperty(key))
        .forEach(key => {
          hasNewKey = true;
          const enterStyle = willEnter(key, mergedStyles[key], styles, currentStyles, currentVelocities);

          // We can mutate this here because mergeDiff returns a new Obj
          mergedStyles[key] = enterStyle;

          currentStyles = {
            ...currentStyles,
            [key]: enterStyle,
          };
          currentVelocities = {
            ...currentVelocities,
            [key]: mapObject(zero, enterStyle),
          };
        });

      const newCurrentStyles = mapObject((mergedStyle, key) => {
        return updateCurrentStyle(timestep, currentStyles[key], currentVelocities[key], mergedStyle);
      }, mergedStyles);
      const newCurrentVelocities = mapObject((mergedStyle, key) => {
        return updateCurrentVelocity(timestep, currentStyles[key], currentVelocities[key], mergedStyle);
      }, mergedStyles);

      if (!hasNewKey &&
          everyObj((v, k) => noVelocity(v, currentStyles[k]), currentVelocities) &&
          everyObj((v, k) => noVelocity(v, newCurrentStyles[k]), newCurrentVelocities)) {
        // check explanation in `Motion.animationRender`
        this.stopAnimation(); // Nasty side effects....
      }

      return {
        currentStyles: newCurrentStyles,
        currentVelocities: newCurrentVelocities,
      };
    },

    stopAnimation: null,

    // used in animationRender
    hasUnmounted: false,

    componentWillUnmount() {
      this.stopAnimation();
      this.hasUnmounted = true;
    },

    startAnimating() {
      this.stopAnimation = startAnimation(
        this.state,
        this.animationStep,
        this.animationRender,
      );
    },

    animationRender(alpha, nextState, prevState) {
      // See comment in Motion.
      if (!this.hasUnmounted) {
        const currentStyles = mapObject((style, key) => {
          return interpolateValue(alpha, style, prevState.currentStyles[key]);
        }, nextState.currentStyles);
        this.setState({
          currentStyles,
          currentVelocities: nextState.currentVelocities,
        });
      }
    },

    render() {
      const strippedStyle = mapObject(stripStyle, this.state.currentStyles);
      const renderedChildren = this.props.children(strippedStyle);
      return renderedChildren && React.Children.only(renderedChildren);
    },
  });

  const {Spring, TransitionSpring} = deprecatedSprings(React);

  return {Spring, TransitionSpring, Motion, StaggeredMotion, TransitionMotion};
}
<commit_msg>Check in some partial local changes to make build pass<commit_after>/* @flow */
import noVelocity from './noVelocity';
import hasReachedStyle from './hasReachedStyle';
import mergeDiff from './mergeDiff';
import * as animationLoop from './animationLoop';
import zero from './zero';
import {interpolateValue, updateCurrentStyle, updateCurrentVelocity} from './updateTree';
import deprecatedSprings from './deprecatedSprings';
import stripStyle from './stripStyle';
import stepper from './stepper';
import {default as defaultNow} from 'performance-now';
import {default as defaultRaf} from 'raf';

import type {CurrentStyle, Style, Velocity} from './Types';
const startAnimation = animationLoop.configAnimation();
const msPerFrame = 1000 / 60;

function mapObject(f, obj: Object): Object {
  let ret = {};
  for (const key in obj) {
    if (!obj.hasOwnProperty(key)) {
      continue;
    }
    ret[key] = f(obj[key], key);
  }
  return ret;
}

function everyObj(f: (_: any) => boolean, obj: Object): boolean {
  for (const key in obj) {
    if (!obj.hasOwnProperty(key)) {
      continue;
    }
    if (!f(obj[key], key)) {
      return false;
    }
  }
  return true;
}

export default function components(React: Object): Object {
  const {PropTypes} = React;

  type CurrentStyles = Array<CurrentStyle>;
  type Styles = Array<Style>;
  type Velocities = Array<Velocity>;

  type StaggerMotionState = {
    currentStyles: CurrentStyles,
    currentVelocities: Velocities,
    previousIdealStyles: CurrentStyles,
    previousIdealVelocities: Velocities,
    nextIdealStyles: CurrentStyles,
    nextIdealVelocities: Velocities,
  };

  type DestStylesFunc = (_: ?CurrentStyles) => Styles;

  const StaggeredMotion = React.createClass({
    propTypes: {
      defaultStyle: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'You forgot the "s" for `StaggeredMotion`\'s `defaultStyles`.'
          );
        }
      },
      style: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'You forgot the "s" for `StaggeredMotion`\'s `styles`.'
          );
        }
      },
      // TOOD: warn against putting configs in here
      defaultStyles: PropTypes.arrayOf(PropTypes.object),
      styles: PropTypes.func.isRequired,
      children: PropTypes.func.isRequired,
    },

    getInitialState() {
      const {styles, defaultStyles} = this.props;
      const currentStyles = defaultStyles ? defaultStyles : styles();
      return {
        currentStyles: currentStyles,
        currentVelocities: currentStyles.map(s => mapObject(zero, s)),
      };
    },

    componentDidMount() {
      this.startAnimating();
    },

    componentWillReceiveProps() {
      this.startAnimating();
    },

    animationStep(timestep, state) {
      const {currentStyles, currentVelocities} = state;
      const styles = this.props.styles(currentStyles.map(stripStyle));

      const newCurrentStyles = currentStyles.map((currentStyle, i) => {
        return updateCurrentStyle(timestep, currentStyle, currentVelocities[i], styles[i]);
      });
      const newCurrentVelocities = currentStyles.map((currentStyle, i) => {
        return updateCurrentVelocity(timestep, currentStyle, currentVelocities[i], styles[i]);
      });

      // TODO: is this right?
      if (currentVelocities.every((v, k) => noVelocity(v, currentStyles[k])) &&
          newCurrentVelocities.every((v, k) => noVelocity(v, newCurrentStyles[k]))) {
        this.stopAnimation();
      }

      return {
        currentStyles: newCurrentStyles,
        currentVelocities: newCurrentVelocities,
      };
    },

    stopAnimation: null,

    // used in animationRender
    hasUnmounted: false,

    componentWillUnmount() {
      this.stopAnimation();
      this.hasUnmounted = true;
    },

    startAnimating() {
      this.stopAnimation = startAnimation(
        this.state,
        this.animationStep,
        this.animationRender,
      );
    },

    animationRender(alpha, nextState, prevState) {
      // See comment in Motion.
      if (!this.hasUnmounted) {
        const currentStyles = nextState.currentStyles.map((style, i) => {
          return interpolateValue(alpha, style, prevState.currentStyles[i]);
        });
        this.setState({
          currentStyles,
          currentVelocities: nextState.currentVelocities,
        });
      }
    },

    render() {
      const strippedStyle = this.state.currentStyles.map(stripStyle);
      const renderedChildren = this.props.children(strippedStyle);
      return renderedChildren && React.Children.only(renderedChildren);
    },
  });

  const TransitionMotion = React.createClass({
    propTypes: {
      defaultValue: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'TransitionSpring\'s `defaultValue` has been changed to ' +
            '`defaultStyles`. Its format received a few (easy to update!) ' +
            'changes as well.'
          );
        }
      },
      endValue: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'TransitionSpring\'s `endValue` has been changed to `styles`. ' +
            'Its format received a few (easy to update!) changes as well.'
          );
        }
      },
      defaultStyle: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'You forgot the "s" for `TransitionMotion`\'s `defaultStyles`.'
          );
        }
      },
      style: (prop, propName) => {
        if (prop[propName]) {
          return new Error(
            'You forgot the "s" for `TransitionMotion`\'s `styles`.'
          );
        }
      },
      // TOOD: warn against putting configs in here
      defaultStyles: PropTypes.objectOf(PropTypes.any),
      styles: PropTypes.oneOfType([
        PropTypes.func,
        PropTypes.objectOf(PropTypes.any.isRequired),
      ]).isRequired,
      willLeave: PropTypes.oneOfType([
        PropTypes.func,
      ]),
      // TOOD: warn against putting configs in here
      willEnter: PropTypes.oneOfType([
        PropTypes.func,
      ]),
      children: PropTypes.func.isRequired,
    },

    getDefaultProps() {
      return {
        willEnter: (key, value) => value,
        willLeave: () => null,
      };
    },

    getInitialState() {
      const {styles, defaultStyles} = this.props;
      let currentStyles;
      if (defaultStyles == null) {
        if (typeof styles === 'function') {
          currentStyles = styles();
        } else {
          currentStyles = styles;
        }
      } else {
        currentStyles = defaultStyles;
      }
      return {
        currentStyles: currentStyles,
        currentVelocities: mapObject(s => mapObject(zero, s), currentStyles),
      };
    },

    componentDidMount() {
      this.startAnimating();
    },

    componentWillReceiveProps() {
      this.startAnimating();
    },

    animationStep(timestep, state) {
      let {currentStyles, currentVelocities} = state;
      const {willEnter, willLeave} = this.props;

      let styles = this.props.styles;
      if (typeof styles === 'function') {
        styles = styles(currentStyles);
      }

      // TODO: huh?
      let mergedStyles = styles; // set mergedStyles to styles as the default
      let hasNewKey = false;

      mergedStyles = mergeDiff(
        currentStyles,
        styles,
        // TODO: stop allocating like crazy in this whole code path
        key => {
          const res = willLeave(key, currentStyles[key], styles, currentStyles, currentVelocities);
          if (res == null) {
            // For legacy reason. We won't allow returning null soon
            // TODO: remove, after next release
            return null;
          }

          if (noVelocity(currentVelocities[key], currentStyles[key]) &&
              hasReachedStyle(currentStyles[key], res)) {
            return null;
          }
          return res;
        }
      );

      Object.keys(mergedStyles)
        .filter(key => !currentStyles.hasOwnProperty(key))
        .forEach(key => {
          hasNewKey = true;
          const enterStyle = willEnter(key, mergedStyles[key], styles, currentStyles, currentVelocities);

          // We can mutate this here because mergeDiff returns a new Obj
          mergedStyles[key] = enterStyle;

          currentStyles = {
            ...currentStyles,
            [key]: enterStyle,
          };
          currentVelocities = {
            ...currentVelocities,
            [key]: mapObject(zero, enterStyle),
          };
        });

      const newCurrentStyles = mapObject((mergedStyle, key) => {
        return updateCurrentStyle(timestep, currentStyles[key], currentVelocities[key], mergedStyle);
      }, mergedStyles);
      const newCurrentVelocities = mapObject((mergedStyle, key) => {
        return updateCurrentVelocity(timestep, currentStyles[key], currentVelocities[key], mergedStyle);
      }, mergedStyles);

      if (!hasNewKey &&
          everyObj((v, k) => noVelocity(v, currentStyles[k]), currentVelocities) &&
          everyObj((v, k) => noVelocity(v, newCurrentStyles[k]), newCurrentVelocities)) {
        // check explanation in `Motion.animationRender`
        this.stopAnimation(); // Nasty side effects....
      }

      return {
        currentStyles: newCurrentStyles,
        currentVelocities: newCurrentVelocities,
      };
    },

    stopAnimation: null,

    // used in animationRender
    hasUnmounted: false,

    componentWillUnmount() {
      this.stopAnimation();
      this.hasUnmounted = true;
    },

    startAnimating() {
      this.stopAnimation = startAnimation(
        this.state,
        this.animationStep,
        this.animationRender,
      );
    },

    animationRender(alpha, nextState, prevState) {
      // See comment in Motion.
      if (!this.hasUnmounted) {
        const currentStyles = mapObject((style, key) => {
          return interpolateValue(alpha, style, prevState.currentStyles[key]);
        }, nextState.currentStyles);
        this.setState({
          currentStyles,
          currentVelocities: nextState.currentVelocities,
        });
      }
    },

    render() {
      const strippedStyle = mapObject(stripStyle, this.state.currentStyles);
      const renderedChildren = this.props.children(strippedStyle);
      return renderedChildren && React.Children.only(renderedChildren);
    },
  });

  const {Spring, TransitionSpring} = deprecatedSprings(React);

  return {Spring, TransitionSpring, StaggeredMotion, TransitionMotion};
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import * as TracksActions from '../actions/tracks';
import * as TrackActions from '../actions/track';
import * as MeasureActions from '../actions/measure';
import * as PlayingIndexActions from '../actions/playingIndex';
import * as CursorActions from '../actions/cursor';

import Soundfont from 'soundfont-player';
import audioContext from '../util/audioContext';

import TabStaff from '../components/TabStaff';
import EditorArea from '../components/editor/EditorArea';
import TimeSignatureModal from '../components/editor/TimeSignatureModal';
import TuningModal from '../components/editor/TuningModal';
import BpmModal from '../components/editor/BpmModal';
import Playback from '../components/Playback';

const Actions = Object.assign(TracksActions, TrackActions, MeasureActions, PlayingIndexActions, CursorActions);

class App extends Component {
  constructor(props) {
    super(props);

    if (typeof window !== 'undefined') {
      window.addEventListener('keydown', this.handleKeyPress);
      window.addEventListener('resize', this.handleResize);
    }

    this.state = {
      openModal: null
    };
  }

  componentWillMount() {
    this.loadSoundfont2(this.props.instrument);
    // this.loadSoundfont(this.props.instrument);
  }

  componentWillReceiveProps(nextProps) {
    const { playingIndex } = nextProps;

    if(this.props.playingIndex && playingIndex) {
      if(playingIndex.noteIndex !== this.props.playingIndex.noteIndex
          || playingIndex.measureIndex !== this.props.playingIndex.measureIndex) {
        this.updateScrollPosition(nextProps.playingIndex, nextProps.measures);
      }
    } else if(this.props.instrument !== nextProps.instrument) {
      this.loadSoundfont2(nextProps.instrument);
      // this.loadSoundfont(nextProps.instrument);
    }
  }

  loadSoundfont = (instrument) => {
    Soundfont.loadBuffers(audioContext, instrument).then((buffers) => {
      this.setState({
        buffers: Object.assign({}, this.state.buffers, { [instrument]: buffers })
      });
    });
  };

  loadSoundfont2 = (instrument) => {
    const nonbuffers = localStorage.getItem(instrument);

    if(nonbuffers) {
      Soundfont.decodeArray(audioContext, JSON.parse(nonbuffers)).then((buffers) => {
        this.setState({
          buffers: Object.assign({}, this.state.buffers, { [instrument]: buffers })
        });
      });
    } else {
      Soundfont.loadNonBuffers(audioContext, instrument).then((ns) => {
        localStorage.setItem(instrument, JSON.stringify(ns));
        Soundfont.decodeArray(audioContext, ns).then((buffers) => {
          this.setState({
            buffers: Object.assign({}, this.state.buffers, { [instrument]: buffers })
          });
        });
      });
    }
  };

  handleResize = () => {
    this.props.actions.resize();
  };

  getXOfCurrentNote = (playingIndex, measures) => {
    const { measureIndex, noteIndex } = playingIndex;
    const xOfMeasures = measures.reduce((acc, curr, i) => {
      if(i >= measureIndex) {
        return acc;
      }
      return acc + curr.width;
    }, 0);

    return xOfMeasures + 55 * noteIndex;
  };

  getYOfCurrentNote = (playingIndex, measures) => {
    const position = measures[playingIndex.measureIndex];
    return (position.rowIndex) * (27 * this.props.tuning.length) + 50;
  };

  updateScrollPosition = (playingIndex, measures) => {
    if(this.props.layout === 'linear') {
      const x = this.getXOfCurrentNote(playingIndex, measures);
      const { scrollX, innerWidth } = window;

      if(x > innerWidth + scrollX - 200) {
        window.scroll(x - 200, 0);
      }
    } else {
      const y = this.getYOfCurrentNote(playingIndex, measures);
      const { innerHeight, scrollY } = window;

      if(y > innerHeight + scrollY - 270) {
        window.scroll(0, y - 100);
      }
    }
  };

  handleStop = () => {
    this.props.actions.setCursor({
      measureIndex: this.props.playingIndex.measureIndex,
      noteIndex: this.props.playingIndex.noteIndex,
      stringIndex: this.props.cursor.stringIndex
    });
    this.props.actions.setPlayingIndex(null);
  };

  handlePlay = () => {
    if(this.props.playingIndex || !this.state.buffers) {
      return;
    }

    const { noteIndex, measureIndex } = this.props.cursor;

    this.props.actions.setPlayingIndex({
      measureIndex,
      noteIndex
    });
  };

  getCurrentNote = () => {
    const { measures } = this.props;
    const { measureIndex, noteIndex } = this.props.cursor;

    return measures[measureIndex].notes[noteIndex];
  };

  navigateCursor = (event) => {
    if(event.keyCode === 39) { // right arrow
      event.preventDefault();
      const { measures } = this.props;
      const { measureIndex, noteIndex } = this.props.cursor;
      if(measureIndex === measures.length - 1 &&
        (noteIndex === measures[measureIndex].notes.length - 1 || measures[measureIndex].notes.length === 0)
      ) {
        this.props.actions.insertMeasure();
      }
      this.props.actions.moveCursorRight();
    } else if(event.keyCode === 37) { // left arrow
      event.preventDefault();
      this.props.actions.moveCursorLeft();
    } else if(event.keyCode === 38) { // up arrow
      this.props.actions.moveCursorUp();
    } else if(event.keyCode === 40) { // down arrow
      this.props.actions.moveCursorDown();
    }
  };

  editNote = (fret) => {
    this.props.actions.changeNote(this.props.cursor, fret);
  };

  changeNoteLength = (duration) => {
    this.props.actions.changeNoteLength(this.props.cursor, duration);
  };

  deleteNote = () => {
    const { measureIndex } = this.props.cursor;
    let notes = this.props.measures[measureIndex].notes;

    if(notes.length > 0) {
      this.props.actions.deleteNote(this.props.cursor);
    } else if(notes.length === 0) {
      this.props.actions.deleteMeasure(measureIndex);
    }
  };

  insertNote = () => {
    this.props.actions.insertNote(this.props.cursor);
  };

  pasteNote = () => {
    if(this.props.clipboard) {
      event.preventDefault();
      this.props.actions.pasteNote(this.props.cursor, this.props.clipboard);
    }
  };

  handleKeyPress = (event) => {
    if(this.state.openModal || (this.props.playingIndex && event.keyCode !== 32)) {
      return;
    }

    if((event.metaKey || event.ctrlKey) && event.keyCode === 67) { // cmd/ctrl+c
      event.preventDefault();
      return this.props.actions.copyNote(this.getCurrentNote());
    }
    if((event.metaKey || event.ctrlKey) && event.keyCode === 86) { // cmd/ctrl+v
      return this.pasteNote();
    }
    if((event.metaKey || event.ctrlKey) && event.keyCode === 88) { // cmd/ctrl+x
      event.preventDefault();
      this.props.actions.cutNote(this.props.cursor, this.getCurrentNote());
    }

    if(event.keyCode <= 57 && event.keyCode >= 48 && !event.metaKey) {
      return this.editNote(event.keyCode - 48);
    } else if(event.keyCode === 82 && !event.metaKey && !event.ctrlKey) {
      this.props.actions.changeNote(this.props.cursor, 'rest');
    } else if(event.keyCode === 8) { // delete
      event.preventDefault();
      this.deleteNote();
    } else if(event.keyCode === 69) { // e
      return this.changeNoteLength('e');
    } else if(event.keyCode === 83) { // s
      return this.changeNoteLength('s');
    } else if(event.keyCode === 81) { // q
      return this.changeNoteLength('q');
    } else if(event.keyCode === 87) { // w
      return this.changeNoteLength('w');
    } else if(event.keyCode === 72 && !event.ctrlKey) { // h
      return this.changeNoteLength('h');
    } else if(event.keyCode === 73 && !event.metaKey) { // i
      return this.insertNote();
    } else if(event.keyCode === 32) { // spacebar
      event.preventDefault();
      return this.props.playingIndex ? this.handleStop() : this.handlePlay();
    } else if(event.keyCode === 190) { // period
      this.props.actions.toggleNoteDotted(this.props.cursor);
    } else if(event.shiftKey && event.keyCode === 187) { // plus
      return this.props.actions.increaseNoteLength(this.props.cursor);
    } else if(event.keyCode === 189) { // minus
      return this.props.actions.decreaseNoteLength(this.props.cursor);
    } else if(event.shiftKey && event.keyCode === 222) { // "
      this.props.actions.toggleNoteTremolo(this.props.cursor);
    } else if(event.keyCode === 86) { // v
      this.props.actions.toggleNoteVibrato(this.props.cursor);
    } else if(event.shiftKey && event.keyCode === 78) { // N
      this.props.actions.toggleNoteTrill(this.props.cursor);
    } else {
      return this.navigateCursor(event);
    }
  };

  openModal = (openModal) => {
    this.setState({ openModal });
  };

  closeModal = () => {
    this.setState({ openModal: null });
  };

  render() {
    const { openModal, buffers } = this.state;

    return (

        { this.props.playingIndex ? <Playback buffers={buffers} /> : null}
        <EditorArea handlePlay={this.handlePlay} openModal={this.openModal} />
        <TabStaff />
        <TimeSignatureModal isOpen={openModal === 'timeSig'} closeModal={this.closeModal} />
        <TuningModal isOpen={openModal === 'tuning'} closeModal={this.closeModal} />
        <BpmModal isOpen={openModal === 'bpm'} closeModal={this.closeModal} />

    );
  }
}

function mapStateToProps(state) {
  return {
    measures: state.tracks[state.currentTrackIndex].measures,
    clipboard: state.clipboard,
    layout: state.layout,
    playingIndex: state.playingIndex,
    cursor: state.cursor,
    tuning: state.tracks[state.currentTrackIndex].tuning,
    instrument: state.tracks[state.currentTrackIndex].instrument
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(Actions, dispatch)
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(App);
<commit_msg>go back to old method of loading soundfont buffers<commit_after>import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import * as TracksActions from '../actions/tracks';
import * as TrackActions from '../actions/track';
import * as MeasureActions from '../actions/measure';
import * as PlayingIndexActions from '../actions/playingIndex';
import * as CursorActions from '../actions/cursor';

import Soundfont from 'soundfont-player';
import audioContext from '../util/audioContext';

import TabStaff from '../components/TabStaff';
import EditorArea from '../components/editor/EditorArea';
import TimeSignatureModal from '../components/editor/TimeSignatureModal';
import TuningModal from '../components/editor/TuningModal';
import BpmModal from '../components/editor/BpmModal';
import Playback from '../components/Playback';

const Actions = Object.assign(TracksActions, TrackActions, MeasureActions, PlayingIndexActions, CursorActions);

class App extends Component {
  constructor(props) {
    super(props);

    if (typeof window !== 'undefined') {
      window.addEventListener('keydown', this.handleKeyPress);
      window.addEventListener('resize', this.handleResize);
    }

    this.state = {
      openModal: null
    };
  }

  componentWillMount() {
    this.loadSoundfont(this.props.instrument);
  }

  componentWillReceiveProps(nextProps) {
    const { playingIndex } = nextProps;

    if(this.props.playingIndex && playingIndex) {
      if(playingIndex.noteIndex !== this.props.playingIndex.noteIndex
          || playingIndex.measureIndex !== this.props.playingIndex.measureIndex) {
        this.updateScrollPosition(nextProps.playingIndex, nextProps.measures);
      }
    } else if(this.props.instrument !== nextProps.instrument) {
      this.loadSoundfont(nextProps.instrument);
    }
  }

  loadSoundfont = (instrument) => {
    Soundfont.loadBuffers(audioContext, instrument).then((buffers) => {
      this.setState({
        buffers: Object.assign({}, this.state.buffers, { [instrument]: buffers })
      });
    });
  };

  loadSoundfont2 = (instrument) => {
    const nonbuffers = localStorage.getItem(instrument);

    if(nonbuffers) {
      Soundfont.decodeArray(audioContext, JSON.parse(nonbuffers)).then((buffers) => {
        this.setState({
          buffers: Object.assign({}, this.state.buffers, { [instrument]: buffers })
        });
      });
    } else {
      Soundfont.loadNonBuffers(audioContext, instrument).then((ns) => {
        localStorage.setItem(instrument, JSON.stringify(ns));
        Soundfont.decodeArray(audioContext, ns).then((buffers) => {
          this.setState({
            buffers: Object.assign({}, this.state.buffers, { [instrument]: buffers })
          });
        });
      });
    }
  };

  handleResize = () => {
    this.props.actions.resize();
  };

  getXOfCurrentNote = (playingIndex, measures) => {
    const { measureIndex, noteIndex } = playingIndex;
    const xOfMeasures = measures.reduce((acc, curr, i) => {
      if(i >= measureIndex) {
        return acc;
      }
      return acc + curr.width;
    }, 0);

    return xOfMeasures + 55 * noteIndex;
  };

  getYOfCurrentNote = (playingIndex, measures) => {
    const position = measures[playingIndex.measureIndex];
    return (position.rowIndex) * (27 * this.props.tuning.length) + 50;
  };

  updateScrollPosition = (playingIndex, measures) => {
    if(this.props.layout === 'linear') {
      const x = this.getXOfCurrentNote(playingIndex, measures);
      const { scrollX, innerWidth } = window;

      if(x > innerWidth + scrollX - 200) {
        window.scroll(x - 200, 0);
      }
    } else {
      const y = this.getYOfCurrentNote(playingIndex, measures);
      const { innerHeight, scrollY } = window;

      if(y > innerHeight + scrollY - 270) {
        window.scroll(0, y - 100);
      }
    }
  };

  handleStop = () => {
    this.props.actions.setCursor({
      measureIndex: this.props.playingIndex.measureIndex,
      noteIndex: this.props.playingIndex.noteIndex,
      stringIndex: this.props.cursor.stringIndex
    });
    this.props.actions.setPlayingIndex(null);
  };

  handlePlay = () => {
    if(this.props.playingIndex || !this.state.buffers) {
      return;
    }

    const { noteIndex, measureIndex } = this.props.cursor;

    this.props.actions.setPlayingIndex({
      measureIndex,
      noteIndex
    });
  };

  getCurrentNote = () => {
    const { measures } = this.props;
    const { measureIndex, noteIndex } = this.props.cursor;

    return measures[measureIndex].notes[noteIndex];
  };

  navigateCursor = (event) => {
    if(event.keyCode === 39) { // right arrow
      event.preventDefault();
      const { measures } = this.props;
      const { measureIndex, noteIndex } = this.props.cursor;
      if(measureIndex === measures.length - 1 &&
        (noteIndex === measures[measureIndex].notes.length - 1 || measures[measureIndex].notes.length === 0)
      ) {
        this.props.actions.insertMeasure();
      }
      this.props.actions.moveCursorRight();
    } else if(event.keyCode === 37) { // left arrow
      event.preventDefault();
      this.props.actions.moveCursorLeft();
    } else if(event.keyCode === 38) { // up arrow
      this.props.actions.moveCursorUp();
    } else if(event.keyCode === 40) { // down arrow
      this.props.actions.moveCursorDown();
    }
  };

  editNote = (fret) => {
    this.props.actions.changeNote(this.props.cursor, fret);
  };

  changeNoteLength = (duration) => {
    this.props.actions.changeNoteLength(this.props.cursor, duration);
  };

  deleteNote = () => {
    const { measureIndex } = this.props.cursor;
    let notes = this.props.measures[measureIndex].notes;

    if(notes.length > 0) {
      this.props.actions.deleteNote(this.props.cursor);
    } else if(notes.length === 0) {
      this.props.actions.deleteMeasure(measureIndex);
    }
  };

  insertNote = () => {
    this.props.actions.insertNote(this.props.cursor);
  };

  pasteNote = () => {
    if(this.props.clipboard) {
      event.preventDefault();
      this.props.actions.pasteNote(this.props.cursor, this.props.clipboard);
    }
  };

  handleKeyPress = (event) => {
    if(this.state.openModal || (this.props.playingIndex && event.keyCode !== 32)) {
      return;
    }

    if((event.metaKey || event.ctrlKey) && event.keyCode === 67) { // cmd/ctrl+c
      event.preventDefault();
      return this.props.actions.copyNote(this.getCurrentNote());
    }
    if((event.metaKey || event.ctrlKey) && event.keyCode === 86) { // cmd/ctrl+v
      return this.pasteNote();
    }
    if((event.metaKey || event.ctrlKey) && event.keyCode === 88) { // cmd/ctrl+x
      event.preventDefault();
      this.props.actions.cutNote(this.props.cursor, this.getCurrentNote());
    }

    if(event.keyCode <= 57 && event.keyCode >= 48 && !event.metaKey) {
      return this.editNote(event.keyCode - 48);
    } else if(event.keyCode === 82 && !event.metaKey && !event.ctrlKey) {
      this.props.actions.changeNote(this.props.cursor, 'rest');
    } else if(event.keyCode === 8) { // delete
      event.preventDefault();
      this.deleteNote();
    } else if(event.keyCode === 69) { // e
      return this.changeNoteLength('e');
    } else if(event.keyCode === 83) { // s
      return this.changeNoteLength('s');
    } else if(event.keyCode === 81) { // q
      return this.changeNoteLength('q');
    } else if(event.keyCode === 87) { // w
      return this.changeNoteLength('w');
    } else if(event.keyCode === 72 && !event.ctrlKey) { // h
      return this.changeNoteLength('h');
    } else if(event.keyCode === 73 && !event.metaKey) { // i
      return this.insertNote();
    } else if(event.keyCode === 32) { // spacebar
      event.preventDefault();
      return this.props.playingIndex ? this.handleStop() : this.handlePlay();
    } else if(event.keyCode === 190) { // period
      this.props.actions.toggleNoteDotted(this.props.cursor);
    } else if(event.shiftKey && event.keyCode === 187) { // plus
      return this.props.actions.increaseNoteLength(this.props.cursor);
    } else if(event.keyCode === 189) { // minus
      return this.props.actions.decreaseNoteLength(this.props.cursor);
    } else if(event.shiftKey && event.keyCode === 222) { // "
      this.props.actions.toggleNoteTremolo(this.props.cursor);
    } else if(event.keyCode === 86) { // v
      this.props.actions.toggleNoteVibrato(this.props.cursor);
    } else if(event.shiftKey && event.keyCode === 78) { // N
      this.props.actions.toggleNoteTrill(this.props.cursor);
    } else {
      return this.navigateCursor(event);
    }
  };

  openModal = (openModal) => {
    this.setState({ openModal });
  };

  closeModal = () => {
    this.setState({ openModal: null });
  };

  render() {
    const { openModal, buffers } = this.state;

    return (

        { this.props.playingIndex ? <Playback buffers={buffers} /> : null}
        <EditorArea handlePlay={this.handlePlay} openModal={this.openModal} />
        <TabStaff />
        <TimeSignatureModal isOpen={openModal === 'timeSig'} closeModal={this.closeModal} />
        <TuningModal isOpen={openModal === 'tuning'} closeModal={this.closeModal} />
        <BpmModal isOpen={openModal === 'bpm'} closeModal={this.closeModal} />

    );
  }
}

function mapStateToProps(state) {
  return {
    measures: state.tracks[state.currentTrackIndex].measures,
    clipboard: state.clipboard,
    layout: state.layout,
    playingIndex: state.playingIndex,
    cursor: state.cursor,
    tuning: state.tracks[state.currentTrackIndex].tuning,
    instrument: state.tracks[state.currentTrackIndex].instrument
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(Actions, dispatch)
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(App);
<|endoftext|>


<commit_before>console.log( "=== simpread contentscripts load ===" )

/*
    keyboard event handler
*/
Mousetrap.bind([ "a s" ], focuseMode );

/*
    message request listener
*/
chrome.runtime.onMessage.addListener( function( request, sender, sendResponse ) {
    console.log( request );
    focuseMode();
});

/*
    Focus mode
*/
function focuseMode() {
    console.log( "=== simpread focus mode active ===" )

    var $focus,
        sel, range, node, tag;

    // get focus tag
    if ( $( "body" ).find( "article" ).length > 0 ) {
        // find article tag
        $focus = $( "body" ).find( "article" );
    }
    else {
        // focus
        try {
            sel    = window.getSelection();
            range  = sel.getRangeAt( sel.rangeCount - 1 );
            node   = range.startContainer.nodeName;
        if ( node.toLowerCase() === "body" ) throw( "selection area is body tag." );
            $focus = $( range.startContainer.parentNode );
        } catch ( error ) {
            console.log( sel, range, node )
            console.error( error )
            new Notify().Render( 1, "当前并未获取任何正文，请重新选取。" );
            return;
        }
    }

    // add focus mode
    focus.Render( fixFocus( $focus ));

    return false;
}

/*
    Fix $focus get bad tag, include: p, span, section
    good tag include: div, article
 */
function fixFocus( $focus ) {
    var tag = $focus[0].tagName.toLowerCase();
    while (
        ( tag === "p" ) ||
        ( tag === "span" ) ||
        ( tag === "section" )
        ) {
            $focus = $focus.parent();
            tag    = $focus[0].tagName.toLowerCase();
    }
    return $focus;
}<commit_msg>Update fixFocus logic.<commit_after>console.log( "=== simpread contentscripts load ===" )

/*
    keyboard event handler
*/
Mousetrap.bind([ "a s" ], focuseMode );

/*
    message request listener
*/
chrome.runtime.onMessage.addListener( function( request, sender, sendResponse ) {
    console.log( request );
    focuseMode();
});

/*
    Focus mode
*/
function focuseMode() {
    console.log( "=== simpread focus mode active ===" )

    var $focus,
        sel, range, node, tag;

    // get focus tag
    if ( $( "body" ).find( "article" ).length > 0 ) {
        // find article tag
        $focus = $( "body" ).find( "article" );
    }
    else {
        // focus
        try {
            sel    = window.getSelection();
            range  = sel.getRangeAt( sel.rangeCount - 1 );
            node   = range.startContainer.nodeName;
        if ( node.toLowerCase() === "body" ) throw( "selection area is body tag." );
            $focus = $( range.startContainer.parentNode );
        } catch ( error ) {
            console.log( sel, range, node )
            console.error( error )
            new Notify().Render( 1, "当前并未获取任何正文，请重新选取。" );
            return;
        }
    }

    // add focus mode
    focus.Render( fixFocus( $focus ));

    return false;
}

/*
    Fix $focus get bad tag, include: p, span, section
    good tag include: div, article
 */
function fixFocus( $focus ) {
    var tag = $focus[0].tagName.toLowerCase();
    while (
        ( tag === "p" ) ||
        ( tag === "span" ) ||
        ( tag === "strong" ) ||
        ( tag === "section" )
        ) {
            $focus = $focus.parent();
            tag    = $focus[0].tagName.toLowerCase();
    }
    return $focus;
}<|endoftext|>


<commit_before>export const patterns = [{
	name:"Date in format dd/mm/yyyy",
	regex:/^([1-9]|0[1-9]|[12][0-9]|3[01])\D([1-9]|0[1-9]|1[012])\D(19[0-9][0-9]|20[0-9][0-9])$/,
	description:"Will match dates with slashes or with spaces dd/mm/yyyy dd mm yyyy",
	tags:"date time"
},
{
	name:"HTML tags",
	regex:/^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/,
	description:"Match opening and closing HTML tags with content between",
	tags:"markup,xml,html"
},
{
	name:"Username",
	regex:/^[a-z0-9_-]{3,16}$/,
	description:"A string between 3 and 16 characters, allowing alphanumeric characters and hyphens and underscores",
	tags:"username,validation"
},
{
	name:"Password",
	regex:/^[a-z0-9+_-]{6,18}$/,
	description:"A string between 6 and 18 characters, allowing alphanumeric characters and hypehns and underscores",
	tags:"password,validation"
},
{
	name:"Hex Value",
	regex:/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,
	description:"Base 16 numbers, such as RGB values",
	tags:"hex,color"
},
{
	name:"URL Slug",
	regex:/^[a-z0-9-]+$/,
	description:"Match valid URL slugs",
	tags:"URL"
},
{
	name:"Email",
	regex:/^([a-z0-9+_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,24})$/,
	description:"Match standards complient email addresses",
	tags:"email,validation"
},
{
	name:"SRC of image tag",
	regex:/\< *[img][^\>]*[src] *= *[\"\']{0,1}([^\"\'\ >]*)/,
	description:"Match the src attribute of an HTML image tag",
	tags:"html,tag,image"
},
{
	name:"URL",
	regex:/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/,
	description:"Match URL with optional protocal",
	tags:"url,address,http"
},
{
	name:"IPv4 Address",
	regex:/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
	description:"Match IP v4 addresses",
	tags:"tcpip,internet,address"
},
{
	name:"Positive Integer",
	regex:/^\d+$/,
	descriptions:"Match whole numbers above zero",
	tags:"number"
},
{
	name:"Negative Integer",
	regex:/^-\d+$/,
	description:"Match whole numbers below zero",
	tags:"number"
},
{
	name:"Integer",
	regex:/^-?\d+$/,
	description:"Match whole numbers, above or below zero",
	tags:"number"
},
{
	name:"Positive number",
	regex:/^\d*\.?\d+$/,
	description:"Match integers or floats that are positive",
	tags:"float"
},
{
	name:"Negative number",
	regex:/^-\d*\.?\d+$/,
	description:"Match integers or floats that are negative",
	tags:"float"
},
{
	name:"Positive or negative number",
	regex:/^-?\d*\.?\d+$/,
	description:"Match integers or floats that are positive or negative",
	tags:"float"
},
{
	name:"Phone number",
	regex:/^\+?[\d\s]{3,}$/,
	description:"Match phone numbers at least 3 digits long",
	tags:"validation"
},
{
	name:"New line",
	regex:/[\r\n]|$/,
	description:"Match new lines within text",
	tags:"text"
},
{
	name:"ID of Youtube video",
	regex:/https?:\/\/(?:youtu\.be\/|(?:[a-z]{2,3}\.)?youtube\.com\/watch(?:\?|#\!)v=)([\w-]{11}).*/gi,
	description:"Match the ID of a youtube video URL",
	tags:"video,youtube,url"
},
{
	name:"CSS comment",
	regex:/\/\*[^*]*\*+([^/*][^*]*\*+)*\//,
	description:"Match standard CSS comments",
	tags:"css,comment,code"
}/*,
{
	name:"Word exception",
	regex:/\bTarzan\b|\bJane\b|\bSuperman\b|(\w+)/,
	description:"Match all words apart from the ones listed",
	tags:"words,sentence,blacklist"
}*/
];
<commit_msg>update html tags pattern<commit_after>export const patterns = [{
	name:"Date in format dd/mm/yyyy",
	regex:/^([1-9]|0[1-9]|[12][0-9]|3[01])\D([1-9]|0[1-9]|1[012])\D(19[0-9][0-9]|20[0-9][0-9])$/,
	description:"Will match dates with slashes or with spaces dd/mm/yyyy dd mm yyyy",
	tags:"date time"
},
{
	name:"HTML tags",
	regex:/^<([a-z0-9]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/,
	description:"Match opening and closing HTML tags with content between",
	tags:"markup,xml,html"
},
{
	name:"Username",
	regex:/^[a-z0-9_-]{3,16}$/,
	description:"A string between 3 and 16 characters, allowing alphanumeric characters and hyphens and underscores",
	tags:"username,validation"
},
{
	name:"Password",
	regex:/^[a-z0-9+_-]{6,18}$/,
	description:"A string between 6 and 18 characters, allowing alphanumeric characters and hypehns and underscores",
	tags:"password,validation"
},
{
	name:"Hex Value",
	regex:/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,
	description:"Base 16 numbers, such as RGB values",
	tags:"hex,color"
},
{
	name:"URL Slug",
	regex:/^[a-z0-9-]+$/,
	description:"Match valid URL slugs",
	tags:"URL"
},
{
	name:"Email",
	regex:/^([a-z0-9+_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,24})$/,
	description:"Match standards complient email addresses",
	tags:"email,validation"
},
{
	name:"SRC of image tag",
	regex:/\< *[img][^\>]*[src] *= *[\"\']{0,1}([^\"\'\ >]*)/,
	description:"Match the src attribute of an HTML image tag",
	tags:"html,tag,image"
},
{
	name:"URL",
	regex:/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/,
	description:"Match URL with optional protocal",
	tags:"url,address,http"
},
{
	name:"IPv4 Address",
	regex:/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
	description:"Match IP v4 addresses",
	tags:"tcpip,internet,address"
},
{
	name:"Positive Integer",
	regex:/^\d+$/,
	descriptions:"Match whole numbers above zero",
	tags:"number"
},
{
	name:"Negative Integer",
	regex:/^-\d+$/,
	description:"Match whole numbers below zero",
	tags:"number"
},
{
	name:"Integer",
	regex:/^-?\d+$/,
	description:"Match whole numbers, above or below zero",
	tags:"number"
},
{
	name:"Positive number",
	regex:/^\d*\.?\d+$/,
	description:"Match integers or floats that are positive",
	tags:"float"
},
{
	name:"Negative number",
	regex:/^-\d*\.?\d+$/,
	description:"Match integers or floats that are negative",
	tags:"float"
},
{
	name:"Positive or negative number",
	regex:/^-?\d*\.?\d+$/,
	description:"Match integers or floats that are positive or negative",
	tags:"float"
},
{
	name:"Phone number",
	regex:/^\+?[\d\s]{3,}$/,
	description:"Match phone numbers at least 3 digits long",
	tags:"validation"
},
{
	name:"New line",
	regex:/[\r\n]|$/,
	description:"Match new lines within text",
	tags:"text"
},
{
	name:"ID of Youtube video",
	regex:/https?:\/\/(?:youtu\.be\/|(?:[a-z]{2,3}\.)?youtube\.com\/watch(?:\?|#\!)v=)([\w-]{11}).*/gi,
	description:"Match the ID of a youtube video URL",
	tags:"video,youtube,url"
},
{
	name:"CSS comment",
	regex:/\/\*[^*]*\*+([^/*][^*]*\*+)*\//,
	description:"Match standard CSS comments",
	tags:"css,comment,code"
}/*,
{
	name:"Word exception",
	regex:/\bTarzan\b|\bJane\b|\bSuperman\b|(\w+)/,
	description:"Match all words apart from the ones listed",
	tags:"words,sentence,blacklist"
}*/
];
<|endoftext|>


<commit_before>"use strict";

/**
 * @param {Node} picker
 * @param {Object} options
 * @constructor
 */
var DatePicker = function( picker, options ) {
	var that = this;

	this.picker = picker;

	this.options = {
		outputFormat      : 'Y-m-d',
		days              : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
		months            : ["January", "February", "March", "April", "May", "June",
			"July", "August", "September", "October", "November", "December"],
		next              : '▶',
		prev              : '◀',
		date              : new Date(),
		minDate           : false,
		maxDate           : false,
		onPick            : function() { /*....*/ },
		triggerChangeEvent: true
	};

	if( typeof options == "object" ) {
		for( var attr in options ) {
			if( options.hasOwnProperty(attr) ) {
				this.options[attr] = options[attr];
			}
		}
	}

	this.calendar = document.createElement('div');
	this.calendar.className = 'DatePicker';
	document.querySelector('body').appendChild(this.calendar);

	this.offset = 0;

	this.display = function() {
		var rect = that.picker.getBoundingClientRect();

		that.calendar.style.top = rect.bottom + "px";
		that.calendar.style.left = rect.left + "px";
		that.calendar.style.display = 'inline-block';
		this.calendar.style.visibility = 'inherit';
	};

	this.hide = function() {
		that.calendar.style.display = 'none';
	};

	var hideTimeout;
	this.picker.addEventListener('focus', function() {
		clearTimeout(hideTimeout);
		that.display();
	});

	this.picker.addEventListener('blur', function() {
		//that.calendar.style.visibility = 'hidden';
		hideTimeout = setTimeout(that.hide, 300);
	});

	this.render();
	that.hide();
};

DatePicker.prototype = {

	/**
	 * @param {Date} date
	 * @returns {number}
	 */
	getDaysInMonth: function( date ) {
		for( var i = 27; i <= 32; i++ ) {
			var workingDate = new Date(date.getFullYear(), date.getMonth(), i);
			if( workingDate.getMonth() != date.getMonth() ) {
				return i - 1;
			}
		}

		throw "Days in Month Unknown!";
	},

	/**
	 * @param {Date} date
	 */
	setPickerDate: function( date ) {
		this.picker.value = this.format(date, this.options.outputFormat);
	},

	/**
	 * @param {number} month
	 */
	setMonth: function( month ) {
		this.options.date.setMonth(month);
		this.render();
	},

	/**
	 * @param {number} year
	 */
	setYear: function( year ) {
		this.options.date.setYear(year);
		this.render();
	},

	getWorkingDate: function() {
		return (new Date(this.options.date.getFullYear(), this.options.date.getMonth(), 1))
	},

	render: function() {
		var that = this;
		this.calendar.innerHTML = '';

		var workingDate = this.getWorkingDate();
		var header = document.createElement('div');
		header.className = 'DatePicker-header';

		header.innerHTML = this.format(workingDate, 'F Y');

		this.calendar.appendChild(header);

		var next = document.createElement('span');

		next.className = 'DatePicker-next-month';
		next.innerHTML = this.options.next;

		next.addEventListener('click', function() {
			that.picker.focus();
			that.setMonth(that.options.date.getMonth() + 1);
		});

		var prev = document.createElement('span');

		prev.className = 'DatePicker-prev-month';
		prev.innerHTML = this.options.prev;

		prev.addEventListener('click', function() {
			that.picker.focus();
			that.setMonth(that.options.date.getMonth() - 1);
		});

		header.appendChild(next);
		header.appendChild(prev);

		var tbl = document.createElement('table');
		this.calendar.appendChild(tbl);

		var wday = workingDate.getDay() - this.offset;

		var tr = document.createElement('tr');
		tbl.appendChild(tr);

		var count = wday + 1;

		if( wday > 0 ) {
			var startTd = document.createElement('td');
			startTd.colSpan = wday;
			startTd.innerHTML = ' ';
			tr.appendChild(startTd);
		}

		for( var i = 1; i <= this.getDaysInMonth(this.options.date); i++ ) {
			var td = document.createElement('td');
			td.innerHTML = i;
			td.className = 'DatePicker-date';

			var dayDate = new Date(workingDate.getFullYear(), workingDate.getMonth(), i);

			if( (this.options.minDate === false || this.options.minDate <= dayDate) && (this.options.maxDate === false || this.options.maxDate >= dayDate) ) {
				td.addEventListener('click', function( date ) {
					return function() {
						that.setPickerDate(date);
						that.options.onPick.apply(that.picker);
						if( that.options.triggerChangeEvent ) {
							if( that.picker.dispatchEvent ) { // IE9+
								var evt = document.createEvent("HTMLEvents");
								evt.initEvent('change', true, true);
								return !that.picker.dispatchEvent(evt);
							}
						}
					}
				}(dayDate));
			} else {
				td.className += " DatePicker-date-disabled";
			}

			tr.appendChild(td);

			if( count > 6 ) {
				tr = document.createElement('tr');
				tbl.appendChild(tr);

				count = 0;
			}

			count++;
		}

		if( count != 1 ) {
			var endTd = document.createElement('td');
			endTd.colSpan = 8 - count;
			endTd.innerHTML = ' ';
			tr.appendChild(endTd);
		}

	},

	/**
	 * From: http://www.electricprism.com/aeron/calendar/
	 *
	 * License:
	 * MIT-style license.
	 *
	 * Copyright:
	 * Copyright (c) 2008 [Aeron Glemann](http://www.electricprism.com/aeron/)
	 *
	 * @param date
	 * @param format
	 * @returns {string}
	 */
	format: function( date, format ) {
		var str = '';
		if( date ) {
			var j = date.getDate(), w = date.getDay(),
				l = this.options.days[w],
				n = date.getMonth() + 1,
				f = this.options.months[n - 1],
				y = date.getFullYear() + '';
			for( var i = 0, len = format.length; i < len; i++ ) {
				var cha = format.charAt(i);
				switch( cha ) {
					case 'y': // xx - xx
						y = y.substr(2);
					case 'Y': // 19xx - 20xx
						str += y;
						break;
					case 'm': // 01 - 12
						if( n < 10 ) {
							n = '0' + n;
						}
					case 'n': // 1 - 12
						str += n;
						break;
					case 'M': // Jan - Dec
						f = f.substr(0, 3);
					case 'F': // January - December
						str += f;
						break;
					case 'd': // 01 - 31
						if( j < 10 ) {
							j = '0' + j;
						}
					case 'j': // 1 - 31
						str += j;
						break;
					case 'D': // Sun - Sat
						l = l.substr(0, 3);
					case 'l': // Sunday - Saturday
						str += l;
						break;
					case 'N': // 1 - 7
						w += 1;
					case 'w': // 0 - 6
						str += w;
						break;
					case 'S': // st, nd, rd or th (works well with j)
						if( j % 10 == 1 && j != '11' ) {
							str += 'st';
						} else if( j % 10 == 2 && j != '12' ) {
							str += 'nd';
						} else if( j % 10 == 3 && j != '13' ) {
							str += 'rd';
						} else {
							str += 'th';
						}
						break;
					default:
						str += cha;
				}
			}
		}
		return str;
	}
};

if( typeof define == "function" ) {
	define([], function() {
		return DatePicker;
	});
}
<commit_msg>x and y<commit_after>"use strict";

/**
 * @param {Node} picker
 * @param {Object} options
 * @constructor
 */
var DatePicker = function( picker, options, x, y ) {
	var that = this;

	this.picker = picker;

	this.options = {
		outputFormat      : 'Y-m-d',
		days              : ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
		months            : ["January", "February", "March", "April", "May", "June",
			"July", "August", "September", "October", "November", "December"],
		next              : '▶',
		prev              : '◀',
		date              : new Date(),
		minDate           : false,
		maxDate           : false,
		onPick            : function() { /*....*/ },
		triggerChangeEvent: true,
		x                 : x || 0,
		y                 : y || 0

	};

	if( typeof options == "object" ) {
		for( var attr in options ) {
			if( options.hasOwnProperty(attr) ) {
				this.options[attr] = options[attr];
			}
		}
	}

	this.calendar = document.createElement('div');
	this.calendar.className = 'DatePicker';
	document.querySelector('body').appendChild(this.calendar);

	this.offset = 0;

	this.display = function() {
		var rect = that.picker.getBoundingClientRect();

		that.calendar.style.top = rect.bottom - that.options.x + "px";
		that.calendar.style.left = rect.left - that.options.y + "px";
		that.calendar.style.display = 'inline-block';
		this.calendar.style.visibility = 'inherit';
	};

	this.hide = function() {
		that.calendar.style.display = 'none';
	};

	var hideTimeout;
	this.picker.addEventListener('focus', function() {
		clearTimeout(hideTimeout);
		that.display();
	});

	this.picker.addEventListener('blur', function() {
		//that.calendar.style.visibility = 'hidden';
		hideTimeout = setTimeout(that.hide, 300);
	});

	this.render();
	that.hide();
};

DatePicker.prototype = {

	/**
	 * @param {Date} date
	 * @returns {number}
	 */
	getDaysInMonth: function( date ) {
		for( var i = 27; i <= 32; i++ ) {
			var workingDate = new Date(date.getFullYear(), date.getMonth(), i);
			if( workingDate.getMonth() != date.getMonth() ) {
				return i - 1;
			}
		}

		throw "Days in Month Unknown!";
	},

	/**
	 * @param {Date} date
	 */
	setPickerDate: function( date ) {
		this.picker.value = this.format(date, this.options.outputFormat);
	},

	/**
	 * @param {number} month
	 */
	setMonth: function( month ) {
		this.options.date.setMonth(month);
		this.render();
	},

	/**
	 * @param {number} year
	 */
	setYear: function( year ) {
		this.options.date.setYear(year);
		this.render();
	},

	getWorkingDate: function() {
		return (new Date(this.options.date.getFullYear(), this.options.date.getMonth(), 1))
	},

	render: function() {
		var that = this;
		this.calendar.innerHTML = '';

		var workingDate = this.getWorkingDate();
		var header = document.createElement('div');
		header.className = 'DatePicker-header';

		header.innerHTML = this.format(workingDate, 'F Y');

		this.calendar.appendChild(header);

		var next = document.createElement('span');

		next.className = 'DatePicker-next-month';
		next.innerHTML = this.options.next;

		next.addEventListener('click', function() {
			that.picker.focus();
			that.setMonth(that.options.date.getMonth() + 1);
		});

		var prev = document.createElement('span');

		prev.className = 'DatePicker-prev-month';
		prev.innerHTML = this.options.prev;

		prev.addEventListener('click', function() {
			that.picker.focus();
			that.setMonth(that.options.date.getMonth() - 1);
		});

		header.appendChild(next);
		header.appendChild(prev);

		var tbl = document.createElement('table');
		this.calendar.appendChild(tbl);

		var wday = workingDate.getDay() - this.offset;

		var tr = document.createElement('tr');
		tbl.appendChild(tr);

		var count = wday + 1;

		if( wday > 0 ) {
			var startTd = document.createElement('td');
			startTd.colSpan = wday;
			startTd.innerHTML = ' ';
			tr.appendChild(startTd);
		}

		for( var i = 1; i <= this.getDaysInMonth(this.options.date); i++ ) {
			var td = document.createElement('td');
			td.innerHTML = i;
			td.className = 'DatePicker-date';

			var dayDate = new Date(workingDate.getFullYear(), workingDate.getMonth(), i);

			if( (this.options.minDate === false || this.options.minDate <= dayDate) && (this.options.maxDate === false || this.options.maxDate >= dayDate) ) {
				td.addEventListener('click', function( date ) {
					return function() {
						that.setPickerDate(date);
						that.options.onPick.apply(that.picker);
						if( that.options.triggerChangeEvent ) {
							if( that.picker.dispatchEvent ) { // IE9+
								var evt = document.createEvent("HTMLEvents");
								evt.initEvent('change', true, true);
								return !that.picker.dispatchEvent(evt);
							}
						}
					}
				}(dayDate));
			} else {
				td.className += " DatePicker-date-disabled";
			}

			tr.appendChild(td);

			if( count > 6 ) {
				tr = document.createElement('tr');
				tbl.appendChild(tr);

				count = 0;
			}

			count++;
		}

		if( count != 1 ) {
			var endTd = document.createElement('td');
			endTd.colSpan = 8 - count;
			endTd.innerHTML = ' ';
			tr.appendChild(endTd);
		}

	},

	/**
	 * From: http://www.electricprism.com/aeron/calendar/
	 *
	 * License:
	 * MIT-style license.
	 *
	 * Copyright:
	 * Copyright (c) 2008 [Aeron Glemann](http://www.electricprism.com/aeron/)
	 *
	 * @param date
	 * @param format
	 * @returns {string}
	 */
	format: function( date, format ) {
		var str = '';
		if( date ) {
			var j = date.getDate(), w = date.getDay(),
				l = this.options.days[w],
				n = date.getMonth() + 1,
				f = this.options.months[n - 1],
				y = date.getFullYear() + '';
			for( var i = 0, len = format.length; i < len; i++ ) {
				var cha = format.charAt(i);
				switch( cha ) {
					case 'y': // xx - xx
						y = y.substr(2);
					case 'Y': // 19xx - 20xx
						str += y;
						break;
					case 'm': // 01 - 12
						if( n < 10 ) {
							n = '0' + n;
						}
					case 'n': // 1 - 12
						str += n;
						break;
					case 'M': // Jan - Dec
						f = f.substr(0, 3);
					case 'F': // January - December
						str += f;
						break;
					case 'd': // 01 - 31
						if( j < 10 ) {
							j = '0' + j;
						}
					case 'j': // 1 - 31
						str += j;
						break;
					case 'D': // Sun - Sat
						l = l.substr(0, 3);
					case 'l': // Sunday - Saturday
						str += l;
						break;
					case 'N': // 1 - 7
						w += 1;
					case 'w': // 0 - 6
						str += w;
						break;
					case 'S': // st, nd, rd or th (works well with j)
						if( j % 10 == 1 && j != '11' ) {
							str += 'st';
						} else if( j % 10 == 2 && j != '12' ) {
							str += 'nd';
						} else if( j % 10 == 3 && j != '13' ) {
							str += 'rd';
						} else {
							str += 'th';
						}
						break;
					default:
						str += cha;
				}
			}
		}
		return str;
	}
};

if( typeof define == "function" ) {
	define([], function() {
		return DatePicker;
	});
}
<|endoftext|>