<commit_before>'use strict';
const keycode = require('keycode');
const util = require('./util');
const Packets = require('beam-interactive-node/dist/robot/packets').default;
const nodeUtil = require('util');
const EventEmitter = require('events').EventEmitter;

function ControlsProcessor(config) {
	this.config = config;

	this.joyStickConsensus = require(`./consensus/mouse/${config.joyStickConsensus}`);
	this.screenConsensus = require(`./consensus/screen/democracy.js`);
	this.consensus = require(`./consensus/keyboard/${config.consensus}`);

	this.handler = require(`./handlers/robot-js.js`);
	this.windowHandler = null;
	this.mouseHandler = null;

	if (this.config.mouseEnabled) {
		this.mouseHandler = require('./handlers/mouse/robot-js');
		if (this.config.windowTarget) {
			this.windowHandler = require('./handlers/window/robot-js');
			this.constrainWindow(this.config.windowTarget);
		}
	}
	EventEmitter.call(this);
}

nodeUtil.inherits(ControlsProcessor, EventEmitter);

ControlsProcessor.prototype.constrainWindow = function (title) {
	if (this.windowHandler !== null) {
		const details = this.windowHandler.getWindowInfo(title);
		if (details) {
			this.mouseHandler.constrainToWindow(details);
		}
	}
};

/**
 * Given a Key name "W" or a keycode 87 transform that key using the
 * remapping table from the config.
 * @param  {Number|String} code
 * @return {String} the keyname of the remapped key
 */
ControlsProcessor.prototype.remapKey = function (code) {
	let stringCode;
	if (typeof code === 'number') {
		stringCode = keycode(code).toUpperCase();
	} else {
		stringCode = code;
	}

	if (this.config.remap[stringCode]) {
		return this.config.remap[stringCode].toLowerCase();
	}
	return code;
};

ControlsProcessor.prototype.clearAllKeys = function () {
	// this.setKeys(Object.keys(map), false, config.remap);
};

ControlsProcessor.prototype.process = function (report, controlState) {
	const result = {
		state: 'default',
		tactile: [],
		joystick: []
	};
	if (report.screen && report.screen.length > 0) {
		result.screen = report.screen.map(screen => this.processScreen(controlState, report.users, screen))
		.filter(value => value !== undefined);
	}
	if (report.tactile && report.tactile.length > 0) {
		result.tactile = report.tactile.map(tactile => this.processTactile(controlState, report.users, tactile))
		.filter(value => value !== undefined);
	}
	if (report.joystick && report.joystick.length > 0) {
		result.joystick = report.joystick.map(joystick => this.processJoyStick(controlState, report.users, joystick))
		.filter(value => value !== undefined);
	}
	if (result.tactile.length > 0 || result.joystick.length > 0) {
		this.emit('changed', report, controlState);
	}
	return result;
};
ControlsProcessor.prototype.processTactile = function (controlState, users, tactileState) {
	const control = controlState.getTactileById(tactileState.id);
	let decision = this.consensus(tactileState, users, this.config);
	let changed = false;
	decision = this.checkBlocks(tactileState, decision, controlState);
	if (!decision || decision.action === null) {
		return undefined;
	}
	if (control.action !== decision.action) {
		changed = true;
		if (control.isMouseClick()) {
			this.handleClick(control.label.toLowerCase(), decision.action);
		} else {
			this.setKey(control.name, decision.action);
		}
		control.action = decision.action;

		if (control.action) {
			decision.cooldown = control.cooldown;
		} else {
			decision.cooldown = 0;
		}
	}
	if (decision.progress !== control.progress || changed) {
		changed = true;
		control.progress = decision.progress;
	}

	// Here we only send a progress update if something has changed. be it the progress
	if (changed) {
		return this.createProgressForKey(control, decision);
	}
	return undefined;
};

ControlsProcessor.prototype.processScreen = function (controlState, users, screenState) {
	if (!this.config.mouseEnabled || this.config.mouseSource !== 'screen') {
		return undefined;
	}
	const control = screenState;
	const result = this.screenConsensus(screenState, users, this.config, controlState);
	if (result) {
		this.mouseHandler.relativeConstrainedMove(result.x, result.y);
		return this.createProgressForScreen(control, result);
	}
};

ControlsProcessor.prototype.processJoyStick = function (controlState, users, joyStickState) {
	if (!this.config.mouseEnabled || this.config.mouseSource !== 'joystick') {
		return undefined;
	}
	const control = controlState.getJoyStickById(joyStickState.id);
	const result = this.joyStickConsensus(joyStickState, users, this.config, controlState);
	if (result) {
		// this.mouseHandler.moveTo(result.x, result.y);
		return this.createProgressForJoyStick(control, result);
	}
};

/**
 * Given a tactile state, an in progress decision and a set of 2 paired keys
 * Block the current key from being pushed if its paired key is down.
 * @param  {Object} keyState State to check
 * @param  {Object} decision Decision in progress
 * @param  {String} a        The first key in the pair, the one to block
 * @param  {String} b        The second key in the pair, the one to check for
 * @return {Object}          The updated decision
 */
ControlsProcessor.prototype.checkBlock = function (stateA, stateB, decision) {
	if (stateB && stateB.action) {
		decision.action = false;
		decision.progress = 0;
	}
	return decision;
};

/**
 * Give a tactile state loop through the blocks as defined in the config,
 * working out if this current decision should be blocked
 * @param  {Object} keyState State to check
 * @param  {Object} decision Current decision in progress
 * @return {Object}
 */
ControlsProcessor.prototype.checkBlocks = function (keyState, decision, state) {
	Object.keys(this.config.blocks).forEach(blockA => {
		if (keyState.label.toLowerCase() !== blockA.toLowerCase()) {
			return;
		}
		decision = this.checkBlock(keyState, state.getTactileByLabel(this.config.blocks[blockA]), decision);
	});
	return decision;
};
/**
 * Given a key name set it to the apropriate status
 * @param {String} keyName The key name, "W" and not 87
 * @param {Boolean} status  true to push the key, false to release
 */
ControlsProcessor.prototype.setKey = function (keyName, status) {
	// Beam reports back keycodes, convert them to keynames, which our handlers accept
	if (typeof keyName === 'number') {
		console.log('warning setting by number');
		keyName = keycode(keyName);
	}

	// Something in remapping or handling sometimes makes this undefined
	// It causes an error to proceed so we'll stop here
	if (!keyName) {
		return;
	}

	if (status) {
		this.handler.press(keyName.toUpperCase());
	} else {
		this.handler.release(keyName.toUpperCase());
	}
};

ControlsProcessor.prototype.handleClick = function (button, action) {
	if (button.search('left') !== -1) {
		//this.mouseHandler.leftClick();
		this.mouseHandler.leftHold(action);
		return;
	}
	if (button.search('right') !== -1) {
		//this.mouseHandler.rightClick();
		this.mouseHandler.rightHold(action);
		return;
	}
};

/**
 * Given a tactile from a Tetris report, generate a ProgressUpdate packet
 * to be sent back to Tetris
 * @param  {Object} keyObj The tactile from the report
 * @param  {Object} result The decision from the decision maker process
 * @return {Object}        The tactile progress update to be sent back to tetris
 */
ControlsProcessor.prototype.createProgressForKey = function (keyObj, result) {
	return new Packets.ProgressUpdate.TactileUpdate({
		id: keyObj.id,
		cooldown: keyObj.cooldown,
		fired: result.action,
		progress: result.progress
	});
};

ControlsProcessor.prototype.createProgressForJoyStick = function (state, result) {
	if (result) {
		return new Packets.ProgressUpdate.JoystickUpdate({
			id: state.id,
			angle: result.angle,
			intensity: result.intensity
		});
	}
};

ControlsProcessor.prototype.createProgressForScreen = function (state, result) {

};

ControlsProcessor.prototype.constrainMouse = function (mouseBounds) {
	this.mouseHandler.constrainMouse(mouseBounds);
};

ControlsProcessor.prototype.clearKeys = function (keysToClear) {
	util.convertToArray(keysToClear)
	.forEach(tactile => {
		if (tactile.action) {
			tactile.clear();
			this.setKey(tactile.name, false);
		}
	});
};

module.exports = ControlsProcessor;
<commit_msg>Or draw<commit_after>'use strict';
const keycode = require('keycode');
const util = require('./util');
const Packets = require('beam-interactive-node/dist/robot/packets').default;
const nodeUtil = require('util');
const EventEmitter = require('events').EventEmitter;

function ControlsProcessor(config) {
	this.config = config;

	this.joyStickConsensus = require(`./consensus/mouse/${config.joyStickConsensus}`);
	this.screenConsensus = require(`./consensus/screen/democracy.js`);
	this.consensus = require(`./consensus/keyboard/${config.consensus}`);

	this.handler = require(`./handlers/robot-js.js`);
	this.windowHandler = null;
	this.mouseHandler = null;

	if (this.config.mouseEnabled) {
		this.mouseHandler = require('./handlers/mouse/robot-js');
		if (this.config.windowTarget) {
			this.windowHandler = require('./handlers/window/robot-js');
			this.constrainWindow(this.config.windowTarget);
		}
	}
	EventEmitter.call(this);
}

nodeUtil.inherits(ControlsProcessor, EventEmitter);

ControlsProcessor.prototype.constrainWindow = function (title) {
	if (this.windowHandler !== null) {
		const details = this.windowHandler.getWindowInfo(title);
		if (details) {
			this.mouseHandler.constrainToWindow(details);
		}
	}
};

/**
 * Given a Key name "W" or a keycode 87 transform that key using the
 * remapping table from the config.
 * @param  {Number|String} code
 * @return {String} the keyname of the remapped key
 */
ControlsProcessor.prototype.remapKey = function (code) {
	let stringCode;
	if (typeof code === 'number') {
		stringCode = keycode(code).toUpperCase();
	} else {
		stringCode = code;
	}

	if (this.config.remap[stringCode]) {
		return this.config.remap[stringCode].toLowerCase();
	}
	return code;
};

ControlsProcessor.prototype.clearAllKeys = function () {
	// this.setKeys(Object.keys(map), false, config.remap);
};

