<commit_before>var chai = require('chai');
var jsdom = require('jsdom-global');
var adapter = require('../index');
var assert = chai.assert;
var expect = chai.expect;

before(function() {
	global.$ = require('jquery');
});

var dom = {
	make: function(data) {
		var html = this.makeHtml(data);
		$('body').append(html);
	},
	makeHtml: function(data) {
		var html = '';
		for (var k in data)
			html += '<script type="text/html" id="' + k + '">' + data[k] + '</script>';
		return html;
	}
};

afterEach(function() {
	$('body').empty();
});

describe.only('#getHtml', function() {

	it ('retrun html of script by name', function() {
		dom.make({template_: '{{variable}}'})
		var html = adapter.getHtml('template');
		expect(html).to.eql('{{variable}}');
	});

	it('throw if script element cannot be found', function() {
		expect(adapter.getHtml.bind(adapter, 'tmpl')).to.throw();
	});
});

describe('#getPartials', function() {
	it ('return object with partial', function(done) {
		this.make({template_: 'text'}, function() {
			var partials = adapter.getPartials('template');
			assert(partials.template == 'text');
			done();
		});
	});
});

describe('#render', function() {
	it ('render without data', function(done) {
		this.make({template_: 'text'}, function() {
			var html = adapter.render('template');
			assert(html == 'text');
			done();
		});
	});

	it('if data is passed it should be injected in template', function(done) {
		this.make({template_: '{{myVar}}'}, function() {
			var html = adapter.render('template', {myVar: 'hello'});
			assert(html == 'hello');
			done();
		});
	});

	it('if partials list are passed it should be rendered', function(done) {
		this.make({
			template_: '{{> subTemplate }}',
			subTemplate_: 'hello'
		}, function() {
			var html = adapter.render('template', {}, 'subTemplate');
			assert(html == 'hello');
			done();
		});
	});
});

global.l = function (x) {
	console.log(x);
};<commit_msg>format: remove whitespace<commit_after>var chai = require('chai');
var jsdom = require('jsdom-global');
var adapter = require('../index');
var assert = chai.assert;
var expect = chai.expect;

before(function() {
	global.$ = require('jquery');
});

var dom = {
	make: function(data) {
		var html = this.makeHtml(data);
		$('body').append(html);
	},
	makeHtml: function(data) {
		var html = '';
		for (var k in data)
			html += '<script type="text/html" id="' + k + '">' + data[k] + '</script>';
		return html;
	}
};

afterEach(function() {
	$('body').empty();
});

describe.only('#getHtml', function() {

	it('retrun html of script by name', function() {
		dom.make({template_: '{{variable}}'});
		var html = adapter.getHtml('template');
		expect(html).to.eql('{{variable}}');
	});

	it('throw if script element cannot be found', function() {
		expect(adapter.getHtml.bind(adapter, 'tmpl')).to.throw();
	});
});

describe('#getPartials', function() {
	it('return object with partial', function(done) {
		this.make({template_: 'text'}, function() {
			var partials = adapter.getPartials('template');
			assert(partials.template == 'text');
			done();
		});
	});
});

describe('#render', function() {
	it('render without data', function(done) {
		this.make({template_: 'text'}, function() {
			var html = adapter.render('template');
			assert(html == 'text');
			done();
		});
	});

	it('if data is passed it should be injected in template', function(done) {
		this.make({template_: '{{myVar}}'}, function() {
			var html = adapter.render('template', {myVar: 'hello'});
			assert(html == 'hello');
			done();
		});
	});

	it('if partials list are passed it should be rendered', function(done) {
		this.make({
			template_: '{{> subTemplate }}',
			subTemplate_: 'hello'
		}, function() {
			var html = adapter.render('template', {}, 'subTemplate');
			assert(html == 'hello');
			done();
		});
	});
});

global.l = function (x) {
	console.log(x);
};<|endoftext|>


<commit_before>import { defaults, set, get } from 'lodash';
import Joi from 'joi';
import moment from 'moment';
import 'twix';
import { constants } from '../../lib/constants';
import { parsePartitionUnit, parseWithTimestamp } from '../../lib/parse_index_pattern';

export function pull(server) {
  const index = server.config().get('notification_center.index');
  const type = 'notification';
  const { callWithRequest } = server.plugins.elasticsearch.getCluster('data');
  const { maxSize } = server.config().get('notification_center.api.pull');
  const partitionUnit = parsePartitionUnit(index);

  server.route({
    path: `${constants.API_BASE_URL}/notification`,
    method: 'GET',
    handler(request, reply) {
      const { size, from, to } = request.query;

      callWithRequest(request, 'search', {
        index: partitionUnit ? moment(from)
          .twix(moment(to))
          .toArray(partitionUnit)
          .map(time => parseWithTimestamp(index, time)) : index,
        type,
        size,
        ignoreUnavailable: true,
        body: (() => {
          const rangeQueries = [];

          if (from) {
            rangeQueries.push(set({}, 'range.timestamp.gte', moment(from).valueOf()));
          }

          if (to) {
            rangeQueries.push(set({}, 'range.timestamp.lte', moment(to).valueOf()));
          }

          return rangeQueries.length ? set({}, 'query.bool.must', rangeQueries) : undefined;
        })()
      })
      .then(resp => {
        return reply(get(resp, 'hits.hits', []).map(hit => hit._source));
      })
      .catch(reply);
    },
    config: {
      validate: {
        query: Joi.object({
          size: Joi.number().min(1).max(maxSize).default(maxSize),
          from: Joi.date().optional(),
          to: Joi.date().optional()
        }).default()
      }
    }
  });
};
<commit_msg>Change pull API spec. gte query to gt.<commit_after>import { defaults, set, get } from 'lodash';
import Joi from 'joi';
import moment from 'moment';
import 'twix';
import { constants } from '../../lib/constants';
import { parsePartitionUnit, parseWithTimestamp } from '../../lib/parse_index_pattern';

export function pull(server) {
  const index = server.config().get('notification_center.index');
  const type = 'notification';
  const { callWithRequest } = server.plugins.elasticsearch.getCluster('data');
  const { maxSize } = server.config().get('notification_center.api.pull');
  const partitionUnit = parsePartitionUnit(index);

  server.route({
    path: `${constants.API_BASE_URL}/notification`,
    method: 'GET',
    handler(request, reply) {
      const { size, from, to } = request.query;

      callWithRequest(request, 'search', {
        index: partitionUnit ? moment(from)
          .twix(moment(to))
          .toArray(partitionUnit)
          .map(time => parseWithTimestamp(index, time)) : index,
        type,
        size,
        ignoreUnavailable: true,
        body: (() => {
          const rangeQueries = [];

          if (from) {
            rangeQueries.push(set({}, 'range.timestamp.gt', moment(from).valueOf()));
          }

          if (to) {
            rangeQueries.push(set({}, 'range.timestamp.lt', moment(to).valueOf()));
          }

          return rangeQueries.length ? set({}, 'query.bool.must', rangeQueries) : undefined;
        })()
      })
      .then(resp => {
        return reply(get(resp, 'hits.hits', []).map(hit => hit._source));
      })
      .catch(reply);
    },
    config: {
      validate: {
        query: Joi.object({
          size: Joi.number().min(1).max(maxSize).default(maxSize),
          from: Joi.date().optional(),
          to: Joi.date().optional()
        }).default()
      }
    }
  });
};
<|endoftext|>


<commit_before>const React = require("react");
const PropTypes = require("prop-types");
const { Localized } = require("fluent-react/compat");
const sendEvent = require("../../browser-send-event.js");
const { Selection } = require("../../../shared/selection");
const { ColorPicker } = require("./color-picker");

// Text input height is determined by text size and padding
// See frame.scss mixin type-box($size)
const TEXT_INPUT_PADDING = 4;

// Padding used by draggable div
const DRAG_DIV_PADDING = 10;

// Editor header height in pixel
const EDITOR_HEADER_HEIGHT = 100;

const FONT_STYLE = "sans-serif";
const FONT_WEIGHT = 900;
const INIT_FONT_SIZE = 36;

let previousTextInputWidth;
let previousInputText = "";

