<commit_before>import * as Types from './types';
import ConfigField from './config-field';
import envParser from './env-parser';

class TwConf {
  static Types = Types;

  /**
   * @type {Map.<string, *>}
   */
  config = new Map();

  /**
   * @type {Map.<string, string>}
   */
  env = new Map();

  /**
   * @method get
   * @public
   * @param {string} key
   * @return {*}
   */
  get(key) {
    return this.config.get(key);
  }

  get flatObject() {
    const result = {};

    this.config.forEach((value, key) => {
      result[key.replace(/([._-])([a-z\d])/g, str => str[1].toUpperCase())] = value;
    });

    return Object.freeze(result);
  }

  toString() {
    return JSON.stringify(this.config);
  }

  /**
   * Create TwConf object
   * @param {(Map.<string, ConfigField>|Array.<string, ConfigField>[]|object)} confSkeleton
   * @param {object=} options
   * @param {boolean} [options.allowUnspecified=true]
   * @param {boolean} [options.flatOnly=false]
   * @param {boolean} [options.validationOnDemand=false]
   */
  constructor(confSkeleton, {
    allowUnspecified = true,
    flatOnly = false,
    validationOnDemand = false,
  } = {}) {
    this.options = {};
    this.options.allowUnspecified = allowUnspecified;
    this.options.flatOnly = flatOnly;
    this.options.validationOnDemand = validationOnDemand;

    /**
     * @type {Map.<string, ConfigField>}
     */
    this.skeleton = null;

    if (confSkeleton instanceof Map) {
      this.skeleton = confSkeleton;
    }

    if (confSkeleton instanceof Array) {
      this.skeleton = new Map(confSkeleton);
    }

    if (typeof confSkeleton === 'object') {
      this.skeleton = new Map(Object.keys(confSkeleton).map(key => [key, confSkeleton[key]]));
    }

    this.skeleton.forEach((value, key) => {
      if (!(value instanceof ConfigField)) {
        if (typeof value !== 'object') {
          const err = new TypeError('Value of ConfigRule must be a object');
          err.field = key;
          throw err;
        }

        this.skeleton.set(key, new ConfigField(value));
      }
    });

    if (!this.options.validationOnDemand) {
      this.validate();
    }
  }

  /**
   * @method validate
   * @public
   */
  validate() {
    this.env = envParser(this.options);

    const errors = [];

    this.skeleton.forEach((configField, key) => {
      try {
        const validatedValue = configField.validate(this.env.get(key));
        configField.splitter(validatedValue, key, this.env)
          .forEach((newValue, newKey) => this.config.set(newKey, newValue));
      } catch (err) {
        err.field = key;
        errors.push(err);
      }
    });

    if (errors.length) {
      const newError = new Error('Validation errors');
      newError.errors = errors;
      throw newError;
    }
  }
}

module.exports = TwConf;
<commit_msg>refactor(twconf): Use utils/to-map in twconf class constructor.<commit_after>import * as Types from './types';
import ConfigField from './config-field';
import envParser from './env-parser';
import toMap from './utils/to-map';

class TwConf {
  static Types = Types;

  /**
   * @type {Map.<string, *>}
   */
  config = new Map();

  /**
   * @type {Map.<string, string>}
   */
  env = new Map();

  /**
   * @method get
   * @public
   * @param {string} key
   * @return {*}
   */
  get(key) {
    return this.config.get(key);
  }

  get flatObject() {
    const result = {};

    this.config.forEach((value, key) => {
      result[key.replace(/([._-])([a-z\d])/g, str => str[1].toUpperCase())] = value;
    });

    return Object.freeze(result);
  }

  toString() {
    return JSON.stringify(this.config);
  }

  /**
   * Create TwConf object
   * @param {(Map.<string, ConfigField>|Array.<string, ConfigField>[]|object)} skeleton
   * @param {object=} options
   * @param {boolean} [options.allowUnspecified=true]
   * @param {boolean} [options.flatOnly=false]
   * @param {boolean} [options.validationOnDemand=false]
   */
  constructor(skeleton, {
    allowUnspecified = true,
    flatOnly = false,
    validationOnDemand = false,
  } = {}) {
    this.options = {};
    this.options.allowUnspecified = allowUnspecified;
    this.options.flatOnly = flatOnly;
    this.options.validationOnDemand = validationOnDemand;

    /**
     * @type {Map.<string, ConfigField>}
     */
    this.skeleton = toMap(skeleton);

    this.skeleton.forEach((value, key) => {
      if (!(value instanceof ConfigField)) {
        if (typeof value !== 'object') {
          const err = new TypeError('Value of ConfigRule must be a object');
          err.field = key;
          throw err;
        }

        this.skeleton.set(key, new ConfigField(value));
      }
    });

    if (!this.options.validationOnDemand) {
      this.validate();
    }
  }

  /**
   * @method validate
   * @public
   */
  validate() {
    this.env = envParser(this.options);

    const errors = [];

    this.skeleton.forEach((configField, key) => {
      try {
        const validatedValue = configField.validate(this.env.get(key));
        configField.splitter(validatedValue, key, this.env)
          .forEach((newValue, newKey) => this.config.set(newKey, newValue));
      } catch (err) {
        err.field = key;
        errors.push(err);
      }
    });

    if (errors.length) {
      const newError = new Error('Validation errors');
      newError.errors = errors;
      throw newError;
    }
  }
}

module.exports = TwConf;
<|endoftext|>


<commit_before>import atom from '../atom/index';
import Immutable from 'immutable';

const store = atom(Immutable.fromJS({clients: {}, locks: {}}));

function set(state) {
  store.reset(state);
}

function update(f) {
  store.swap(f);
}

function updateCollection(coll, f, ...args) {
  update(state => state.update(coll, xs => f(xs, ...args)));
}

function updateFilteredCollection(coll, pred, f, ...args) {
  updateCollection(coll, xs => xs.merge(xs.filter(pred).map(x => f(x, ...args))));
}

function updateEntity(coll, id, f, ...args) {
  update(state => state.updateIn([coll, id], x => f(x, ...args)));
}

function setEntity(coll, id, x) {
  update(state => state.setIn([coll, id], x));
}

function getEntity(coll, id) {
  return store.deref().getIn([coll, id]);
}

function updateLocks(f) {
  updateCollection("locks", f);
}

export function updateLocksWithClient(clientID, f) {
  updateFilteredCollection("locks", l => l.get("clientID") === clientID, f);
}

export function updateLock(id, f, ...args) {
  updateEntity("locks", id, f, ...args);
}

export function setLock(lock) {
  setEntity("locks", lock.get("id"), lock);
}

export function getLock(id) {
  getEntity("locks", id);
}

export function setClient(client) {
  setEntity("clients", client.get("id"), client);
}

export function addWatch(key, f) {
  store.addWatch(key, f);
}

// DEV
// store.addWatch("keepHistory", (key, oldState, newState) => {
//   if (!global.window.h) global.window.h = []; global.window.h.push(newState);
//   console.debug("something changed", newState.toJS());
// });
<commit_msg>Add an empty Map as a notSetValue for entities<commit_after>import atom from '../atom/index';
import Immutable, { Map } from 'immutable';

const store = atom(Immutable.fromJS({clients: {}, locks: {}}));

function set(state) {
  store.reset(state);
}

function update(f) {
  store.swap(f);
}

function updateCollection(coll, f, ...args) {
  update(state => state.update(coll, xs => f(xs, ...args)));
}

function updateFilteredCollection(coll, pred, f, ...args) {
  updateCollection(coll, xs => xs.merge(xs.filter(pred).map(x => f(x, ...args))));
}

function updateEntity(coll, id, f, ...args) {
  update(state => state.updateIn([coll, id], new Map({}), x => f(x, ...args)));
}

function setEntity(coll, id, x) {
  update(state => state.setIn([coll, id], x));
}

function getEntity(coll, id) {
  return store.deref().getIn([coll, id]);
}

function updateLocks(f) {
  updateCollection("locks", f);
}

export function updateLocksWithClient(clientID, f) {
  updateFilteredCollection("locks", l => l.get("clientID") === clientID, f);
}

export function updateLock(id, f, ...args) {
  updateEntity("locks", id, f, ...args);
}

export function setLock(lock) {
  setEntity("locks", lock.get("id"), lock);
}

export function getLock(id) {
  getEntity("locks", id);
}

export function setClient(client) {
  setEntity("clients", client.get("id"), client);
}

export function addWatch(key, f) {
  store.addWatch(key, f);
}

// DEV
// store.addWatch("keepHistory", (key, oldState, newState) => {
//   if (!global.window.h) global.window.h = []; global.window.h.push(newState);
//   console.debug("something changed", newState.toJS());
// });
<|endoftext|>


<commit_before>
	var findIndexByAttr = function(array, attr, value) {
	    for(var i = 0; i < array.length; i += 1) {
	        if(array[i][attr] === value) {
	            return i;
	        }
	    }
	}

	var sounds = [];

	sounds.push({
		name: "Fire",
		urls: ['audio/fire.mp3'],
		autoplay: true,
		loop: true,
		volume: 0.0
	});

	sounds.push({
		name: "Rainstorm",
		urls: ['audio/rainstorm.mp3'],
		autoplay: true,
		loop: true,
		volume: 0.0
	});

	sounds.push({
		name: "Birds",
		urls: ['audio/birds.mp3'],
		autoplay: true,
		loop: true,
		volume: 0.0
	});

	sounds.push({
		name: "Brooding",
		urls: ['audio/brooding.mp3'],
		autoplay: true,
		loop: true,
		volume: 0.0
	});

	sounds.push({
		name: "Waves",
		urls: ['audio/waves.mp3'],
		autoplay: true,
		loop: true,
		volume: 0.0
	});

	var playerControls = [];
	var masterSlider = '
Master
<input class="master" type="range" min="0" max="100" value="0"></input>'
	$('body').append(masterSlider);

	// Loop through the sounds
	for(var i=0; i < sounds.length; i++){
		var sound = sounds[i];
		// Init Howler for the sound
		playerControls.push(new Howl(sound));
		// Add a name identifier to the player control object
		playerControls[playerControls.length-1].name = sound.name;
		var elem = '
'+sound.name+'
<input class="'+sound.name+'" type="range" min="0" max="100" value="0"></input>'
		$('body').append(elem);
	}

	$('input[type="range"]').rangeslider().change(function(){
		var identifier = this.className;
		var vol = this.value;
		// Get the player control object by name
		var control = findIndexByAttr(playerControls, 'name', identifier);
		playerControls[control].volume(vol/100);
		/*playerControls[control].play();*/
		// TODO: stop autoplay and play only when started first
	});