ControlsProcessor.prototype.process = function (report, controlState) {
	const result = {
		state: 'default',
		tactile: [],
		joystick: []
	};
	if (report.screen && report.screen.length > 0) {
		result.screen = report.screen.map(screen => this.processScreen(controlState, report.users, screen))
		.filter(value => value !== undefined);
	}
	if (report.tactile && report.tactile.length > 0) {
		result.tactile = report.tactile.map(tactile => this.processTactile(controlState, report.users, tactile))
		.filter(value => value !== undefined);
	}
	if (report.joystick && report.joystick.length > 0) {
		result.joystick = report.joystick.map(joystick => this.processJoyStick(controlState, report.users, joystick))
		.filter(value => value !== undefined);
	}
	if (result.tactile.length > 0 || result.joystick.length > 0) {
		this.emit('changed', report, controlState);
	}
	return result;
};
ControlsProcessor.prototype.processTactile = function (controlState, users, tactileState) {
	const control = controlState.getTactileById(tactileState.id);
	let decision = this.consensus(tactileState, users, this.config);
	let changed = false;
	decision = this.checkBlocks(tactileState, decision, controlState);
	if (!decision || decision.action === null) {
		return undefined;
	}
	if (control.action !== decision.action) {
		changed = true;
		if (control.isMouseClick()) {
			this.handleClick(control.label.toLowerCase(), decision.action);
		} else {
			this.setKey(control.name, decision.action);
		}
		control.action = decision.action;

		if (control.action) {
			decision.cooldown = control.cooldown;
		} else {
			decision.cooldown = 0;
		}
	}
	if (decision.progress !== control.progress || changed) {
		changed = true;
		control.progress = decision.progress;
	}

	// Here we only send a progress update if something has changed. be it the progress
	if (changed) {
		return this.createProgressForKey(control, decision);
	}
	return undefined;
};

ControlsProcessor.prototype.processScreen = function (controlState, users, screenState) {
	if (!this.config.mouseEnabled || this.config.mouseSource !== 'screen') {
		return undefined;
	}
	const control = screenState;
	const result = this.screenConsensus(screenState, users, this.config, controlState);
	if (result) {
		this.mouseHandler.relativeConstrainedMove(result.x, result.y);
		return this.createProgressForScreen(control, result);
	}
};

ControlsProcessor.prototype.processJoyStick = function (controlState, users, joyStickState) {
	if (!this.config.mouseEnabled || this.config.mouseSource !== 'joystick') {
		return undefined;
	}
	const control = controlState.getJoyStickById(joyStickState.id);
	const result = this.joyStickConsensus(joyStickState, users, this.config, controlState);
	if (result) {
		// this.mouseHandler.moveTo(result.x, result.y);
		return this.createProgressForJoyStick(control, result);
	}
};

/**
 * Given a tactile state, an in progress decision and a set of 2 paired keys
 * Block the current key from being pushed if its paired key is down.
 * @param  {Object} keyState State to check
 * @param  {Object} decision Decision in progress
 * @param  {String} a        The first key in the pair, the one to block
 * @param  {String} b        The second key in the pair, the one to check for
 * @return {Object}          The updated decision
 */
ControlsProcessor.prototype.checkBlock = function (stateA, stateB, decision) {
	if (stateB && stateB.action) {
		decision.action = false;
		decision.progress = 0;
	}
	return decision;
};

/**
 * Give a tactile state loop through the blocks as defined in the config,
 * working out if this current decision should be blocked
 * @param  {Object} keyState State to check
 * @param  {Object} decision Current decision in progress
 * @return {Object}
 */
ControlsProcessor.prototype.checkBlocks = function (keyState, decision, state) {
	Object.keys(this.config.blocks).forEach(blockA => {
		if (keyState.label.toLowerCase() !== blockA.toLowerCase()) {
			return;
		}
		decision = this.checkBlock(keyState, state.getTactileByLabel(this.config.blocks[blockA]), decision);
	});
	return decision;
};
/**
 * Given a key name set it to the apropriate status
 * @param {String} keyName The key name, "W" and not 87
 * @param {Boolean} status  true to push the key, false to release
 */
ControlsProcessor.prototype.setKey = function (keyName, status) {
	// Beam reports back keycodes, convert them to keynames, which our handlers accept
	if (typeof keyName === 'number') {
		console.log('warning setting by number');
		keyName = keycode(keyName);
	}

	// Something in remapping or handling sometimes makes this undefined
	// It causes an error to proceed so we'll stop here
	if (!keyName) {
		return;
	}

	if (status) {
		this.handler.press(keyName.toUpperCase());
	} else {
		this.handler.release(keyName.toUpperCase());
	}
};

ControlsProcessor.prototype.handleClick = function (button, action) {
	if (button.search('left') !== -1 || button.search('draw') !== -1) {
		//this.mouseHandler.leftClick();
		this.mouseHandler.leftHold(action);
		return;
	}
	if (button.search('right') !== -1) {
		//this.mouseHandler.rightClick();
		this.mouseHandler.rightHold(action);
		return;
	}
};

/**
 * Given a tactile from a Tetris report, generate a ProgressUpdate packet
 * to be sent back to Tetris
 * @param  {Object} keyObj The tactile from the report
 * @param  {Object} result The decision from the decision maker process
 * @return {Object}        The tactile progress update to be sent back to tetris
 */
ControlsProcessor.prototype.createProgressForKey = function (keyObj, result) {
	return new Packets.ProgressUpdate.TactileUpdate({
		id: keyObj.id,
		cooldown: keyObj.cooldown,
		fired: result.action,
		progress: result.progress
	});
};

ControlsProcessor.prototype.createProgressForJoyStick = function (state, result) {
	if (result) {
		return new Packets.ProgressUpdate.JoystickUpdate({
			id: state.id,
			angle: result.angle,
			intensity: result.intensity
		});
	}
};

ControlsProcessor.prototype.createProgressForScreen = function (state, result) {

};

ControlsProcessor.prototype.constrainMouse = function (mouseBounds) {
	this.mouseHandler.constrainMouse(mouseBounds);
};

ControlsProcessor.prototype.clearKeys = function (keysToClear) {
	util.convertToArray(keysToClear)
	.forEach(tactile => {
		if (tactile.action) {
			tactile.clear();
			this.setKey(tactile.name, false);
		}
	});
};

module.exports = ControlsProcessor;
<|endoftext|>


<commit_before>import React from 'react';
import { Header, Feed, Divider, Label } from 'semantic-ui-react';
import { capitalize, toLower } from 'lodash/string';

const { ipcRenderer, remote } = require('electron');

const config = remote.getGlobal('config');

class Logs extends React.Component {
  constructor() {
    super();
    this.state = { entries: [] };
  }

  componentDidMount() {
    ipcRenderer.on('logupdated', (event, message) => {
      this.update(message);
    });
    this.setState({ entries: ipcRenderer.sendSync('logGetEntries') });
  }

  componentWillUnmount() {
    ipcRenderer.removeAllListeners('logupdated');
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (this.state.entries.length === nextState.entries.length) {
      return false;
    }

    return true;
  }

  update(entries) {
    this.setState({ entries });
  }

  labelColor(logType) {
    switch (toLower(logType)) {
      case 'info':
        return 'blue';
      case 'success':
        return 'green';
      case 'warning':
        return 'yellow';
      case 'error':
        return 'red';
      case 'debug':
        return 'black';
      default:
        return 'grey';
    }
  }

  render() {
    const LogEntries = this.state.entries.map(entry => {
      if (entry.type !== 'debug' || config.Config.App.debug) {
        return (
          <Feed key={entry.id} className="log" size="small">
            <Feed.Event>
              <Feed.Content>
                <Feed.Summary>

                    {capitalize(entry.type)}

                  {capitalize(entry.source)} {entry.name ? ` - ${entry.name}` : ''} <Feed.Date>{entry.date}</Feed.Date>
                </Feed.Summary>
                <Feed.Extra>

                </Feed.Extra>
              </Feed.Content>
            </Feed.Event>
            <Divider />
          </Feed>
        );
      }
    });

    return (

        Logs
        {LogEntries}

    );
  }
}

module.exports = Logs;
<commit_msg>Fixed error with new maximum logs setting, resolves #223<commit_after>import React from 'react';
import { Header, Feed, Divider, Label } from 'semantic-ui-react';
import { capitalize, toLower } from 'lodash/string';

const { ipcRenderer, remote } = require('electron');

const config = remote.getGlobal('config');

class Logs extends React.Component {
  constructor() {
    super();
    this.state = { entries: [] };
  }

  componentDidMount() {
    ipcRenderer.on('logupdated', (event, message) => {
      this.update(message);
    });
    this.setState({ entries: ipcRenderer.sendSync('logGetEntries') });
  }

  componentWillUnmount() {
    ipcRenderer.removeAllListeners('logupdated');
  }

  update(entries) {
    this.setState({ entries });
  }

  labelColor(logType) {
    switch (toLower(logType)) {
      case 'info':
        return 'blue';
      case 'success':
        return 'green';
      case 'warning':
        return 'yellow';
      case 'error':
        return 'red';
      case 'debug':
        return 'black';
      default:
        return 'grey';
    }
  }

  render() {
    const LogEntries = this.state.entries.map(entry => {
      if (entry.type !== 'debug' || config.Config.App.debug) {
        return (
          <Feed key={entry.id} className="log" size="small">
            <Feed.Event>
              <Feed.Content>
                <Feed.Summary>

                    {capitalize(entry.type)}

                  {capitalize(entry.source)} {entry.name ? ` - ${entry.name}` : ''} <Feed.Date>{entry.date}</Feed.Date>
                </Feed.Summary>
                <Feed.Extra>

                </Feed.Extra>
              </Feed.Content>
            </Feed.Event>
            <Divider />
          </Feed>
        );
      }
    });

    return (

        Logs
        {LogEntries}

    );
  }
}

module.exports = Logs;
<|endoftext|>


<commit_before>var remark = require('remark');
var visit = require('unist-util-visit');
var remove = require('unist-util-remove');
var program = require('commander');
var fs = require('fs');

function spliterator(code_out) {
  // Our Remark "plugin".
  return function () {
    return function(ast, file) {
      visit(ast, 'code', function (node) {
        code_out.push(node.value);
        remove(ast, node);
      });
    };
  };
}

// Construct the plugin. We'll accumulate the code into `code_chunks` while
// stripping it out of the AST.
var code_chunks = [];
var plugin = spliterator(code_chunks);

program
  .option('-m --markdown <file>', 'markdown output file')
  .option('-c --code <file>', 'code output file')
  .parse(process.argv);

// Process the document.
var processor = remark().use(plugin);
var markdown = processor.process('hello\nfoo\n\n    bar\n\nbaz *qux*');
var code = code_chunks.join('\n') + '\n';

// Output Markdown.
if (program.markdown) {
  fs.writeFile(program.markdown, markdown);
}

// Output extracted code.
if (program.code) {
  fs.writeFile(program.code, code);
}

// If neither is specified, just dump the code to stdout.
if (!program.markdown && !program.code) {
  process.stdout.write(code);
}
<commit_msg>Read input Markdown from a file<commit_after>var remark = require('remark');
var visit = require('unist-util-visit');
var remove = require('unist-util-remove');
var program = require('commander');
var fs = require('fs');

function spliterator(code_out) {
  // Our Remark "plugin".
  return function () {
    return function(ast, file) {
      visit(ast, 'code', function (node) {
        code_out.push(node.value);
        remove(ast, node);
      });
    };
  };
}