exports.TextTool = class TextTool extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = React.createRef();

    this.canvasCssWidth = props.canvasCssWidth;
    this.canvasCssHeight = props.canvasCssHeight;

    const VISIBLE_HEIGHT = this.canvasCssHeight > window.innerHeight ? window.innerHeight - EDITOR_HEADER_HEIGHT :
                                                                       this.canvasCssHeight;

    const INIT_LEFT = Math.floor((this.canvasCssWidth / 2) - (INIT_FONT_SIZE / 2));
    const INIT_TOP = window.scrollY + Math.floor((VISIBLE_HEIGHT / 2) - ((INIT_FONT_SIZE) / 2) - TEXT_INPUT_PADDING);

    this.state = {
      left: INIT_LEFT,
      top: INIT_TOP,
      color: this.props.color,
      colorName: this.props.colorName,
      textSize: "large-text"
    };
  }

  componentDidMount() {
    this.textInput.current.focus();
    previousTextInputWidth = this.textInput.current.clientWidth;
    this.adjustHeight();
    if (this.props.toolbarOverrideCallback) {
      this.props.toolbarOverrideCallback();
    }
  }

  componentDidUpdate(oldProps, oldState) {
    if (oldState.textSize !== this.state.textSize) {
      this.props.toolbarOverrideCallback();
      this.adjustHeight();
    }
  }

  componentWillUnmount() {
    if (this.props.toolbarOverrideCallback) {
      this.props.toolbarOverrideCallback();
    }
  }

  adjustHeight() {
    const styles = window.getComputedStyle(this.textInput.current);
    const height = Math.ceil(parseFloat(styles.lineHeight) + parseFloat(styles.paddingTop) + parseFloat(styles.paddingBottom));
    this.textInput.current.style.minHeight = `${height}px`;
  }

  render() {
    const textToolBox = this.renderTextBox();
    return <div
      className={`text-tool-container centered`}
      onDragOver={this.onDragOver.bind(this)}
      onDrop={this.onDrop.bind(this)}
      style={{height: this.props.baseCanvas.style.height, width: this.props.baseCanvas.style.width}}>
      {textToolBox}

;
  }

  renderTextBox() {
    const dragDivTopPx = `${this.state.top - DRAG_DIV_PADDING}px`;
    const dragDivLeftPx = `${this.state.left - DRAG_DIV_PADDING}px`;
    const dragDivPadding = `${DRAG_DIV_PADDING}px`;

    const dragDivStyles = {
      position: "absolute",
      top: dragDivTopPx,
      left: dragDivLeftPx,
      padding: dragDivPadding,
      cursor: "move"
    };

    return [

        <div id="text-input" ref={this.textInput} contentEditable="true" key="text" onKeyDown={this.onKeyDown.bind(this)}
          onKeyUp={this.onKeyUp.bind(this)} className={`${this.state.textSize} ${this.state.colorName} text`} onFocus={this.moveCursorToEnd.bind(this)}>

    ];
  }

  moveCursorToEnd(e) {
    if (document.createRange) {
        const range = document.createRange();
        range.selectNodeContents(e.target); // Select contents of the element with the range
        range.collapse(false); // false means collapse to end rather than the start
        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    }
  }

  renderToolbar() {
    return

      <Localized id="annotationTextSize">
        <select className={`text-select`} title="Text Size" onChange={this.onChangeTextSize.bind(this)} value={this.state.textSize}>
          <Localized id="textSizeSmall"><option value="small-text">Small</option></Localized>
          <Localized id="textSizeMedium"><option value="medium-text">Medium</option></Localized>
          <Localized id="textSizeLarge"><option value="large-text">Large</option></Localized>
        </select>
      </Localized>
      <ColorPicker activeTool={this.state.tool}
        setColorCallback={this.setColor.bind(this)}
        color={this.state.color} />

      <Localized id="annotationTextConfirmButton">
        <button className={`button transparent confirm-text`} id="confirm-text" onClick={this.onClickConfirm.bind(this)} title="Confirm Text">Confirm</button>
      </Localized>
      <Localized id="annotationTextCancelButton">
        <button className={`button transparent cancel-text`} id="cancel-text" onClick={this.onClickCancel.bind(this)} title="Cancel Text">Cancel</button>
      </Localized>

;
  }

  setColor(color, colorName) {
    this.setState({color, colorName});
    this.textInput.current.focus();
  }

  onClickConfirm(e) {
    // Exit if user doesn't enter any text
    if (!this.textInput.current.textContent) {
       if (this.props.cancelTextHandler) {
          this.props.cancelTextHandler();
        }
        sendEvent("cancel-text", "text-toolbar");
        return;
    }
    const styles = window.getComputedStyle(this.textInput.current);
    const FONT_SIZE = parseInt(styles["font-size"], 10);
    const x = this.state.left + parseFloat(styles["padding-left"]);
    const y = this.state.top + TEXT_INPUT_PADDING + parseFloat(styles["line-height"]) / 2;

    const textCanvas = document.createElement("canvas");
    textCanvas.width = this.props.baseCanvas.width;
    textCanvas.height = this.props.baseCanvas.height;
    const drawingContext = textCanvas.getContext("2d");

    drawingContext.scale(this.props.canvasPixelRatio, this.props.canvasPixelRatio);
    drawingContext.textBaseline = "middle";
    drawingContext.fillStyle = styles.backgroundColor;
    drawingContext.fillRect(this.state.left,
                            this.state.top,
                            this.textInput.current.clientWidth,
                            this.textInput.current.clientHeight);
    drawingContext.fillStyle = styles.color;
    drawingContext.font = `${FONT_WEIGHT} ${FONT_SIZE}px ${FONT_STYLE}`;
    drawingContext.fillText(this.textInput.current.textContent, x, y);

    const textSelection = new Selection(this.state.left,
                                        this.state.top,
                                        this.state.left + this.textInput.current.clientWidth,
                                        this.state.top + this.textInput.current.clientHeight);

    if (this.props.confirmTextHandler) {
      this.props.confirmTextHandler(textSelection, textCanvas);
    }
    sendEvent("confirm-text", "text-toolbar");
  }

  onClickCancel(e) {
    if (this.props.cancelTextHandler) {
      this.props.cancelTextHandler();
    }
    sendEvent("cancel-text", "text-toolbar");
  }

  onKeyDown(e) {
    this.adjustX(e);
    if (e.key === "Enter") {
      e.preventDefault();
    }
  }

  onKeyUp(e) {
    // Fix to remove
 element inserted on press of space bar inside contenteditable div
    while (this.textInput.current.firstElementChild) {
      this.textInput.current.removeChild(this.textInput.current.firstElementChild);
    }
    this.adjustX(e);
  }

  adjustX(e) {
    if (previousInputText === this.textInput.current.textContent) {
      return;
    }
    const rectInput = e.target.getBoundingClientRect();
    const rectCanvas = this.props.baseCanvas.getBoundingClientRect();
    const WIDTH_DIFF = this.textInput.current.clientWidth - previousTextInputWidth;
    this.setState({left: Math.floor(rectInput.left - rectCanvas.left - WIDTH_DIFF / 2)});
    previousTextInputWidth = this.textInput.current.clientWidth;
    previousInputText = this.textInput.current.textContent;
  }

  onChangeTextSize(event) {
    const size = event.target.value;
    this.setState({textSize: size});
    this.textInput.current.focus();
  }

  onDragStart(event) {
    const style = window.getComputedStyle(event.target);
    event.dataTransfer.setData("text/plain",
      (parseFloat(style.getPropertyValue("left")) - event.clientX) +
       "," + (parseFloat(style.getPropertyValue("top")) - event.clientY));
  }

  onDragOver(event) {
    event.preventDefault();
    return false;
  }

  onDrop(event) {
    const offset = event.dataTransfer.getData("text/plain").split(",");
    const dragLeft = event.clientX + parseFloat(offset[0]);
    const dragTop = event.clientY + parseFloat(offset[1]);

    this.setState({left: dragLeft + DRAG_DIV_PADDING, top: dragTop + DRAG_DIV_PADDING});
    event.preventDefault();
    return false;
  }
};

exports.TextTool.propTypes = {
  baseCanvas: PropTypes.object,
  color: PropTypes.string,
  colorName: PropTypes.string,
  toolbarOverrideCallback: PropTypes.func,
  confirmTextHandler: PropTypes.func,
  cancelTextHandler: PropTypes.func,
  canvasPixelRatio: PropTypes.number,
  canvasCssWidth: PropTypes.number,
  canvasCssHeight: PropTypes.number,
};
<commit_msg>Fixes #4620 - Text tool vertical shift on confirm<commit_after>const React = require("react");
const PropTypes = require("prop-types");
const { Localized } = require("fluent-react/compat");
const sendEvent = require("../../browser-send-event.js");
const { Selection } = require("../../../shared/selection");
const { ColorPicker } = require("./color-picker");

// Text input height is determined by text size and padding
// See frame.scss mixin type-box($size)
const TEXT_INPUT_PADDING = 4;

// Padding used by draggable div
const DRAG_DIV_PADDING = 10;

// Editor header height in pixel
const EDITOR_HEADER_HEIGHT = 100;

const FONT_STYLE = "sans-serif";
const FONT_WEIGHT = 900;
const INIT_FONT_SIZE = 36;

let previousTextInputWidth;
let previousInputText = "";