<commit_msg>Added credits, removed loop until it's fixed<commit_after>
	var findIndexByAttr = function(array, attr, value) {
	    for(var i = 0; i < array.length; i += 1) {
	        if(array[i][attr] === value) {
	            return i;
	        }
	    }
	}

	var sounds = [];

	sounds.push({
		name: "Fire",
		credit: 'Credits to dobroide in freesound.org. CC 3.0',
		urls: ['audio/fire.mp3'],
		autoplay: true,
		loop: false,
		volume: 0.0
	});

	sounds.push({
		name: "Rainstorm",
		urls: ['audio/rainstorm.mp3'],
		autoplay: true,
		loop: false,
		volume: 0.0
	});

	sounds.push({
		name: "Birds",
		urls: ['audio/birds.mp3'],
		autoplay: true,
		loop: false,
		volume: 0.0
	});

	sounds.push({
		name: "Brooding",
		credit: 'Credits to klankbeeld in freesound.org. CC 3.0',
		urls: ['audio/brooding.mp3'],
		autoplay: true,
		loop: false,
		volume: 0.0
	});

	sounds.push({
		name: "Waves",
		urls: ['audio/waves.mp3'],
		autoplay: true,
		loop: false,
		volume: 0.0
	});

	var playerControls = [];
	var masterSlider = '
Master
<input class="master" type="range" min="0" max="100" value="0"></input>'
	$('body').append(masterSlider);

	// Loop through the sounds
	for(var i=0; i < sounds.length; i++){
		var sound = sounds[i];
		// Init Howler for the sound
		playerControls.push(new Howl(sound));
		// Add a name identifier to the player control object
		playerControls[playerControls.length-1].name = sound.name;
		var elem = '
'+sound.name+'
<input class="'+sound.name+'" type="range" min="0" max="100" value="0"></input>';
		sound.credit ? elem += sound.credit : '';
		$('body').append(elem);
	}

	$('input[type="range"]').rangeslider().change(function(){
		var identifier = this.className;
		var vol = this.value;
		// Get the player control object by name
		var control = findIndexByAttr(playerControls, 'name', identifier);
		playerControls[control].volume(vol/100);
		/*playerControls[control].play();*/
		// TODO: stop autoplay and play only when started first
	});

<|endoftext|>


<commit_before>;(function(window, document, undefined){
  'use strict'

  var options = {
    searchInput: null,
    resultsContainer: null,
    json: [],
    searchResultTemplate: '
{title}
',
    templateMiddleware: function(){},
    noResultsText: 'No results found',
    limit: 10,
    fuzzy: false,
    exclude: []
  }

  var requiredOptions = ['searchInput','resultsContainer','json']

  var templater = require('./Templater')
  var repository = require('./Repository')
  var jsonLoader = require('./JSONLoader')
  var optionsValidator = require('./OptionsValidator')({
    required: requiredOptions
  })
  var utils = require('./utils')

  /*
    Public API
  */
  window.SimpleJekyllSearch = function SimpleJekyllSearch(_options){
    var errors = optionsValidator.validate(_options)
    if( errors.length > 0 ){
      throwError('You must specify the following required options: ' + requiredOptions)
    }

    options = utils.merge(options, _options)

    templater.setOptions({
      template: options.searchResultTemplate,
      middleware: options.templateMiddleware,
    })

    repository.setOptions({
      fuzzy: options.fuzzy,
      limit: options.limit,
    })

    if( utils.isJSON(options.json) ){
      initWithJSON(options.json)
    }else{
      initWithURL(options.json)
    }
  }

  // for backwards compatibility
  window.SimpleJekyllSearch.init = window.SimpleJekyllSearch

  function initWithJSON(json){
    repository.put(json)
    registerInput()
  }

  function initWithURL(url){
    jsonLoader.load(url, function(err,json){
      if( err ){
        throwError('failed to get JSON (' + url + ')')
      }
      initWithJSON(json)
    })
  }

  function emptyResultsContainer(){
    options.resultsContainer.innerHTML = ''
  }

  function appendToResultsContainer(text){
    options.resultsContainer.innerHTML += text
  }

  function registerInput(){

    // https://remysharp.com/2010/07/21/throttling-function-calls
    function debounce(fn, delay) {
      var timer = null;
      return function () {
        var context = this, args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function () {
          fn.apply(context, args);
        }, delay);
      };
    }

    options.searchInput.addEventListener('keyup', debounce(function(e){

      // whitelist the following keycodes
      var whitelist = [37,38,39,40];

      var keyCodes = whitelist.map(function(code){
        return 'e.which != ' + code;
      }).join(' && ');

      // if the key pressed isn't one of the following whitelisted codes precede
      if( eval(keyCodes) ){
        emptyResultsContainer()
        if( e.target.value.length > 0 ){
          render( repository.search(e.target.value) )
        }
      }

    }, 250)) // timeout
  }

  function render(results){
    if( results.length === 0 ){
      return appendToResultsContainer(options.noResultsText)
    }
    for (var i = 0; i < results.length; i++) {
      appendToResultsContainer( templater.compile(results[i]) )
    }
  }

  function throwError(message){ throw new Error('SimpleJekyllSearch --- '+ message) }
})(window, document);<commit_msg>reduced the timeout from 250ms to 100ms<commit_after>;(function(window, document, undefined){
  'use strict'

  var options = {
    searchInput: null,
    resultsContainer: null,
    json: [],
    searchResultTemplate: '
{title}
',
    templateMiddleware: function(){},
    noResultsText: 'No results found',
    limit: 10,
    fuzzy: false,
    exclude: []
  }

  var requiredOptions = ['searchInput','resultsContainer','json']

  var templater = require('./Templater')
  var repository = require('./Repository')
  var jsonLoader = require('./JSONLoader')
  var optionsValidator = require('./OptionsValidator')({
    required: requiredOptions
  })
  var utils = require('./utils')

  /*
    Public API
  */
  window.SimpleJekyllSearch = function SimpleJekyllSearch(_options){
    var errors = optionsValidator.validate(_options)
    if( errors.length > 0 ){
      throwError('You must specify the following required options: ' + requiredOptions)
    }

    options = utils.merge(options, _options)

    templater.setOptions({
      template: options.searchResultTemplate,
      middleware: options.templateMiddleware,
    })

    repository.setOptions({
      fuzzy: options.fuzzy,
      limit: options.limit,
    })

    if( utils.isJSON(options.json) ){
      initWithJSON(options.json)
    }else{
      initWithURL(options.json)
    }
  }

  // for backwards compatibility
  window.SimpleJekyllSearch.init = window.SimpleJekyllSearch

  function initWithJSON(json){
    repository.put(json)
    registerInput()
  }

  function initWithURL(url){
    jsonLoader.load(url, function(err,json){
      if( err ){
        throwError('failed to get JSON (' + url + ')')
      }
      initWithJSON(json)
    })
  }

  function emptyResultsContainer(){
    options.resultsContainer.innerHTML = ''
  }

  function appendToResultsContainer(text){
    options.resultsContainer.innerHTML += text
  }

  function registerInput(){

    // https://remysharp.com/2010/07/21/throttling-function-calls
    function debounce(fn, delay) {
      var timer = null;
      return function () {
        var context = this, args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function () {
          fn.apply(context, args);
        }, delay);
      };
    }

    options.searchInput.addEventListener('keyup', debounce(function(e){

      // whitelist the following keycodes
      var whitelist = [37,38,39,40];

      var keyCodes = whitelist.map(function(code){
        return 'e.which != ' + code;
      }).join(' && ');

      // if the key pressed isn't one of the following whitelisted codes precede
      if( eval(keyCodes) ){
        emptyResultsContainer()
        if( e.target.value.length > 0 ){
          render( repository.search(e.target.value) )
        }
      }

    }, 100)) // timeout
  }

  function render(results){
    if( results.length === 0 ){
      return appendToResultsContainer(options.noResultsText)
    }
    for (var i = 0; i < results.length; i++) {
      appendToResultsContainer( templater.compile(results[i]) )
    }
  }

  function throwError(message){ throw new Error('SimpleJekyllSearch --- '+ message) }
})(window, document);<|endoftext|>


<commit_before>import { observable } from 'mobx';
import { service } from '../app';
import _ from 'lodash';

export default class PostStore {

  query = {};

  @observable filter = 'all';

  @observable list = [];

  constructor(post) {
    Object.assign(this, post);
  }

  mergeQuery(query) {
    _.merge(this.query, query);
  }

  filterBy(filter) {
    this.filter = filter;
    let completed;

    switch (this.filter) {
      case 'all': this.query.query.completed = undefined; break;
      case 'todo': completed = true; break;
      case 'done': completed = false; break;
      default: completed = 'all';
    }

    if (filter === 'all') return this.find();
    return this.find({ query: { completed } });
  }

  search(title) {
    return this.find({ query: { title: `%${title}%` } });
  }

  find(query = {}) {
    this.mergeQuery(query);
    console.log('this.query', this.query);

    return service('post')
      .find(this.query)
      .then((json) => this.list = json.data);
  }
}
<commit_msg>update<commit_after>import { observable } from 'mobx';
import { service } from '../app';
import _ from 'lodash';

export default class PostStore {

  query = {};

  @observable filter = 'all';

  @observable list = [];

  constructor(post) {
    Object.assign(this, post);
  }

  filterBy(filter) {
    this.filter = filter;
    let completed;

    switch (this.filter) {
      case 'all': this.query.query.completed = undefined; break;
      case 'todo': completed = true; break;
      case 'done': completed = false; break;
      default: completed = 'all';
    }

    if (filter === 'all') return this.find();
    return this.find({ query: { completed } });
  }

  search(title) {
    return this.find({ query: { title: `%${title}%` } });
  }

  find(query = {}) {
    _.merge(this.query, query);

    return service('post')
      .find(this.query)
      .then((json) => this.list = json.data);
  }
}
<|endoftext|>


<commit_before>'use strict';

var CC = require("chemcalc");
var Similarity = require("peaks-similarity");

var CE=exports;

CE.analyseMF=CC.analyseMF;
CE.getInfo=CC.getInfo;

/*
We will extentend mfFromMonoisotopicMass in order to include in the options:
* experimental : an array of [[x1,y1],[x2,y2],...] or [[x1,x2,x3,...][y1,y2,y3,...]]
* widthTop : top width of the trapezoid
* widthBottom : bottom width of the trapezoid
* from : mass "from" which calculate the similarity
* to : mass "to" which calculate the similarity
* As an alternative the from / to parameters can be calculated based target mass
*
* decimalsPPM : number of decimals for PPM
* decimalsMass : number odecimals for the mass
 */