// Construct the plugin. We'll accumulate the code into `code_chunks` while
// stripping it out of the AST.
var code_chunks = [];
var plugin = spliterator(code_chunks);

program
  .usage('[options] <file>')
  .option('-m --markdown <file>', 'markdown output file')
  .option('-c --code <file>', 'code output file')
  .parse(process.argv);

// Get the input document.
var infile = program.args[0];
if (!infile) {
  program.help();
}

var indoc = fs.readFile(infile, function (err, data) {
  if (err)
    throw err;
  var indoc = data.toString();

  // Process the document.
  var processor = remark().use(plugin);
  var markdown = processor.process(indoc);
  var code = code_chunks.join('\n') + '\n';

  // Output Markdown.
  if (program.markdown) {
    fs.writeFileSync(program.markdown, markdown);
  }

  // Output extracted code.
  if (program.code) {
    fs.writeFileSync(program.code, code);
  }

  // If neither is specified, just dump the code to stdout.
  if (!program.markdown && !program.code) {
    process.stdout.write(code);
  }
});
<|endoftext|>


<commit_before>function WalkontableBorder(instance, settings) {
  //reference to instance
  this.instance = instance;
  this.settings = settings;
  this.wtDom = this.instance.wtDom;

  this.main = document.createElement("div");
  this.main.style.position = 'absolute';
  this.main.style.top = 0;
  this.main.style.left = 0;

  for (var i = 0; i < 5; i++) {
    var DIV = document.createElement('DIV');
    DIV.className = 'wtBorder ' + (settings.className || '');
    DIV.style.backgroundColor = settings.border.color;
    DIV.style.height = settings.border.width + 'px';
    DIV.style.width = settings.border.width + 'px';
    this.main.appendChild(DIV);
  }

  this.top = this.main.childNodes[0];
  this.left = this.main.childNodes[1];
  this.bottom = this.main.childNodes[2];
  this.right = this.main.childNodes[3];

  this.corner = this.main.childNodes[4];
  this.corner.className += ' corner';
  this.corner.style.width = '5px';
  this.corner.style.height = '5px';
  this.corner.style.border = '2px solid #FFF';

  this.disappear();
  instance.wtTable.hider.appendChild(this.main);
}

/**
 * Show border around one or many cells
 * @param {Array} corners
 */
WalkontableBorder.prototype.appear = function (corners) {
  var isMultiple, $from, $to, fromOffset, toOffset, containerOffset, top, minTop, left, minLeft, height, width;
  if (this.disabled) {
    return;
  }

  var offsetRow = this.instance.getSetting('offsetRow')
    , offsetColumn = this.instance.getSetting('offsetColumn')
    , displayRows = this.instance.getSetting('displayRows')
    , displayColumns = this.instance.getSetting('displayColumns');

  var hideTop = false, hideLeft = false, hideBottom = false, hideRight = false;

  if (displayRows !== null) {
    if (corners[0] > offsetRow + displayRows - 1 || corners[2] < offsetRow) {
      hideTop = hideLeft = hideBottom = hideRight = true;
    }
    else {
      if (corners[0] < offsetRow) {
        corners[0] = offsetRow;
        hideTop = true;
      }
      if (corners[2] > offsetRow + displayRows - 1) {
        corners[2] = offsetRow + displayRows - 1;
        hideBottom = true;
      }
    }
  }

  if (displayColumns !== null) {
    if (corners[1] > offsetColumn + displayColumns - 1 || corners[3] < offsetColumn) {
      hideTop = hideLeft = hideBottom = hideRight = true;
    }
    else {
      if (corners[1] < offsetColumn) {
        corners[1] = offsetColumn;
        hideLeft = true;
      }
      if (corners[3] > offsetColumn + displayColumns - 1) {
        corners[3] = offsetColumn + displayColumns - 1;
        hideRight = true;
      }
    }
  }

  if (hideTop + hideLeft + hideBottom + hideRight < 4) { //at least one border is not hidden
    isMultiple = (corners[0] !== corners[2] || corners[1] !== corners[3]);
    $from = $(this.instance.wtTable.getCell([corners[0], corners[1]]));
    $to = isMultiple ? $(this.instance.wtTable.getCell([corners[2], corners[3]])) : $from;
    fromOffset = this.wtDom.offset($from[0]);
    toOffset = isMultiple ? this.wtDom.offset($to[0]) : fromOffset;
    containerOffset = this.wtDom.offset(this.instance.wtTable.TABLE);

    minTop = fromOffset.top;
    height = toOffset.top + $to.outerHeight() - minTop;
    minLeft = fromOffset.left;
    width = toOffset.left + $to.outerWidth() - minLeft;

    top = minTop - containerOffset.top - 1;
    left = minLeft - containerOffset.left - 1;

    if (parseInt($from.css('border-top-width'), 10) > 0) {
      top += 1;
      height -= 1;
    }
    if (parseInt($from.css('border-left-width'), 10) > 0) {
      left += 1;
      width -= 1;
    }
  }

  if (hideTop) {
    this.top.style.display = 'none';
  }
  else {
    this.top.style.top = top + 'px';
    this.top.style.left = left + 'px';
    this.top.style.width = width + 'px';
    this.top.style.display = 'block';
  }

  if (hideLeft) {
    this.left.style.display = 'none';
  }
  else {
    this.left.style.top = top + 'px';
    this.left.style.left = left + 'px';
    this.left.style.height = height + 'px';
    this.left.style.display = 'block';
  }

  var delta = Math.floor(this.settings.border.width / 2);

  if (hideBottom) {
    this.bottom.style.display = 'none';
  }
  else {
    this.bottom.style.top = top + height - delta + 'px';
    this.bottom.style.left = left + 'px';
    this.bottom.style.width = width + 'px';
    this.bottom.style.display = 'block';
  }

  if (hideRight) {
    this.right.style.display = 'none';
  }
  else {
    this.right.style.top = top + 'px';
    this.right.style.left = left + width - delta + 'px';
    this.right.style.height = height + 1 + 'px';
    this.right.style.display = 'block';
  }

  if (hideBottom && hideRight || !this.hasSetting(this.settings.border.cornerVisible)) {
    this.corner.style.display = 'none';
  }
  else {
    this.corner.style.top = top + height - 4 + 'px';
    this.corner.style.left = left + width - 4 + 'px';
    this.corner.style.display = 'block';
  }
};

/**
 * Hide border
 */
WalkontableBorder.prototype.disappear = function () {
  this.top.style.display = 'none';
  this.left.style.display = 'none';
  this.bottom.style.display = 'none';
  this.right.style.display = 'none';
  this.corner.style.display = 'none';
};

WalkontableBorder.prototype.hasSetting = function (setting) {
  if (typeof setting === 'function') {
    return setting();
  }
  return !!setting;
};<commit_msg>bugfix: correct cell border and cell editor positioning after `border-collapse` was changed to `collapse`<commit_after>function WalkontableBorder(instance, settings) {
  //reference to instance
  this.instance = instance;
  this.settings = settings;
  this.wtDom = this.instance.wtDom;

  this.main = document.createElement("div");
  this.main.style.position = 'absolute';
  this.main.style.top = 0;
  this.main.style.left = 0;

  for (var i = 0; i < 5; i++) {
    var DIV = document.createElement('DIV');
    DIV.className = 'wtBorder ' + (settings.className || '');
    DIV.style.backgroundColor = settings.border.color;
    DIV.style.height = settings.border.width + 'px';
    DIV.style.width = settings.border.width + 'px';
    this.main.appendChild(DIV);
  }

  this.top = this.main.childNodes[0];
  this.left = this.main.childNodes[1];
  this.bottom = this.main.childNodes[2];
  this.right = this.main.childNodes[3];

  this.corner = this.main.childNodes[4];
  this.corner.className += ' corner';
  this.corner.style.width = '5px';
  this.corner.style.height = '5px';
  this.corner.style.border = '2px solid #FFF';

  this.disappear();
  instance.wtTable.hider.appendChild(this.main);
}

/**
 * Show border around one or many cells
 * @param {Array} corners
 */
WalkontableBorder.prototype.appear = function (corners) {
  var isMultiple, $from, $to, fromOffset, toOffset, containerOffset, top, minTop, left, minLeft, height, width;
  if (this.disabled) {
    return;
  }

  var offsetRow = this.instance.getSetting('offsetRow')
    , offsetColumn = this.instance.getSetting('offsetColumn')
    , displayRows = this.instance.getSetting('displayRows')
    , displayColumns = this.instance.getSetting('displayColumns');

  var hideTop = false, hideLeft = false, hideBottom = false, hideRight = false;

  if (displayRows !== null) {
    if (corners[0] > offsetRow + displayRows - 1 || corners[2] < offsetRow) {
      hideTop = hideLeft = hideBottom = hideRight = true;
    }
    else {
      if (corners[0] < offsetRow) {
        corners[0] = offsetRow;
        hideTop = true;
      }
      if (corners[2] > offsetRow + displayRows - 1) {
        corners[2] = offsetRow + displayRows - 1;
        hideBottom = true;
      }
    }
  }

  if (displayColumns !== null) {
    if (corners[1] > offsetColumn + displayColumns - 1 || corners[3] < offsetColumn) {
      hideTop = hideLeft = hideBottom = hideRight = true;
    }
    else {
      if (corners[1] < offsetColumn) {
        corners[1] = offsetColumn;
        hideLeft = true;
      }
      if (corners[3] > offsetColumn + displayColumns - 1) {
        corners[3] = offsetColumn + displayColumns - 1;
        hideRight = true;
      }
    }
  }

  if (hideTop + hideLeft + hideBottom + hideRight < 4) { //at least one border is not hidden
    isMultiple = (corners[0] !== corners[2] || corners[1] !== corners[3]);
    $from = $(this.instance.wtTable.getCell([corners[0], corners[1]]));
    $to = isMultiple ? $(this.instance.wtTable.getCell([corners[2], corners[3]])) : $from;
    fromOffset = this.wtDom.offset($from[0]);
    toOffset = isMultiple ? this.wtDom.offset($to[0]) : fromOffset;
    containerOffset = this.wtDom.offset(this.instance.wtTable.TABLE);

    minTop = fromOffset.top;
    height = toOffset.top + $to.outerHeight() - minTop;
    minLeft = fromOffset.left;
    width = toOffset.left + $to.outerWidth() - minLeft;

    top = minTop - containerOffset.top;
    left = minLeft - containerOffset.left;

    if (parseInt($from.css('border-top-width'), 10) > 0) {
      top += 1;
      height -= 1;
    }
    if (parseInt($from.css('border-left-width'), 10) > 0) {
      left += 1;
      width -= 1;
    }
  }

  if (hideTop) {
    this.top.style.display = 'none';
  }
  else {
    this.top.style.top = top + 'px';
    this.top.style.left = left + 'px';
    this.top.style.width = width + 'px';
    this.top.style.display = 'block';
  }

  if (hideLeft) {
    this.left.style.display = 'none';
  }
  else {
    this.left.style.top = top + 'px';
    this.left.style.left = left + 'px';
    this.left.style.height = height + 'px';
    this.left.style.display = 'block';
  }

  var delta = Math.floor(this.settings.border.width / 2);

  if (hideBottom) {
    this.bottom.style.display = 'none';
  }
  else {
    this.bottom.style.top = top + height - delta + 'px';
    this.bottom.style.left = left + 'px';
    this.bottom.style.width = width + 'px';
    this.bottom.style.display = 'block';
  }

  if (hideRight) {
    this.right.style.display = 'none';
  }
  else {
    this.right.style.top = top + 'px';
    this.right.style.left = left + width - delta + 'px';
    this.right.style.height = height + 1 + 'px';
    this.right.style.display = 'block';
  }

  if (hideBottom && hideRight || !this.hasSetting(this.settings.border.cornerVisible)) {
    this.corner.style.display = 'none';
  }
  else {
    this.corner.style.top = top + height - 4 + 'px';
    this.corner.style.left = left + width - 4 + 'px';
    this.corner.style.display = 'block';
  }
};