exports.TextTool = class TextTool extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = React.createRef();

    this.canvasCssWidth = props.canvasCssWidth;
    this.canvasCssHeight = props.canvasCssHeight;

    const VISIBLE_HEIGHT = this.canvasCssHeight > window.innerHeight ? window.innerHeight - EDITOR_HEADER_HEIGHT :
                                                                       this.canvasCssHeight;

    const INIT_LEFT = Math.floor((this.canvasCssWidth / 2) - (INIT_FONT_SIZE / 2));
    const INIT_TOP = window.scrollY + Math.floor((VISIBLE_HEIGHT / 2) - ((INIT_FONT_SIZE) / 2) - TEXT_INPUT_PADDING);

    this.state = {
      left: INIT_LEFT,
      top: INIT_TOP,
      color: this.props.color,
      colorName: this.props.colorName,
      textSize: "large-text"
    };
  }

  componentDidMount() {
    this.textInput.current.focus();
    previousTextInputWidth = this.textInput.current.clientWidth;
    this.adjustHeight();
    if (this.props.toolbarOverrideCallback) {
      this.props.toolbarOverrideCallback();
    }
  }

  componentDidUpdate(oldProps, oldState) {
    if (oldState.textSize !== this.state.textSize) {
      this.props.toolbarOverrideCallback();
      this.adjustHeight();
    }
  }

  componentWillUnmount() {
    if (this.props.toolbarOverrideCallback) {
      this.props.toolbarOverrideCallback();
    }
  }

  adjustHeight() {
    const styles = window.getComputedStyle(this.textInput.current);
    const height = Math.ceil(parseFloat(styles.lineHeight) + parseFloat(styles.paddingTop) + parseFloat(styles.paddingBottom));
    this.textInput.current.style.minHeight = `${height}px`;
  }

  render() {
    const textToolBox = this.renderTextBox();
    return <div
      className={`text-tool-container centered`}
      onDragOver={this.onDragOver.bind(this)}
      onDrop={this.onDrop.bind(this)}
      style={{height: this.props.baseCanvas.style.height, width: this.props.baseCanvas.style.width}}>
      {textToolBox}

;
  }

  renderTextBox() {
    const dragDivTopPx = `${this.state.top - DRAG_DIV_PADDING}px`;
    const dragDivLeftPx = `${this.state.left - DRAG_DIV_PADDING}px`;
    const dragDivPadding = `${DRAG_DIV_PADDING}px`;

    const dragDivStyles = {
      position: "absolute",
      top: dragDivTopPx,
      left: dragDivLeftPx,
      padding: dragDivPadding,
      cursor: "move"
    };

    return [

        <div id="text-input" ref={this.textInput} contentEditable="true" key="text" onKeyDown={this.onKeyDown.bind(this)}
          onKeyUp={this.onKeyUp.bind(this)} className={`${this.state.textSize} ${this.state.colorName} text`} onFocus={this.moveCursorToEnd.bind(this)}>

    ];
  }

  moveCursorToEnd(e) {
    if (document.createRange) {
        const range = document.createRange();
        range.selectNodeContents(e.target); // Select contents of the element with the range
        range.collapse(false); // false means collapse to end rather than the start
        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    }
  }

  renderToolbar() {
    return

      <Localized id="annotationTextSize">
        <select className={`text-select`} title="Text Size" onChange={this.onChangeTextSize.bind(this)} value={this.state.textSize}>
          <Localized id="textSizeSmall"><option value="small-text">Small</option></Localized>
          <Localized id="textSizeMedium"><option value="medium-text">Medium</option></Localized>
          <Localized id="textSizeLarge"><option value="large-text">Large</option></Localized>
        </select>
      </Localized>
      <ColorPicker activeTool={this.state.tool}
        setColorCallback={this.setColor.bind(this)}
        color={this.state.color} />

      <Localized id="annotationTextConfirmButton">
        <button className={`button transparent confirm-text`} id="confirm-text" onClick={this.onClickConfirm.bind(this)} title="Confirm Text">Confirm</button>
      </Localized>
      <Localized id="annotationTextCancelButton">
        <button className={`button transparent cancel-text`} id="cancel-text" onClick={this.onClickCancel.bind(this)} title="Cancel Text">Cancel</button>
      </Localized>

;
  }

  setColor(color, colorName) {
    this.setState({color, colorName});
    this.textInput.current.focus();
  }

  onClickConfirm(e) {
    // Exit if user doesn't enter any text
    if (!this.textInput.current.textContent) {
       if (this.props.cancelTextHandler) {
          this.props.cancelTextHandler();
        }
        sendEvent("cancel-text", "text-toolbar");
        return;
    }
    const styles = window.getComputedStyle(this.textInput.current);
    const FONT_SIZE = parseInt(styles["font-size"], 10);

    // Due to line-height differences of how fonts are rendered across platforms
    // adjust text y position to one-third of difference of line-height and font-size
    const ADJUST_VERTICAL_SHIFT = (parseFloat(styles["line-height"]) - FONT_SIZE) / 3;
    const x = this.state.left + parseFloat(styles["padding-left"]);
    const y = this.state.top + TEXT_INPUT_PADDING + parseFloat(styles["line-height"]) / 2 + ADJUST_VERTICAL_SHIFT;

    const textCanvas = document.createElement("canvas");
    textCanvas.width = this.props.baseCanvas.width;
    textCanvas.height = this.props.baseCanvas.height;
    const drawingContext = textCanvas.getContext("2d");

    drawingContext.scale(this.props.canvasPixelRatio, this.props.canvasPixelRatio);
    drawingContext.textBaseline = "middle";
    drawingContext.fillStyle = styles.backgroundColor;
    drawingContext.fillRect(this.state.left,
                            this.state.top,
                            this.textInput.current.clientWidth,
                            this.textInput.current.clientHeight);
    drawingContext.fillStyle = styles.color;
    drawingContext.font = `${FONT_WEIGHT} ${FONT_SIZE}px ${FONT_STYLE}`;
    drawingContext.fillText(this.textInput.current.textContent, x, y);

    const textSelection = new Selection(this.state.left,
                                        this.state.top,
                                        this.state.left + this.textInput.current.clientWidth,
                                        this.state.top + this.textInput.current.clientHeight);

    if (this.props.confirmTextHandler) {
      this.props.confirmTextHandler(textSelection, textCanvas);
    }
    sendEvent("confirm-text", "text-toolbar");
  }

  onClickCancel(e) {
    if (this.props.cancelTextHandler) {
      this.props.cancelTextHandler();
    }
    sendEvent("cancel-text", "text-toolbar");
  }

  onKeyDown(e) {
    this.adjustX(e);
    if (e.key === "Enter") {
      e.preventDefault();
    }
  }

  onKeyUp(e) {
    // Fix to remove
 element inserted on press of space bar inside contenteditable div
    while (this.textInput.current.firstElementChild) {
      this.textInput.current.removeChild(this.textInput.current.firstElementChild);
    }
    this.adjustX(e);
  }

  adjustX(e) {
    if (previousInputText === this.textInput.current.textContent) {
      return;
    }
    const rectInput = e.target.getBoundingClientRect();
    const rectCanvas = this.props.baseCanvas.getBoundingClientRect();
    const WIDTH_DIFF = this.textInput.current.clientWidth - previousTextInputWidth;
    this.setState({left: Math.floor(rectInput.left - rectCanvas.left - WIDTH_DIFF / 2)});
    previousTextInputWidth = this.textInput.current.clientWidth;
    previousInputText = this.textInput.current.textContent;
  }

  onChangeTextSize(event) {
    const size = event.target.value;
    this.setState({textSize: size});
    this.textInput.current.focus();
  }

  onDragStart(event) {
    const style = window.getComputedStyle(event.target);
    event.dataTransfer.setData("text/plain",
      (parseFloat(style.getPropertyValue("left")) - event.clientX) +
       "," + (parseFloat(style.getPropertyValue("top")) - event.clientY));
  }

  onDragOver(event) {
    event.preventDefault();
    return false;
  }

  onDrop(event) {
    const offset = event.dataTransfer.getData("text/plain").split(",");
    const dragLeft = event.clientX + parseFloat(offset[0]);
    const dragTop = event.clientY + parseFloat(offset[1]);

    this.setState({left: dragLeft + DRAG_DIV_PADDING, top: dragTop + DRAG_DIV_PADDING});
    event.preventDefault();
    return false;
  }
};

exports.TextTool.propTypes = {
  baseCanvas: PropTypes.object,
  color: PropTypes.string,
  colorName: PropTypes.string,
  toolbarOverrideCallback: PropTypes.func,
  confirmTextHandler: PropTypes.func,
  cancelTextHandler: PropTypes.func,
  canvasPixelRatio: PropTypes.number,
  canvasCssWidth: PropTypes.number,
  canvasCssHeight: PropTypes.number,
};
<|endoftext|>


<commit_before>var core = require('../lib/core');
var util = require('../lib/util');

describe('evac tasks', function(){
  describe('parseRecipeFile()', function() {
    it('should be parse recipe file. (JSON format)', function(done){
      util.parseSettingFile(__dirname + '/fixtures/recipe/sample.json', function(err, config){
        err.should.be.false;
        config.out.stdout.should.be.a('object');
        done();
      });
    });

    it('should be parse recipe file. (YAML format)', function(done){
      util.parseSettingFile(__dirname + '/fixtures/recipe/sample.yaml', function(err, config){
        err.should.be.false;
        config.out.stdout.should.be.a('object');
        done();
      });
    });
  });

  describe('parseRecipeJson()', function(){
    it('should be parse recipe.', function(done){
      var recipe = {
        "in": {
          "staticWord": {
            "text": "test word."
          }
        },
        "filter": {
          "through": {}
        },
        "out": {
          "stdout": {}
        }
      };

      core.parseRecipeJson(recipe, function(err, message){
        err.should.be.false;
        done();
      });
    });

    it('should be parse abbreviated recipe.', function(done){
      var recipe = {
        "in": {
          "staticWord": {
            "text": "test word."
          }
        },
        "out": {
          "stdout": {}
        }
      };

      core.parseRecipeJson(recipe, function(err, message){
        err.should.be.false;
        done();
      });
    });

    it.skip('should be raise error with invalid recipe.', function(done){
      var recipe = {
        "inin": {
          "staticWord": {
            "text": "test word."
          }
        }
      };

      core.parseRecipeJson(recipe, function(err, message){
        err.should.be.not.false;
        done();
      });
    });
  });
});
<commit_msg>複数のレシピを単一のファイルに記述できる様に仕様のテスト追加<commit_after>var core = require('../lib/core');
var util = require('../lib/util');

describe('evac tasks', function(){
  describe('parseRecipeFile()', function() {
    it('should be parse recipe file. (JSON format)', function(done){
      util.parseSettingFile(__dirname + '/fixtures/recipe/sample.json', function(err, config){
        err.should.be.false;
        config.out.stdout.should.be.a('object');
        done();
      });
    });

    it('should be parse recipe file. (YAML format)', function(done){
      util.parseSettingFile(__dirname + '/fixtures/recipe/sample.yaml', function(err, config){
        err.should.be.false;
        config.out.stdout.should.be.a('object');
        done();
      });
    });
  });

  describe('parseRecipeJson()', function(){
    it('should be parse recipe.', function(done){
      var recipe = {
        "in": {
          "staticWord": {
            "text": "test word."
          }
        },
        "filter": {
          "through": {}
        },
        "out": {
          "stdout": {}
        }
      };

      core.parseRecipeJson(recipe, function(err, message){
        err.should.be.false;
        done();
      });
    });

    it('should be parse multiple recipe.', function(done){
      var recipe = [
        {
          "in": {
            "staticWord": {
              "text": "1st recipe."
            }
          },
          "filter": {
            "through": {}
          },
          "out": {
            "stdout": {}
          }
        },
        {
          "in": {
            "staticWord": {
              "text": "2nd recipe."
            }
          },
          "filter": {
            "through": {}
          },
          "out": {
            "stdout": {}
          }
        }
      ];

      core.parseRecipeJson(recipe, function(err, message){
        err.should.be.false;
        done();
      });
    });

    it('should be parse abbreviated recipe.', function(done){
      var recipe = {
        "in": {
          "staticWord": {
            "text": "test word."
          }
        },
        "out": {
          "stdout": {}
        }
      };

      core.parseRecipeJson(recipe, function(err, message){
        err.should.be.false;
        done();
      });
    });

    it.skip('should be raise error with invalid recipe.', function(done){
      var recipe = {
        "inin": {
          "staticWord": {
            "text": "test word."
          }
        }
      };

      core.parseRecipeJson(recipe, function(err, message){
        err.should.be.not.false;
        done();
      });
    });
  });
});
<|endoftext|>