CE.mfFromMonoisotopicMass = function(mass, options) {
    var factorPPM, factorMass;
    if (! options) throw "Options are mandatory";
    if (! options.experimental) throw "You need to have an experimental list of peaks in options.experimental";

    var mfResults = CC.mfFromMonoisotopicMass(mass, options);
    var similarity=new Similarity({widthTop: options.widthTop, widthBottom: options.widthBottom});
    similarity.setFromTo(options.from, options.to);
    similarity.setPeaks1(options.experimental);

    var results=mfResults.results;

    if (options.decimalsPPM) var factorPPM=Math.pow(10,options.decimalsPPM);
    if (options.decimalsMass) var factorMass=Math.pow(10,options.decimalsMass);

    // we could improve a little bit the result ...
    for (var i=0; i<results.length; i++) {
        var result=results[i];
        processMF(result, similarity, result.mf.value, options);
        if (factorPPM) result.ppm=Math.round(result.ppm*factorPPM)/factorPPM;
        if (factorMass) result.em=Math.round(result.em*factorMass)/factorMass;
     }
    mfResults.extractExperimental=similarity.getExtract1();
    return mfResults;
}

CE.matchMFs = function(mfsArray, experimental, options) {
    var factorPPM, factorMass;
    options=options||{};
    options.addExperimentalExtract=true;
    var similarity=new Similarity({widthTop: options.widthTop, widthBottom: options.widthBottom});
    similarity.setPeaks1(experimental);

    var mfs=CE.combineMFs(mfsArray);

    if (options.decimalsMass) var factorMass=Math.pow(10,options.decimalsMass);

    var results=[];
    for (var i=0; i<mfs.length; i++) {
        console.log("Analysing: "+i+"/"+mfs.length+" ("+mfs[i]+")");
        var result={};
        results.push(result);
        processMF(result, similarity, mfs[i], options);
        if (factorMass) result.em=Math.round(result.em*factorMass)/factorMass;
    }

    return {options: options, results:results};
}

CE.getEutrophicationPotential=function(mf) {
    var chemcalc=CC.analyseMF(mf);
    var atoms=chemcalc.parts[0].ea;
    var mw=chemcalc.mw;
    var nC=0, nO=0, nN=0, nP=0, nH=0;
    for (var i=0; i<atoms.length; i++) {
        var atom=atoms[i];
        switch(atom.element) {
            case "C":
                nC=atom.number;
                break;
            case "N":
                nN=atom.number;
                break;
            case "O":
                nO=atom.number;
                break;
            case "H":
                nH=atom.number;
                break;
            case "P":
                nP=atom.number;
                break;
            default:
                return {log:"EP can not be calculated because the MF contains the element: "+atom.element}
        }
    }

    var vRef=1;
    var mwRef=94.97;

    var thOD = nC + (nH-3*nN)/4 - nO/2;
    var v = nP + nN/16 + thOD/138;
    var ep = (v / mw) / (vRef / mwRef)

    return {
        v: v,
        thOD: thOD,
        ep: ep,
        mf: {type:"mf", value:mf},
        mw: chemcalc.mw,
        log:"Successful calculation"
    }
}

CE.combineMFs=function (keys) {
    function appendResult(results, currents, keys) {
        // this script is designed to combine molecular formula
        // that may contain comments after a "$" sign
        // therefore we should put all the comments at the ned
        var result="";
        var comments=[];
        for (var i=0; i<keys.length; i++) {
            var key=keys[i][currents[i]];
            if (key.indexOf("$")>-1) {
                comments.push(key.replace(/^[^$]*\$/,""));
                key=key.replace(/\$.*/,"");
            }
            result+=key;
        }
        if (comments.length>0) result+="$"+comments.join(" ");
        results.push(result);
    }

    if (! Array.isArray(keys)) return [];
    if (! Array.isArray(keys[0])) keys=[keys];
    var results=[];
    var sizes=new Array(keys.length);
    var currents=new Array(keys.length);
    for (var i=0; i<keys.length; i++) {
        sizes[i]=keys[i].length-1;
        currents[i]=0;
    }
    var position=0;
    var evolution=0;

    while (position<currents.length) {
        if (currents[position]<sizes[position]) {
            evolution++;
            appendResult(results, currents, keys);
            currents[position]++;
            for (var i=0; i<position; i++) {
                currents[i]=0;
            }
            position=0;
        } else {
            position++;
        }
    }
    appendResult(results, currents, keys);
    return results;
}

function processMF(result, similarity, mf, options) {
    options=options || {};
    options.isotopomers="array";
    var ccResult=CC.analyseMF(mf, options);

    var from, to;
    if (options.from && options.to) {
        from=options.from
        to=options.to;
    } else {
        var charge=Math.abs(ccResult.parts[0].charge || 1);
        options.zone = options.zone || {};
        if (!options.zone.low) options.zone.low = 0.5;
        if (!options.zone.high) options.zone.high = 4.5;

        var target=ccResult.parts[0].msem || ccResult.parts[0].em;
        from=target+options.zone.low/charge;
        to=target+options.zone.high/charge;
    }

    similarity.setFromTo(from, to);
    similarity.setPeaks2(ccResult.spectrum);

    var similarityResult=similarity.getSimilarity();

    if (! result.em) result.em=ccResult.em;
    if (! result.info) result.info=mf;
    if (! result.mf) result.mf=ccResult.mf;
    if (! result.charge) result.charge=ccResult.parts[0].charge;
    result.fromTo={from: from, to:to};
    result.extract=similarityResult.extract2;
    result.diff=similarityResult.diff;
    result.similarity=Math.floor(similarityResult.similarity*1e4)/1e2;
    result.color="hsla("+Math.round(similarityResult.similarity*120)+",100%,60%,0.6)";
    if (options.addExperimentalExtract) result.extractExperimental=similarityResult.extract1;
}

<commit_msg>Update index.js<commit_after>'use strict';

var CC = require("chemcalc");
var Similarity = require("peaks-similarity");

var CE=exports;

CE.analyseMF=CC.analyseMF;
CE.getInfo=CC.getInfo;

/*
We will extentend mfFromMonoisotopicMass in order to include in the options:
* experimental : an array of [[x1,y1],[x2,y2],...] or [[x1,x2,x3,...][y1,y2,y3,...]]
* widthTop : top width of the trapezoid
* widthBottom : bottom width of the trapezoid
* from : mass "from" which calculate the similarity
* to : mass "to" which calculate the similarity
* As an alternative the from / to parameters can be calculated based target mass
*
* decimalsPPM : number of decimals for PPM
* decimalsMass : number odecimals for the mass
 */

CE.mfFromMonoisotopicMass = function(mass, options) {
    var factorPPM, factorMass;
    if (! options) throw "Options are mandatory";
    if (! options.experimental) throw "You need to have an experimental list of peaks in options.experimental";

    var mfResults = CC.mfFromMonoisotopicMass(mass, options);
    var similarity=new Similarity({widthTop: options.widthTop, widthBottom: options.widthBottom});
    similarity.setFromTo(options.from, options.to);
    similarity.setPeaks1(options.experimental);

    var results=mfResults.results;

    if (options.decimalsPPM) var factorPPM=Math.pow(10,options.decimalsPPM);
    if (options.decimalsMass) var factorMass=Math.pow(10,options.decimalsMass);

    // we could improve a little bit the result ...
    for (var i=0; i<results.length; i++) {
        var result=results[i];
        processMF(result, similarity, result.mf.value, options);
        if (factorPPM) result.ppm=Math.round(result.ppm*factorPPM)/factorPPM;
        if (factorMass) result.em=Math.round(result.em*factorMass)/factorMass;
     }
    mfResults.extractExperimental=similarity.getExtract1();
    return mfResults;
}

CE.matchMFs = function(mfsArray, experimental, options) {
    var factorPPM, factorMass;
    options=options||{};
    options.addExperimentalExtract=true;
    var similarity=new Similarity({widthTop: options.widthTop, widthBottom: options.widthBottom});
    similarity.setPeaks1(experimental);

    var mfs=CE.combineMFs(mfsArray);

    if (options.decimalsMass) var factorMass=Math.pow(10,options.decimalsMass);

    var results=[];
    for (var i=0; i<mfs.length; i++) {
        console.log("Analysing: "+i+"/"+mfs.length+" ("+mfs[i]+")");
        var result={};
        results.push(result);
        processMF(result, similarity, mfs[i], options);
        if (factorMass) result.em=Math.round(result.em*factorMass)/factorMass;
    }

    return {options: options, results:results};
}

CE.getEutrophicationPotential=function(mf) {
    var chemcalc=CC.analyseMF(mf);
    var atoms=chemcalc.parts[0].ea;
    var mw=chemcalc.mw;
    var nC=0, nO=0, nN=0, nP=0, nH=0;
    for (var i=0; i<atoms.length; i++) {
        var atom=atoms[i];
        switch(atom.element) {
            case "C":
                nC=atom.number;
                break;
            case "N":
                nN=atom.number;
                break;
            case "O":
                nO=atom.number;
                break;
            case "H":
                nH=atom.number;
                break;
            case "P":
                nP=atom.number;
                break;
            default:
                return {log:"EP can not be calculated because the MF contains the element: "+atom.element}
        }
    }

    var vRef=1;
    var mwRef=94.97;

    var thOD = nC + (nH-3*nN)/4 - nO/2;
    var v = nP + nN/16 + thOD/138;
    var ep = (v / mw) / (vRef / mwRef)

    return {
        v: v,
        thOD: thOD,
        ep: ep,
        mf: {type:"mf", value:mf},
        mw: chemcalc.mw,
        log:"Successful calculation"
    }
}

CE.combineMFs=function (keys) {
    function appendResult(results, currents, keys) {
        // this script is designed to combine molecular formula
        // that may contain comments after a "$" sign
        // therefore we should put all the comments at the ned
        var result="";
        var comments=[];
        for (var i=0; i<keys.length; i++) {
            var key=keys[i][currents[i]];
            if (key.indexOf("$")>-1) {
                comments.push(key.replace(/^[^$]*\$/,""));
                key=key.replace(/\$.*/,"");
            }
            result+=key;
        }
        if (comments.length>0) result+="$"+comments.join(" ");
        results.push(result);
    }

    if (! Array.isArray(keys)) return [];
    if (! Array.isArray(keys[0])) keys=[keys];
    var results=[];
    var sizes=new Array(keys.length);
    var currents=new Array(keys.length);
    for (var i=0; i<keys.length; i++) {
        sizes[i]=keys[i].length-1;
        currents[i]=0;
    }
    var position=0;
    var evolution=0;

    while (position<currents.length) {
        if (currents[position]<sizes[position]) {
            evolution++;
            appendResult(results, currents, keys);
            currents[position]++;
            for (var i=0; i<position; i++) {
                currents[i]=0;
            }
            position=0;
        } else {
            position++;
        }
    }
    appendResult(results, currents, keys);
    return results;
}