/**
 * Hide border
 */
WalkontableBorder.prototype.disappear = function () {
  this.top.style.display = 'none';
  this.left.style.display = 'none';
  this.bottom.style.display = 'none';
  this.right.style.display = 'none';
  this.corner.style.display = 'none';
};

WalkontableBorder.prototype.hasSetting = function (setting) {
  if (typeof setting === 'function') {
    return setting();
  }
  return !!setting;
};<|endoftext|>


<commit_before>"use strict";

meta.class("Entity.Particle", "Entity.Geometry",
{
	init: function()
	{
		var max = this.cfg.numMax;

		this.particles = new Array(max);
		for(var n = 0; n < max; n++) {
			this.particles[n] = new this.Particle();
		}

		this._canvas = document.createElement("canvas");
		this._ctx = this._canvas.getContext("2d");
	},

	update: function(tDelta)
	{
		this.elapsed += tDelta;
		if(this.elapsed > this.duration) {
			this.updating = false;
			return;
		}

		if(this.cfg.emissionRate > 0)
		{
			var rate = 1.0 / this.cfg.emissionRate;
			this.emissionCounter += tDelta;

			var num = Math.floor(this.emissionCounter / rate);
			if(num > 0)
			{
				this.emissionCounter -= (num * rate);

				if(num > (this.cfg.numMax - this.numActive)) {
					num = (this.cfg.numMax - this.numActive);
				}

				var newNumActive = this.numActive + num;
				for(var i = this.numActive; i < newNumActive; i++) {
					this.initParticle(this.particles[i]);
				}

				this.numActive = newNumActive;
			}
		}

		var particle;
		for(var n = 0; n < this.numActive; n++)
		{
			particle = this.particles[n];
			particle.life -= tDelta;
			if(particle.life <= 0) {
				this.numActive--;
				this.particles[n] = this.particles[this.numActive];
				this.particles[this.numActive] = particle;
				continue;
			}

			this.updateParticle(particle, tDelta);
		}

		this.renderer.needRender =  true;
	},

	initParticle: function(particle)
	{
		particle.x = meta.random.numberF(-1, 1) * this.cfg.xVar;
		particle.y = meta.random.numberF(-1, 1) * this.cfg.yVar;
		particle.life = this.cfg.life + (meta.random.numberF(-1, 1) * this.cfg.lifeVar);

		var speed = this.cfg.speed + (meta.random.numberF(-1, 1) * this.cfg.speedVar);
		var angle = this.cfg.angle + (meta.random.numberF(-1, 1) * this.cfg.angleVar);
		particle.velX = Math.cos((Math.PI * angle) / 180) * speed;
		particle.vecY = -Math.sin((Math.PI * angle) / 180) * speed;

		particle.radialAccel = this.cfg.radialAccel + (this.cfg.radialAccelVar * meta.random.numberF(-1, 1));
		particle.tangentialAccel = this.cfg.tangentialAccel + (this.cfg.tangentialAccelVar * meta.random.numberF(-1, 1));

		particle.color[0] = this.cfg.startColor[0] + (this.cfg.startColorVar[0] * meta.random.numberF(-1, 1));
		particle.color[1] = this.cfg.startColor[1] + (this.cfg.startColorVar[1] * meta.random.numberF(-1, 1));
		particle.color[2] = this.cfg.startColor[2] + (this.cfg.startColorVar[2] * meta.random.numberF(-1, 1));
		particle.color[3] = this.cfg.startColor[3] + (this.cfg.startColorVar[3] * meta.random.numberF(-1, 1));

		this._endColor[0] = this.cfg.endColor[0] + (this.cfg.endColorVar[0] * meta.random.numberF(-1, 1));
		this._endColor[1] = this.cfg.endColor[1] + (this.cfg.endColorVar[1] * meta.random.numberF(-1, 1));
		this._endColor[2] = this.cfg.endColor[2] + (this.cfg.endColorVar[2] * meta.random.numberF(-1, 1));
		this._endColor[3] = this.cfg.endColor[3] + (this.cfg.endColorVar[3] * meta.random.numberF(-1, 1));

		particle.colorDelta[0] = (this._endColor[0] - this.cfg.startColor[0]) / particle.life;
		particle.colorDelta[1] = (this._endColor[1] - this.cfg.startColor[1]) / particle.life;
		particle.colorDelta[2] = (this._endColor[2] - this.cfg.startColor[2]) / particle.life;
		particle.colorDelta[3] = (this._endColor[3] - this.cfg.startColor[3]) / particle.life;

		particle.scale = this.cfg.scale + (this.cfg.scaleVar * meta.random.numberF(-1, 1));
		var endScale = this.cfg.endScale + (this.cfg.endScaleVar * meta.random.numberF(-1, 1));
		particle.scaleDelta = (endScale - particle.scale) / particle.life;
	},

	updateParticle: function(particle, tDelta)
	{
		particle.forcesX = (this.cfg.gravityX) * tDelta;
		particle.forcesY = (this.cfg.gravityY) * tDelta;
		particle.velX += particle.forcesX;
		particle.vecY += particle.forcesY

		particle.x += particle.velX * tDelta;
		particle.y += particle.vecY * tDelta;

		if(particle.color)
		{
			particle.color[0] += particle.colorDelta[0] * tDelta;
			particle.color[1] += particle.colorDelta[1] * tDelta;
			particle.color[2] += particle.colorDelta[2] * tDelta;
			particle.color[3] += particle.colorDelta[3] * tDelta;
		}

		particle.scale += this.scaleDelta;
	},

	draw: function(ctx)
	{
		var tDelta = meta.time.deltaF;
		var img = this.texture.canvas;
		var parentX = this.volume.minX;
		var parentY = this.volume.minY;

		var particle, color;
		for(var n = 0; n < this.numActive; n++)
		{
			particle = this.particles[n];
			color = particle.color;

			this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
			this._ctx.globalCompositeOperation = "source-over";
			this._ctx.globalAlpha = color[3];
			this._ctx.drawImage(img, 0, 0);

			this._ctx.globalCompositeOperation = "source-atop";
			this._ctx.fillStyle = "rgba(" +
				(color[0] | 0) + ", " +
				(color[1] | 0) + ", " +
				(color[2] | 0) + ", 1.0)";
// console.log("rgba(" +
// 				(color[0] | 0) + ", " +
// 				(color[1] | 0) + ", " +
// 				(color[2] | 0) + ", 1.0)");
			this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);

			this._ctx.globalCompositeOperation = "source-over";
			this._ctx.globalAlpha = color[3];

			ctx.globalCompositeOperation = 'lighter';
			ctx.drawImage(this._canvas, parentX + particle.x, parentY + particle.y);
		}
	},

	play: function() {
		this.updating = true;
	},

	pause: function() {
		this.updating = false;
	},

	togglePlay: function()
	{
		if(this.updating) {
			this.pause();
		}
		else {
			this.play();
		}
	},

	reset: function()
	{

	},

	setTexture: function(texture)
	{
		this._super(texture);

		if(!this.texture)
		{
			if(this._cache.texture) {
				this._svgTexture = new Resource.SVG();
				this._svgTexture.fillStyle = "white";
				this._svgTexture.circle(this.cfg.radius);
			}
			this.texture = this._svgTexture;
		}
	},

	updateFromTexture: function()
	{
		this._super();

		this._canvas.width = this.texture.width;
		this._canvas.height = this.texture.height;
	},

	Particle: function()
	{
		this.life = 0;
		this.x = 0;
		this.y = 0;
		this.velX = 0;
		this.velY = 0;
		this.radialAccel = 0;
		this.tangentialAccel = 0;
		this.forcesX = 0;
		this.forcesY = 0;

		this.color = new Float32Array(4);
		this.colorDelta = new Float32Array(4);
		this.scale = 1;
		this.scaleDelta = 1;
	},

	cfg:
	{
		numMax: 150,
		emissionRate: 75,

		life: 2,
		lifeVar: 1,

		xVar: 0,
		yVar: 0,

		speed: 15,
		speedVar: 5,
		angle: 90,
		angleVar: 360,
		gravityX: -200,
		gravityY: -200,
		radialAccel: 0,
		radialAccelVar: 0,
		tangentialAccel: 0,
		tangentialAccelVar: 0,

		startColor: [ 51, 102, 179, 1 ],
		startColorVar: [ 0, 0, 51, 0.1 ],
		endColor: [ 0, 0, 0, 1 ],
		endColorVar: [ 0, 0, 0, 0 ],
		scale: 1.0,
		scaleVar: 1.0,
		endScale: 1.0,
		endScaleVar: 1.0,

		texture: null,
		radius: 10
	},

	//
	particles: null,

	numActive: 0,

	emissionCounter: 0,
	elapsed: 0,
	duration: Infinity,

	addictive: false,

	_endColor: new Float32Array(4),
	_canvas: null,
	_ctx: null,
	_svgTexture: null
});
<commit_msg>Added Entity.Particle.totalParticles attribute.<commit_after>"use strict";