<commit_before>var socket;
var chat_colors = {
    self: 'lime',
    public: 'white',
    party_from: 'pink',
    party_to: 'orange',
    guild: 'lightgreen',
    private_from: 'yellow',
    private_to: 'yellow'
};

$(document).ready(function()
{
    socket = io.connect();

    socket.on('refresh', function(response)
    {
        // Reload player data when refresh event is recieved
        ragnarok.ui.load('/player');
        populate_map(response.characters);
    });

    socket.on('chat', function(chat)
    {
        chat.color = chat_colors[chat.type];

        if(chat.type == "private_from")     chat.user = "( From: " + chat.user + " )";
        else if(chat.type == "private_to")  chat.user = "( To: " + chat.user + " )";

        var date = new Date(chat.timestamp);
        var dateString = date.getUTCFullYear() +"/"+
                          ("0" + (date.getUTCMonth()+1)).slice(-2) +"/"+
                          ("0" + date.getUTCDate()).slice(-2) + " " +
                          ("0" + date.getUTCHours()).slice(-2) + ":" +
                          ("0" + date.getUTCMinutes()).slice(-2) + ":" +
                          ("0" + date.getUTCSeconds()).slice(-2);

        chat.timestamp = date;
        ragnarok.data.chat.messages.push(chat);

        if(ragnarok.data.chat.messages.length > 100) ragnarok.data.chat.messages.shift();
        ragnarok.ui.populate.chat();
    });

    socket.on('move', function(move)
    {
        ragnarok.player.pos = move.to;
        ragnarok.ui.populate.map();

        ragnarok.map.move(move.to);
    });

    socket.on('item', function(item)
    {
        if(item.action == 'add')
        {
            ragnarok.inventory.add(item.item_id, item.quantity);
            ragnarok.ui.event.item_obtained(item.item_id, item.quantity);
        }
        else if(item.action == 'remove')
        {
            ragnarok.inventory.remove(item.item_id, item.quantity);
        }

        ragnarok.ui.clear.inventory('.inventory .ro-items');
        ragnarok.ui.populate.inventory('.inventory .ro-items', $('.ragnarok-tab-inventory.active, .ro-tab-inv.active').attr('tab'));
    });

    socket.on('map', function(map)
    {
        ragnarok.player.map = map.map;
        ragnarok.player.pos = map.pos;
        ragnarok.ui.populate.map();

        ragnarok.map.position(map.pos);
    });

    socket.on('info', function(info)
    {
        // Ensure the server didn't send us something we can't handle
        if(typeof ragnarok.lookup.info_types[info.type] != "undefined" &&
            typeof ragnarok.lookup.info_types[info.type].process == "function")
        {
            ragnarok.lookup.info_types[info.type].process(info.value);
            ragnarok.ui.populate.player();
        }
    });

    socket.on('storage', function(storage)
    {
        if(storage.status == "open")
        {
            ragnarok.window.open('storage');

            ragnarok.ui.clear.storage('.storage .ro-items');
            ragnarok.ui.populate.storage('.storage .ro-items', $('.ragnarok-tab-storage.active, .ro-tab-stor.active').attr('tab'));
        }
        else
        {
            ragnarok.window.close('storage');
        }

        if(storage.action == 'add')
        {
            ragnarok.storage.add(storage.item_id, storage.quantity);
        }
        else if(storage.action == 'remove')
        {
            ragnarok.storage.remove(storage.item_id, storage.quantity);
        }

        ragnarok.ui.clear.storage('.storage .ro-items');
        ragnarok.ui.populate.storage('.storage .ro-items', $('.ragnarok-tab-storage.active, .ro-tab-stor.active').attr('tab'));
    });

    socket.on('equip', function(equip)
    {
        if(equip.equipped)
        {
            var slot = ragnarok.lookup.equipment_slots[equip.type.equip],
                item_id = equip.item;

            ragnarok.ui.equip(item_id, slot);
        }
        else
        {
            var slot = ragnarok.lookup.equipment_slots[equip.type.equip];
            ragnarok.ui.unequip(slot);
        }

        ragnarok.inventory.equip(equip.item, equip.equipped);
        ragnarok.ui.clear.inventory('.inventory .ro-items');
        ragnarok.ui.populate.inventory('.inventory .ro-items', $('.ragnarok-tab-inventory.active, .ro-tab-inv.active').attr('tab'));
    });

    socket.on('message', function(message)
    {
        // Construct chat messages from message value
        var messages = message.value.split('\n');

        for(var i = 0, l = messages.length; i < l; i++)
        {
            var chat = {
                color: chat_colors.party_from,
                user: '|',
                message: messages[i].replace(/ /g, ' ')
            };

            ragnarok.data.chat.messages.push(chat);
            if(ragnarok.data.chat.messages.length > 100) ragnarok.data.chat.messages.shift();
        }

        ragnarok.ui.populate.chat();
    });

    socket.on('character', function(character)
    {
        // Display a character
        if(character.action == "display")
        {
            // If the character doesn't exist
            if($('#'+character.id).length == 0)
            {
                ragnarok.map.character.add(character.id, character.name, character.type, character.pos.from);
            }

            // If the character is moving
            if(character.pos.from.x != character.pos.to.x || character.pos.from.y != character.pos.to.y)
            {
                // TODO: Include character speed
                ragnarok.map.character.move(character.id, character.pos.to);
            }
        }
        else
        {
            ragnarok.map.character.remove(character.id);
        }
    });

    socket.on('vendor', function(vendor)
    {
        if(vendor.action == "display")
        {
            var title = ragnarok.template.clone('vendor-title', vendor);
            $('#'+vendor.id).append(title);
        }
        else if(vendor.action == "list")
        {
            vendor.name = $('#'+vendor.id).find('.name').text();

            for(var i = 0, l = vendor.items.length; i < l; i++)
            {
                if(!ragnarok.items) return;

                var item = vendor.items[i];
                var item_db = ragnarok.items[item.id];

                vendor.items[i].price = number_format(item.price);
                vendor.items[i].name = (item_db) ? item_db.name : 'Unknown Item!';
            }

            ragnarok.template.update('vendor-window', vendor);
            ragnarok.window.open('vendor-window');
            $('#vendor-window').css('height', 'auto');
        }
        else
        {
            $('#'+vendor.id).find('.ragnarok-shop').remove();
        }
    });

    socket.on('chat_window', function(chat)
    {
        if(chat.action == "display")
        {
            var title = ragnarok.template.clone('chat-title', chat);
            $('#'+chat.id).append(title);
        }
        else
        {
            $('#chat-'+chat.chat_id).remove();
        }
    });

});
<commit_msg>Setting color using new color features :D<commit_after>var socket;
var chat_colors = {
    self: 'lime',
    public: 'white',
    party_from: 'pink',
    party_to: 'orange',
    guild: 'lightgreen',
    private_from: 'yellow',
    private_to: 'yellow'
};