function processMF(result, similarity, mf, options) {
    options=options || {};
    options.isotopomers="array";
    var ccResult=CC.analyseMF(mf, options);

    var from, to;
    if (options.from && options.to) {
        from=options.from
        to=options.to;
    } else {
        var charge=Math.abs(ccResult.parts[0].charge || 1);
        options.zone = options.zone || {};
        if (!options.zone.low) options.zone.low = -0.5;
        if (!options.zone.high) options.zone.high = 4.5;

        var target=ccResult.parts[0].msem || ccResult.parts[0].em;
        from=target+options.zone.low/charge;
        to=target+options.zone.high/charge;
    }

    similarity.setFromTo(from, to);
    similarity.setPeaks2(ccResult.spectrum);

    var similarityResult=similarity.getSimilarity();

    if (! result.em) result.em=ccResult.em;
    if (! result.info) result.info=mf;
    if (! result.mf) result.mf=ccResult.mf;
    if (! result.charge) result.charge=ccResult.parts[0].charge;
    result.fromTo={from: from, to:to};
    result.extract=similarityResult.extract2;
    result.diff=similarityResult.diff;
    result.similarity=Math.floor(similarityResult.similarity*1e4)/1e2;
    result.color="hsla("+Math.round(similarityResult.similarity*120)+",100%,60%,0.6)";
    if (options.addExperimentalExtract) result.extractExperimental=similarityResult.extract1;
}

<|endoftext|>


<commit_before>const styles = {
  title: {
    textAlign: "center",
    fontSize: 60,
    fontWeight: 100,
    color: "rgb(38, 48, 83)"
  },
  subtitle: {
    textAlign: "center",
    fontSize: 18,
    fontWeight: 300,
    paddingTop: 10,
    color: "rgb(38, 48, 83)"
  },
  banner: {
    position: "absolute",
    top: 0,
    left: 0,
    right: 0,
    height: 400,
    backgroundImage: `url(//cdn.rawgit.com/dabbott/react-native-express/master/static/background-compressed.jpg)`,
    backgroundSize: "cover",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    zIndex: -1,
    flexDirection: "column"
  },
  container: {
    flex: "1 1 auto",
    display: "flex",
    flexDirection: "column",
    minWidth: 0,
    minHeight: 0
  },
  content: {
    flex: "1 1 auto",
    paddingTop: 400,
    overflowY: "auto",
    zIndex: 1,
    minWidth: 0,
    minHeight: 0
  },
  well: {
    padding: "20px 20px"
  },
  li: {
    margin: "10px 0"
  },
  pageHeader: {
    fontSize: 20,
    fontWeight: 300,
    marginTop: 15,
    marginBottom: 15
  },
  h3: {
    fontSize: 20,
    fontWeight: 300,
    marginTop: 60,
    marginBottom: 15
  },
  h4: {
    fontSize: 14,
    fontWeight: 500,
    marginTop: 35,
    marginBottom: 15
  },
  p: {
    fontSize: 14,
    fontWeight: 400,
    lineHeight: "22px",
    marginBottom: 15
  },
  strong: {
    fontWeight: "bold"
  },
  blockquote: {
    borderLeft: "4px solid #DEDFE8",
    paddingLeft: 10
  },
  img: {
    maxWidth: "100%"
  },
  pre: {
    marginBottom: 15
  }
};

Object.assign(styles, {
  h4_monospace: {
    ...styles.h4,
    fontFamily: "monospace",
    fontWeight: "bold"
  }
});

export default styles;
<commit_msg>Update index.js<commit_after>const styles = {
  title: {
    textAlign: "center",
    fontSize: 60,
    fontWeight: 100,
    color: "rgb(38, 48, 83)"
  },
  subtitle: {
    textAlign: "center",
    fontSize: 18,
    fontWeight: 300,
    paddingTop: 10,
    color: "rgb(38, 48, 83)"
  },
  banner: {
    position: "absolute",
    top: 0,
    left: 0,
    right: 0,
    height: 400,
    backgroundImage: `url(//cdn.rawgit.com/dabbott/react-native-express/master/images/background-compressed.jpg)`,
    backgroundSize: "cover",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    zIndex: -1,
    flexDirection: "column"
  },
  container: {
    flex: "1 1 auto",
    display: "flex",
    flexDirection: "column",
    minWidth: 0,
    minHeight: 0
  },
  content: {
    flex: "1 1 auto",
    paddingTop: 400,
    overflowY: "auto",
    zIndex: 1,
    minWidth: 0,
    minHeight: 0
  },
  well: {
    padding: "20px 20px"
  },
  li: {
    margin: "10px 0"
  },
  pageHeader: {
    fontSize: 20,
    fontWeight: 300,
    marginTop: 15,
    marginBottom: 15
  },
  h3: {
    fontSize: 20,
    fontWeight: 300,
    marginTop: 60,
    marginBottom: 15
  },
  h4: {
    fontSize: 14,
    fontWeight: 500,
    marginTop: 35,
    marginBottom: 15
  },
  p: {
    fontSize: 14,
    fontWeight: 400,
    lineHeight: "22px",
    marginBottom: 15
  },
  strong: {
    fontWeight: "bold"
  },
  blockquote: {
    borderLeft: "4px solid #DEDFE8",
    paddingLeft: 10
  },
  img: {
    maxWidth: "100%"
  },
  pre: {
    marginBottom: 15
  }
};

Object.assign(styles, {
  h4_monospace: {
    ...styles.h4,
    fontFamily: "monospace",
    fontWeight: "bold"
  }
});

export default styles;
<|endoftext|>


<commit_before>var replaceAll = function( oldToken ) {
  var configs = this;
  return {
    from: function( string ) {
      return {
        to: function( newToken ) {
          var _token;
          var index = -1;
          if ( configs.ignoringCase ) {
              _token = oldToken.toLowerCase();
              while((
                  index = string
                    .toLowerCase()
                    .indexOf(
                      _token,
                      index >= 0 ?
                        index + newToken.length : 0
                      )
                    ) !== -1
              ) {

                  string = string
                    .substring( 0, index ) +
                      newToken +
                    string.substring( index + newToken.length );
              }
              return string;
          }
          return string.split( oldToken ).join( newToken );
        }
      };
    },
    ignoreCase: function() {
      return replaceAll.call({
        ignoringCase: true
      }, oldToken );
    }
  };
};

module.exports = {
  all: replaceAll
};
<commit_msg>Remove unnecessary newline<commit_after>var replaceAll = function( oldToken ) {
  var configs = this;
  return {
    from: function( string ) {
      return {
        to: function( newToken ) {
          var _token;
          var index = -1;
          if ( configs.ignoringCase ) {
              _token = oldToken.toLowerCase();
              while((
                  index = string
                    .toLowerCase()
                    .indexOf(
                      _token,
                      index >= 0 ?
                        index + newToken.length : 0
                      )
                    ) !== -1
              ) {
                  string = string
                    .substring( 0, index ) +
                      newToken +
                    string.substring( index + newToken.length );
              }
              return string;
          }
          return string.split( oldToken ).join( newToken );
        }
      };
    },
    ignoreCase: function() {
      return replaceAll.call({
        ignoringCase: true
      }, oldToken );
    }
  };
};

module.exports = {
  all: replaceAll
};
<|endoftext|>


<commit_before>/**
 * Build a HTML
 list for each string of an array
 *
 * @param   {String[]} array  The elements to be used
 * @returns {Element}         The built
 list
 */
function buildList(array) {
  return stringToElement("
" + array.reduce(function(previousValue, currentValue, index, array){
    return previousValue + "
" + currentValue + "
\n";
  }, "") + "
");
}

/**
 * Transforms a number of seconds into a human-readable (if this human reads English) string.
 * It will show weeks, days, minutes and seconds in a way the the first unit will not be a zero
 *
 * @param   {Number} delta  The number of seconds to compute
 * @returns {String}        The human-readable string
 */
function prettyPrintDelta(delta) {
  var weeks   = Math.floor(delta / 604800),
      days    = Math.floor(delta / 86400) % 7,
      hours   = Math.floor(delta / 3600) % 24,
      minutes = Math.floor(delta / 60) % 60,
      seconds = delta % 60;

  var output = "";
  if(delta >= 604800) output += weeks   + " week"   + (weeks != 1 ? 's' : '')   + ', ';
  if(delta >= 86400)  output += days    + " day"    + (days != 1 ? 's' : '')    + ', ';
  if(delta >= 3600)   output += hours   + " hour"   + (hours != 1 ? 's' : '')   + ', ';
  if(delta >= 60)     output += minutes + " minute" + (minutes != 1 ? 's' : '') + ' and ';
                      output += seconds + " second" + (seconds != 1 ? 's' : '');
  return output;
}

/**
 * Decimal adjustment of a number.
 * Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round#Example:_Decimal_rounding
 *
 * @param   {(Number|String)} value    The number.
 * @param   {Number}          [exp=0]  The exponent (the 10 logarithm of the adjustment base).
 * @returns {Number}                   The adjusted value.
 */
function round(value, exp) {
  // If the exp is undefined or zero...
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp   = +exp;

  // If the value is not a number or the exp is not an integer...
  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}

function computeProgressBar(ratio) {
  ratio = Math.min(Math.max(0.0, ratio), 1.0);

  var progress    = document.querySelector("#output .progress"),
      progressBar = document.querySelector("#output .progress-bar"),
      value = round(100 * ratio, 2);
  document.querySelector("#output .value").innerHTML =  value + " %";
  progressBar.style.width = (100 * ratio) + "%";
  progressBar.setAttribute("aria-valuenow", value);

  if(ratio === 1.0) {
    progress.classList.remove("active");
    progressBar.classList.add("progress-bar-success");
  }
  else {
    progress.classList.add("active");
    progressBar.classList.remove("progress-bar-success");
  }
}