meta.class("Entity.Particle", "Entity.Geometry",
{
	init: function()
	{
		this.particles = [];
		this.totalParticles = this.cfg.totalParticles;

		this._canvas = document.createElement("canvas");
		this._ctx = this._canvas.getContext("2d");
	},

	update: function(tDelta)
	{
		this.elapsed += tDelta;
		if(this.elapsed > this.duration) {
			this.updating = false;
			return;
		}

		if(this.cfg.emissionRate > 0)
		{
			var rate = 1.0 / this.cfg.emissionRate;
			this.emissionCounter += tDelta;

			var num = Math.floor(this.emissionCounter / rate);
			if(num > 0)
			{
				this.emissionCounter -= (num * rate);

				if(num > (this.cfg.totalParticles - this.numActive)) {
					num = (this.cfg.totalParticles - this.numActive);
				}

				var newNumActive = this.numActive + num;
				for(var i = this.numActive; i < newNumActive; i++) {
					this.initParticle(this.particles[i]);
				}

				this.numActive = newNumActive;
			}
		}

		var particle;
		for(var n = 0; n < this.numActive; n++)
		{
			particle = this.particles[n];
			particle.life -= tDelta;
			if(particle.life <= 0) {
				this.numActive--;
				this.particles[n] = this.particles[this.numActive];
				this.particles[this.numActive] = particle;
				continue;
			}

			this.updateParticle(particle, tDelta);
		}

		this.renderer.needRender =  true;
	},

	initParticle: function(particle)
	{
		particle.x = meta.random.numberF(-1, 1) * this.cfg.xVar;
		particle.y = meta.random.numberF(-1, 1) * this.cfg.yVar;
		particle.life = this.cfg.life + (meta.random.numberF(-1, 1) * this.cfg.lifeVar);

		var speed = this.cfg.speed + (meta.random.numberF(-1, 1) * this.cfg.speedVar);
		var angle = this.cfg.angle + (meta.random.numberF(-1, 1) * this.cfg.angleVar);
		particle.velX = Math.cos((Math.PI * angle) / 180) * speed;
		particle.vecY = -Math.sin((Math.PI * angle) / 180) * speed;

		particle.radialAccel = this.cfg.radialAccel + (this.cfg.radialAccelVar * meta.random.numberF(-1, 1));
		particle.tangentialAccel = this.cfg.tangentialAccel + (this.cfg.tangentialAccelVar * meta.random.numberF(-1, 1));

		particle.color[0] = this.cfg.startColor[0] + (this.cfg.startColorVar[0] * meta.random.numberF(-1, 1));
		particle.color[1] = this.cfg.startColor[1] + (this.cfg.startColorVar[1] * meta.random.numberF(-1, 1));
		particle.color[2] = this.cfg.startColor[2] + (this.cfg.startColorVar[2] * meta.random.numberF(-1, 1));
		particle.color[3] = this.cfg.startColor[3] + (this.cfg.startColorVar[3] * meta.random.numberF(-1, 1));

		this._endColor[0] = this.cfg.endColor[0] + (this.cfg.endColorVar[0] * meta.random.numberF(-1, 1));
		this._endColor[1] = this.cfg.endColor[1] + (this.cfg.endColorVar[1] * meta.random.numberF(-1, 1));
		this._endColor[2] = this.cfg.endColor[2] + (this.cfg.endColorVar[2] * meta.random.numberF(-1, 1));
		this._endColor[3] = this.cfg.endColor[3] + (this.cfg.endColorVar[3] * meta.random.numberF(-1, 1));

		particle.colorDelta[0] = (this._endColor[0] - this.cfg.startColor[0]) / particle.life;
		particle.colorDelta[1] = (this._endColor[1] - this.cfg.startColor[1]) / particle.life;
		particle.colorDelta[2] = (this._endColor[2] - this.cfg.startColor[2]) / particle.life;
		particle.colorDelta[3] = (this._endColor[3] - this.cfg.startColor[3]) / particle.life;

		particle.scale = this.cfg.scale + (this.cfg.scaleVar * meta.random.numberF(-1, 1));
		var endScale = this.cfg.endScale + (this.cfg.endScaleVar * meta.random.numberF(-1, 1));
		particle.scaleDelta = (endScale - particle.scale) / particle.life;
	},

	updateParticle: function(particle, tDelta)
	{
		particle.forcesX = (this.cfg.gravityX) * tDelta;
		particle.forcesY = (this.cfg.gravityY) * tDelta;
		particle.velX += particle.forcesX;
		particle.vecY += particle.forcesY

		particle.x += particle.velX * tDelta;
		particle.y += particle.vecY * tDelta;

		if(particle.color)
		{
			particle.color[0] += particle.colorDelta[0] * tDelta;
			particle.color[1] += particle.colorDelta[1] * tDelta;
			particle.color[2] += particle.colorDelta[2] * tDelta;
			particle.color[3] += particle.colorDelta[3] * tDelta;
		}

		particle.scale += this.scaleDelta;
	},

	draw: function(ctx)
	{
		var tDelta = meta.time.deltaF;
		var img = this.texture.canvas;
		var parentX = this.volume.minX;
		var parentY = this.volume.minY;

		var particle, color;
		for(var n = 0; n < this.numActive; n++)
		{
			particle = this.particles[n];
			color = particle.color;

			this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);
			this._ctx.globalCompositeOperation = "source-over";
			this._ctx.globalAlpha = color[3];
			this._ctx.drawImage(img, 0, 0);

			this._ctx.globalCompositeOperation = "source-atop";
			this._ctx.fillStyle = "rgba(" +
				(color[0] | 0) + ", " +
				(color[1] | 0) + ", " +
				(color[2] | 0) + ", 1.0)";
// console.log("rgba(" +
// 				(color[0] | 0) + ", " +
// 				(color[1] | 0) + ", " +
// 				(color[2] | 0) + ", 1.0)");
			this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);

			this._ctx.globalCompositeOperation = "source-over";
			this._ctx.globalAlpha = color[3];

			ctx.globalCompositeOperation = 'lighter';
			ctx.drawImage(this._canvas, parentX + particle.x, parentY + particle.y);
		}
	},

	play: function() {
		this.updating = true;
	},

	pause: function() {
		this.updating = false;
	},

	togglePlay: function()
	{
		if(this.updating) {
			this.pause();
		}
		else {
			this.play();
		}
	},

	reset: function()
	{

	},

	setTexture: function(texture)
	{
		this._super(texture);

		if(!this.texture)
		{
			if(this._cache.texture) {
				this._svgTexture = new Resource.SVG();
				this._svgTexture.fillStyle = "white";
				this._svgTexture.circle(this.cfg.radius);
			}
			this.texture = this._svgTexture;
		}
	},

	updateFromTexture: function()
	{
		this._super();

		this._canvas.width = this.texture.width;
		this._canvas.height = this.texture.height;
	},

	set totalParticles(value)
	{
		var num = this.particles.length;
		this.particles.length = value;
		this.cfg.totalParticles = value;

		for(var n = num; n < value; n++) {
			this.particles[n] = new this.Particle();
		}

		if(this.numActive > value) {
			this.numActive = value;
		}
	},

	get totalParticles() {
		return this.cfg.totalParticles;
	},

	Particle: function()
	{
		this.life = 0;
		this.x = 0;
		this.y = 0;
		this.velX = 0;
		this.velY = 0;
		this.radialAccel = 0;
		this.tangentialAccel = 0;
		this.forcesX = 0;
		this.forcesY = 0;

		this.color = new Float32Array(4);
		this.colorDelta = new Float32Array(4);
		this.scale = 1;
		this.scaleDelta = 1;
	},

	cfg:
	{
		totalParticles: 150,
		emissionRate: 75,

		life: 2,
		lifeVar: 1,

		xVar: 0,
		yVar: 0,

		speed: 15,
		speedVar: 5,
		angle: 90,
		angleVar: 360,
		gravityX: -200,
		gravityY: -200,
		radialAccel: 0,
		radialAccelVar: 0,
		tangentialAccel: 0,
		tangentialAccelVar: 0,

		startColor: [ 51, 102, 179, 1 ],
		startColorVar: [ 0, 0, 51, 0.1 ],
		endColor: [ 0, 0, 0, 1 ],
		endColorVar: [ 0, 0, 0, 0 ],
		scale: 1.0,
		scaleVar: 1.0,
		endScale: 1.0,
		endScaleVar: 1.0,

		texture: null,
		radius: 10
	},

	//
	particles: null,

	numActive: 0,

	emissionCounter: 0,
	elapsed: 0,
	duration: Infinity,

	addictive: false,

	_endColor: new Float32Array(4),
	_canvas: null,
	_ctx: null,
	_svgTexture: null
});
<|endoftext|>


<commit_before>/* @flow strict-local */
// import { Vibration } from 'react-native';

import type { GeneralEvent, GlobalState, MessageEvent } from '../types';
import { isHomeNarrow, isMessageInNarrow } from '../utils/narrow';
import { getActiveAccount, getChatScreenParams, getOwnEmail, getIsActive } from '../selectors';
import { playMessageSound } from '../utils/sound';
import { NULL_ARRAY } from '../nullObjects';

/**
 * React to incoming `MessageEvent`s.
 *
 * Beware: this function modifies its `event` argument, and has other side
 * effects besides!
 */
const messageEvent = (state: GlobalState, event: MessageEvent): void => {
  // Move `flags` key from `event` to `event.message` for consistency, and
  // default to an empty array if `event.flags` is not set.
  const flags = event.message.flags ?? event.flags ?? NULL_ARRAY;
  if (!event.message.flags) {
    // $FlowFixMe: Message is readonly to serve our use of it in Redux.
    event.message.flags = flags;
    delete event.flags;
  }

  const isActive = getIsActive(state);
  if (!isActive) {
    return;
  }

  const isPrivateMessage = Array.isArray(event.message.display_recipient);
  const isMentioned = flags.includes('mentioned') || flags.includes('wildcard_mentioned');
  if (!(isPrivateMessage || isMentioned)) {
    return;
  }

  const activeAccount = getActiveAccount(state);
  const { narrow } = getChatScreenParams(state);
  const isUserInSameNarrow =
    activeAccount
    && (narrow !== undefined // chat screen is not at top
      && (!isHomeNarrow(narrow) && isMessageInNarrow(event.message, narrow, activeAccount.email)));
  const isSenderSelf = getOwnEmail(state) === event.message.sender_email;
  if (!isUserInSameNarrow && !isSenderSelf) {
    playMessageSound();
    // Vibration.vibrate();
  }
};

/**
 * React to, and possibly normalize, incoming Zulip server events (from
 * `/events` polling).
 */
export default (state: GlobalState, event_: GeneralEvent) => {
  switch (event_.type) {
    case 'message': {
      // $FlowFixMe This expresses our unchecked assumptions about `message` events.
      messageEvent(state, (event_: MessageEvent));
      break;
    }
    default:
  }
};
<commit_msg>eventMiddleware: Reduce raciness of app-activity test.<commit_after>/* @flow strict-local */
// import { Vibration } from 'react-native';

import { AppState } from 'react-native';
import type { GeneralEvent, GlobalState, MessageEvent } from '../types';
import { isHomeNarrow, isMessageInNarrow } from '../utils/narrow';
import { getActiveAccount, getChatScreenParams, getOwnEmail } from '../selectors';
import { playMessageSound } from '../utils/sound';
import { NULL_ARRAY } from '../nullObjects';

/**
 * React to incoming `MessageEvent`s.
 *
 * Beware: this function modifies its `event` argument, and has other side
 * effects besides!
 */