$(document).ready(function()
{
    socket = io.connect();

    socket.on('refresh', function(response)
    {
        // Reload player data when refresh event is recieved
        ragnarok.ui.load('/player');
        populate_map(response.characters);
    });

    socket.on('chat', function(chat)
    {
        chat.color = chat_colors[chat.type];

        if(chat.type == "private_from")     chat.user = "( From: " + chat.user + " )";
        else if(chat.type == "private_to")  chat.user = "( To: " + chat.user + " )";

        var date = new Date(chat.timestamp);
        var dateString = date.getUTCFullYear() +"/"+
                          ("0" + (date.getUTCMonth()+1)).slice(-2) +"/"+
                          ("0" + date.getUTCDate()).slice(-2) + " " +
                          ("0" + date.getUTCHours()).slice(-2) + ":" +
                          ("0" + date.getUTCMinutes()).slice(-2) + ":" +
                          ("0" + date.getUTCSeconds()).slice(-2);

        chat.timestamp = date;
        ragnarok.data.chat.messages.push(chat);

        if(ragnarok.data.chat.messages.length > 100) ragnarok.data.chat.messages.shift();
        ragnarok.ui.populate.chat();
    });

    socket.on('move', function(move)
    {
        ragnarok.player.pos = move.to;
        ragnarok.ui.populate.map();

        ragnarok.map.move(move.to);
    });

    socket.on('item', function(item)
    {
        if(item.action == 'add')
        {
            ragnarok.inventory.add(item.item_id, item.quantity);
            ragnarok.ui.event.item_obtained(item.item_id, item.quantity);
        }
        else if(item.action == 'remove')
        {
            ragnarok.inventory.remove(item.item_id, item.quantity);
        }

        ragnarok.ui.clear.inventory('.inventory .ro-items');
        ragnarok.ui.populate.inventory('.inventory .ro-items', $('.ragnarok-tab-inventory.active, .ro-tab-inv.active').attr('tab'));
    });

    socket.on('map', function(map)
    {
        ragnarok.player.map = map.map;
        ragnarok.player.pos = map.pos;
        ragnarok.ui.populate.map();

        ragnarok.map.position(map.pos);
    });

    socket.on('info', function(info)
    {
        // Ensure the server didn't send us something we can't handle
        if(typeof ragnarok.lookup.info_types[info.type] != "undefined" &&
            typeof ragnarok.lookup.info_types[info.type].process == "function")
        {
            ragnarok.lookup.info_types[info.type].process(info.value);
            ragnarok.ui.populate.player();
        }
    });

    socket.on('storage', function(storage)
    {
        if(storage.status == "open")
        {
            ragnarok.window.open('storage');

            ragnarok.ui.clear.storage('.storage .ro-items');
            ragnarok.ui.populate.storage('.storage .ro-items', $('.ragnarok-tab-storage.active, .ro-tab-stor.active').attr('tab'));
        }
        else
        {
            ragnarok.window.close('storage');
        }

        if(storage.action == 'add')
        {
            ragnarok.storage.add(storage.item_id, storage.quantity);
        }
        else if(storage.action == 'remove')
        {
            ragnarok.storage.remove(storage.item_id, storage.quantity);
        }

        ragnarok.ui.clear.storage('.storage .ro-items');
        ragnarok.ui.populate.storage('.storage .ro-items', $('.ragnarok-tab-storage.active, .ro-tab-stor.active').attr('tab'));
    });

    socket.on('equip', function(equip)
    {
        if(equip.equipped)
        {
            var slot = ragnarok.lookup.equipment_slots[equip.type.equip],
                item_id = equip.item;

            ragnarok.ui.equip(item_id, slot);
        }
        else
        {
            var slot = ragnarok.lookup.equipment_slots[equip.type.equip];
            ragnarok.ui.unequip(slot);
        }

        ragnarok.inventory.equip(equip.item, equip.equipped);
        ragnarok.ui.clear.inventory('.inventory .ro-items');
        ragnarok.ui.populate.inventory('.inventory .ro-items', $('.ragnarok-tab-inventory.active, .ro-tab-inv.active').attr('tab'));
    });

    socket.on('message', function(message)
    {
        // Construct chat messages from message value
        var messages = message.value.split('\n');

        for(var i = 0, l = messages.length; i < l; i++)
        {
            var chat = {
                color: chat_colors.party_from,
                user: '|',
                message: messages[i].replace(/ /g, ' ')
            };

            ragnarok.data.chat.messages.push(chat);
            if(ragnarok.data.chat.messages.length > 100) ragnarok.data.chat.messages.shift();
        }

        ragnarok.ui.populate.chat();
    });

    socket.on('character', function(character)
    {
        // Display a character
        if(character.action == "display")
        {
            // If the character doesn't exist
            if($('#'+character.id).length == 0)
            {
                ragnarok.map.character.add(character.id, character.name, character.type, character.pos.from);
            }

            // If the character is moving
            if(character.pos.from.x != character.pos.to.x || character.pos.from.y != character.pos.to.y)
            {
                // TODO: Include character speed
                ragnarok.map.character.move(character.id, character.pos.to);
            }
        }
        else
        {
            ragnarok.map.character.remove(character.id);
        }
    });

    socket.on('vendor', function(vendor)
    {
        if(vendor.action == "display")
        {
            var title = ragnarok.template.clone('vendor-title', vendor);
            $('#'+vendor.id).append(title);
        }
        else if(vendor.action == "list")
        {
            vendor.name = $('#'+vendor.id).find('.name').text();

            for(var i = 0, l = vendor.items.length; i < l; i++)
            {
                if(!ragnarok.items) return;

                var item = vendor.items[i];
                var item_db = ragnarok.items[item.id];

                vendor.items[i].color = ragnarok.ui.vendor_color(item.price);
                vendor.items[i].price = number_format(item.price);
                vendor.items[i].name = (item_db) ? item_db.name : 'Unknown Item!';
            }

            ragnarok.template.update('vendor-window', vendor);
            ragnarok.window.open('vendor-window');
            $('#vendor-window').css('height', 'auto');
        }
        else
        {
            $('#'+vendor.id).find('.ragnarok-shop').remove();
        }
    });

    socket.on('chat_window', function(chat)
    {
        if(chat.action == "display")
        {
            var title = ragnarok.template.clone('chat-title', chat);
            $('#'+chat.id).append(title);
        }
        else
        {
            $('#chat-'+chat.chat_id).remove();
        }
    });

});
<|endoftext|>


<commit_before>/**
 * EventEmitter tests
 */

(function() {
	test('Adding and retrieving listeners', function() {
		var ee = new EventEmitter();

		equal(ee.listeners('testEvent'), false, 'Checking for any listeners');

		ee.addListener('testEvent', function() {
			// Listener
		});
		equal(ee.listeners('testEvent')[0].type, 'testEvent', 'Retrieving the first listener');

		ee.addListener('testEvent', function() {
			// Another listener for the same event
		});
		equal(ee.listeners('testEvent')[1].type, 'testEvent', 'Retrieving the second listener');

		ee.addListener('anotherTestEvent', function() {
			// Listener for new event
		});
		equal(ee.listeners('anotherTestEvent')[0].type, 'anotherTestEvent', 'Retrieving the first listener for a different event');

		ee.addListener('anotherTestEvent', function() {
			// Another listener for new event
		});
		equal(ee.listeners('anotherTestEvent')[1].type, 'anotherTestEvent', 'Retrieving the second listener for a different event');

		ee.addListener('onTest', function() {
			// Listener via the alias
		});
		equal(ee.listeners('onTest')[0].type, 'onTest', 'Retrieving the first listener for a different event added via the on alias');
	});

	test('Removing listeners', function() {
		var ee = new EventEmitter();

		function testListener() {
			// Listener
		}

		function testListener2() {
			// Listener 2
		}

		ee.addListener('testEvent', testListener);
		equal(ee.listeners('testEvent')[0].type, 'testEvent', 'Retrieving the first listener');

		ee.addListener('testEvent', testListener2);
		equal(ee.listeners('testEvent')[1].type, 'testEvent', 'Retrieving the second listener');

		ee.removeListener('testEvent', testListener);
		equal(ee.listeners('testEvent')[1], undefined, 'Retrieving the second listener (should be gone)');
		equal(ee.listeners('testEvent')[0].listener, testListener2, 'First should now be the second');

		ee.removeListener('testEvent', testListener2);
		equal(ee.listeners('testEvent'), false, 'Retrieving any listeners (should be gone)');

		ee.addListener('removeAllTest', function() {
			// Listener
		});
		ee.addListener('removeAllTest', function() {
			// Another listener for the same event
		});
		equal(ee.listeners('removeAllTest')[1].type, 'removeAllTest', 'Check for a second removeAllTest listener');
		ee.removeAllListeners('removeAllTest');
		equal(ee.listeners('removeAllTest'), false, 'Retrieving any listeners from removeAllTest (should be gone)');
	});

	test('Adding and calling a once event', function() {
		var ee = new EventEmitter();

		function normalFunction() {
			// Another listener for the same event but not a once event
		}

		ee.once('onceTest', function() {
			// Listener
		});
		ee.once('onceTest', function() {
			// Another listener for the same event
		});
		ee.addListener('onceTest', normalFunction);
		equal(ee.listeners('onceTest')[2].type, 'onceTest', 'Check for a third onceTest listener');

		// Emit the once test event
		ee.emit('onceTest');
		equal(ee.listeners('onceTest')[0].listener, normalFunction, 'There should only be one survivor, the normalFunction one');
		equal(ee.listeners('onceTest')[2], undefined, 'And a second should be undefined');
	});
}());<commit_msg>Added emitting tests<commit_after>/**
 * EventEmitter tests
 */

(function() {
	test('Adding and retrieving listeners', function() {
		var ee = new EventEmitter();

		equal(ee.listeners('testEvent'), false, 'Checking for any listeners');

		ee.addListener('testEvent', function() {
			// Listener
		});
		equal(ee.listeners('testEvent')[0].type, 'testEvent', 'Retrieving the first listener');

		ee.addListener('testEvent', function() {
			// Another listener for the same event
		});
		equal(ee.listeners('testEvent')[1].type, 'testEvent', 'Retrieving the second listener');

		ee.addListener('anotherTestEvent', function() {
			// Listener for new event
		});
		equal(ee.listeners('anotherTestEvent')[0].type, 'anotherTestEvent', 'Retrieving the first listener for a different event');

		ee.addListener('anotherTestEvent', function() {
			// Another listener for new event
		});
		equal(ee.listeners('anotherTestEvent')[1].type, 'anotherTestEvent', 'Retrieving the second listener for a different event');

		ee.addListener('onTest', function() {
			// Listener via the alias
		});
		equal(ee.listeners('onTest')[0].type, 'onTest', 'Retrieving the first listener for a different event added via the on alias');
	});

	test('Removing listeners', function() {
		var ee = new EventEmitter();

		function testListener() {
			// Listener
		}

		function testListener2() {
			// Listener 2
		}

		ee.addListener('testEvent', testListener);
		equal(ee.listeners('testEvent')[0].type, 'testEvent', 'Retrieving the first listener');

		ee.addListener('testEvent', testListener2);
		equal(ee.listeners('testEvent')[1].type, 'testEvent', 'Retrieving the second listener');

		ee.removeListener('testEvent', testListener);
		equal(ee.listeners('testEvent')[1], undefined, 'Retrieving the second listener (should be gone)');
		equal(ee.listeners('testEvent')[0].listener, testListener2, 'First should now be the second');

		ee.removeListener('testEvent', testListener2);
		equal(ee.listeners('testEvent'), false, 'Retrieving any listeners (should be gone)');

		ee.addListener('removeAllTest', function() {
			// Listener
		});
		ee.addListener('removeAllTest', function() {
			// Another listener for the same event
		});
		equal(ee.listeners('removeAllTest')[1].type, 'removeAllTest', 'Check for a second removeAllTest listener');
		ee.removeAllListeners('removeAllTest');
		equal(ee.listeners('removeAllTest'), false, 'Retrieving any listeners from removeAllTest (should be gone)');
	});

	test('Emitting events', function() {
		var ee = new EventEmitter();

		ee.addListener('emittingTest', function() {
			// Listener
			ok(true, 'First called');
		});
		ee.addListener('emittingTest', function() {
			// Another listener for the same event
			ok(true, 'Second called');
		});
		ee.addListener('differentEvent', function() {
			// Another listener for the same event
			ok(false, 'Wrong event called');
		});
		ee.emit('emittingTest');
	});

	test('Adding and calling a once event', function() {
		var ee = new EventEmitter();

		function normalFunction() {
			// Another listener for the same event but not a once event
		}

		ee.once('onceTest', function() {
			// Listener
		});
		ee.once('onceTest', function() {
			// Another listener for the same event
		});
		ee.addListener('onceTest', normalFunction);
		equal(ee.listeners('onceTest')[2].type, 'onceTest', 'Check for a third onceTest listener');

		// Emit the once test event
		ee.emit('onceTest');
		equal(ee.listeners('onceTest')[0].listener, normalFunction, 'There should only be one survivor, the normalFunction one');
		equal(ee.listeners('onceTest')[2], undefined, 'And a second should be undefined');
	});
}());<|endoftext|>