function playTimers(dateEvents) {
  function loop() {
    var currentTime = new Date();

    var ratio = round(currentTime - dateEvents[0], -3) / (dateEvents[dateEvents.length - 1] - dateEvents[0]);
    computeProgressBar(ratio);

    var counters = [];
    forEach(dateEvents, function(element, index) {
      counters.push(render(currentTime >= element ? "pastEvent" : "futureEvent", {
        index: index + 1,
        time: prettyPrintDelta(round(Math.abs(currentTime - element) / 1000))
      }));
    });
    removeAllChildren(document.querySelector("#output .alert"));
    document.querySelector("#output .alert").appendChild(buildList(counters));

    var alertClasses = document.querySelector("#output .alert").classList;

    forEach(["alert-warning", "alert-success", "alert-info"], function(element) {
      alertClasses.remove(element);
    });

    alertClasses.add(
      ratio <  0.0 ? "alert-warning" :
      ratio >= 1.0 ? "alert-success" :
                     "alert-info"
    );
  }

  loop();

  document.dispatchEvent(new CustomEvent("timerStarted", {
    detail: {
      newIntervalId: window.setInterval(loop, 1000)
    }
  }));
}

/**
 * Renders a set of data inside a template
 *
 * @param   {String} templateId  The name that will be used to fetch the template content from the HTML markup
 * @param   {Object} data        The set of data to be used. Keys must exist with format {{key}} to be used in the template
 * @returns {String}             The template after rendering the data
 */
function render(templateId, data) {
  var template = document.querySelector("#template-" + templateId).textContent;
  for (var key in data)
    template = template.replace(new RegExp('{{' + key + '}}', 'g'), data[key]);
  return template;
}

/**
 * Transforms a string-based HTML element into a native HTML element where DOM API applies
 *
 * @param   {String}  str  A string containing an HTML element
 * @returns {Element}      An HTML element
 */
function stringToElement(str) {
  var div = document.createElement('div');
  div.innerHTML = str;
  return div.firstElementChild;
}

/**
 * Generic usage of Array.prototype.forEach that can also be used on NodeList elements.
 *
 * @param {(*[]|NodeList)} elements  The elements to be processed
 * @param {}               callback  Function to execute for each element
 */
function forEach(elements, callback) {
  [].forEach.call(elements, callback);
}

/**
 * Generic usage of Array.prototype.map that can also be used on NodeList elements.
 *
 * @param {(*[]|NodeList)} elements  The elements to be processed
 * @param {}               callback  Function to execute for each element
 * @return *[]                       The mapped array
 */
function map(elements, callback) {
  return [].map.call(elements, callback);
}

/**
 * Generate a random identifier, random enough to be considered as unique.
 *
 * @returns {Number}  A random string (16 alphanumerical characters)
 */
function generateId() {
  return Math.random().toString(36).substr(2, 16);
}

/**
 * Displays a non-visible HTML element
 *
 * @param {(Element|Element[]|NodeList)} elements  The HTML element(s) to show
 */
function show(elements) {
  if(typeof elements.length === "undefined")
    elements.classList.remove("hidden");
  else
    forEach(elements, function(element) {
      element.classList.remove("hidden");
    });
}

/**
 * Hides an HTML element
 *
 * @param {(Element|Element[]|NodeList)} elements  The HTML element(s) to hide
 */
function hide(elements) {
  if(typeof elements.length === "undefined")
    elements.classList.add("hidden");
  else
    forEach(elements, function(element) {
      element.classList.add("hidden");
    });
}

/**
 * Removes all children ofa given HTML element
 *
 * @param {Element} element  The element to empty
 */
function removeAllChildren(element) {
  while(element.firstChild)
    element.removeChild(element.firstChild);
}

function newEventInput(value, index, showCloseBtn) {
  var eventElement = stringToElement(render("input", {
    id: generateId(),
    index: index,
    value: value
  }));

  eventElement.querySelector(".close").addEventListener("click", function(evt) {
    evt.preventDefault();
    eventElement.remove();
    document.dispatchEvent(new Event("eventDeleted"));
  });

  if(!showCloseBtn)
    hide(eventElement.querySelector(".close"));

  return eventElement;
}

function createEventInputs(strings) {
  if(strings.length < 2)
    return [].push(newEventInput("", 1, false))
             .push(newEventInput("", 2, false));
  else
    return map(strings, function(element, index) {
      return newEventInput(element, index + 1, strings.length > 2);
    });
}

function controller(events) {
  var dateEvents = map(events, Date.parse);

  var errorsElement  = document.querySelector("#errors"),
      markersElement = document.querySelector(".markers"),
      outputElement  = document.querySelector("#output");

  var errors = [];

  removeAllChildren(markersElement);
  removeAllChildren(errorsElement);

  hide(errorsElement);
  hide(outputElement);

  forEach(document.querySelectorAll("#events .form-group"), function(element) {
    element.classList.remove("has-error");
  });

  // Validates the date format
  for (var i = 0; i < dateEvents.length; i++) {
    if (isNaN(dateEvents[i])) {
      document.querySelector("#events .form-group:nth-child(" + (i + 1) + ")").classList.add("has-error");
      errors.push(render("invalidEvent", {
        index: i + 1
      }));
    }
  }

  // Validates the order on dates
  for (i = 0; i < dateEvents.length - 1; i++) {
    if (!isNaN(dateEvents[i]) && !isNaN(dateEvents[i + 1]) && dateEvents[i] >= dateEvents[i + 1]) {
      document.querySelector("#events .form-group:nth-child(" + (i + 1) + ")").classList.add("has-error");
      document.querySelector("#events .form-group:nth-child(" + (i + 2) + ")").classList.add("has-error");
      errors.push(render("predatedEvent", {
        index1: i + 1,
        index2: i + 2
      }));
    }
  }

  // Creates the circled markers above the progress bar
  forEach(dateEvents, function(element, index, array) {
    var newMarker = stringToElement(render("marker", {
      index: index + 1,
      left:  100 * (element - array[0]) / (array[array.length - 1] - array[0]) + "%"
    }));
    markersElement.appendChild(newMarker);
  });

  if(errors.length !== 0) {
    errorsElement.appendChild(buildList(errors));
    show(errorsElement);
    hide(outputElement);
  }

  if(dateEvents.length >= 2 && errors.length === 0) {
    show(outputElement);
    playTimers(dateEvents);
  }
}

// EVENT HANDLERS
// --------------

// Stops the previous timer when a new one is started
document.addEventListener("timerStarted", function(e) {
  if(typeof currentIntervalId !== "undefined")
    clearInterval(currentIntervalId);
  currentIntervalId = e.detail.newIntervalId;
});

// The user submitted the form for computation
document.querySelector("#form").addEventListener("submit", function(e) {
  e.preventDefault();

  var events = map(document.querySelectorAll("#events input"), function(element) {
    return element.value;
  });

  history.pushState({
    events: events
  }, document.title, "?" + map(events, function(element) {
    return "e=" + encodeURIComponent(element);
  }).join("&"));

  controller(events);
});

// The user moved into the history of the browser
window.addEventListener("popstate", function (e) {
  if(e.state === null)
    return;

  var events = e.state.events;

  removeAllChildren(document.querySelector("#events"));

  forEach(createEventInputs(events), function (element) {
    document.querySelector("#events").appendChild(element);
  });

  controller(events);
});

// The user requested the addition of a new event input to the form
document.querySelector("#addEvent").addEventListener("click", function(e) {
  e.preventDefault();
  document.querySelector("#events").appendChild(newEventInput(
    "",
    document.querySelector("#events").children.length + 2,
    true
  ));
  show(document.querySelectorAll("#form .close"));
});

// The user deleted an event input from the form
document.addEventListener("eventDeleted", function() {
  forEach(document.querySelectorAll("#form label"), function(element, index) {
    element.textContent = index + 1;
  });

  if (document.querySelector("#events").children.length <= 2)
    hide(document.querySelectorAll("#form .close"));
});

var currentIntervalId;

var events = map(window.location.search.substring(1).split("&"), function (element) {
  var pair = element.split("="),
      key = decodeURIComponent(pair[0]),
      val = decodeURIComponent(pair[1]);
  return key === "e" ? val : null;
}).filter(function (element) { return element !== null; });

history.replaceState({
  events: events,
}, document.title);

forEach(createEventInputs(events), function (element) {
  document.querySelector("#events").appendChild(element);
});

controller(events);
<commit_msg>Minor code refactoring<commit_after>/**
 * Build a HTML
 list for each string of an array
 *
 * @param   {String[]} array  The elements to be used
 * @returns {Element}         The built
 list
 */
function buildList(array) {
  return stringToElement("
" + array.reduce(function(previousValue, currentValue, index, array){
    return previousValue + "
" + currentValue + "
\n";
  }, "") + "
");
}

/**
 * Transforms a number of seconds into a human-readable (if this human reads English) string.
 * It will show weeks, days, minutes and seconds in a way the the first unit will not be a zero
 *
 * @param   {Number} delta  The number of seconds to compute
 * @returns {String}        The human-readable string
 */
function prettyPrintDelta(delta) {
  var weeks   = Math.floor(delta / 604800),
      days    = Math.floor(delta / 86400) % 7,
      hours   = Math.floor(delta / 3600) % 24,
      minutes = Math.floor(delta / 60) % 60,
      seconds = delta % 60;

  var output = "";
  if(delta >= 604800) output += weeks   + " week"   + (weeks != 1 ? 's' : '')   + ', ';
  if(delta >= 86400)  output += days    + " day"    + (days != 1 ? 's' : '')    + ', ';
  if(delta >= 3600)   output += hours   + " hour"   + (hours != 1 ? 's' : '')   + ', ';
  if(delta >= 60)     output += minutes + " minute" + (minutes != 1 ? 's' : '') + ' and ';
                      output += seconds + " second" + (seconds != 1 ? 's' : '');
  return output;
}

/**
 * Decimal adjustment of a number.
 * Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round#Example:_Decimal_rounding
 *
 * @param   {(Number|String)} value    The number.
 * @param   {Number}          [exp=0]  The exponent (the 10 logarithm of the adjustment base).
 * @returns {Number}                   The adjusted value.
 */
function round(value, exp) {
  // If the exp is undefined or zero...
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp   = +exp;

  // If the value is not a number or the exp is not an integer...
  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}

/**
 *
 */
function updateProgressBar(ratio) {
  ratio = Math.min(Math.max(0.0, ratio), 1.0);

  var progress    = document.querySelector("#output .progress"),
      progressBar = document.querySelector("#output .progress-bar"),
      value = round(100 * ratio, 2);
  document.querySelector("#output .value").innerHTML =  value + "%";
  progressBar.style.width = (100 * ratio) + "%";
  progressBar.setAttribute("aria-valuenow", value);

  if(ratio === 1.0) {
    progress.classList.remove("active");
    progressBar.classList.add("progress-bar-success");
  }
  else {
    progress.classList.add("active");
    progressBar.classList.remove("progress-bar-success");
  }
}