const messageEvent = (state: GlobalState, event: MessageEvent): void => {
  // Move `flags` key from `event` to `event.message` for consistency, and
  // default to an empty array if `event.flags` is not set.
  const flags = event.message.flags ?? event.flags ?? NULL_ARRAY;
  if (!event.message.flags) {
    // $FlowFixMe: Message is readonly to serve our use of it in Redux.
    event.message.flags = flags;
    delete event.flags;
  }

  if (AppState.currentState !== 'active') {
    return;
  }

  const isPrivateMessage = Array.isArray(event.message.display_recipient);
  const isMentioned = flags.includes('mentioned') || flags.includes('wildcard_mentioned');
  if (!(isPrivateMessage || isMentioned)) {
    return;
  }

  const activeAccount = getActiveAccount(state);
  const { narrow } = getChatScreenParams(state);
  const isUserInSameNarrow =
    activeAccount
    && (narrow !== undefined // chat screen is not at top
      && (!isHomeNarrow(narrow) && isMessageInNarrow(event.message, narrow, activeAccount.email)));
  const isSenderSelf = getOwnEmail(state) === event.message.sender_email;
  if (!isUserInSameNarrow && !isSenderSelf) {
    playMessageSound();
    // Vibration.vibrate();
  }
};

/**
 * React to, and possibly normalize, incoming Zulip server events (from
 * `/events` polling).
 */
export default (state: GlobalState, event_: GeneralEvent) => {
  switch (event_.type) {
    case 'message': {
      // $FlowFixMe This expresses our unchecked assumptions about `message` events.
      messageEvent(state, (event_: MessageEvent));
      break;
    }
    default:
  }
};
<|endoftext|>


<commit_before>var url = require("url");
var http = require("http");
var https = require("https");
var ideal = require("ideal");
var oden = module.parent.exports;

oden.HttpClientRequest = ideal.Observable.clone().newSlots({
	type: "oden.HttpClientRequest",

	url: null,
	method: "GET",
	headers: null,
	maxRedirects: 0,
	body: "",

	nodeRequest: null,

	error: null,
	response: null
}).setSlots({
	init: function()
	{
		ideal.Observable.init.call(this);
		this.setUrl(oden.Url.clone());
		this.setHeaders(map({
			Accept: "*/*"
		}));
	},

	setUrlString: function(urlString)
	{
		this.url().setString(urlString);
		return this;
	},

	start: function()
	{
		var self = this;
		var url = this.url();

		var nodeRequest = (url.isHttp() ? http : https).request({
			auth: url.auth(),
			host: url.host(),
			port: url.port(),
			method: this.method(),
			path: url.resource(),
			agent: false,
			headers: this.headers().jsMap()
		});

		nodeRequest.end(this.body());

		nodeRequest.on('response', function(response){
			self.receivedResponse(response);
		});

		nodeRequest.on('error', function(e){
			self.failed(e);
		});

		nodeRequest.end();

		this.setNodeRequest(nodeRequest);

		return this;
	},

	setHeader: function(name, value)
	{
		this.headers().atPut(name, value);
		return this;
	},

	receivedResponse: function(nodeResponse)
	{
		var response = oden.HttpClientResponse.clone().setNodeResponse(nodeResponse);
		if (response.isRedirect() && this.maxRedirects() > 0)
		{
			this.setUrlString(response.headers().lowerCased().at("location"));
			this.setMaxRedirects(this.maxRedirects() - 1);
			this.start();
		}
		else
		{
			response.addObserver(this);
			response.start();
			this.setResponse(response);
			this.sendNotification("receivedResponse");
		}
	},

	httpClientResponseEnded: function()
	{
		this.sendNotification("completed");
	},

	failed: function(error)
	{
		this.setError(error);
		this.sendNotification("failed");
	},

	cancel: function()
	{
		if (this.nodeRequest())
		{
			this.nodeRequest().abort();
		}

		this.removeAllObservers();
		return this;
	}
});

String.prototype.httpGet = function()
{
	return oden.HttpClientRequest.clone().setUrl(this.asUrl()).start();
}<commit_msg>change map to ideal.map<commit_after>var url = require("url");
var http = require("http");
var https = require("https");
var ideal = require("ideal");
var oden = module.parent.exports;

oden.HttpClientRequest = ideal.Observable.clone().newSlots({
	type: "oden.HttpClientRequest",

	url: null,
	method: "GET",
	headers: null,
	maxRedirects: 0,
	body: "",

	nodeRequest: null,

	error: null,
	response: null
}).setSlots({
	init: function()
	{
		ideal.Observable.init.call(this);
		this.setUrl(oden.Url.clone());
		this.setHeaders(ideal.map({
			Accept: "*/*"
		}));
	},

	setUrlString: function(urlString)
	{
		this.url().setString(urlString);
		return this;
	},

	start: function()
	{
		var self = this;
		var url = this.url();

		var nodeRequest = (url.isHttp() ? http : https).request({
			auth: url.auth(),
			host: url.host(),
			port: url.port(),
			method: this.method(),
			path: url.resource(),
			agent: false,
			headers: this.headers().jsMap()
		});

		nodeRequest.end(this.body());

		nodeRequest.on('response', function(response){
			self.receivedResponse(response);
		});

		nodeRequest.on('error', function(e){
			self.failed(e);
		});

		nodeRequest.end();

		this.setNodeRequest(nodeRequest);

		return this;
	},

	setHeader: function(name, value)
	{
		this.headers().atPut(name, value);
		return this;
	},

	receivedResponse: function(nodeResponse)
	{
		var response = oden.HttpClientResponse.clone().setNodeResponse(nodeResponse);
		if (response.isRedirect() && this.maxRedirects() > 0)
		{
			this.setUrlString(response.headers().lowerCased().at("location"));
			this.setMaxRedirects(this.maxRedirects() - 1);
			this.start();
		}
		else
		{
			response.addObserver(this);
			response.start();
			this.setResponse(response);
			this.sendNotification("receivedResponse");
		}
	},

	httpClientResponseEnded: function()
	{
		this.sendNotification("completed");
	},

	failed: function(error)
	{
		this.setError(error);
		this.sendNotification("failed");
	},

	cancel: function()
	{
		if (this.nodeRequest())
		{
			this.nodeRequest().abort();
		}

		this.removeAllObservers();
		return this;
	}
});

String.prototype.httpGet = function()
{
	return oden.HttpClientRequest.clone().setUrl(this.asUrl()).start();
}<|endoftext|>