<commit_before>/*global JsonML */
/*
	JsonML_BST.js
	JsonML + Browser-Side Templating (JBST) support

	Created: 2008-07-28-2337
	Modified: 2009-02-28-0902

	Copyright (c)2006-2009 Stephen M. McKamey
	Distributed under an open-source license: http://jsonml.org/license

    This file creates a JsonML.BST type containing these methods:

		// JBST + JSON => JsonML
		var jsonml = new JsonML.BST(jbst).dataBind(data);

		// JBST + JSON => DOM
		var dom = new JsonML.BST(jbst).bind(data);

		Implement filter to intercept and perform automatic filtering of the resulting DOM tree while binding:
		JsonML.BST.filter = function (element) {
			if (condition) {
				return document.createElement("foo");
			}
			return element;
		};
*/

/* namespace JsonML */
if ("undefined" === typeof window.JsonML) {
	window.JsonML = {};
}

JsonML.BST = function(/*JBST*/ jbst) {
	if (jbst instanceof JsonML.BST) {
		return jbst;
	}

	var self = this;

	// unique id for generated method names
	var g = 0;

	// recursively applies dataBind to all nodes of the template graph
	// NOTE: it is very important to replace each node with a copy,
	// otherwise it destroys the original template.
	// t: current template node being data bound
	// d: current data item being bound
	// n: index of current data item
	// j: nested JBST template
	// returns: JsonML nodes
	/*object*/ function db(/*JBST*/ t, /*object*/ d, /*int*/ n, /*JBST*/ j) {
		// process JBST node
		if (t) {
			if ("function" === typeof t) {
				// temporary method name using a counter to
				// avoid collisions when recursively calling
				var m = "$jbst."+(g++);
				try {
					// setup context for code block
					self[m] = t;
					self.data = d;
					self.jbst = j;
					self.index = isFinite(n) ? Number(n) : NaN;
					// execute in the context of template as "this"
					return self[m]();
				} finally {
					g--;
					delete self[m];
					delete self.data;
					delete self.jbst;
					delete self.index;
				}
			}

			var o;
			if (t instanceof Array) {
				// output array
				o = [];
				for (var i=0; i<t.length; i++) {
					// result
					var r = db(t[i], d, n, j);
					if (r instanceof Array && r.length && r[0] === "") {
						// result was multiple JsonML trees (documentFragment)
						r.shift();// remove fragment ident
						o = o.concat(r); // directly append children
					} else if ("object" === typeof r) {
						// result was a JsonML node (attributes or children)
						o.push(r);
					} else if ("undefined" !== typeof r && r !== null) {
						// must convert to string or JsonML will discard
						o.push(String(r));
					}
				}

				// if o has attributes, check for JBST commands
				if (o.length > 1 && ("object" === typeof o[1]) && !(o[1] instanceof Array)) {
					// visibility JBST command
					var c = o[1]["jbst:visible"];
					if ("undefined" !== typeof c) {
						// must match exactly
						if (String(c) === "false") {
							// suppress rendering of entire subtree
							return "";
						}
						// remove attribute
						delete o[1]["jbst:visible"];
					}
				}
				return o;
			}

			if ("object" === typeof t) {
				// output object
				o = {};
				// for each property in template node
				for (var p in t) {
					if (t.hasOwnProperty(p)) {
						// evaluate property's value
						var v = db(t[p], d, n, j);
						if ("undefined" !== typeof v && v !== null) {
							o[p] = String(v);
						}
					}
				}
				return o;
			}
		}

		// rest are value types, so return node directly
		return t;
	}

	// the publicly exposed instance method
	// combines JBST and JSON to produce JsonML
	/*JsonML*/ self.dataBind = function(/*object*/ data, /*int*/ index, /*JBST*/ inner) {
		if (data instanceof Array) {
			// create a document fragment to hold list
			var o = [""];

			for (var i=0; i<data.length; i++) {
				// apply template to each item in array
				o.push(db(jbst, data[i], i, inner));
			}
			return o;
		} else {
			// data is singular so apply template once
			return db(jbst, data, index, inner);
		}
	};

	/* JBST + JSON => JsonML => DOM */
	/*DOM*/ self.bind = function(/*object*/ data, /*int*/ index, /*JBST*/ inner) {

		// databind JSON data to a JBST template, resulting in a JsonML representation
		var jml = self.dataBind(data, index, inner);

		// hydrate the resulting JsonML
		return JsonML.parse(jml, JsonML.BST.filter);
	};
};

// override this to perform default filtering of the resulting DOM tree
/*DOM function(DOM)*/ JsonML.BST.filter = null;
<commit_msg>- changing JsonML.BST from constructor to factory (i.e. "JsonML.BST(jbst);" rather than "new JsonML.BST(jbst);") - further reduced redundant output of JBST server control<commit_after>/*global JsonML */
/*
	JsonML_BST.js
	JsonML + Browser-Side Templating (JBST) support

	Created: 2008-07-28-2337
	Modified: 2009-02-28-0902

	Copyright (c)2006-2009 Stephen M. McKamey
	Distributed under an open-source license: http://jsonml.org/license

    This file creates a JsonML.BST type containing these methods:

		// JBST + JSON => JsonML
		var jsonml = JsonML.BST(jbst).dataBind(data);

		// JBST + JSON => DOM
		var dom = JsonML.BST(jbst).bind(data);

		Implement filter to intercept and perform automatic filtering of the resulting DOM tree while binding:
		JsonML.BST.filter = function (element) {
			if (condition) {
				return document.createElement("foo");
			}
			return element;
		};
*/

/* namespace JsonML */
if ("undefined" === typeof window.JsonML) {
	window.JsonML = {};
}

/* wrapper */
JsonML.BST = function(/*JBST*/ jbst) {
	if (jbst instanceof JsonML.BST.init) {
		return jbst;
	}
	return new JsonML.BST.init(jbst);
};

/* ctor */
JsonML.BST.init = function(/*JBST*/ jbst) {
	var self = this;

	// unique id for generated method names
	var g = 0;

	// recursively applies dataBind to all nodes of the template graph
	// NOTE: it is very important to replace each node with a copy,
	// otherwise it destroys the original template.
	// t: current template node being data bound
	// d: current data item being bound
	// n: index of current data item
	// j: nested JBST template
	// returns: JsonML nodes
	/*object*/ function db(/*JBST*/ t, /*object*/ d, /*int*/ n, /*JBST*/ j) {
		// process JBST node
		if (t) {
			if ("function" === typeof t) {
				// temporary method name using a counter to
				// avoid collisions when recursively calling
				var m = "$jbst."+(g++);
				try {
					// setup context for code block
					self[m] = t;
					self.data = d;
					self.jbst = j;
					self.index = isFinite(n) ? Number(n) : NaN;
					// execute in the context of template as "this"
					return self[m]();
				} finally {
					g--;
					delete self[m];
					delete self.data;
					delete self.jbst;
					delete self.index;
				}
			}

			var o;
			if (t instanceof Array) {
				// output array
				o = [];
				for (var i=0; i<t.length; i++) {
					// result
					var r = db(t[i], d, n, j);
					if (r instanceof Array && r.length && r[0] === "") {
						// result was multiple JsonML trees (documentFragment)
						r.shift();// remove fragment ident
						o = o.concat(r); // directly append children
					} else if ("object" === typeof r) {
						// result was a JsonML node (attributes or children)
						o.push(r);
					} else if ("undefined" !== typeof r && r !== null) {
						// must convert to string or JsonML will discard
						o.push(String(r));
					}
				}

				// if o has attributes, check for JBST commands
				if (o.length > 1 && ("object" === typeof o[1]) && !(o[1] instanceof Array)) {
					// visibility JBST command
					var c = o[1]["jbst:visible"];
					if ("undefined" !== typeof c) {
						// must match exactly
						if (String(c) === "false") {
							// suppress rendering of entire subtree
							return "";
						}
						// remove attribute
						delete o[1]["jbst:visible"];
					}
				}
				return o;
			}

			if ("object" === typeof t) {
				// output object
				o = {};
				// for each property in template node
				for (var p in t) {
					if (t.hasOwnProperty(p)) {
						// evaluate property's value
						var v = db(t[p], d, n, j);
						if ("undefined" !== typeof v && v !== null) {
							o[p] = String(v);
						}
					}
				}
				return o;
			}
		}

		// rest are value types, so return node directly
		return t;
	}

	// the publicly exposed instance method
	// combines JBST and JSON to produce JsonML
	/*JsonML*/ self.dataBind = function(/*object*/ data, /*int*/ index, /*JBST*/ inner) {
		if (data instanceof Array) {
			// create a document fragment to hold list
			var o = [""];

			for (var i=0; i<data.length; i++) {
				// apply template to each item in array
				o.push(db(jbst, data[i], i, inner));
			}
			return o;
		} else {
			// data is singular so apply template once
			return db(jbst, data, index, inner);
		}
	};

	/* JBST + JSON => JsonML => DOM */
	/*DOM*/ self.bind = function(/*object*/ data, /*int*/ index, /*JBST*/ inner) {

		// databind JSON data to a JBST template, resulting in a JsonML representation
		var jml = self.dataBind(data, index, inner);

		// hydrate the resulting JsonML
		return JsonML.parse(jml, JsonML.BST.filter);
	};
};

/* override this to perform default filtering of the resulting DOM tree */
/*DOM function(DOM)*/ JsonML.BST.filter = null;
<|endoftext|>