function playTimers(dateEvents) {
  function loop() {
    var counterElement = document.querySelector("#output .alert"),
        currentTime = new Date(), // Now
        ratio = round(currentTime - dateEvents[0], -3) / (dateEvents[dateEvents.length - 1] - dateEvents[0]),
        counters = [];

    updateProgressBar(ratio);

    forEach(dateEvents, function(element, index) {
      counters.push(render(currentTime >= element ? "pastEvent" : "futureEvent", {
        index: index + 1,
        time: prettyPrintDelta(round(Math.abs(currentTime - element) / 1000))
      }));
    });
    removeAllChildren(counterElement);
    counterElement.appendChild(buildList(counters));

    forEach(["alert-warning", "alert-success", "alert-info"], function(element) {
      counterElement.classList.remove(element);
    });

    counterElement.classList.add(
      ratio <  0.0 ? "alert-warning" :
      ratio >= 1.0 ? "alert-success" :
                     "alert-info"
    );
  }

  loop();

  document.dispatchEvent(new CustomEvent("timerStarted", {
    detail: {
      newIntervalId: window.setInterval(loop, 1000)
    }
  }));
}

/**
 * Renders a set of data inside a template
 *
 * @param   {String} templateId  The name that will be used to fetch the template content from the HTML markup
 * @param   {Object} data        The set of data to be used. Keys must exist with format {{key}} to be used in the template
 * @returns {String}             The template after rendering the data
 */
function render(templateId, data) {
  var template = document.querySelector("#template-" + templateId).textContent;
  for (var key in data)
    template = template.replace(new RegExp('{{' + key + '}}', 'g'), data[key]);
  return template;
}

/**
 * Transforms a string-based HTML element into a native HTML element where DOM API applies
 *
 * @param   {String}  str  A string containing an HTML element
 * @returns {Element}      An HTML element
 */
function stringToElement(str) {
  var div = document.createElement('div');
  div.innerHTML = str;
  return div.firstElementChild;
}

/**
 * Generic usage of Array.prototype.forEach that can also be used on NodeList elements.
 *
 * @param {(*[]|NodeList)} elements  The elements to be processed
 * @param {}               callback  Function to execute for each element
 */
function forEach(elements, callback) {
  [].forEach.call(elements, callback);
}

/**
 * Generic usage of Array.prototype.map that can also be used on NodeList elements.
 *
 * @param {(*[]|NodeList)} elements  The elements to be processed
 * @param {}               callback  Function to execute for each element
 * @return *[]                       The mapped array
 */
function map(elements, callback) {
  return [].map.call(elements, callback);
}

/**
 * Generate a random identifier, random enough to be considered as unique.
 *
 * @returns {Number}  A random string (16 alphanumerical characters)
 */
function generateId() {
  return Math.random().toString(36).substr(2, 16);
}

/**
 * Displays a non-visible HTML element
 *
 * @param {(Element|Element[]|NodeList)} elements  The HTML element(s) to show
 */
function show(elements) {
  if(typeof elements.length === "undefined")
    elements.classList.remove("hidden");
  else
    forEach(elements, function(element) {
      element.classList.remove("hidden");
    });
}

/**
 * Hides an HTML element
 *
 * @param {(Element|Element[]|NodeList)} elements  The HTML element(s) to hide
 */
function hide(elements) {
  if(typeof elements.length === "undefined")
    elements.classList.add("hidden");
  else
    forEach(elements, function(element) {
      element.classList.add("hidden");
    });
}

/**
 * Removes all children ofa given HTML element
 *
 * @param {Element} element  The element to empty
 */
function removeAllChildren(element) {
  while(element.firstChild)
    element.removeChild(element.firstChild);
}

function newEventInput(value, index, showCloseBtn) {
  var eventElement = stringToElement(render("input", {
    id: generateId(),
    index: index,
    value: value
  }));

  eventElement.querySelector(".close").addEventListener("click", function(evt) {
    evt.preventDefault();
    eventElement.remove();
    document.dispatchEvent(new Event("eventDeleted"));
  });

  if(!showCloseBtn)
    hide(eventElement.querySelector(".close"));

  return eventElement;
}

function createEventInputs(strings) {
  if(strings.length < 2)
    return [].push(newEventInput("", 1, false))
             .push(newEventInput("", 2, false));
  else
    return map(strings, function(element, index) {
      return newEventInput(element, index + 1, strings.length > 2);
    });
}

function controller(events) {
  var dateEvents = map(events, Date.parse);

  var errorsElement  = document.querySelector("#errors"),
      markersElement = document.querySelector(".markers"),
      outputElement  = document.querySelector("#output");

  var errors = [];

  removeAllChildren(markersElement);
  removeAllChildren(errorsElement);

  hide(errorsElement);
  hide(outputElement);

  forEach(document.querySelectorAll("#events .form-group"), function(element) {
    element.classList.remove("has-error");
  });

  // Validates the date format
  for (var i = 0; i < dateEvents.length; i++) {
    if (isNaN(dateEvents[i])) {
      document.querySelector("#events .form-group:nth-child(" + (i + 1) + ")").classList.add("has-error");
      errors.push(render("invalidEvent", {
        index: i + 1
      }));
    }
  }

  // Validates the order on dates
  for (i = 0; i < dateEvents.length - 1; i++) {
    if (!isNaN(dateEvents[i]) && !isNaN(dateEvents[i + 1]) && dateEvents[i] >= dateEvents[i + 1]) {
      document.querySelector("#events .form-group:nth-child(" + (i + 1) + ")").classList.add("has-error");
      document.querySelector("#events .form-group:nth-child(" + (i + 2) + ")").classList.add("has-error");
      errors.push(render("predatedEvent", {
        index1: i + 1,
        index2: i + 2
      }));
    }
  }

  // Creates the circled markers above the progress bar
  forEach(dateEvents, function(element, index, array) {
    var newMarker = stringToElement(render("marker", {
      index: index + 1,
      left:  100 * (element - array[0]) / (array[array.length - 1] - array[0]) + "%"
    }));
    markersElement.appendChild(newMarker);
  });

  if(errors.length !== 0) {
    errorsElement.appendChild(buildList(errors));
    show(errorsElement);
    hide(outputElement);
  }

  if(dateEvents.length >= 2 && errors.length === 0) {
    show(outputElement);
    playTimers(dateEvents);
  }
}

// EVENT HANDLERS
// --------------

// Stops the previous timer when a new one is started
document.addEventListener("timerStarted", function(e) {
  if(typeof currentIntervalId !== "undefined")
    clearInterval(currentIntervalId);
  currentIntervalId = e.detail.newIntervalId;
});

// The user submitted the form for computation
document.querySelector("#form").addEventListener("submit", function(e) {
  e.preventDefault();

  var events = map(document.querySelectorAll("#events input"), function(element) {
    return element.value;
  });

  history.pushState({
    events: events
  }, document.title, "?" + map(events, function(element) {
    return "e=" + encodeURIComponent(element);
  }).join("&"));

  controller(events);
});

// The user moved into the history of the browser
window.addEventListener("popstate", function (e) {
  if(e.state === null)
    return;

  var events = e.state.events;

  removeAllChildren(document.querySelector("#events"));

  forEach(createEventInputs(events), function (element) {
    document.querySelector("#events").appendChild(element);
  });

  controller(events);
});

// The user requested the addition of a new event input to the form
document.querySelector("#addEvent").addEventListener("click", function(e) {
  e.preventDefault();
  document.querySelector("#events").appendChild(newEventInput(
    "",
    document.querySelector("#events").children.length + 2,
    true
  ));
  show(document.querySelectorAll("#form .close"));
});

// The user deleted an event input from the form
document.addEventListener("eventDeleted", function() {
  forEach(document.querySelectorAll("#form label"), function(element, index) {
    element.textContent = index + 1;
  });

  if (document.querySelector("#events").children.length <= 2)
    hide(document.querySelectorAll("#form .close"));
});

var currentIntervalId;

var events = map(window.location.search.substring(1).split("&"), function (element) {
  var pair = element.split("="),
      key = decodeURIComponent(pair[0]),
      val = decodeURIComponent(pair[1]);
  return key === "e" ? val : null;
}).filter(function (element) { return element !== null; });

history.replaceState({
  events: events,
}, document.title);

forEach(createEventInputs(events), function (element) {
  document.querySelector("#events").appendChild(element);
});

controller(events);
<|endoftext|>


<commit_before>/*
 * restraint:
 *   1. common code: import 'xx';
 *   2. export: export xx from xx, export x, { xx } from 'xx';
 *
 */

import Module from 'module';
import path from 'path';
import fs from 'fs';
import * as babylon from "babylon";
import traverse from "@babel/traverse";
import * as t from '@babel/types';

const recharts = 'recharts';
const rechartsLib = 'recharts/lib';

const _module = new Module();

const rechartsLibPath = path.dirname(Module._resolveFilename('recharts', {
  ..._module,
  paths: Module._nodeModulePaths(process.cwd()),
}));
const rechartsPath = path.join(rechartsLibPath, '..');
const rechartsSrcPath = path.join(rechartsPath, 'src');
const rechartsSrcIndexPath = path.join(rechartsSrcPath, 'index.js');
const srcCode = fs.readFileSync(rechartsSrcIndexPath, 'utf-8');

const srcAst = babylon.parse(srcCode, {
  sourceType: 'module',
  plugins: ["exportExtensions"],
});

function findPath(source) {
  const finalModule = {
    ..._module,
    paths: Module._nodeModulePaths(rechartsSrcPath),
  };

  const nodeMajorVersion = process.versions.node.split('.')[0];
  let paths;
  let id;
  // This internal API has changed it's functionality
  if (nodeMajorVersion < 12) {
    // NodeJS version <= 10: use _resolveLookupPaths
    [id, paths] = Module._resolveLookupPaths(source, finalModule);
  } else {
    // NodeJS version 12: use _nodeModulePaths from above
    paths = finalModule.paths;
  }
  const finalPaths = [...paths, rechartsSrcPath];

  let sourceFullPath;
  try {
    const fullPath = path.resolve(rechartsSrcPath, source.indexOf('.js') >= 0 ? source : `${source}.js`);
    require.resolve(fullPath);
    sourceFullPath = fullPath;
  } catch(err) {

  }
  if (sourceFullPath) {
    // parse the component of project src
    // full quote path
    const sourceLibPath = `${rechartsLib}/${path.relative(rechartsSrcPath, sourceFullPath)}`;
    return sourceLibPath;
  }

  const absPath = Module._findPath(source, finalPaths);

  if (absPath && (absPath.indexOf(path.join(rechartsPath, 'node_modules')) >= 0) || absPath.indexOf('node_modules') >= 0) {
    // node_modules source
    return source;
  }

  return '';
}