<commit_before>;(function($$){ 'use strict';

  var defaults = {
    fit: true, // whether to fit the viewport to the graph
    padding: 30, // padding used on fit
    rows: undefined, // force num of rows in the grid
    columns: undefined, // force num of cols in the grid
    position: function( node ){}, // returns { row, col } for element
    animate: true, // whether to transition the node positions
    animationDuration: 500, // duration of animation in ms if enabled
    ready: undefined, // callback on layoutready
    stop: undefined // callback on layoutstop
  };

  function GridLayout( options ){
    this.options = $$.util.extend({}, defaults, options);
  }

  GridLayout.prototype.run = function(){
    var params = this.options;
    var options = params;

    var cy = params.cy;

    var nodes = cy.nodes().not(':parent');
    var container = cy.container();

    var width = cy.width();
    var height = cy.width();

    if( height === 0 || width === 0){
      nodes.layoutPositions(this, options, function(){
        return { x: 0, y: 0 };
      });

    } else {

      // width/height * splits^2 = cells where splits is number of times to split width
      var cells = nodes.size();
      var splits = Math.sqrt( cells * height/width );
      var rows = Math.round( splits );
      var cols = Math.round( width/height * splits );

      var small = function(val){
        if( val == null ){
          return Math.min(rows, cols);
        } else {
          var min = Math.min(rows, cols);
          if( min == rows ){
            rows = val;
          } else {
            cols = val;
          }
        }
      };

      var large = function(val){
        if( val == null ){
          return Math.max(rows, cols);
        } else {
          var max = Math.max(rows, cols);
          if( max == rows ){
            rows = val;
          } else {
            cols = val;
          }
        }
      };

      // if rows or columns were set in options, use those values
      if( options.rows != null && options.columns != null ){
        rows = options.rows;
        cols = options.columns;
      } else if( options.rows != null && options.columns == null ){
        rows = options.rows;
        cols = Math.ceil( cells / rows );
      } else if( options.rows == null && options.columns != null ){
        cols = options.columns;
        rows = Math.ceil( cells / cols );
      }

      // otherwise use the automatic values and adjust accordingly

      // if rounding was up, see if we can reduce rows or columns
      else if( cols * rows > cells ){
        var sm = small();
        var lg = large();

        // reducing the small side takes away the most cells, so try it first
        if( (sm - 1) * lg >= cells ){
          small(sm - 1);
        } else if( (lg - 1) * sm >= cells ){
          large(lg - 1);
        }
      } else {

        // if rounding was too low, add rows or columns
        while( cols * rows < cells ){
          var sm = small();
          var lg = large();

          // try to add to larger side first (adds less in multiplication)
          if( (lg + 1) * sm >= cells ){
            large(lg + 1);
          } else {
            small(sm + 1);
          }
        }
      }

      var cellWidth = width / cols;
      var cellHeight = height / rows;

      for( var i = 0; i < nodes.length; i++ ){
        var node = nodes[i];
        var w = node.outerWidth();
        var h = node.outerHeight();

        cellWidth = Math.max( cellWidth, w );
        cellHeight = Math.max( cellHeight, h );
      }

      var cellUsed = {}; // e.g. 'c-0-2' => true

      var used = function(row, col){
        return cellUsed['c-' + row + '-' + col] ? true : false;
      };

      var use = function(row, col){
        cellUsed['c-' + row + '-' + col] = true;
      };

      // to keep track of current cell position
      var row = 0;
      var col = 0;
      var moveToNextCell = function(){
        col++;
        if( col >= cols ){
          col = 0;
          row++;
        }
      };

      // get a cache of all the manual positions
      var id2manPos = {};
      for( var i = 0; i < nodes.length; i++ ){
        var node = nodes[i];
        var rcPos = options.position( node );

        if( rcPos && (rcPos.row !== undefined || rcPos.col !== undefined) ){ // must have at least row or col def'd
          var pos = {
            row: rcPos.row,
            col: rcPos.col
          };

          if( pos.col === undefined ){ // find unused col
            pos.col = 0;

            while( used(pos.row, pos.col) ){
              pos.col++;
            }
          } else if( pos.row === undefined ){ // find unused row
            pos.row = 0;

            while( used(pos.row, pos.col) ){
              pos.row++;
            }
          }

          id2manPos[ node.id() ] = pos;
          use( pos.row, pos.col );
        }
      }

      var getPos = function(i, element){
        var x, y;

        if( element.locked() || element.isFullAutoParent() ){
          return false;
        }

        // see if we have a manual position set
        var rcPos = id2manPos[ element.id() ];
        if( rcPos ){
          x = rcPos.col * cellWidth + cellWidth/2;
          y = rcPos.row * cellHeight + cellHeight/2;

        } else { // otherwise set automatically

          while( used(row, col) ){
            moveToNextCell();
          }

          x = col * cellWidth + cellWidth/2;
          y = row * cellHeight + cellHeight/2;
          use( row, col );

          moveToNextCell();
        }

        return { x: x, y: y };

      };

      nodes.layoutPositions( this, options, getPos );
    }

  };

  GridLayout.prototype.stop = function(){
    // not a continuous layout
  };

  $$('layout', 'grid', GridLayout);

})( cytoscape );
<commit_msg>fix grid layout dims<commit_after>;(function($$){ 'use strict';

  var defaults = {
    fit: true, // whether to fit the viewport to the graph
    padding: 30, // padding used on fit
    rows: undefined, // force num of rows in the grid
    columns: undefined, // force num of cols in the grid
    position: function( node ){}, // returns { row, col } for element
    animate: true, // whether to transition the node positions
    animationDuration: 500, // duration of animation in ms if enabled
    ready: undefined, // callback on layoutready
    stop: undefined // callback on layoutstop
  };

  function GridLayout( options ){
    this.options = $$.util.extend({}, defaults, options);
  }

  GridLayout.prototype.run = function(){
    var params = this.options;
    var options = params;

    var cy = params.cy;

    var nodes = cy.nodes().not(':parent');
    var container = cy.container();

    var width = cy.width();
    var height = cy.height();

    if( height === 0 || width === 0){
      nodes.layoutPositions(this, options, function(){
        return { x: 0, y: 0 };
      });

    } else {

      // width/height * splits^2 = cells where splits is number of times to split width
      var cells = nodes.size();
      var splits = Math.sqrt( cells * height/width );
      var rows = Math.round( splits );
      var cols = Math.round( width/height * splits );

      var small = function(val){
        if( val == null ){
          return Math.min(rows, cols);
        } else {
          var min = Math.min(rows, cols);
          if( min == rows ){
            rows = val;
          } else {
            cols = val;
          }
        }
      };

      var large = function(val){
        if( val == null ){
          return Math.max(rows, cols);
        } else {
          var max = Math.max(rows, cols);
          if( max == rows ){
            rows = val;
          } else {
            cols = val;
          }
        }
      };

      // if rows or columns were set in options, use those values
      if( options.rows != null && options.columns != null ){
        rows = options.rows;
        cols = options.columns;
      } else if( options.rows != null && options.columns == null ){
        rows = options.rows;
        cols = Math.ceil( cells / rows );
      } else if( options.rows == null && options.columns != null ){
        cols = options.columns;
        rows = Math.ceil( cells / cols );
      }

      // otherwise use the automatic values and adjust accordingly

      // if rounding was up, see if we can reduce rows or columns
      else if( cols * rows > cells ){
        var sm = small();
        var lg = large();

        // reducing the small side takes away the most cells, so try it first
        if( (sm - 1) * lg >= cells ){
          small(sm - 1);
        } else if( (lg - 1) * sm >= cells ){
          large(lg - 1);
        }
      } else {

        // if rounding was too low, add rows or columns
        while( cols * rows < cells ){
          var sm = small();
          var lg = large();

          // try to add to larger side first (adds less in multiplication)
          if( (lg + 1) * sm >= cells ){
            large(lg + 1);
          } else {
            small(sm + 1);
          }
        }
      }

      var cellWidth = width / cols;
      var cellHeight = height / rows;

      for( var i = 0; i < nodes.length; i++ ){
        var node = nodes[i];
        var w = node.outerWidth();
        var h = node.outerHeight();

        cellWidth = Math.max( cellWidth, w );
        cellHeight = Math.max( cellHeight, h );
      }

      var cellUsed = {}; // e.g. 'c-0-2' => true

      var used = function(row, col){
        return cellUsed['c-' + row + '-' + col] ? true : false;
      };

      var use = function(row, col){
        cellUsed['c-' + row + '-' + col] = true;
      };

      // to keep track of current cell position
      var row = 0;
      var col = 0;
      var moveToNextCell = function(){
        col++;
        if( col >= cols ){
          col = 0;
          row++;
        }
      };

      // get a cache of all the manual positions
      var id2manPos = {};
      for( var i = 0; i < nodes.length; i++ ){
        var node = nodes[i];
        var rcPos = options.position( node );

        if( rcPos && (rcPos.row !== undefined || rcPos.col !== undefined) ){ // must have at least row or col def'd
          var pos = {
            row: rcPos.row,
            col: rcPos.col
          };

          if( pos.col === undefined ){ // find unused col
            pos.col = 0;

            while( used(pos.row, pos.col) ){
              pos.col++;
            }
          } else if( pos.row === undefined ){ // find unused row
            pos.row = 0;

            while( used(pos.row, pos.col) ){
              pos.row++;
            }
          }

          id2manPos[ node.id() ] = pos;
          use( pos.row, pos.col );
        }
      }

      var getPos = function(i, element){
        var x, y;

        if( element.locked() || element.isFullAutoParent() ){
          return false;
        }

        // see if we have a manual position set
        var rcPos = id2manPos[ element.id() ];
        if( rcPos ){
          x = rcPos.col * cellWidth + cellWidth/2;
          y = rcPos.row * cellHeight + cellHeight/2;

        } else { // otherwise set automatically

          while( used(row, col) ){
            moveToNextCell();
          }

          x = col * cellWidth + cellWidth/2;
          y = row * cellHeight + cellHeight/2;
          use( row, col );

          moveToNextCell();
        }

        return { x: x, y: y };

      };

      nodes.layoutPositions( this, options, getPos );
    }

  };

  GridLayout.prototype.stop = function(){
    // not a continuous layout
  };

  $$('layout', 'grid', GridLayout);

})( cytoscape );
<|endoftext|>


<commit_before>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe(FILL_ME_IN); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(FILL_ME_IN);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(FILL_ME_IN);
    expect(multiTypeArray[2]).toBe(FILL_ME_IN);
    expect(multiTypeArray[3]()).toBe(FILL_ME_IN);
    expect(multiTypeArray[4].value1).toBe(FILL_ME_IN);
    expect(multiTypeArray[4]["value2"]).toBe(FILL_ME_IN);
    expect(multiTypeArray[5][0]).toBe(FILL_ME_IN);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, FILL_ME_IN]);

    array.push(3);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(FILL_ME_IN);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(FILL_ME_IN);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
    expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<commit_msg>"About arrays completed"<commit_after>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe("object"); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(4);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(["peanut"]);
    expect(array.slice(0, 2)).toEqual(["peanut", "butter"]);
    expect(array.slice(2, 2)).toEqual([]);
    expect(array.slice(2, 20)).toEqual(["and", "jelly"]);
    expect(array.slice(3, 0)).toEqual([]);
    expect(array.slice(3, 100)).toEqual(["jelly"]);
    expect(array.slice(5, 1)).toEqual([]);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe("changed in function");

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe("changed in assignedArray");

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe("three");
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual([1,2,3]);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(3);
    expect(array).toEqual([1,2]);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual([3,1,2]);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(3);
    expect(array).toEqual([1,2]);
  });
});
<|endoftext|>


<commit_before>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe('two');
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, FILL_ME_IN]);

    array.push(3);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(FILL_ME_IN);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(FILL_ME_IN);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
    expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<commit_msg>Complete AboutArrays<commit_after>describe("About Arrays", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe('object'); //A mistake? - http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function () { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe('two');
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function () {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function () {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(4);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);
  });

  it("should slice arrays", function () {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(['peanut']);
    expect(array.slice(0, 2)).toEqual(['peanut', 'butter']);
    expect(array.slice(2, 2)).toEqual([]);
    expect(array.slice(2, 20)).toEqual(['and', 'jelly']);
    expect(array.slice(3, 0)).toEqual([]);
    expect(array.slice(3, 100)).toEqual(['jelly']);
    expect(array.slice(5, 1)).toEqual([]);
  });

  it("should know array references", function () {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe('changed in function');

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe('changed in assignedArray');

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe('three');
  });

  it("should push and pop", function () {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual([1, 2, 3]);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(3);
    expect(array).toEqual([1, 2]);
  });

  it("should know about shifting arrays", function () {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual([3, 1, 2]);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(3);
    expect(array).toEqual([1, 2]);
  });
});
<|endoftext|>


<commit_before>import Node from '../Node.js';

export default class VariableDeclarator extends Node {
	initialise ( transforms ) {
		let kind = this.parent.kind;
		if ( kind === 'let' && this.parent.parent.type === 'ForStatement' ) {
			kind = 'for.let'; // special case...
		}

		this.parent.scope.addDeclaration( this.id, kind );
		super.initialise( transforms );
	}

	transpile ( code, transforms ) {
		if ( !this.init && transforms.letConst && this.parent.kind !== 'var' ) {
			let inLoop = this.findNearest( /Function|^ForStatement|^ForOfStatement|^(?:Do)?WhileStatement/ );
			if ( inLoop && ! /Function/.test( inLoop.type ) && ! this.isLeftDeclaratorOfForLoop() ) {
				code.insertLeft( this.id.end, ' = (void 0)' );
			}
		}

		if ( this.init ) this.init.transpile( code, transforms );
	}

	isLeftDeclaratorOfForLoop () {
		return this.parent
			&& this.parent.type === 'VariableDeclaration'
			&& this.parent.parent
			&& this.parent.parent.type === 'ForOfStatement'
			&& this.parent.parent.left
			&& this.parent.parent.left.declarations[0] === this;
	}
}
<commit_msg>rename method isLeftDeclaratorOfForOfLoop<commit_after>import Node from '../Node.js';

export default class VariableDeclarator extends Node {
	initialise ( transforms ) {
		let kind = this.parent.kind;
		if ( kind === 'let' && this.parent.parent.type === 'ForStatement' ) {
			kind = 'for.let'; // special case...
		}

		this.parent.scope.addDeclaration( this.id, kind );
		super.initialise( transforms );
	}

	transpile ( code, transforms ) {
		if ( !this.init && transforms.letConst && this.parent.kind !== 'var' ) {
			let inLoop = this.findNearest( /Function|^ForStatement|^ForOfStatement|^(?:Do)?WhileStatement/ );
			if ( inLoop && ! /Function/.test( inLoop.type ) && ! this.isLeftDeclaratorOfForOfLoop() ) {
				code.insertLeft( this.id.end, ' = (void 0)' );
			}
		}

		if ( this.init ) this.init.transpile( code, transforms );
	}