<commit_before>/*global describe, it */
'use strict';

var path = require('path');
var assert = require('assert');
var helpers = require('yeoman-generator').test;

describe('Chrome Extension generator test: ', function () {
  beforeEach(function (done) {
    helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
      if (err) {
        return done(err);
      }

      this.extension = helpers.createGenerator('chrome-extension:app', [
        '../../app', [
          helpers.createDummyGenerator(),
          'mocha:app'
        ]
      ]);
      done();
    }.bind(this));
  });

  it('the generator can be required without throwing', function () {
    // not testing the actual run of generators yet
    this.app = require('../app');
  });

  it('creates expected files in no UI Action', function (done) {
    var expected = [
      'app/bower_components',
      ['bower.json', /"name": "temp"/],
      ['package.json', /"name": "temp"/],
      'Gruntfile.js',
      'app/manifest.json',
      'app/_locales/en/messages.json',
      'app/images/icon-128.png',
      'app/images/icon-16.png',
      'app/styles/main.css'
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates expected files in Browser Action', function (done) {
    var expected = [
      'app/bower_components',
      ['bower.json', /"name": "temp"/],
      ['package.json', /"name": "temp"/],
      'Gruntfile.js',
      ['app/manifest.json', /"browser_action": {\s+"default_icon": {\s+"19": "images\/icon-19.png",\s+"38": "images\/icon-38.png"\s+},\s+"default_title": "temp",\s+"default_popup": "popup.html"\s+}/],
      'app/_locales/en/messages.json',
      'app/images/icon-128.png',
      'app/images/icon-16.png',
      'app/images/icon-19.png',
      'app/images/icon-38.png',
      'app/scripts/background.js',
      'app/scripts/popup.js',
      'app/popup.html',
      'app/styles/main.css'
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'action': 'Browser'
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates expected files in Page Action', function (done) {
    var expected = [
      'app/bower_components',
      ['bower.json', /"name": "temp"/],
      ['package.json', /"name": "temp"/],
      'Gruntfile.js',
      ['app/manifest.json', /"page_action": {\s+"default_icon": {\s+"19": "images\/icon-19.png",\s+"38": "images\/icon-38.png"\s+},\s+"default_title": "temp",\s+"default_popup": "popup.html"\s+}/],
      'app/_locales/en/messages.json',
      'app/images/icon-128.png',
      'app/images/icon-16.png',
      'app/images/icon-19.png',
      'app/images/icon-38.png',
      'app/scripts/background.js',
      'app/scripts/popup.js',
      'app/popup.html',
      'app/styles/main.css'
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'action': 'Page'
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates expected files with Options Page', function (done) {
    var expected = [
      'app/bower_components',
      ['bower.json', /"name": "temp"/],
      ['package.json', /"name": "temp"/],
      'Gruntfile.js',
      ['app/manifest.json', /"options_page": "options.html"/],
      'app/_locales/en/messages.json',
      'app/images/icon-128.png',
      'app/images/icon-16.png',
      'app/scripts/background.js',
      'app/scripts/options.js',
      'app/options.html',
      'app/styles/main.css'
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'options': true
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates manifest.json with Omnibox option', function (done) {
    var expected = [
      ['app/manifest.json', /"omnibox": {\s+"keyword": "omnibox"\s+}/]
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'omnibox': 'omnibox'
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates expected files with Content-script option', function (done) {
    var expected = [
      'app/bower_components',
      ['bower.json', /"name": "temp"/],
      ['package.json', /"name": "temp"/],
      'Gruntfile.js',
      ['app/manifest.json', /"content_scripts": \[\s+{\s+"matches": \[\s+"http:\/\/\*\/\*",\s+"https:\/\/\*\/\*"\s+\],\s+"css": \[\s+"styles\/main.css"\s+\],\s+"js": \[\s+"scripts\/contentscript.js"\s+\],\s+"run_at": "document_end",\s+"all_frames": false/],
      'app/_locales/en/messages.json',
      'app/images/icon-128.png',
      'app/images/icon-16.png',
      'app/scripts/background.js',
      'app/scripts/contentscript.js',
      'app/styles/main.css'
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'contentscript': true
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates expected manifest permission properties', function (done) {
    var expected = [
      ['app/manifest.json', /"permissions"/],
      ['app/manifest.json', /"tabs"/],
      ['app/manifest.json', /"bookmarks"/],
      ['app/manifest.json', /"cookies"/],
      ['app/manifest.json', /"history"/],
      ['app/manifest.json', /\s+"http:\/\/\*\/\*",\s+"https:\/\/\*\/\*"/],
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'permission': true,
      'tabs': true,
      'bookmark': true,
      'cookie': true,
      'history': true,
      'management': true,
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

});
<commit_msg>Added description to mock prompt to pass the test<commit_after>/*global describe, it */
'use strict';

var path = require('path');
var assert = require('assert');
var helpers = require('yeoman-generator').test;

describe('Chrome Extension generator test: ', function () {
  beforeEach(function (done) {
    helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
      if (err) {
        return done(err);
      }

      this.extension = helpers.createGenerator('chrome-extension:app', [
        '../../app', [
          helpers.createDummyGenerator(),
          'mocha:app'
        ]
      ]);
      done();
    }.bind(this));
  });

  it('the generator can be required without throwing', function () {
    // not testing the actual run of generators yet
    this.app = require('../app');
  });

  it('creates expected files in no UI Action', function (done) {
    var expected = [
      'app/bower_components',
      ['bower.json', /"name": "temp"/],
      ['package.json', /"name": "temp"/],
      'Gruntfile.js',
      'app/manifest.json',
      'app/_locales/en/messages.json',
      'app/images/icon-128.png',
      'app/images/icon-16.png',
      'app/styles/main.css'
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'description': 'description',
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates expected files in Browser Action', function (done) {
    var expected = [
      'app/bower_components',
      ['bower.json', /"name": "temp"/],
      ['package.json', /"name": "temp"/],
      'Gruntfile.js',
      ['app/manifest.json', /"browser_action": {\s+"default_icon": {\s+"19": "images\/icon-19.png",\s+"38": "images\/icon-38.png"\s+},\s+"default_title": "temp",\s+"default_popup": "popup.html"\s+}/],
      'app/_locales/en/messages.json',
      'app/images/icon-128.png',
      'app/images/icon-16.png',
      'app/images/icon-19.png',
      'app/images/icon-38.png',
      'app/scripts/background.js',
      'app/scripts/popup.js',
      'app/popup.html',
      'app/styles/main.css'
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'description': 'description',
      'action': 'Browser'
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates expected files in Page Action', function (done) {
    var expected = [
      'app/bower_components',
      ['bower.json', /"name": "temp"/],
      ['package.json', /"name": "temp"/],
      'Gruntfile.js',
      ['app/manifest.json', /"page_action": {\s+"default_icon": {\s+"19": "images\/icon-19.png",\s+"38": "images\/icon-38.png"\s+},\s+"default_title": "temp",\s+"default_popup": "popup.html"\s+}/],
      'app/_locales/en/messages.json',
      'app/images/icon-128.png',
      'app/images/icon-16.png',
      'app/images/icon-19.png',
      'app/images/icon-38.png',
      'app/scripts/background.js',
      'app/scripts/popup.js',
      'app/popup.html',
      'app/styles/main.css'
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'description': 'description',
      'action': 'Page'
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates expected files with Options Page', function (done) {
    var expected = [
      'app/bower_components',
      ['bower.json', /"name": "temp"/],
      ['package.json', /"name": "temp"/],
      'Gruntfile.js',
      ['app/manifest.json', /"options_page": "options.html"/],
      'app/_locales/en/messages.json',
      'app/images/icon-128.png',
      'app/images/icon-16.png',
      'app/scripts/background.js',
      'app/scripts/options.js',
      'app/options.html',
      'app/styles/main.css'
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'description': 'description',
      'options': true
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates manifest.json with Omnibox option', function (done) {
    var expected = [
      ['app/manifest.json', /"omnibox": {\s+"keyword": "omnibox"\s+}/]
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'description': 'description',
      'omnibox': 'omnibox'
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates expected files with Content-script option', function (done) {
    var expected = [
      'app/bower_components',
      ['bower.json', /"name": "temp"/],
      ['package.json', /"name": "temp"/],
      'Gruntfile.js',
      ['app/manifest.json', /"content_scripts": \[\s+{\s+"matches": \[\s+"http:\/\/\*\/\*",\s+"https:\/\/\*\/\*"\s+\],\s+"css": \[\s+"styles\/main.css"\s+\],\s+"js": \[\s+"scripts\/contentscript.js"\s+\],\s+"run_at": "document_end",\s+"all_frames": false/],
      'app/_locales/en/messages.json',
      'app/images/icon-128.png',
      'app/images/icon-16.png',
      'app/scripts/background.js',
      'app/scripts/contentscript.js',
      'app/styles/main.css'
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'description': 'description',
      'contentscript': true
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

  it('creates expected manifest permission properties', function (done) {
    var expected = [
      ['app/manifest.json', /"permissions"/],
      ['app/manifest.json', /"tabs"/],
      ['app/manifest.json', /"bookmarks"/],
      ['app/manifest.json', /"cookies"/],
      ['app/manifest.json', /"history"/],
      ['app/manifest.json', /\s+"http:\/\/\*\/\*",\s+"https:\/\/\*\/\*"/],
    ];

    helpers.mockPrompt(this.extension, {
      'name': 'temp',
      'description': 'description',
      'permission': true,
      'tabs': true,
      'bookmark': true,
      'cookie': true,
      'history': true,
      'management': true,
    });

    this.extension.options['skip-install'] = true;
    this.extension.run({}, function () {
      helpers.assertFiles(expected);
      done();
    });
  });

});
<|endoftext|>


<commit_before>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * All rights reserved.
 */

/**
 * The ToolEvent object is received by the {@link Tool}'s mouse event handlers
 * {@link Tool#getOnMouseDown()}, {@link Tool#getOnMouseDrag()},
 * {@link Tool#getOnMouseMove()} and {@link Tool#getOnMouseUp()}. The ToolEvent
 * object is the only parameter passed to these functions and contains
 * information about the mouse event.
 *
 * Sample code:
 *
 * function onMouseUp(event) {
 * 	// the position of the mouse when it is released
 * 	print(event.point);
 * }
 *
 *
 * @author lehni
 */
var ToolEvent = this.ToolEvent = Base.extend({
	beans: true,

	initialize: function(tool, type, event) {
		this.tool = tool;
		this.type = type;
		this.event = event;
	},

	/**
	 * Convenience method to allow local overrides of point values.
	 * See application below.
	 */
	_choosePoint: function(point, toolPoint) {
		return point ? point : toolPoint ? toolPoint.clone() : null;
	},

	/**
	 * The position of the mouse in document coordinates when the event was
	 * fired.
	 *
	 * Sample code:
	 *
	 * function onMouseDrag(event) {
	 * 	// the position of the mouse when it is dragged
	 * 	print(event.point);
	 * }
	 *
	 * function onMouseUp(event) {
	 * 	// the position of the mouse when it is released
	 * 	print(event.point);
	 * }
	 *
	 */
	getPoint: function() {
		return this._choosePoint(this._point, this.tool.point);
	},

	setPoint: function(point) {
		this._point = point;
	},

	/**
	 * The position of the mouse in document coordinates when the previous
	 * event was fired.
	 */
	getLastPoint: function() {
		return this._choosePoint(this._lastPoint, this.tool.lastPoint);
	},

	setLastPoint: function(lastPoint) {
		this._lastPoint = lastPoint;
	},

	/**
	 * The position of the mouse in document coordinates when the mouse button
	 * was last clicked.
	 */
	getDownPoint: function() {
		return this._choosePoint(this._downPoint, this.tool.downPoint);
	},

	setDownPoint: function(downPoint) {
		this._downPoint = downPoint;
	},

	/**
	 * The point in the middle between {@link #getLastPoint()} and
	 * {@link #getPoint()}. This is a useful position to use when creating
	 * artwork based on the moving direction of the mouse, as returned by
	 * {@link #getDelta()}.
	 */
	getMiddlePoint: function() {
		// For explanations, see getDelta()
		if (!this._middlePoint && this.tool.lastPoint) {
			// (point + lastPoint) / 2
			return this.tool.point.add(this.tool.lastPoint).divide(2);
		}
		return this.middlePoint;
	},

	setMiddlePoint: function(middlePoint) {
		this._middlePoint = middlePoint;
	},

	/**
	 * The difference between the current position and the last position of the
	 * mouse when the event was fired. In case of the mouseup event, the
	 * difference to the mousedown position is returned.
	 */
	getDelta: function() {
		// Do not put the calculated delta into delta, since this only reserved
		// for overriding event.delta.
		// Instead, keep calculating the delta each time, so the result can be
		// directly modified by the script without changing the internal values.
		// We could cache this and use clone, but this is almost as fast...
		return this._delta && this.tool.lastPoint
		 		? this.tool.point.subtract(this.tool.lastPoint)
				: this._delta;
	},

	setDelta: function(delta) {
		this._delta = delta;
	},

	/**
	 * The number of times the mouse event was fired.
	 *
	 * Sample code:
	 *
	 * function onMouseDrag(event) {
	 * 	// the amount of times the onMouseDrag event was fired
	 * 	// since the last onMouseDown event
	 * 	print(event.count);
	 * }
	 *
	 * function onMouseUp(event) {
	 * 	// the amount of times the onMouseUp event was fired
	 * 	// since the tool was activated
	 * 	print(event.point);
	 * }
	 *
	 */
	getCount: function() {
		// Return downCount for both mouse down and up, since
		// the count is the same.
		return /^mouse(down|up)$/.test(this.type)
			? this.tool.downCount
			: this.tool.count;
	},

	setCount: function(count) {
		this.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count']
			= count;
	},

	getModifiers: function() {
		return Key.modifiers;
	},

	// TODO: implement hitTest first
	// getItem: function() {
	// 	if (this.item == null) {
	// 		var result = Document.getActiveDocument().hitTest(this.getPoint());
	// 		if (result != null) {
	// 			this.item = result.getItem();
	// 			// Find group parent
	// 			var parent = item.getParent();
	// 			while (parent instanceof Group || parent instanceof CompoundPath) {
	// 				item = parent;
	// 				parent = parent.getParent();
	// 			}
	// 		}
	// 	}
	// 	return item;
	// }
	//
	// setItem: function(Item item) {
	// 	this.item = item;
	// }

	toString: function() {
		return '{ type: ' + this.type
				+ ', point: ' + this.point
				+ ', count: ' + this.count
				+ ', modifiers: ' + this.getModifiers()
				+ ' }';
	}
});
<commit_msg>Use getters rather than beans.<commit_after>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * All rights reserved.
 */

/**
 * The ToolEvent object is received by the {@link Tool}'s mouse event handlers
 * {@link Tool#getOnMouseDown()}, {@link Tool#getOnMouseDrag()},
 * {@link Tool#getOnMouseMove()} and {@link Tool#getOnMouseUp()}. The ToolEvent
 * object is the only parameter passed to these functions and contains
 * information about the mouse event.
 *
 * Sample code:
 *
 * function onMouseUp(event) {
 * 	// the position of the mouse when it is released
 * 	print(event.point);
 * }
 *
 *
 * @author lehni
 */
var ToolEvent = this.ToolEvent = Base.extend({
	beans: true,

	initialize: function(tool, type, event) {
		this.tool = tool;
		this.type = type;
		this.event = event;
	},

	/**
	 * Convenience method to allow local overrides of point values.
	 * See application below.
	 */
	_choosePoint: function(point, toolPoint) {
		return point ? point : toolPoint ? toolPoint.clone() : null;
	},

	/**
	 * The position of the mouse in document coordinates when the event was
	 * fired.
	 *
	 * Sample code:
	 *
	 * function onMouseDrag(event) {
	 * 	// the position of the mouse when it is dragged
	 * 	print(event.point);
	 * }
	 *
	 * function onMouseUp(event) {
	 * 	// the position of the mouse when it is released
	 * 	print(event.point);
	 * }
	 *
	 */
	getPoint: function() {
		return this._choosePoint(this._point, this.tool.point);
	},

	setPoint: function(point) {
		this._point = point;
	},

	/**
	 * The position of the mouse in document coordinates when the previous
	 * event was fired.
	 */
	getLastPoint: function() {
		return this._choosePoint(this._lastPoint, this.tool.lastPoint);
	},

	setLastPoint: function(lastPoint) {
		this._lastPoint = lastPoint;
	},

	/**
	 * The position of the mouse in document coordinates when the mouse button
	 * was last clicked.
	 */
	getDownPoint: function() {
		return this._choosePoint(this._downPoint, this.tool.downPoint);
	},

	setDownPoint: function(downPoint) {
		this._downPoint = downPoint;
	},

	/**
	 * The point in the middle between {@link #getLastPoint()} and
	 * {@link #getPoint()}. This is a useful position to use when creating
	 * artwork based on the moving direction of the mouse, as returned by
	 * {@link #getDelta()}.
	 */
	getMiddlePoint: function() {
		// For explanations, see getDelta()
		if (!this._middlePoint && this.tool.lastPoint) {
			// (point + lastPoint) / 2
			return this.tool.point.add(this.tool.lastPoint).divide(2);
		}
		return this.middlePoint;
	},

	setMiddlePoint: function(middlePoint) {
		this._middlePoint = middlePoint;
	},

	/**
	 * The difference between the current position and the last position of the
	 * mouse when the event was fired. In case of the mouseup event, the
	 * difference to the mousedown position is returned.
	 */
	getDelta: function() {
		// Do not put the calculated delta into delta, since this only reserved
		// for overriding event.delta.
		// Instead, keep calculating the delta each time, so the result can be
		// directly modified by the script without changing the internal values.
		// We could cache this and use clone, but this is almost as fast...
		return this._delta && this.tool.lastPoint
		 		? this.tool.point.subtract(this.tool.lastPoint)
				: this._delta;
	},

	setDelta: function(delta) {
		this._delta = delta;
	},

	/**
	 * The number of times the mouse event was fired.
	 *
	 * Sample code:
	 *
	 * function onMouseDrag(event) {
	 * 	// the amount of times the onMouseDrag event was fired
	 * 	// since the last onMouseDown event
	 * 	print(event.count);
	 * }
	 *
	 * function onMouseUp(event) {
	 * 	// the amount of times the onMouseUp event was fired
	 * 	// since the tool was activated
	 * 	print(event.point);
	 * }
	 *
	 */
	getCount: function() {
		// Return downCount for both mouse down and up, since
		// the count is the same.
		return /^mouse(down|up)$/.test(this.type)
			? this.tool.downCount
			: this.tool.count;
	},

	setCount: function(count) {
		this.tool[/^mouse(down|up)$/.test(this.type) ? 'downCount' : 'count']
			= count;
	},

	getModifiers: function() {
		return Key.modifiers;
	},

	// TODO: implement hitTest first
	// getItem: function() {
	// 	if (this.item == null) {
	// 		var result = Document.getActiveDocument().hitTest(this.getPoint());
	// 		if (result != null) {
	// 			this.item = result.getItem();
	// 			// Find group parent
	// 			var parent = item.getParent();
	// 			while (parent instanceof Group || parent instanceof CompoundPath) {
	// 				item = parent;
	// 				parent = parent.getParent();
	// 			}
	// 		}
	// 	}
	// 	return item;
	// }
	//
	// setItem: function(Item item) {
	// 	this.item = item;
	// }

	toString: function() {
		return '{ type: ' + this.type
				+ ', point: ' + this.getPoint()
				+ ', count: ' + this.getCount()
				+ ', modifiers: ' + this.getModifiers()
				+ ' }';
	}
});
<|endoftext|>