let pkgMap = {};
let commonImport = [];

traverse(srcAst, {
  ImportDeclaration(path) {
    const { source, specifiers } = path.node;

    if (!specifiers.length) {
      // get common import like import 'polyfill'
      commonImport = [...commonImport, source.value];
    }
  },

  ExportNamedDeclaration(path) {
    const { source, specifiers } = path.node;

    specifiers.forEach(spec => {
      const { exported, local } = spec;

      if (t.isExportDefaultSpecifier(spec)) {
        pkgMap = {
          ...pkgMap,
          [exported.name]: source.value,
        };
      } else {
        pkgMap = {
          ...pkgMap,
          [exported.name]: [source.value, local.name],
        };
      }
    });
  },
});

Object.keys(pkgMap).forEach(key => {
  const pkgMapVal = pkgMap[key];

  if (Array.isArray(pkgMapVal)) {
    const source = findPath(pkgMapVal[0]);

    pkgMap[key] = [source, ...pkgMap.slice(1)];
  }

  pkgMap[key] = findPath(pkgMapVal);
});

commonImport = commonImport.map(source => {
  return findPath(source);
});

export default function ({types: t}) {
  // import common code once in a file
  let hasAddCommonCode = false;

  return {
    visitor: {
      ImportDeclaration(path) {
        const { node } = path;
        const { specifiers, source } = node;
        const { value: pkgId } = source;
        const specs = [];

        if (pkgId !== recharts) {
          return ;
        }

        if (!specifiers.filter(t.isImportSpecifier).length) {
          return;
        }

        specifiers.forEach(spec => {
          const { local , imported } = spec;
          const { name: localName } = local;

          let importedPath = recharts;

          if (t.isImportSpecifier(spec)) {
            const { name: importedName } = imported;

            spec = t.importDefaultSpecifier(t.identifier(localName));

            if (!pkgMap[importedName]) {
              throw new Error(`Recharts ${importedName} was not in known modules.`);
            }

            importedPath = pkgMap[importedName];
          }

          if (!hasAddCommonCode) {
            hasAddCommonCode = true;
            commonImport.forEach(cPath => {
              path.insertBefore(t.importDeclaration([], t.stringLiteral(cPath)));
            });
          }

          path.insertAfter(t.importDeclaration([spec], t.stringLiteral(importedPath)));
        });

        path.remove();
      }
    }
  };
}
<commit_msg>Update src/index.js<commit_after>/*
 * restraint:
 *   1. common code: import 'xx';
 *   2. export: export xx from xx, export x, { xx } from 'xx';
 *
 */

import Module from 'module';
import path from 'path';
import fs from 'fs';
import * as babylon from "babylon";
import traverse from "@babel/traverse";
import * as t from '@babel/types';

const recharts = 'recharts';
const rechartsLib = 'recharts/lib';

const _module = new Module();

const rechartsLibPath = path.dirname(Module._resolveFilename('recharts', {
  ..._module,
  paths: Module._nodeModulePaths(process.cwd()),
}));
const rechartsPath = path.join(rechartsLibPath, '..');
const rechartsSrcPath = path.join(rechartsPath, 'src');
const rechartsSrcIndexPath = path.join(rechartsSrcPath, 'index.js');
const srcCode = fs.readFileSync(rechartsSrcIndexPath, 'utf-8');

const srcAst = babylon.parse(srcCode, {
  sourceType: 'module',
  plugins: ["exportExtensions"],
});

function findPath(source) {
  const finalModule = {
    ..._module,
    paths: Module._nodeModulePaths(rechartsSrcPath),
  };

  const nodeMajorVersion = process.versions.node.split('.')[0];
  let paths;
  let id;
  // This internal API has changed it's functionality
  if (nodeMajorVersion < 12) {
    // NodeJS version <= 10: use _resolveLookupPaths
    [id, paths] = Module._resolveLookupPaths(source, finalModule);
  } else {
    // Node.js version >= 12: use _nodeModulePaths from above
    paths = finalModule.paths;
  }
  const finalPaths = [...paths, rechartsSrcPath];

  let sourceFullPath;
  try {
    const fullPath = path.resolve(rechartsSrcPath, source.indexOf('.js') >= 0 ? source : `${source}.js`);
    require.resolve(fullPath);
    sourceFullPath = fullPath;
  } catch(err) {

  }
  if (sourceFullPath) {
    // parse the component of project src
    // full quote path
    const sourceLibPath = `${rechartsLib}/${path.relative(rechartsSrcPath, sourceFullPath)}`;
    return sourceLibPath;
  }

  const absPath = Module._findPath(source, finalPaths);

  if (absPath && (absPath.indexOf(path.join(rechartsPath, 'node_modules')) >= 0) || absPath.indexOf('node_modules') >= 0) {
    // node_modules source
    return source;
  }

  return '';
}

let pkgMap = {};
let commonImport = [];

traverse(srcAst, {
  ImportDeclaration(path) {
    const { source, specifiers } = path.node;

    if (!specifiers.length) {
      // get common import like import 'polyfill'
      commonImport = [...commonImport, source.value];
    }
  },

  ExportNamedDeclaration(path) {
    const { source, specifiers } = path.node;

    specifiers.forEach(spec => {
      const { exported, local } = spec;

      if (t.isExportDefaultSpecifier(spec)) {
        pkgMap = {
          ...pkgMap,
          [exported.name]: source.value,
        };
      } else {
        pkgMap = {
          ...pkgMap,
          [exported.name]: [source.value, local.name],
        };
      }
    });
  },
});

Object.keys(pkgMap).forEach(key => {
  const pkgMapVal = pkgMap[key];

  if (Array.isArray(pkgMapVal)) {
    const source = findPath(pkgMapVal[0]);

    pkgMap[key] = [source, ...pkgMap.slice(1)];
  }

  pkgMap[key] = findPath(pkgMapVal);
});

commonImport = commonImport.map(source => {
  return findPath(source);
});

export default function ({types: t}) {
  // import common code once in a file
  let hasAddCommonCode = false;

  return {
    visitor: {
      ImportDeclaration(path) {
        const { node } = path;
        const { specifiers, source } = node;
        const { value: pkgId } = source;
        const specs = [];

        if (pkgId !== recharts) {
          return ;
        }

        if (!specifiers.filter(t.isImportSpecifier).length) {
          return;
        }

        specifiers.forEach(spec => {
          const { local , imported } = spec;
          const { name: localName } = local;

          let importedPath = recharts;

          if (t.isImportSpecifier(spec)) {
            const { name: importedName } = imported;

            spec = t.importDefaultSpecifier(t.identifier(localName));

            if (!pkgMap[importedName]) {
              throw new Error(`Recharts ${importedName} was not in known modules.`);
            }

            importedPath = pkgMap[importedName];
          }

          if (!hasAddCommonCode) {
            hasAddCommonCode = true;
            commonImport.forEach(cPath => {
              path.insertBefore(t.importDeclaration([], t.stringLiteral(cPath)));
            });
          }

          path.insertAfter(t.importDeclaration([spec], t.stringLiteral(importedPath)));
        });

        path.remove();
      }
    }
  };
}
<|endoftext|>


<commit_before>// LRU cache of mottos - up to 3 mottos you can have. New ones will overwrite old ones.
function addMotto(text) {
  var current = getMottos();;
  if(current === null) current = [];

  current.push({motto: text});
  if(current.length > 3) {
    current.splice(0, 1);
  }

  localStorage.setItem('mottos',
                       JSON.stringify(current));
}

function removeMotto(index) {
  var current = localStorage.getItem('mottos');
  localStorage.setItem('mottos',
                       JSON.stringify(current.splice(index, 1)));
}

function getMottos() {
  return JSON.parse(localStorage.getItem('mottos'));
}

function getRandom(ar) {
  var rand = Math.floor(Math.random() * ar.length);
  return ar[rand];
}

// You can have up to 5 Mottos. LRU cache to erase old ones.
var Motto = React.createClass({
  render: function() {
    return (

{this.props.motto}

    );
  }
});

var MottoList = React.createClass({
  render: function() {
    var mottoNodes = this.props.data.map(function(m, index) {
      return (

          <Motto key={index} motto={m.motto} />

      );
    });

    return (

        {mottoNodes}

    );
  }
});

var MottoForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();
    var motto = React.findDOMNode(this.refs.motto).value.trim();
    if(!motto) {
      return;
    }

    this.props.onMottoSubmit({motto: motto});
    React.findDOMNode(this.refs.motto).value = '';
  },
  render: function() {
    return (
      <form className="motto-form" onSubmit={this.handleSubmit}>
          <input type="text" placeholder="New motto" ref="motto" />
          <input type="submit" value="New motto" />
      </form>
    );
  }
});

var MottoContainer = React.createClass({
  loadMottos: function() {
    this.setState(getMottos());
  },
  handleMottoSubmit: function(motto) {
    addMotto(motto);
    this.setState({data: getMottos()}, function() {

    });
  },
  getInitialState: function() {
    return {data: getMottos()};
  },
  componentDidMount: function() {
    this.loadMottos();
  },
  render: function() {
    return (

        <Motto motto={getRandom(this.state.data)} />
        <MottoForm onMottoSubmit={this.handleMottoSubmit} />

    );
  }
});

var data = getMottos();

if(data === null) {
  data = [];
  localStorage.setItem('mottos', JSON.stringify(data));
}

React.render(
  <MottoContainer data={data} />,
  document.getElementById('content')
);

<commit_msg>changed some placeholders<commit_after>// LRU cache of mottos - up to 3 mottos you can have. New ones will overwrite old ones.
function addMotto(text) {
  var current = getMottos();;
  if(current === null) current = [];

  current.push({motto: text});
  if(current.length > 3) {
    current.splice(0, 1);
  }

  localStorage.setItem('mottos',
                       JSON.stringify(current));
}

function removeMotto(index) {
  var current = localStorage.getItem('mottos');
  localStorage.setItem('mottos',
                       JSON.stringify(current.splice(index, 1)));
}

function getMottos() {
  return JSON.parse(localStorage.getItem('mottos'));
}

function getRandom(ar) {
  var rand = Math.floor(Math.random() * ar.length);
  return ar[rand];
}