	isLeftDeclaratorOfForOfLoop () {
		return this.parent
			&& this.parent.type === 'VariableDeclaration'
			&& this.parent.parent
			&& this.parent.parent.type === 'ForOfStatement'
			&& this.parent.parent.left
			&& this.parent.parent.left.declarations[0] === this;
	}
}
<|endoftext|>


<commit_before>

define([

	'underscore',
	'backbone',
	'marionette',
	'bootstrap',
	'templates',
	'settings',
	'osm-auth',
],
function (

	_,
	Backbone,
	Marionette,
	Bootstrap,
	templates,
	settings,
	osmAuth
) {

	'use strict';

	return Marionette.LayoutView.extend({

		template: JST['editPoiDataColumn.html'],
		templateField: JST['editPoiDataField.html'],

		behaviors: {

			'l20n': {},
			'column': {},
		},

		ui: {

			'column': '#edit_poi_data_column',
			'fields': '.fields',
		},

		events: {

			'submit': 'onSubmit',
			'reset': 'onReset',
		},

		initialize: function () {

			var self = this;

			this._radio = Backbone.Wreqr.radio.channel('global');

			if ( !this._radio.reqres.request('var', 'isLogged') ) {

				return false;
			}
		},

		open: function () {

			this._radio.vent.trigger('column:closeAll');

			this.triggerMethod('open');
		},

		close: function () {

			this.triggerMethod('close');
		},

		onRender: function () {

			if ( !this._radio.reqres.request('var', 'isLogged') ) {

				return this;
			}

			var tag,
			self = this,
			html = '',
			dataFromOSM = this.options.dataFromOSM,
			poiLayerModel = this.options.poiLayerModel,
			popupContent = poiLayerModel.get('popupContent'),
			re = new RegExp('{(.*?)}', 'g'),
			tags = popupContent.match(re);

			for (var i in tags) {

				tag = tags[i].replace( /\{(.*?)\}/g, '$1' );

				html += this.templateField({

					'tag': tag,
					'value': dataFromOSM.tags[tag],
				});
			}

			this.ui.fields.html( html );
		},

		onSubmit: function (e) {

			if ( !this._radio.reqres.request('var', 'isLogged') ) {

				return false;
			}

			e.preventDefault();

			var self = this,
			newValues = {},
			nodeId = this.options.dataFromOSM.id;

			this.ui.fields
			.find('input')
			.each(function (i, input) {

				var tag = $(input).data('tag');

				newValues[tag] = input.value;
			});

			$.ajax({

				'method': 'GET',
				'dataType': 'xml',
				'url': 'https://api.openstreetmap.org/api/0.6/node/'+ nodeId,
				'success': function (nodeXml, jqXHR, textStatus) {

					var oldTags = {},
					parentNode = nodeXml.getElementsByTagName('node')[0],
					tags = nodeXml.documentElement.getElementsByTagName('tag');

					for (var j in tags) {

						if ( !tags[j].getAttribute ) {

							continue;
						}

						oldTags[ tags[j].getAttribute('k') ] = tags[j];
					}

					for (var k in newValues) {

						if ( !newValues[k] ) {

							if ( oldTags[k] ) {

								parentNode.removeChild( oldTags[k] );
							}

							continue;
						}

						if ( oldTags[k] ) {

							oldTags[k].setAttribute('v', newValues[k]);
						}
						else {

							var newTag = nodeXml.createElement('tag');

							newTag.setAttribute('k', k);
							newTag.setAttribute('v', newValues[k]);

							parentNode.appendChild(newTag);
						}
					}

					self.onNodeXmlReceived( nodeXml );
				},
				'error': function (jqXHR, textStatus, error) {

					console.error('FIXME');
				},
			});
		},

		onNodeXmlReceived: function (nodeXml) {

			var self = this,
			nodeId = this.options.dataFromOSM.id,
			user = this._radio.reqres.request('model', 'user'),
			auth = osmAuth({

				'oauth_consumer_key': settings.oauthConsumerKey,
				'oauth_secret': settings.oauthSecret,
				'oauth_token': user.get('token'),
				'oauth_token_secret': user.get('tokenSecret'),
			}),
			xmlChangeset = '<osm><changeset><tag k="created_by" v="Rudomap"/><tag k="comment" v="Test from Rudomap (developpement in progress)"/></changeset></osm>';

			auth.xhr({

				'method': 'PUT',
				'path': '/api/0.6/changeset/create',
				'options': { 'header': { 'Content-Type': 'text/xml' } },
				'content': xmlChangeset
			},
			function(err, res) {

				if (err) {

					console.log('ERROR on put changeset: ' + err.response);
					return;
				}

				var data,
				changesetId = res,
				node = nodeXml.documentElement.getElementsByTagName('node')[0],
				serializer = new XMLSerializer();

				node.setAttribute('changeset', changesetId);

				data = serializer.serializeToString(nodeXml);

				auth.xhr({

					'method': 'PUT',
					'path': '/api/0.6/node/'+ nodeId,
					'options': { 'header': { 'Content-Type': 'text/xml' } },
					'content': data,
				},
				function(err, res) {

					if (err) {

						console.log('ERROR on put node/way : '+ err.response);
						return;
					}

					auth.xhr({

						'method': 'PUT',
						'path': '/api/0.6/changeset/'+ changesetId +'/close',
					},
					function(err, res) {

						if (err) {

							console.log('ERROR on put changeset/close : '+ err.response);
							return;
						}
						else {

							console.log("Successfully modification of an OSM object !");
						}
					});
				});
			});

			this.close();
		},

		onReset: function () {

			// this._radio.commands.execute('ui:setTitleColor', this.model.get('color'));

			this.close();
		},
	});
});
<commit_msg>Better semantic this way ^^<commit_after>

define([

	'underscore',
	'backbone',
	'marionette',
	'bootstrap',
	'templates',
	'settings',
	'osm-auth',
],
function (

	_,
	Backbone,
	Marionette,
	Bootstrap,
	templates,
	settings,
	osmAuth
) {

	'use strict';

	return Marionette.LayoutView.extend({

		template: JST['editPoiDataColumn.html'],
		templateField: JST['editPoiDataField.html'],

		behaviors: {

			'l20n': {},
			'column': {},
		},

		ui: {

			'column': '#edit_poi_data_column',
			'fields': '.fields',
		},

		events: {

			'submit': 'onSubmit',
			'reset': 'onReset',
		},

		initialize: function () {

			var self = this;

			this._radio = Backbone.Wreqr.radio.channel('global');

			if ( !this._radio.reqres.request('var', 'isLogged') ) {

				return false;
			}
		},

		open: function () {

			this._radio.vent.trigger('column:closeAll');

			this.triggerMethod('open');
		},

		close: function () {

			this.triggerMethod('close');
		},

		onRender: function () {

			if ( !this._radio.reqres.request('var', 'isLogged') ) {

				return this;
			}

			var tag,
			self = this,
			html = '',
			dataFromOSM = this.options.dataFromOSM,
			poiLayerModel = this.options.poiLayerModel,
			popupContent = poiLayerModel.get('popupContent'),
			re = new RegExp('{(.*?)}', 'g'),
			tags = popupContent.match(re);

			for (var i in tags) {

				tag = tags[i].replace( /\{(.*?)\}/g, '$1' );

				html += this.templateField({

					'tag': tag,
					'value': dataFromOSM.tags[tag],
				});
			}

			this.ui.fields.html( html );
		},

		onSubmit: function (e) {

			if ( !this._radio.reqres.request('var', 'isLogged') ) {

				return false;
			}

			e.preventDefault();

			var self = this,
			newTags = {},
			nodeId = this.options.dataFromOSM.id;

			this.ui.fields
			.find('input')
			.each(function (i, input) {

				var tag = $(input).data('tag');

				newTags[tag] = input.value;
			});

			$.ajax({

				'method': 'GET',
				'dataType': 'xml',
				'url': 'https://api.openstreetmap.org/api/0.6/node/'+ nodeId,
				'success': function (nodeXml, jqXHR, textStatus) {

					var oldTags = {},
					parentNode = nodeXml.getElementsByTagName('node')[0],
					tags = nodeXml.documentElement.getElementsByTagName('tag');

					for (var j in tags) {

						if ( !tags[j].getAttribute ) {

							continue;
						}

						oldTags[ tags[j].getAttribute('k') ] = tags[j];
					}

					for (var k in newTags) {

						if ( !newTags[k] ) {

							if ( oldTags[k] ) {

								parentNode.removeChild( oldTags[k] );
							}

							continue;
						}

						if ( oldTags[k] ) {

							oldTags[k].setAttribute('v', newTags[k]);
						}
						else {

							var newTag = nodeXml.createElement('tag');

							newTag.setAttribute('k', k);
							newTag.setAttribute('v', newTags[k]);

							parentNode.appendChild(newTag);
						}
					}

					self.onNodeXmlReceived( nodeXml );
				},
				'error': function (jqXHR, textStatus, error) {

					console.error('FIXME');
				},
			});
		},

		onNodeXmlReceived: function (nodeXml) {

			var self = this,
			nodeId = this.options.dataFromOSM.id,
			user = this._radio.reqres.request('model', 'user'),
			auth = osmAuth({

				'oauth_consumer_key': settings.oauthConsumerKey,
				'oauth_secret': settings.oauthSecret,
				'oauth_token': user.get('token'),
				'oauth_token_secret': user.get('tokenSecret'),
			}),
			xmlChangeset = '<osm><changeset><tag k="created_by" v="Rudomap"/><tag k="comment" v="Test from Rudomap (developpement in progress)"/></changeset></osm>';

			auth.xhr({

				'method': 'PUT',
				'path': '/api/0.6/changeset/create',
				'options': { 'header': { 'Content-Type': 'text/xml' } },
				'content': xmlChangeset
			},
			function(err, res) {

				if (err) {

					console.log('ERROR on put changeset: ' + err.response);
					return;
				}

				var data,
				changesetId = res,
				node = nodeXml.documentElement.getElementsByTagName('node')[0],
				serializer = new XMLSerializer();

				node.setAttribute('changeset', changesetId);

				data = serializer.serializeToString(nodeXml);

				auth.xhr({

					'method': 'PUT',
					'path': '/api/0.6/node/'+ nodeId,
					'options': { 'header': { 'Content-Type': 'text/xml' } },
					'content': data,
				},
				function(err, res) {

					if (err) {

						console.log('ERROR on put node/way : '+ err.response);
						return;
					}

					auth.xhr({

						'method': 'PUT',
						'path': '/api/0.6/changeset/'+ changesetId +'/close',
					},
					function(err, res) {

						if (err) {

							console.log('ERROR on put changeset/close : '+ err.response);
							return;
						}
						else {

							console.log("Successfully modification of an OSM object !");
						}
					});
				});
			});

			this.close();
		},

		onReset: function () {

			// this._radio.commands.execute('ui:setTitleColor', this.model.get('color'));

			this.close();
		},
	});
});
<|endoftext|>