// You can have up to 5 Mottos. LRU cache to erase old ones.
var Motto = React.createClass({
  render: function() {
    return (

{this.props.motto}

    );
  }
});

var MottoList = React.createClass({
  render: function() {
    var mottoNodes = this.props.data.map(function(m, index) {
      return (

          <Motto key={index} motto={m.motto} />

      );
    });

    return (

        {mottoNodes}

    );
  }
});

var MottoForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();
    var motto = React.findDOMNode(this.refs.motto).value.trim();
    if(!motto) {
      return;
    }

    this.props.onMottoSubmit({motto: motto});
    React.findDOMNode(this.refs.motto).value = '';
  },
  render: function() {
    return (
      <form className="motto-form" onSubmit={this.handleSubmit}>
          <input type="text" placeholder="I will follow my mottos." ref="motto" />
          <input type="submit" value="New motto" />
      </form>
    );
  }
});

var MottoContainer = React.createClass({
  loadMottos: function() {
    this.setState(getMottos());
  },
  handleMottoSubmit: function(motto) {
    addMotto(motto);
    this.setState({data: getMottos()}, function() {

    });
  },
  getInitialState: function() {
    return {data: getMottos()};
  },
  componentDidMount: function() {
    this.loadMottos();
  },
  render: function() {
    return (

        <Motto motto={getRandom(this.state.data)} />
        <MottoForm onMottoSubmit={this.handleMottoSubmit} />

    );
  }
});

var data = getMottos();

if(data === null) {
  data = [{motto: 'Make new mottos to replace these (max 3)'}];
  localStorage.setItem('mottos', JSON.stringify(data));
}

React.render(
  <MottoContainer data={data} />,
  document.getElementById('content')
);

<|endoftext|>


<commit_before>'use strict'

const is = require( './is' )
const defaultPlugins = require( './plugins' )
const combine = require( './plugins/combine' )

const ApiFactory = ( ...pluginSets ) => {
  const plugins = combine( defaultPlugins, ...pluginSets )

  const Api = ( ...args ) => {
    const {
      createState, isState, onCreate, transformApi,

      hasApi, getApi, memoizeApi
    } = core

    const state = createState( ...args )

    if( !isState( state ) )
      throw Error( 'Api state argument fails isState test' )

    if( hasApi( state ) )
      return getApi( state )

    const privates = plugins.privates.reduce( ( privates, fn ) => {
      fn({ privates, state, core, statics, Api, ApiFactory, plugins })

      return privates
    }, {} )

    const api = transformApi(
      plugins.api.reduce( ( api, fn ) => {
        fn({ api, state, core, privates, statics, Api, ApiFactory, plugins })

        return api
      }, {} )
    )

    memoizeApi( api, state )
    onCreate( api )

    return api
  }

  const core = plugins.core.reduce( ( core, fn ) => {

    return core
  }, {} )

  const statics = plugins.statics.reduce( ( statics, fn ) => {
    fn({ statics, Api, ApiFactory, plugins })

    return statics
  }, {} )

  Object.assign( Api, statics )

  return Api
}

module.exports = ApiFactory
<commit_msg>Didn't check in index properly!<commit_after>'use strict'

const is = require( './is' )
const defaultPlugins = require( './plugins' )
const combine = require( './plugins/combine' )

const ApiFactory = ( ...pluginSets ) => {
  const plugins = combine( defaultPlugins, ...pluginSets )

  const Api = ( ...args ) => {
    const {
      createState, isState, onCreate, transformApi,

      hasApi, getApi, memoizeApi
    } = core

    const state = createState( ...args )

    if( !isState( state ) )
      throw Error( 'Api state argument fails isState test' )

    if( hasApi( state ) )
      return getApi( state )

    const privates = plugins.privates.reduce( ( privates, fn ) => {
      fn({ privates, state, core, statics, Api, ApiFactory, plugins })

      return privates
    }, {} )

    const api = transformApi(
      plugins.api.reduce( ( api, fn ) => {
        fn({ api, state, core, privates, statics, Api, ApiFactory, plugins })

        return api
      }, {} )
    )

    memoizeApi( api, state )
    onCreate( api )

    return api
  }

  const core = plugins.core.reduce( ( core, fn ) => {
    fn({ core, Api, ApiFactory, plugins })

    return core
  }, {} )

  const statics = plugins.statics.reduce( ( statics, fn ) => {
    fn({ statics, Api, ApiFactory, plugins })

    return statics
  }, {} )

  Object.assign( Api, statics )

  return Api
}

module.exports = ApiFactory
<|endoftext|>


<commit_before>
window.pr = {
  methods: {
    loadURL: loadURL,
    addClass: addClass,
    removeClass: removeClass,
    goToTop: goToTop
  }
}

function loadURL(url) {
  window.location.href = url
}

function addClass(className, self) {
  if (self.classList) self.classList.add(className);
  else self.className += ' ' + className;
}

function removeClass(className, self) {
  if (self.classList) self.classList.remove(className);
  else
    self.className = self.className
      .replace(
        new RegExp('(^|\\b)' +
        className
          .split(' ')
          .join('|') +
        '(\\b|$)', 'gi'),
      ' ');
}

function scroll(x, y) {
  window.scrollTo(x, y);
}

function goToTop() {
  scroll(0, 0);
}
<commit_msg>پشتیبانی ساده از برخی ایموجی کدهای فارسی، خارج کردن کدهای جاوااسکریپت از نیم اسپیس گلوبال<commit_after>
(function (w, d) {

  // Export to global namespace
  w.pr = {
    methods: {
      loadURL: loadURL,
      addClass: addClass,
      removeClass: removeClass,
      goToTop: goToTop,
      parseTextForEmojis: parseTextForEmojis
    }
  }

  // Functions and Operations

  function loadURL(url) {
    window.location.href = url
  }

  // addClass && removeClass ; credit of youmightnotneedjquery.com
  function addClass(className, self) {
    if (self.classList) self.classList.add(className);
    else self.className += ' ' + className;
  }

  function removeClass(className, self) {
    if (self.classList) self.classList.remove(className);
    else
      self.className = self.className
        .replace(
        new RegExp('(^|\\b)' +
          className
            .split(' ')
            .join('|') +
          '(\\b|$)', 'gi'),
        ' ');
  }

  // Same as jQuery(el).html() ; gets html of domNode
  function getHTML(domNode) {
    return domNode.innerHTML
  }
  // Same as jQuery(el).html(html) ; sets html of domNode
  function setHTML(domNode, html) {
    domNode.innerHTML = html
  }

  // Scroll window to (x,y)
  function scroll(x, y) {
    window.scrollTo(x, y);
  }

  function goToTop() {
    scroll(0, 0);
  }

  /* Emojis */
  var emojiCodes = {

    ':بوس': '😘',

    ':عشق': '😍',

    ':سوال': '🤔',

    ':آغوش': '🤗',

    ':خنده': '😂',

    ':لبخند': '😊',

    ':پوکرفیس': '😐',

    ':چشمک': '😉',

    ':دی': '😁',

    ':پی': '😋',

  }

  function replaceAllCodesWithEmojis(txt) {
    var codes = Object.keys(emojiCodes)

    codes.forEach(function (code) {
      console.info('replacing ' + code)
      txt = txt.replace(new RegExp(code, 'gi'), emojiCodes[code])
    })

    return txt
  }

  function parseTextForEmojis(domNode) {
    setHTML(domNode, replaceAllCodesWithEmojis(getHTML(domNode)))
  }

})(window, document)
<|endoftext|>


<commit_before>var Chennai = function() {
    var self = this;

    this.displayAndGetMap = function(el) {
        return new google.maps.Map(el, {zoom: 12, center: new google.maps.LatLng(13.0827, 80.2707)});
    }

    this.addDataToMap = function(map, geoJSONString) {
        var geojson = JSON.parse(geoJSONString);
            map.data.addGeoJson(geojson);
    }

    this.styleMap = function(map) {
        map.data.setStyle({
            strokeColor: '#2B70E2',
            strokeWeight: 3
        });

        map.data.addListener('mouseover', function(event) {
            map.data.revertStyle();
            map.data.overrideStyle(event.feature, {strokeColor: 'red'});
        });
    }

    this.render = function() {
        var self = this;
        var map = self.displayAndGetMap(document.getElementById("map"));
        var geoJSONUrl = "/chennai-flooded-streets-Dec2.geojson";

        $.ajax({
            url: geoJSONUrl,
        }).done(function(geoJSONString) {
            self.addDataToMap(map, geoJSONString);
        });

        self.styleMap(map);

            var input = document.getElementById('place-input');
            var searchBox = new google.maps.places.SearchBox(input);
            map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

    }

    this.render();
}<commit_msg>Pointed the url to data/ for the geojson file<commit_after>var Chennai = function() {
    var self = this;

    this.displayAndGetMap = function(el) {
        return new google.maps.Map(el, {zoom: 12, center: new google.maps.LatLng(13.0827, 80.2707)});
    }

    this.addDataToMap = function(map, geoJSONString) {
        var geojson = JSON.parse(geoJSONString);
            map.data.addGeoJson(geojson);
    }

    this.styleMap = function(map) {
        map.data.setStyle({
            strokeColor: '#2B70E2',
            strokeWeight: 3
        });

        map.data.addListener('mouseover', function(event) {
            map.data.revertStyle();
            map.data.overrideStyle(event.feature, {strokeColor: 'red'});
        });
    }

    this.render = function() {
        var self = this;
        var map = self.displayAndGetMap(document.getElementById("map"));
        var geoJSONUrl = "/data/chennai-flooded-streets-Dec2.geojson";

        $.ajax({
            url: geoJSONUrl,
        }).done(function(geoJSONString) {
            self.addDataToMap(map, geoJSONString);
        });

        self.styleMap(map);

            var input = document.getElementById('place-input');
            var searchBox = new google.maps.places.SearchBox(input);
            map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

    }

    this.render();
}<|endoftext|>


<commit_before>import 'babel-polyfill'
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import store from './app/store'
import Forecast from './app/Forecast'
import Root from './app/Root'

/* render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
) */

render(
  <Root store={store} />,
    document.getElementById('root')
)
<commit_msg>Add code cleaning for push<commit_after>import 'babel-polyfill'
import React from 'react'
import { render } from 'react-dom'
// import { Provider } from 'react-redux'
import store from './app/store'
// import Forecast from './app/Forecast'
import Root from './app/Root'

/* render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
) */

render(
  <Root store={store} />,
    document.getElementById('root')
)
<|endoftext|>