<commit_before>/**
 * OpenEyes
 *
 * (C) Moorfields Eye Hospital NHS Foundation Trust, 2008-2011
 * (C) OpenEyes Foundation, 2011-2013
 * This file is part of OpenEyes.
 * OpenEyes is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * OpenEyes is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along with OpenEyes in a file titled COPYING. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package OpenEyes
 * @link http://www.openeyes.org.uk
 * @author OpenEyes <info@openeyes.org.uk>
 * @copyright Copyright (c) 2008-2011, Moorfields Eye Hospital NHS Foundation Trust
 * @copyright Copyright (c) 2011-2013, OpenEyes Foundation
 * @license http://www.gnu.org/licenses/gpl-3.0.html The GNU General Public License V3.0
 */

(function(exports, Util, EventEmitter) {

	'use strict';

	// Set the jQuery UI Dialog default options.
	$.extend($.ui.dialog.prototype.options, {
		dialogClass: 'dialog',
		show: 'fade'
	});

	/**
	 * Dialog constructor.
	 * @constructor
	 * @name OpenEyes.UI.Dialog
	 * @tutorial dialog
	 * @memberOf OpenEyes.UI
	 * @extends OpenEyes.Util.EventEmitter
	 * @example
	 * var dialog = new OpenEyes.UI.Dialog({
	 *	title: 'Title here',
	 *	content: 'Here is some content.'
	 * });
	 * dialog.on('open', function() {
	 *	console.log('The dialog is now open');
	 * });
	 * dialog.open();
	 */
	function Dialog(options) {

		EventEmitter.call(this);

		this.options = $.extend(true, {}, Dialog._defaultOptions, options);

		this.create();
		this.bindEvents();

		// Load dialog content in an iframe.
		if (this.options.iframe) {
			this.loadIframeContent();
		}
		// Load dialog content via an AJAX request.
		else if (this.options.url) {
			this.loadContent();
		}
	}

	Util.inherits(EventEmitter, Dialog);

	/**
	 * The default dialog options. Custom options will be merged with these.
	 * @name OpenEyes.UI.Dialog#_defaultOptions
	 * @property {mixed} [content=null] - Content to be displayed in the dialog.
	 * This option accepts multiple types, including strings, DOM elements, jQuery instances, etc.
	 * @property {boolean} [destroyOnClose=true] - Destroy the dialog when it is closed?
	 * @property {string|null} [url=null] - A URL string to load the dialog content in via an
	 * AJAX request.
	 * @property {object|null} [data=null] - Request data used when loading dialog content
	 * via an AJAX request.
	 * @property {string|null} [iframe=null] - A URL string to load the dialog content
	 * in via an iFrame.
	 * @property {string|null} [title=null] - The dialog title.
	 * @property {string|null} [dialogClass=dialog] - A CSS class string to be added to
	 * the main dialog container.
	 * @property {boolean} [constrainToViewport=false] - Constrain the dialog dimensions
	 * so that it is never displayed outside of the window viewport?
	 * @property {integer|string} [width=400] - The dialog width.
	 * @property {integer|string} [height=auto] - The dialog height.
	 * @private
	 */
	Dialog._defaultOptions = {
		content: null,
		destroyOnClose: true,
		url: null,
		data: null,
		id: null,
		iframe: null,
		autoOpen: false,
		title: null,
		modal: true,
		dialogClass: 'dialog',
		resizable: false,
		draggable: false,
		constrainToViewport: false,
		width: 440,
		height: 'auto',
		minHeight: 'auto',
		show: 'fade'
	};

	/**
	 * Creates and stores the dialog container, and creates a new jQuery UI
	 * instance on the container.
	 * @name OpenEyes.UI.Dialog#create
	 * @method
	 * @private
	 */
	Dialog.prototype.create = function() {

		// Create the dialog content div.
		this.content = $('<div />', { id: this.options.id });

		// Add default content (if any exists)
		this.setContent(this.options.content);

		// Create the jQuery UI dialog.
		this.content.dialog(this.options);

		// Store a reference to the jQuery UI dialog instance.
		this.instance = this.content.data('ui-dialog');
	};

	/**
	 * Add content to the dialog.
	 * @name OpenEyes.UI.Dialog#setContent
	 * @method
	 * @public
	 */
	Dialog.prototype.setContent = function(content) {
		if (typeof(this.getContent) == 'function') {
			var options = $.extend({}, this.options, {content: content});
			content = this.getContent(options);
		}
		this.content.html(content);
	};

	/**
	 * Binds common dialog event handlers.
	 * @name OpenEyes.UI.Dialog#create
	 * @method
	 * @private
	 */
	Dialog.prototype.bindEvents = function() {
		this.content.on({
			dialogclose: this.onDialogClose.bind(this),
			dialogopen: this.onDialogOpen.bind(this)
		});
	};

	/**
	 * Gets a script template from the DOM, compiles it using Mustache, and
	 * returns the HTML.
	 * @name OpenEyes.UI.Dialog#compileTemplate
	 * @method
	 * @private
	 * @param {object} options - An options object container the template selector and data.
	 * @returns {string}
	 */
	Dialog.prototype.compileTemplate = function(options) {

		var template = $(options.selector).html();

		if (!template) {
			throw new Error('Unable to compile dialog template. Template not found: ' + options.selector);
		}

		return Mustache.render(template, options.data || {});
	};

	/**
	 * Sets the dialog to be in a loading state.
	 * @name OpenEyes.UI.Dialog#setLoadingState
	 * @method
	 * @private
	 */
	Dialog.prototype.setLoadingState = function() {
		this.content.addClass('loading');
		this.setTitle('Loading...');
	};

	/**
	 * Removes the loading state from the dialog.
	 * @name OpenEyes.UI.Dialog#removeLoadingState
	 * @method
	 * @private
	 */
	Dialog.prototype.removeLoadingState = function() {
		this.content.removeClass('loading');
	};

	/**
	 * Sets a 'loading' message and retrieves the dialog content via AJAX.
	 * @name OpenEyes.UI.Dialog#loadContent
	 * @method
	 * @private
	 */
	Dialog.prototype.loadContent = function() {

		this.setLoadingState();

		this.xhr = $.ajax({
			url: this.options.url,
			data: this.options.data
		});

		this.xhr.done(this.onContentLoadSuccess.bind(this));
		this.xhr.fail(this.onContentLoadFail.bind(this));
		this.xhr.always(this.onContentLoad.bind(this));
	};

	/**
	 * Sets a 'loading' message and creates an iframe with the appropriate src attribute.
	 * @name OpenEyes.UI.Dialog#loadIframeContent
	 * @method
	 * @private
	 */
	Dialog.prototype.loadIframeContent = function() {

		this.setLoadingState();

		this.iframe = $('<iframe />', {
			width: '100%',
			height: '99%',
			frameborder: 0
		}).hide();

		// We're intentionally setting the load handler before setting the src.
		this.iframe.on('load', this.onIframeLoad.bind(this));
		this.iframe.attr({
			src: this.options.iframe,
		});

		// Add the iframe to the DOM.
		this.setContent(this.iframe);
	};

	/**
	 * Sets the dialog title.
	 * @name OpenEyes.UI.Dialog#setTitle
	 * @method
	 * @public
	 */
	Dialog.prototype.setTitle = function(title) {
		this.instance.option('title', title);
	};

	/**
	 * Repositions the dialog in the center of the page.
	 * @name OpenEyes.UI.Dialog#reposition
	 * @method
	 * @public
	 */
	Dialog.prototype.reposition = function() {
		this.instance._position(this.instance._position());
	};

	/**
	 * Calculates the dialog dimensions. If OpenEyes.UI.Dialog#options.constrainToViewport is
	 * set, then the dimensions will be calculated so that the dialog will not be
	 * displayed outside of the browser viewport.
	 * @name OpenEyes.UI.Dialog#getDimensions
	 * @method
	 * @private
	 */
	Dialog.prototype.getDimensions = function() {

		var dimensions = {
			width: this.options.width,
			height: this.options.height
		};

		if (this.options.constrainToViewport) {
			var actualDimensions = this.getActualDimensions();
			var offset = 40;
			dimensions.width = Math.min(actualDimensions.width, $(window).width() - offset);
			dimensions.height = Math.min(actualDimensions.height, $(window).height() - offset);
		}

		return dimensions;
	};

	/**
	 * Gets the actual dimensions of the dialog. We need to ensure the dialog
	 * is open to calculate the dimensions.
	 * @return {object} An object containing the width and height dimensions.
	 */
	Dialog.prototype.getActualDimensions = function() {

		var options = {
			show: this.options.show,
			modal: this.options.modal,
			destroyOnClose: this.options.destroyOnClose
		};

		this.instance._setOptions($.extend(this.options, {
			show: null,
			destroyOnClose: false,
			modal: false
		}));

		this.instance.open();

		var dimensions = {
			width: parseInt(this.options.width, 10) || this.instance.uiDialog.outerWidth(),
			height: parseInt(this.options.height, 10) || this.instance.uiDialog.outerHeight()
		};

		this.instance.close();
		this.instance._setOptions($.extend(this.options, options));

		return dimensions;
	};

	/**
	 * Calculates and sets the dialog dimensions.
	 * @name OpenEyes.UI.Dialog#setDimensions
	 * @method
	 * @private
	 */
	Dialog.prototype.setDimensions = function() {
		var dimensions = this.getDimensions();
		this.instance.option('width', dimensions.width);
		this.instance.option('height', dimensions.height);
	};

	/**
	 * Opens (shows) the dialog.
	 * @name OpenEyes.UI.Dialog#open
	 * @method
	 * @public
	 */
	Dialog.prototype.open = function() {
		this.setDimensions();
		this.instance.open();
		this.reposition();
	};

	/**
	 * Closes (hides) the dialog.
	 * @name OpenEyes.UI.Dialog#close
	 * @method
	 * @public
	 */
	Dialog.prototype.close = function() {
		this.instance.close();
	};

	/**
	 * Destroys the dialog. Removes all elements from the DOM and detaches all
	 * event handlers.
	 * @name OpenEyes.UI.Dialog#destroy
	 * @fires OpenEyes.UI.Dialog#destroy
	 * @method
	 * @public
	 *
	 */
	Dialog.prototype.destroy = function() {

		if (this.xhr) {
			this.xhr.abort();
		}
		if (this.iframe) {
			this.iframe.remove();
		}

		this.instance.destroy();
		this.content.remove();

		/**
		 * Emitted after the dialog has been destroyed and completed removed from the DOM.
		 *
		 * @event OpenEyes.UI.Dialog#destroy
		 */
		this.emit('destroy');
	};

	/** Event handlers */

	/**
	 * Emit the 'open' event after the dialog has opened.
	 * @name OpenEyes.UI.Dialog#onDialogOpen
	 * @fires OpenEyes.UI.Dialog#open
	 * @method
	 * @private
	 */
	Dialog.prototype.onDialogOpen = function() {
		/**
		 * Emitted after the dialog has opened.
		 *
		 * @event OpenEyes.UI.Dialog#open
		 */
		this.emit('open');
	};

	/**
	 * Emit the 'close' event after the dialog has closed, and optionally destroy
	 * the dialog.
	 * @name OpenEyes.UI.Dialog#onDialogClose
	 * @fires OpenEyes.UI.Dialog#close
	 * @method
	 * @private
	 */
	Dialog.prototype.onDialogClose = function() {
		/**
		 * Emitted after the dialog has closed.
		 *
		 * @event OpenEyes.UI.Dialog#close
		 */
		this.emit('close');

		if (this.options.destroyOnClose) {
			this.destroy();
		}
	};

	/**
	 * Content load handler. This method is always executed *after* the content
	 * request completes (whether there was an error or not), and is executed after
	 * any success or fail handlers. This method removes the loading state of the
	 * dialog, and repositions it in the center of the screen.
	 * @name OpenEyes.UI.Dialog#onContentLoad
	 * @method
	 * @private
	 */
	Dialog.prototype.onContentLoad = function() {
		this.removeLoadingState();
		this.setDimensions();
		this.reposition();
	};

	/**
	 * Content load success handler. Sets the dialog content to be the response of
	 * the content request.
	 * @name OpenEyes.UI.Dialog#onContentLoadSuccess
	 * @method
	 * @private
	 */
	Dialog.prototype.onContentLoadSuccess = function(response) {
		this.setTitle(this.options.title);
		this.setContent(response);
	};

	/**
	 * Content load fail handler. This method is executed if the content request
	 * fails, and shows an error message.
	 * @name OpenEyes.UI.Dialog#onContentLoadFail
	 * @method
	 * @private
	 */
	Dialog.prototype.onContentLoadFail = function() {
		this.setTitle('Error');
		this.setContent('Sorry, there was an error retrieving the content. Please try again.');
	};

	/**
	 * iFrame load handler. This method is always executed after the iFrame
	 * source is loaded. This method removes the loading state of the
	 * dialog, and repositions it in the center of the screen.
	 * @name OpenEyes.UI.Dialog#onIframeLoad
	 * @method
	 * @private
	 */
	Dialog.prototype.onIframeLoad = function() {
		this.setTitle(this.options.title);
		this.iframe.show();
		this.onContentLoad();
	};

	exports.Dialog = Dialog;

}(OpenEyes.UI, OpenEyes.Util, OpenEyes.Util.EventEmitter));<commit_msg>[OE-4288] Fixed forced closing of dialog.<commit_after>/**
 * OpenEyes
 *
 * (C) Moorfields Eye Hospital NHS Foundation Trust, 2008-2011
 * (C) OpenEyes Foundation, 2011-2013
 * This file is part of OpenEyes.
 * OpenEyes is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * OpenEyes is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along with OpenEyes in a file titled COPYING. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package OpenEyes
 * @link http://www.openeyes.org.uk
 * @author OpenEyes <info@openeyes.org.uk>
 * @copyright Copyright (c) 2008-2011, Moorfields Eye Hospital NHS Foundation Trust
 * @copyright Copyright (c) 2011-2013, OpenEyes Foundation
 * @license http://www.gnu.org/licenses/gpl-3.0.html The GNU General Public License V3.0
 */

(function(exports, Util, EventEmitter) {

	'use strict';

	// Set the jQuery UI Dialog default options.
	$.extend($.ui.dialog.prototype.options, {
		dialogClass: 'dialog',
		show: 'fade'
	});

	/**
	 * Dialog constructor.
	 * @constructor
	 * @name OpenEyes.UI.Dialog
	 * @tutorial dialog
	 * @memberOf OpenEyes.UI
	 * @extends OpenEyes.Util.EventEmitter
	 * @example
	 * var dialog = new OpenEyes.UI.Dialog({
	 *	title: 'Title here',
	 *	content: 'Here is some content.'
	 * });
	 * dialog.on('open', function() {
	 *	console.log('The dialog is now open');
	 * });
	 * dialog.open();
	 */
	function Dialog(options) {

		EventEmitter.call(this);

		this.options = $.extend(true, {}, Dialog._defaultOptions, options);

		this.create();
		this.bindEvents();

		// Load dialog content in an iframe.
		if (this.options.iframe) {
			this.loadIframeContent();
		}
		// Load dialog content via an AJAX request.
		else if (this.options.url) {
			this.loadContent();
		}
	}

	Util.inherits(EventEmitter, Dialog);

	/**
	 * The default dialog options. Custom options will be merged with these.
	 * @name OpenEyes.UI.Dialog#_defaultOptions
	 * @property {mixed} [content=null] - Content to be displayed in the dialog.
	 * This option accepts multiple types, including strings, DOM elements, jQuery instances, etc.
	 * @property {boolean} [destroyOnClose=true] - Destroy the dialog when it is closed?
	 * @property {string|null} [url=null] - A URL string to load the dialog content in via an
	 * AJAX request.
	 * @property {object|null} [data=null] - Request data used when loading dialog content
	 * via an AJAX request.
	 * @property {string|null} [iframe=null] - A URL string to load the dialog content
	 * in via an iFrame.
	 * @property {string|null} [title=null] - The dialog title.
	 * @property {string|null} [dialogClass=dialog] - A CSS class string to be added to
	 * the main dialog container.
	 * @property {boolean} [constrainToViewport=false] - Constrain the dialog dimensions
	 * so that it is never displayed outside of the window viewport?
	 * @property {integer|string} [width=400] - The dialog width.
	 * @property {integer|string} [height=auto] - The dialog height.
	 * @private
	 */
	Dialog._defaultOptions = {
		content: null,
		destroyOnClose: true,
		url: null,
		data: null,
		id: null,
		iframe: null,
		autoOpen: false,
		title: null,
		modal: true,
		dialogClass: 'dialog',
		resizable: false,
		draggable: false,
		constrainToViewport: false,
		width: 440,
		height: 'auto',
		minHeight: 'auto',
		show: 'fade'
	};

	/**
	 * Creates and stores the dialog container, and creates a new jQuery UI
	 * instance on the container.
	 * @name OpenEyes.UI.Dialog#create
	 * @method
	 * @private
	 */
	Dialog.prototype.create = function() {

		// Create the dialog content div.
		this.content = $('<div />', { id: this.options.id });

		// Add default content (if any exists)
		this.setContent(this.options.content);

		// Create the jQuery UI dialog.
		this.content.dialog(this.options);

		// Store a reference to the jQuery UI dialog instance.
		this.instance = this.content.data('ui-dialog');
	};

	/**
	 * Add content to the dialog.
	 * @name OpenEyes.UI.Dialog#setContent
	 * @method
	 * @public
	 */
	Dialog.prototype.setContent = function(content) {
		if (typeof(this.getContent) == 'function') {
			var options = $.extend({}, this.options, {content: content});
			content = this.getContent(options);
		}
		this.content.html(content);
	};

	/**
	 * Binds common dialog event handlers.
	 * @name OpenEyes.UI.Dialog#create
	 * @method
	 * @private
	 */
	Dialog.prototype.bindEvents = function() {
		this.content.on({
			dialogclose: this.onDialogClose.bind(this),
			dialogopen: this.onDialogOpen.bind(this)
		});
	};

	/**
	 * Gets a script template from the DOM, compiles it using Mustache, and
	 * returns the HTML.
	 * @name OpenEyes.UI.Dialog#compileTemplate
	 * @method
	 * @private
	 * @param {object} options - An options object container the template selector and data.
	 * @returns {string}
	 */
	Dialog.prototype.compileTemplate = function(options) {

		var template = $(options.selector).html();

		if (!template) {
			throw new Error('Unable to compile dialog template. Template not found: ' + options.selector);
		}

		return Mustache.render(template, options.data || {});
	};

	/**
	 * Sets the dialog to be in a loading state.
	 * @name OpenEyes.UI.Dialog#setLoadingState
	 * @method
	 * @private
	 */
	Dialog.prototype.setLoadingState = function() {
		this.content.addClass('loading');
		this.setTitle('Loading...');
	};

	/**
	 * Removes the loading state from the dialog.
	 * @name OpenEyes.UI.Dialog#removeLoadingState
	 * @method
	 * @private
	 */
	Dialog.prototype.removeLoadingState = function() {
		this.content.removeClass('loading');
	};

	/**
	 * Sets a 'loading' message and retrieves the dialog content via AJAX.
	 * @name OpenEyes.UI.Dialog#loadContent
	 * @method
	 * @private
	 */
	Dialog.prototype.loadContent = function() {

		this.setLoadingState();

		this.xhr = $.ajax({
			url: this.options.url,
			data: this.options.data
		});

		this.xhr.done(this.onContentLoadSuccess.bind(this));
		this.xhr.fail(this.onContentLoadFail.bind(this));
		this.xhr.always(this.onContentLoad.bind(this));
	};

	/**
	 * Sets a 'loading' message and creates an iframe with the appropriate src attribute.
	 * @name OpenEyes.UI.Dialog#loadIframeContent
	 * @method
	 * @private
	 */
	Dialog.prototype.loadIframeContent = function() {

		this.setLoadingState();

		this.iframe = $('<iframe />', {
			width: '100%',
			height: '99%',
			frameborder: 0
		}).hide();

		// We're intentionally setting the load handler before setting the src.
		this.iframe.on('load', this.onIframeLoad.bind(this));
		this.iframe.attr({
			src: this.options.iframe,
		});

		// Add the iframe to the DOM.
		this.setContent(this.iframe);
	};

	/**
	 * Sets the dialog title.
	 * @name OpenEyes.UI.Dialog#setTitle
	 * @method
	 * @public
	 */
	Dialog.prototype.setTitle = function(title) {
		this.instance.option('title', title);
	};

	/**
	 * Repositions the dialog in the center of the page.
	 * @name OpenEyes.UI.Dialog#reposition
	 * @method
	 * @public
	 */
	Dialog.prototype.reposition = function() {
		this.instance._position(this.instance._position());
	};

	/**
	 * Calculates the dialog dimensions. If OpenEyes.UI.Dialog#options.constrainToViewport is
	 * set, then the dimensions will be calculated so that the dialog will not be
	 * displayed outside of the browser viewport.
	 * @name OpenEyes.UI.Dialog#getDimensions
	 * @method
	 * @private
	 */
	Dialog.prototype.getDimensions = function() {

		var dimensions = {
			width: this.options.width,
			height: this.options.height
		};

		// We're just ensuring the maximum height of the dialog does not exceed either
		// the specified height (set in the options), or the height of the viewport. We're
		// not 'fitting' to the viewport.
		if (this.options.constrainToViewport) {
			var actualDimensions = this.getActualDimensions();
			var offset = 40;
			dimensions.width = Math.min(actualDimensions.width, $(window).width() - offset);
			dimensions.height = Math.min(actualDimensions.height, $(window).height() - offset);
		}

		return dimensions;
	};

	/**
	 * Gets the actual dimensions of the dialog. We need to ensure the dialog
	 * is open to calculate the dimensions.
	 * @return {object} An object containing the width and height dimensions.
	 */
	Dialog.prototype.getActualDimensions = function() {

		var isOpen = this.instance.isOpen();
		var destroyOnClose = this.options.destroyOnClose;

		if (!isOpen) {
			this.options.destroyOnClose = false;
			this.instance.open();
		}

		var dimensions = {
			width: parseInt(this.options.width, 10) || this.instance.uiDialog.outerWidth(),
			height: parseInt(this.options.height, 10) || this.instance.uiDialog.outerHeight()
		};

		if (!isOpen) {
			this.instance.close();
			this.options.destroyOnClose = destroyOnClose;
		}

		return dimensions;
	};

	/**
	 * Calculates and sets the dialog dimensions.
	 * @name OpenEyes.UI.Dialog#setDimensions
	 * @method
	 * @private
	 */
	Dialog.prototype.setDimensions = function() {
		var dimensions = this.getDimensions();
		this.instance.option('width', dimensions.width);
		this.instance.option('height', dimensions.height);
	};

	/**
	 * Opens (shows) the dialog.
	 * @name OpenEyes.UI.Dialog#open
	 * @method
	 * @public
	 */
	Dialog.prototype.open = function() {
		this.setDimensions();
		this.instance.open();
		this.reposition();
	};

	/**
	 * Closes (hides) the dialog.
	 * @name OpenEyes.UI.Dialog#close
	 * @method
	 * @public
	 */
	Dialog.prototype.close = function() {
		this.instance.close();
	};

	/**
	 * Destroys the dialog. Removes all elements from the DOM and detaches all
	 * event handlers.
	 * @name OpenEyes.UI.Dialog#destroy
	 * @fires OpenEyes.UI.Dialog#destroy
	 * @method
	 * @public
	 *
	 */
	Dialog.prototype.destroy = function() {

		if (this.xhr) {
			this.xhr.abort();
		}
		if (this.iframe) {
			this.iframe.remove();
		}

		this.instance.destroy();
		this.content.remove();

		/**
		 * Emitted after the dialog has been destroyed and completed removed from the DOM.
		 *
		 * @event OpenEyes.UI.Dialog#destroy
		 */
		this.emit('destroy');
	};

	/** Event handlers */

	/**
	 * Emit the 'open' event after the dialog has opened.
	 * @name OpenEyes.UI.Dialog#onDialogOpen
	 * @fires OpenEyes.UI.Dialog#open
	 * @method
	 * @private
	 */
	Dialog.prototype.onDialogOpen = function() {
		/**
		 * Emitted after the dialog has opened.
		 *
		 * @event OpenEyes.UI.Dialog#open
		 */
		this.emit('open');
	};

	/**
	 * Emit the 'close' event after the dialog has closed, and optionally destroy
	 * the dialog.
	 * @name OpenEyes.UI.Dialog#onDialogClose
	 * @fires OpenEyes.UI.Dialog#close
	 * @method
	 * @private
	 */
	Dialog.prototype.onDialogClose = function() {
		/**
		 * Emitted after the dialog has closed.
		 *
		 * @event OpenEyes.UI.Dialog#close
		 */
		this.emit('close');

		if (this.options.destroyOnClose) {
			this.destroy();
		}
	};

	/**
	 * Content load handler. This method is always executed *after* the content
	 * request completes (whether there was an error or not), and is executed after
	 * any success or fail handlers. This method removes the loading state of the
	 * dialog, and repositions it in the center of the screen.
	 * @name OpenEyes.UI.Dialog#onContentLoad
	 * @method
	 * @private
	 */
	Dialog.prototype.onContentLoad = function() {
		this.removeLoadingState();
		this.setDimensions();
		this.reposition();
	};

	/**
	 * Content load success handler. Sets the dialog content to be the response of
	 * the content request.
	 * @name OpenEyes.UI.Dialog#onContentLoadSuccess
	 * @method
	 * @private
	 */
	Dialog.prototype.onContentLoadSuccess = function(response) {
		this.setTitle(this.options.title);
		this.setContent(response);
	};

	/**
	 * Content load fail handler. This method is executed if the content request
	 * fails, and shows an error message.
	 * @name OpenEyes.UI.Dialog#onContentLoadFail
	 * @method
	 * @private
	 */
	Dialog.prototype.onContentLoadFail = function() {
		this.setTitle('Error');
		this.setContent('Sorry, there was an error retrieving the content. Please try again.');
	};

	/**
	 * iFrame load handler. This method is always executed after the iFrame
	 * source is loaded. This method removes the loading state of the
	 * dialog, and repositions it in the center of the screen.
	 * @name OpenEyes.UI.Dialog#onIframeLoad
	 * @method
	 * @private
	 */
	Dialog.prototype.onIframeLoad = function() {
		this.setTitle(this.options.title);
		this.iframe.show();
		this.onContentLoad();
	};

	exports.Dialog = Dialog;

}(OpenEyes.UI, OpenEyes.Util, OpenEyes.Util.EventEmitter));<|endoftext|>


<commit_before>//= require vendor/jquery.min
//= require plugins/jquery.typed.min

$(document).ready(function(){

  $("body").addClass("js");

  // toggle overlay navigation
  $(document).on('click', '.overlay__menu-trigger', function() {
    // in Firefox transitions break when parent overflow is changed, so we need to wait for the end of the transition to give the body an overflow hidden
    if( $('.overlay__menu').hasClass('is--visible') ) {
      $('.overlay__menu').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
      $('#screen').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    }
    else {
      $('.overlay__menu').addClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
      $('#screen').addClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    }
  });

  // close overlay navigation on button click
  $('.overlay__menu-close, #screen').on('click', function(){
    $('.overlay__menu').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    $('#screen').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
  });

  // open/close overlay navigation on focus
  $('.overlay__menu-item a').on('focus', function(){
    $('.overlay__menu').addClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    $('#screen').addClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
  });
  $('.overlay__menu-close').on('focus', function(){
    $('.overlay__menu').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    $('#screen').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
  });

  // close menu on [esc]
  $(document).on('keydown', function(e){
    if ( e.keyCode === 27 ) { // ESC key
      $('.overlay__menu').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
      $('#screen').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    }
  });

  // home page auto typing
  $("#js-home-typed").typed({
    strings: ["Hello^250 my name is Mî̽̿ͫc͑̔̃͂h͂̽ͤ̊ͭͣa͛̓̍̓el̓͌̂̀̆ Rͩͤ͂̄o̾̽̈́͆ͨ̚s͋̌̊̐e. ^500  I am just another boring, ^250 tattooed, ^250 time traveling designer from Buffalo New York.^500  I enjoy eating chicken wings, ^500 sketching on an iPad, ^500 and playing Xbox.^500  Here you will find a collection of my writing, ^750 Paper by FiftyThree tutorials, ^750 and other creative endeavors."],
    contentType: "html",
    startDelay: 0,
    backDelay: 3000,
    callback: function(){
      glitch_secondary();
    }
  });

  // 404 page auto typing
  $("#js-404-typed").typed({
    strings: ["Your Pixels are on Another Canvas ^500  Sorry, but the page you were trying to view has moved or does not exist -- perhaps you can find it here or by searching below."],
    contentType: "html",
    startDelay: 0,
    backDelay: 3000,
    callback: function(){
      glitch_secondary();
    }
  });

  // reveal secondary container at auto typing completion
  function glitch_secondary(){
    $(".typed__secondary").css("opacity", "1");
  }

});
<commit_msg>Add async font script to glitch.js<commit_after>//= require vendor/jquery.min
//= require plugins/jquery.typed.min

// asynchronously load fonts
WebFontConfig = {
  google: {
    families: ['PT Serif:400,400italic,700', 'PT Sans Narrow:400,700']
  }
};

(function(d) {
  var wf = d.createElement('script'), s = d.scripts[0];
  wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js';
  s.parentNode.insertBefore(wf, s);
})(document);

$(document).ready(function(){

  $("body").addClass("js");

  // toggle overlay navigation
  $(document).on('click', '.overlay__menu-trigger', function() {
    // in Firefox transitions break when parent overflow is changed, so we need to wait for the end of the transition to give the body an overflow hidden
    if( $('.overlay__menu').hasClass('is--visible') ) {
      $('.overlay__menu').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
      $('#screen').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    }
    else {
      $('.overlay__menu').addClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
      $('#screen').addClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    }
  });

  // close overlay navigation on button click
  $('.overlay__menu-close, #screen').on('click', function(){
    $('.overlay__menu').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    $('#screen').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
  });

  // open/close overlay navigation on focus
  $('.overlay__menu-item a').on('focus', function(){
    $('.overlay__menu').addClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    $('#screen').addClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
  });
  $('.overlay__menu-close').on('focus', function(){
    $('.overlay__menu').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    $('#screen').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
  });

  // close menu on [esc]
  $(document).on('keydown', function(e){
    if ( e.keyCode === 27 ) { // ESC key
      $('.overlay__menu').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
      $('#screen').removeClass('is--visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend');
    }
  });

  // home page auto typing
  $("#js-home-typed").typed({
    strings: ["Hello^250 my name is Mî̽̿ͫc͑̔̃͂h͂̽ͤ̊ͭͣa͛̓̍̓el̓͌̂̀̆ Rͩͤ͂̄o̾̽̈́͆ͨ̚s͋̌̊̐e. ^500  I am just another boring, ^250 tattooed, ^250 time traveling designer from Buffalo New York.^500  I enjoy eating chicken wings, ^500 sketching on an iPad, ^500 and playing Xbox.^500  Here you will find a collection of my writing, ^750 Paper by FiftyThree tutorials, ^750 and other creative endeavors."],
    contentType: "html",
    startDelay: 0,
    backDelay: 3000,
    callback: function(){
      glitch_secondary();
    }
  });

  // 404 page auto typing
  $("#js-404-typed").typed({
    strings: ["Your Pixels are on Another Canvas ^500  Sorry, but the page you were trying to view has moved or does not exist -- perhaps you can find it here or by searching below."],
    contentType: "html",
    startDelay: 0,
    backDelay: 3000,
    callback: function(){
      glitch_secondary();
    }
  });

  // reveal secondary container at auto typing completion
  function glitch_secondary(){
    $(".typed__secondary").css("opacity", "1");
  }

});
<|endoftext|>


<commit_before>(function() {
    // Create the connector object
    var myConnector = tableau.makeConnector();

    // Define the schema
    myConnector.getSchema = function(schemaCallback) {
        var cols = [{
            id: "title",
            alias: "title",
            dataType: tableau.dataTypeEnum.string
        }];

        var tableSchema = {
            id: "earthquakeFeed",
            alias: "Earthquakes with magnitude greater than 4.5 in the last seven days",
            columns: cols
        };

        schemaCallback([tableSchema]);
    };

    // Download the data
    myConnector.getData = function(table, doneCallback) {
        $.getJSON("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.geojson", function(resp) {
            var feat = resp.features,
                tableData = [];

            // Iterate over the JSON object
            for (var i = 0, len = feat.length; i < len; i++) {
                tableData.push({

                    "title": feat[i].properties.title,

                });
            }

            table.appendRows(tableData);
            doneCallback();
        });
    };

    tableau.registerConnector(myConnector);

    // Create event listeners for when the user submits the form
    $(document).ready(function() {
        $("#submitButton").click(function() {
            tableau.connectionName = "USGS Earthquake Feed"; // This will be the data source name in Tableau
            tableau.submit(); // This sends the connector object to Tableau
        });
    });
})();
<commit_msg>Update RivCrimeReport.js<commit_after>(function() {
    // Create the connector object
    var myConnector = tableau.makeConnector();

    // Define the schema
    myConnector.getSchema = function(schemaCallback) {
        var cols = [{
            id: "npc",
            alias: "title",
            dataType: tableau.dataTypeEnum.string
        }];

        var tableSchema = {
            id: "earthquakeFeed",
            alias: "Earthquakes with magnitude greater than 4.5 in the last seven days",
            columns: cols
        };

        schemaCallback([tableSchema]);
    };

    // Download the data
    myConnector.getData = function(table, doneCallback) {
        $.getJSON("https://riversideca.gov/transparency/data/dataset/json/27/Crime_Reports", function(resp) {
            var feat = resp.features,
                tableData = [];

            // Iterate over the JSON object
            for (var i = 0, len = feat.length; i < len; i++) {
                tableData.push({

                    "npc": feat[i].properties.npc,

                });
            }

            table.appendRows(tableData);
            doneCallback();
        });
    };

    tableau.registerConnector(myConnector);

    // Create event listeners for when the user submits the form
    $(document).ready(function() {
        $("#submitButton").click(function() {
            tableau.connectionName = "USGS Earthquake Feed"; // This will be the data source name in Tableau
            tableau.submit(); // This sends the connector object to Tableau
        });
    });
})();
<|endoftext|>


<commit_before>var client = require('mongodb').MongoClient;

var url = "mongodb://localhost/IbaMonitoring";

client.connect(url, function (err, db) {
    if (err) { console.log("Error while connecting: " + err); return; }

    var closeDbCallback = CloseTheDatabase(db);

    var surveySite = InitializeFirstSite();
    var surveySite2 = InitializeSecondSite();
    var surveys = [surveySite, surveySite2];

    var collection = db.collection("SurveySite");

    ClearAnyExistingRecords(collection, surveys, closeDbCallback);
});

require('paktc'); // PressAnyKeyToContinue

var ClearAnyExistingRecords = function (collection, surveys, finalCallback) {
    collection.deleteMany({}, function (err) {
        if (err) { console.log("ClearAnyExistingRecords: " + err); db.close(); return; }

        InsertRecords(collection, surveys, finalCallback);
    });
}

var InsertRecords = function (collection, surveys, finalCallback) {
    collection.insertMany(surveys, function (err) {
        if (err) { console.log("InsertRecords: " + err); db.close(); return; }

        RetrieveTheSavedRecords(collection, finalCallback);
    });
}

var RetrieveTheSavedRecords = function (collection, finalCallback) {

    collection.find().toArray(function (err, results) {
        if (err) { console.log("RetrieveTheSavedRecords: " + err); db.close(); return; }

        WriteOutTheRecords(results, finalCallback);
    });
}

var WriteOutTheRecords = function (results, finalCallback) {

    results.forEach(function (x) {
        console.log(x);
    });

    finalCallback();
}

var CloseTheDatabase = function (db) {
    return function () {
        console.log("Closing the database connection");
        db.close();
    }
}

var InitializeFirstSite = function () {
    return {
        "SiteName" : "A Park Somewhere",
        "CodeName" : "abc",
        "SurveyPoints" : [
            { "CodeName" : "P1", "Latitude" : "1.11", "Longitude" : "2.11" },
            { "CodeName" : "P2", "Latitude" : "1.12", "Longitude" : "2.12" },
            { "CodeName" : "P3", "Latitude" : "1.13", "Longitude" : "2.13" },
            { "CodeName" : "P4", "Latitude" : "1.14", "Longitude" : "2.14" },
            { "CodeName" : "P5", "Latitude" : "1.15", "Longitude" : "2.15" },
            { "CodeName" : "P1", "Latitude" : "2.11", "Longitude" : "3.11" },
            { "CodeName" : "P2", "Latitude" : "2.12", "Longitude" : "3.12" },
            { "CodeName" : "P3", "Latitude" : "2.13", "Longitude" : "3.13" },
            { "CodeName" : "P4", "Latitude" : "2.14", "Longitude" : "3.14" }
        ],
        "SiteBoundaries" : [
            { "VertexSequence" : 1, "Latitude" : "1.1", "Longitude" : "2.1" },
            { "VertexSequence" : 2, "Latitude" : "1.2", "Longitude" : "2.2" },
            { "VertexSequence" : 3, "Latitude" : "1.3", "Longitude" : "2.3" },
            { "VertexSequence" : 4, "Latitude" : "1.4", "Longitude" : "2.4" },
            { "VertexSequence" : 5, "Latitude" : "1.5", "Longitude" : "2.5" },
            { "VertexSequence" : 1, "Latitude" : "2.1", "Longitude" : "3.1" },
            { "VertexSequence" : 2, "Latitude" : "2.2", "Longitude" : "3.2" },
            { "VertexSequence" : 3, "Latitude" : "2.3", "Longitude" : "3.3" },
            { "VertexSequence" : 4, "Latitude" : "2.4", "Longitude" : "3.4" }
        ]
    };
}

var InitializeSecondSite = function () {
    return {
        "SiteName" : "A Different Location",
        "CodeName" : "abd",
        "SurveyPoints" : [
            { "CodeName" : "P_2_1", "Latitude" : "2.11", "Longitude" : "3.11" },
            { "CodeName" : "P_2_2", "Latitude" : "2.12", "Longitude" : "3.12" },
            { "CodeName" : "P_2_3", "Latitude" : "2.13", "Longitude" : "3.13" },
            { "CodeName" : "P_2_4", "Latitude" : "2.14", "Longitude" : "3.14" }
        ],
        "SiteBoundaries" : [
            { "VertexSequence" : 1, "Latitude" : "2.1", "Longitude" : "3.1" },
            { "VertexSequence" : 2, "Latitude" : "2.2", "Longitude" : "3.2" },
            { "VertexSequence" : 3, "Latitude" : "2.3", "Longitude" : "3.3" },
            { "VertexSequence" : 4, "Latitude" : "2.4", "Longitude" : "3.4" }
        ]
    };
}<commit_msg>Re-organize callback flow<commit_after>var client = require('mongodb').MongoClient;

var url = "mongodb://localhost/IbaMonitoring";

client.connect(url, function (err, db) {
    if (err) { console.log("Error while connecting: " + err); return; }

    var surveySite = InitializeFirstSite();
    var surveySite2 = InitializeSecondSite();
    var surveys = [surveySite, surveySite2];

    var collection = db.collection("SurveySite");

    // Read these next 4 lines in reverse order to understand the flow of the callbacks
    var closeDbCallback = CloseTheDatabase(db);
    var retrieveAndPrintRecordsCall = RetrieveTheSavedRecords(collection, closeDbCallback);
    var insertRecordsCall = InsertRecords(collection, surveys, retrieveAndPrintRecordsCall);
    var startTheProcess = ClearAnyExistingRecords(collection, surveys, insertRecordsCall);

    startTheProcess();
});

require('paktc'); // PressAnyKeyToContinue

var ClearAnyExistingRecords = function (collection, surveys, callback) {
    return function () {
        collection.deleteMany({}, function (err) {
            if (err) { console.log("ClearAnyExistingRecords: " + err); db.close(); return; }

            callback();
        });
    }
}

var InsertRecords = function (collection, surveys, callback) {
    return function () {
        collection.insertMany(surveys, function (err) {
            if (err) { console.log("InsertRecords: " + err); db.close(); return; }

            callback();
        });
    }
}

var RetrieveTheSavedRecords = function (collection, callback) {
    return function () {
        collection.find().toArray(function (err, results) {
            if (err) { console.log("RetrieveTheSavedRecords: " + err); db.close(); return; }

            WriteOutTheRecords(results);

            callback();
        });
    }
}

var WriteOutTheRecords = function (results) {

    results.forEach(function (x) {
        console.log(x);
    });
}

var CloseTheDatabase = function (db) {
    return function () {
        console.log("Closing the database connection");
        db.close();
    }
}

var InitializeFirstSite = function () {
    return {
        "SiteName" : "A Park Somewhere",
        "CodeName" : "abc",
        "SurveyPoints" : [
            { "CodeName" : "P1", "Latitude" : "1.11", "Longitude" : "2.11" },
            { "CodeName" : "P2", "Latitude" : "1.12", "Longitude" : "2.12" },
            { "CodeName" : "P3", "Latitude" : "1.13", "Longitude" : "2.13" },
            { "CodeName" : "P4", "Latitude" : "1.14", "Longitude" : "2.14" },
            { "CodeName" : "P5", "Latitude" : "1.15", "Longitude" : "2.15" },
            { "CodeName" : "P1", "Latitude" : "2.11", "Longitude" : "3.11" },
            { "CodeName" : "P2", "Latitude" : "2.12", "Longitude" : "3.12" },
            { "CodeName" : "P3", "Latitude" : "2.13", "Longitude" : "3.13" },
            { "CodeName" : "P4", "Latitude" : "2.14", "Longitude" : "3.14" }
        ],
        "SiteBoundaries" : [
            { "VertexSequence" : 1, "Latitude" : "1.1", "Longitude" : "2.1" },
            { "VertexSequence" : 2, "Latitude" : "1.2", "Longitude" : "2.2" },
            { "VertexSequence" : 3, "Latitude" : "1.3", "Longitude" : "2.3" },
            { "VertexSequence" : 4, "Latitude" : "1.4", "Longitude" : "2.4" },
            { "VertexSequence" : 5, "Latitude" : "1.5", "Longitude" : "2.5" },
            { "VertexSequence" : 1, "Latitude" : "2.1", "Longitude" : "3.1" },
            { "VertexSequence" : 2, "Latitude" : "2.2", "Longitude" : "3.2" },
            { "VertexSequence" : 3, "Latitude" : "2.3", "Longitude" : "3.3" },
            { "VertexSequence" : 4, "Latitude" : "2.4", "Longitude" : "3.4" }
        ]
    };
}

var InitializeSecondSite = function () {
    return {
        "SiteName" : "A Different Location",
        "CodeName" : "abd",
        "SurveyPoints" : [
            { "CodeName" : "P_2_1", "Latitude" : "2.11", "Longitude" : "3.11" },
            { "CodeName" : "P_2_2", "Latitude" : "2.12", "Longitude" : "3.12" },
            { "CodeName" : "P_2_3", "Latitude" : "2.13", "Longitude" : "3.13" },
            { "CodeName" : "P_2_4", "Latitude" : "2.14", "Longitude" : "3.14" }
        ],
        "SiteBoundaries" : [
            { "VertexSequence" : 1, "Latitude" : "2.1", "Longitude" : "3.1" },
            { "VertexSequence" : 2, "Latitude" : "2.2", "Longitude" : "3.2" },
            { "VertexSequence" : 3, "Latitude" : "2.3", "Longitude" : "3.3" },
            { "VertexSequence" : 4, "Latitude" : "2.4", "Longitude" : "3.4" }
        ]
    };
}<|endoftext|>


<commit_before>/**
 * @fileoverview Prevent usage of deprecated methods
 * @author Yannick Croissant
 * @author Scott Feeney
 */
'use strict';

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

const rule = require('../../../lib/rules/no-deprecated');
const RuleTester = require('eslint').RuleTester;

const parserOptions = {
  ecmaVersion: 8,
  sourceType: 'module',
  ecmaFeatures: {
    experimentalObjectRestSpread: true,
    jsx: true
  }
};

require('babel-eslint');

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

const ruleTester = new RuleTester({parserOptions});
ruleTester.run('no-deprecated', rule, {

  valid: [
    // Not deprecated
    'var element = React.createElement(\'p\', {}, null);',
    'var clone = React.cloneElement(element);',
    'ReactDOM.render(element, container);',
    'ReactDOM.unmountComponentAtNode(container);',
    'ReactDOM.findDOMNode(instance);',
    'ReactDOMServer.renderToString(element);',
    'ReactDOMServer.renderToStaticMarkup(element);',
    // Deprecated in a later version
    {code: 'React.renderComponent()', settings: {react: {version: '0.11.0'}}},
    {code: 'React.createClass()', settings: {react: {version: '15.4.0'}}},
    {code: 'PropTypes', settings: {react: {version: '15.4.0'}}}
  ],

  invalid: [{
    code: 'React.renderComponent()',
    settings: {react: {version: '0.12.0'}},
    errors: [{
      message: 'React.renderComponent is deprecated since React 0.12.0, use React.render instead'
    }]
  }, {
    code: 'Foo.renderComponent()',
    settings: {react: {pragma: 'Foo', version: '0.12.0'}},
    errors: [{
      message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead'
    }]
  }, {
    code: '/** @jsx Foo */ Foo.renderComponent()',
    settings: {react: {version: '0.12.0'}},
    errors: [{
      message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead'
    }]
  }, {
    code: 'this.transferPropsTo()',
    errors: [{
      message: 'this.transferPropsTo is deprecated since React 0.12.0, use spread operator ({...}) instead'
    }]
  }, {
    code: 'React.addons.classSet()',
    errors: [{
      message: 'React.addons.classSet is deprecated since React 0.13.0, use the npm module classnames instead'
    }]
  }, {
    code: 'React.render(element, container);',
    errors: [{
      message: 'React.render is deprecated since React 0.14.0, use ReactDOM.render instead'
    }]
  }, {
    code: 'React.unmountComponentAtNode(container);',
    errors: [{
      message: (
        'React.unmountComponentAtNode is deprecated since React 0.14.0, ' +
        'use ReactDOM.unmountComponentAtNode instead'
      )
    }]
  }, {
    code: 'React.findDOMNode(instance);',
    errors: [{
      message: 'React.findDOMNode is deprecated since React 0.14.0, use ReactDOM.findDOMNode instead'
    }]
  }, {
    code: 'React.renderToString(element);',
    errors: [{
      message: 'React.renderToString is deprecated since React 0.14.0, use ReactDOMServer.renderToString instead'
    }]
  }, {
    code: 'React.renderToStaticMarkup(element);',
    errors: [{
      message: (
        'React.renderToStaticMarkup is deprecated since React 0.14.0, ' +
        'use ReactDOMServer.renderToStaticMarkup instead'
      )
    }]
  }, {
    code: 'React.createClass({});',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }]
  }, {
    code: 'Foo.createClass({});',
    settings: {react: {pragma: 'Foo'}},
    errors: [{
      message: 'Foo.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }]
  }, {
    code: 'React.PropTypes',
    errors: [{
      message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead'
    }]
  }, {
    code: 'var {createClass} = require(\'react\');',
    parser: 'babel-eslint',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }]
  }, {
    code: 'var {createClass, PropTypes} = require(\'react\');',
    parser: 'babel-eslint',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }, {
      message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead'
    }]
  }, {
    code: 'import {createClass} from \'react\';',
    parser: 'babel-eslint',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }]
  }, {
    code: 'import {createClass, PropTypes} from \'react\';',
    parser: 'babel-eslint',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }, {
      message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead'
    }]
  }, {
    code: [
      'import React from \'react\';',
      'const {createClass, PropTypes} = React;'
    ].join('\n'),
    parser: 'babel-eslint',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }, {
      message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead'
    }]
  }, {
    code: 'import {printDOM} from \'react-addons-perf\';',
    parser: 'babel-eslint',
    errors: [{
      message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead'
    }]
  }, {
    code: [
      'import ReactPerf from \'react-addons-perf\';',
      'const {printDOM} = ReactPerf;'
    ].join('\n'),
    parser: 'babel-eslint',
    errors: [{
      message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead'
    }]
  }]
});
<commit_msg>Rewrite no-deprecated tests with template literals<commit_after>/**
 * @fileoverview Prevent usage of deprecated methods
 * @author Yannick Croissant
 * @author Scott Feeney
 */
'use strict';

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

const rule = require('../../../lib/rules/no-deprecated');
const RuleTester = require('eslint').RuleTester;

const parserOptions = {
  ecmaVersion: 8,
  sourceType: 'module',
  ecmaFeatures: {
    experimentalObjectRestSpread: true,
    jsx: true
  }
};

require('babel-eslint');

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

const ruleTester = new RuleTester({parserOptions});
ruleTester.run('no-deprecated', rule, {

  valid: [
    // Not deprecated
    'var element = React.createElement(\'p\', {}, null);',
    'var clone = React.cloneElement(element);',
    'ReactDOM.render(element, container);',
    'ReactDOM.unmountComponentAtNode(container);',
    'ReactDOM.findDOMNode(instance);',
    'ReactDOMServer.renderToString(element);',
    'ReactDOMServer.renderToStaticMarkup(element);',
    // Deprecated in a later version
    {code: 'React.renderComponent()', settings: {react: {version: '0.11.0'}}},
    {code: 'React.createClass()', settings: {react: {version: '15.4.0'}}},
    {code: 'PropTypes', settings: {react: {version: '15.4.0'}}}
  ],

  invalid: [{
    code: 'React.renderComponent()',
    settings: {react: {version: '0.12.0'}},
    errors: [{
      message: 'React.renderComponent is deprecated since React 0.12.0, use React.render instead'
    }]
  }, {
    code: 'Foo.renderComponent()',
    settings: {react: {pragma: 'Foo', version: '0.12.0'}},
    errors: [{
      message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead'
    }]
  }, {
    code: '/** @jsx Foo */ Foo.renderComponent()',
    settings: {react: {version: '0.12.0'}},
    errors: [{
      message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead'
    }]
  }, {
    code: 'this.transferPropsTo()',
    errors: [{
      message: 'this.transferPropsTo is deprecated since React 0.12.0, use spread operator ({...}) instead'
    }]
  }, {
    code: 'React.addons.classSet()',
    errors: [{
      message: 'React.addons.classSet is deprecated since React 0.13.0, use the npm module classnames instead'
    }]
  }, {
    code: 'React.render(element, container);',
    errors: [{
      message: 'React.render is deprecated since React 0.14.0, use ReactDOM.render instead'
    }]
  }, {
    code: 'React.unmountComponentAtNode(container);',
    errors: [{
      message: (
        'React.unmountComponentAtNode is deprecated since React 0.14.0, ' +
        'use ReactDOM.unmountComponentAtNode instead'
      )
    }]
  }, {
    code: 'React.findDOMNode(instance);',
    errors: [{
      message: 'React.findDOMNode is deprecated since React 0.14.0, use ReactDOM.findDOMNode instead'
    }]
  }, {
    code: 'React.renderToString(element);',
    errors: [{
      message: 'React.renderToString is deprecated since React 0.14.0, use ReactDOMServer.renderToString instead'
    }]
  }, {
    code: 'React.renderToStaticMarkup(element);',
    errors: [{
      message: (
        'React.renderToStaticMarkup is deprecated since React 0.14.0, ' +
        'use ReactDOMServer.renderToStaticMarkup instead'
      )
    }]
  }, {
    code: 'React.createClass({});',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }]
  }, {
    code: 'Foo.createClass({});',
    settings: {react: {pragma: 'Foo'}},
    errors: [{
      message: 'Foo.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }]
  }, {
    code: 'React.PropTypes',
    errors: [{
      message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead'
    }]
  }, {
    code: 'var {createClass} = require(\'react\');',
    parser: 'babel-eslint',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }]
  }, {
    code: 'var {createClass, PropTypes} = require(\'react\');',
    parser: 'babel-eslint',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }, {
      message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead'
    }]
  }, {
    code: 'import {createClass} from \'react\';',
    parser: 'babel-eslint',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }]
  }, {
    code: 'import {createClass, PropTypes} from \'react\';',
    parser: 'babel-eslint',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }, {
      message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead'
    }]
  }, {
    code: `
      import React from 'react';
      const {createClass, PropTypes} = React;
    `,
    parser: 'babel-eslint',
    errors: [{
      message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead'
    }, {
      message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead'
    }]
  }, {
    code: 'import {printDOM} from \'react-addons-perf\';',
    parser: 'babel-eslint',
    errors: [{
      message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead'
    }]
  }, {
    code: `
      import ReactPerf from 'react-addons-perf';
      const {printDOM} = ReactPerf;
    `,
    parser: 'babel-eslint',
    errors: [{
      message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead'
    }]
  }]
});
<|endoftext|>


<commit_before>import $ from 'wee-dom';
import $events from 'wee-events';
import { createDiv, createSingleDiv, createMultiDiv, resetDOM } from '../helpers/dom';

function removeEvents() {
	let elements = document.body.getElementsByTagName('*');

	for (let i = elements.length; i--;) {
		let oldElement = elements[i];
		let newElement = oldElement.cloneNode(true);

		oldElement.parentNode.replaceChild(newElement, oldElement);
	}

	$events.off();
}

function triggerEvent(el, type) {
	let e = document.createEvent('HTMLEvents');
	e.initEvent(type, false, true);
	el.dispatchEvent(e);
}

describe('Events', () => {
	describe('on', () => {
		beforeEach(() => {
			createSingleDiv();
			createMultiDiv();
		});
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('should bind a single event to a single element', () => {
			$events.on('.test', 'click', () => {
				$('.test')[0].style.backgroundColor = 'red';
			});

			triggerEvent($('.test')[0], 'click');

			expect($('.test')[0].style.backgroundColor).to.equal('red');
		});

		it('should bind multiple events to a single element', () => {
			$events.on({
				'.test': {
					click() {
						$('.test')[0].style.backgroundColor = 'red';
					},
					mouseenter() {
						$('.test')[0].style.backgroundColor = 'purple';
					}
				}
			});

			triggerEvent($('.test')[0], 'click');
			expect($('.test')[0].style.backgroundColor).to.equal('red');
			triggerEvent($('.test')[0], 'mouseenter');
			expect($('.test')[0].style.backgroundColor).to.equal('purple');
		});

		// TODO: Try to figure out the best way to test multiple bindings
		it('should bind multiple events to multiple elements', () => {
			$events.on({
				'#first': {
					click(e, el) {
						el.style.backgroundColor = 'red';
					},
					mouseenter(e, el) {
						el.style.backgroundColor = 'purple';
					}
				},
				'.child': {
					click(e, el) {
						el.style.backgroundColor = 'red';
					},
					mouseenter(e, el) {
						el.style.backgroundColor = 'purple';
					}
				}
			});

			triggerEvent($('#first')[0], 'click');
			expect($('#first')[0].style.backgroundColor).to.equal('red');
			triggerEvent($('#first')[0], 'mouseenter');
			expect($('#first')[0].style.backgroundColor).to.equal('purple');

			triggerEvent($('.child')[0], 'click');
			expect($('.child')[0].style.backgroundColor).to.equal('red');
			triggerEvent($('.child')[0], 'mouseenter');
			expect($('.child')[0].style.backgroundColor).to.equal('purple');

			// Reset background color
			$('.child')[0].style.backgroundColor = '';

			triggerEvent($('.child').eq(1)[0], 'click');
			expect($('.child').eq(1)[0].style.backgroundColor).to.equal('red');
			triggerEvent($('.child').eq(1)[0], 'mouseenter');
			expect($('.child').eq(1)[0].style.backgroundColor).to.equal('purple');

		});

		it('should inject the event and element into the callback', () => {
			$events.on('.test', 'click', (e, el) => {
				expect(el.className).to.equal('test');
				expect(e.type).to.equal('click');
			});

			triggerEvent($('.test')[0], 'click');
		});

		it('should bind multiple events to a single element selection', () => {
			$events.on('.test', {
				click() {
					$('.test')[0].style.backgroundColor = 'red';
				},
				mouseenter() {
					$('.test')[0].style.backgroundColor = 'purple';
				}
			});

			triggerEvent($('.test')[0], 'click');
			expect($('.test')[0].style.backgroundColor).to.equal('red');
			triggerEvent($('.test')[0], 'mouseenter');
			expect($('.test')[0].style.backgroundColor).to.equal('purple');
		})

		describe('once', () => {
			it('should bind an event that fires only once', () => {
				$events.on('.test', 'click', () => {
					let bgColor = $('.test')[0].style.backgroundColor;

					$('.test')[0].style.backgroundColor =
						bgColor === 'red' ? 'purple' : 'red';
				}, {
					once: true
				});

				triggerEvent($('.test')[0], 'click');
				triggerEvent($('.test')[0], 'click');

				expect($('.test')[0].style.backgroundColor).to.equal('red');
			});
		});

		describe('targ', () => {
			// TODO: what does this do?
			it('targ', () => {
				$events.on('.test', 'click', () => {
					$('.test')[0].style.backgroundColor = 'red';
				}, {
					targ: '.test'
				});

				triggerEvent($('.test')[0], 'click');

				expect($('.test')[0].style.backgroundColor).to.equal('red');
			});

			// TODO: get clarification
			it('should set ref on targ', () => {
				before(createSingleDiv);

				$events.on('.test', 'click', () => {
					$('.test')[0].style.backgroundColor = 'red'
				}, {
					targ: 'ref:test'
				});

				triggerEvent($('.test')[0], 'click');

				expect($('.test')[0].style.backgroundColor).to.equal('red');
			});
		});

		describe('args', () => {
			it('can add injected arguments', () => {
				let state = false;

				$events.on('.test', 'click', (e, el, arg1, arg2) => {
					expect(arg1).to.equal('arg1');
					expect(arg2).to.equal('arg2');

					state = true;
				}, {
					args: ['arg1', 'arg2']
				});

				expect(state).to.equal(true);

				triggerEvent($('.test')[0], 'click');
			});
		});

		describe('scope', () => {
			it('can add change the scope of the callback', () => {
				let state = false;

				$events.on('.test', 'click', function() {
					expect(this.param).to.equal('test');
					state = true;
				}, {
					scope: {
						param: 'test'
					}
				});

				expect(state).to.equal(true);

				triggerEvent($('.test')[0], 'click');
			});
		});

		describe('delegate', () => {
			it('should delegate bound events to specified ancestor', () => {
				$events.on('.new-el', 'click', (e, el) => {
					el.style.backgroundColor = 'red';
				}, {
					delegate: 'body'
				});

				createDiv({ className: 'new-el' }, {}, true);

				triggerEvent($('.new-el')[0], 'click');
			});
		});

		describe('context', () => {
			it('should use provided context for selection', () => {
				let ctxOne = createDiv({
						className: 'context-one'
					}, {}, true);
				let ctxOneInner = createDiv({
						className: 'context-inner'
					});

				ctxOne.appendChild(ctxOneInner);

				let ctxTwo = createDiv({
						className: 'context-two'
					}, {}, true);
				let ctxTwoInner = createDiv({
						className: 'context-inner'
					});

				ctxTwo.appendChild(ctxTwoInner);

				$events.on('.context-inner', 'click', (e, el) => {
					el.style.backgroundColor = 'red';
				}, {
					context: '.context-two'
				});

				$events.trigger('.context-inner', 'click');

				expect($('.context-inner').eq(1)[0].style.backgroundColor).to.equal('red');
			});
		});

		describe('namespace', () => {
			it('should add a namespace to event', () => {
				// TODO: find the best way to test for namespace existence
				$events.on('.test', 'click', function() {
					$('.test')[0].style.backgroundColor = 'red';
				}, {
					namespace: 'namespace'
				});

				triggerEvent($('.test')[0], 'click');

				expect($('.test')[0].style.backgroundColor).to.equal('red');
			});
		});
	});

	describe('trigger', () => {
		beforeEach(createSingleDiv);
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('should trigger event for matching selection', () => {
			$events.on('.test', 'click', () => {
				$('.test')[0].style.backgroundColor = 'red';
			});

			$events.trigger('.test', 'click');

			expect($('.test')[0].style.backgroundColor).to.equal('red');
		});
	});

	describe('touch', () => {
		beforeEach(createSingleDiv);
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('should bind touch event', () => {
			$events.on('.test', 'swipeLeft', () => {
				$('.test')[0].style.backgroundColor = 'red';
			}, {
				distance: 150,
				movement: 20
			});

			$events.trigger('.test', 'swipeLeft');

			expect($('.test')[0].style.backgroundColor).to.equal('red');
		});
	});

	describe('bound', () => {
		beforeEach(createSingleDiv);
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('it should return an array of all bound events', () => {
			$events.on({
				'.test': {
					click() {
						return 'click';
					},
					mouseenter() {
						return 'mouseenter';
					}
				}
			});

			expect($events.bound()).to.be.an('array');
			expect($events.bound()[0]).to.be.an('object');
			expect($events.bound()[0].el.className).to.equal('test');
			expect($events.bound()[0].ev).to.equal('click');
			expect($events.bound()[0].evt).to.equal('click');
			expect($events.bound()[0].fn()).to.equal('click');

			expect($events.bound()[1].el.className).to.equal('test');
			expect($events.bound()[1].ev).to.equal('mouseenter');
			expect($events.bound()[1].evt).to.equal('mouseenter');
			expect($events.bound()[1].fn()).to.equal('mouseenter');
		});

		// TODO: finish this test
		// it('should check delegated selector against targeted selector', () => {
		// 	$events.on('ref:test', 'click', (e, el) => {
		// 		el.style.backgroundColor = 'red';
		// 	}, {
		// 		delegate: 'ref:test'
		// 	});
		//
		// 	createDiv({
		// 		className: 'new-el'
		// 	}, {
		// 		'data-ref': 'test'
		// 	}, true);
		//
		// 	triggerEvent($('ref:test')[0], 'click');
		// });
	});

	describe('off', () => {
		beforeEach(createSingleDiv);
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('should remove a bound element', () => {
			$events.on('.test', 'click', () => {
				$('.test')[0].style.backgroundColor = 'red';
			});

			triggerEvent($('.test')[0], 'click');

			expect($('.test')[0].style.backgroundColor).to.equal('red');

			$events.off('.test');

			expect($events.bound().length).to.equal(0);
		});

		it('should remove a bound element by namespace', () => {
			$events.on('.test', 'click.namespace', () => {
				$('.test')[0].style.backgroundColor = 'red';
			});

			triggerEvent($('.test')[0], 'click');

			expect($('.test')[0].style.backgroundColor).to.equal('red');

			$events.off(null, '.namespace');

			expect($events.bound().length).to.equal(0);
		});
	});

	describe('addEvent', () => {
		beforeEach(() => {
			createSingleDiv();
			createMultiDiv();
		});
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('should register custom event', () => {
			$events.addEvent('pressHold', function(el, fn, conf) {
				$events.on(el, 'mousedown.pressHold', function(e, el) {
					expect(el.className).to.equal('test');
				}, conf);

				$events.on(el, 'mouseup.pressHold', function(e, el) {
					expect(el.className).to.equal('test');
				});
			}, function(el, fn) {
				$events.off(el, 'mouseup.pressHold', fn);
			});

			$events.on('.test', 'pressHold', function(e, el) {
				$('.test')[0].style.backgroundColor = 'red';
			});

			$events.trigger('.test', 'pressHold');

			expect($('.test')[0].style.backgroundColor).to.equal('red');

			$events.off('.test', null, (e) => {
				// TODO: Find a better way to test this
			});
		});
	});

	// TODO: finish this test - line 99
	// describe('init', () => {
	// 	beforeEach(createSingleDiv);
	// 	afterEach(resetDOM);
	//
	// 	it('should fire event immediately', () => {
	// 		$events.on('.test', 'click', () => {
	// 			$('.test')[0].style.backgroundColor = 'red';
	// 		}, {
	// 			init: true
	// 		});
	//
	// 		triggerEvent($('.test')[0], 'click');
	//
	// 		expect($('.test')[0].style.backgroundColor).to.equal('red');
	// 	});
	// });
});<commit_msg>Remove TODO<commit_after>import $ from 'wee-dom';
import $events from 'wee-events';
import { createDiv, createSingleDiv, createMultiDiv, resetDOM } from '../helpers/dom';

function removeEvents() {
	let elements = document.body.getElementsByTagName('*');

	for (let i = elements.length; i--;) {
		let oldElement = elements[i];
		let newElement = oldElement.cloneNode(true);

		oldElement.parentNode.replaceChild(newElement, oldElement);
	}

	$events.off();
}

function triggerEvent(el, type) {
	let e = document.createEvent('HTMLEvents');
	e.initEvent(type, false, true);
	el.dispatchEvent(e);
}

describe('Events', () => {
	describe('on', () => {
		beforeEach(() => {
			createSingleDiv();
			createMultiDiv();
		});
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('should bind a single event to a single element', () => {
			$events.on('.test', 'click', () => {
				$('.test')[0].style.backgroundColor = 'red';
			});

			triggerEvent($('.test')[0], 'click');

			expect($('.test')[0].style.backgroundColor).to.equal('red');
		});

		it('should bind multiple events to a single element', () => {
			$events.on({
				'.test': {
					click() {
						$('.test')[0].style.backgroundColor = 'red';
					},
					mouseenter() {
						$('.test')[0].style.backgroundColor = 'purple';
					}
				}
			});

			triggerEvent($('.test')[0], 'click');
			expect($('.test')[0].style.backgroundColor).to.equal('red');
			triggerEvent($('.test')[0], 'mouseenter');
			expect($('.test')[0].style.backgroundColor).to.equal('purple');
		});

		it('should bind multiple events to multiple elements', () => {
			$events.on({
				'#first': {
					click(e, el) {
						el.style.backgroundColor = 'red';
					},
					mouseenter(e, el) {
						el.style.backgroundColor = 'purple';
					}
				},
				'.child': {
					click(e, el) {
						el.style.backgroundColor = 'red';
					},
					mouseenter(e, el) {
						el.style.backgroundColor = 'purple';
					}
				}
			});

			triggerEvent($('#first')[0], 'click');
			expect($('#first')[0].style.backgroundColor).to.equal('red');
			triggerEvent($('#first')[0], 'mouseenter');
			expect($('#first')[0].style.backgroundColor).to.equal('purple');

			triggerEvent($('.child')[0], 'click');
			expect($('.child')[0].style.backgroundColor).to.equal('red');
			triggerEvent($('.child')[0], 'mouseenter');
			expect($('.child')[0].style.backgroundColor).to.equal('purple');

			// Reset background color
			$('.child')[0].style.backgroundColor = '';

			triggerEvent($('.child').eq(1)[0], 'click');
			expect($('.child').eq(1)[0].style.backgroundColor).to.equal('red');
			triggerEvent($('.child').eq(1)[0], 'mouseenter');
			expect($('.child').eq(1)[0].style.backgroundColor).to.equal('purple');

		});

		it('should inject the event and element into the callback', () => {
			$events.on('.test', 'click', (e, el) => {
				expect(el.className).to.equal('test');
				expect(e.type).to.equal('click');
			});

			triggerEvent($('.test')[0], 'click');
		});

		it('should bind multiple events to a single element selection', () => {
			$events.on('.test', {
				click() {
					$('.test')[0].style.backgroundColor = 'red';
				},
				mouseenter() {
					$('.test')[0].style.backgroundColor = 'purple';
				}
			});

			triggerEvent($('.test')[0], 'click');
			expect($('.test')[0].style.backgroundColor).to.equal('red');
			triggerEvent($('.test')[0], 'mouseenter');
			expect($('.test')[0].style.backgroundColor).to.equal('purple');
		})

		describe('once', () => {
			it('should bind an event that fires only once', () => {
				$events.on('.test', 'click', () => {
					let bgColor = $('.test')[0].style.backgroundColor;

					$('.test')[0].style.backgroundColor =
						bgColor === 'red' ? 'purple' : 'red';
				}, {
					once: true
				});

				triggerEvent($('.test')[0], 'click');
				triggerEvent($('.test')[0], 'click');

				expect($('.test')[0].style.backgroundColor).to.equal('red');
			});
		});

		describe('targ', () => {
			// TODO: what does this do?
			it('targ', () => {
				$events.on('.test', 'click', () => {
					$('.test')[0].style.backgroundColor = 'red';
				}, {
					targ: '.test'
				});

				triggerEvent($('.test')[0], 'click');

				expect($('.test')[0].style.backgroundColor).to.equal('red');
			});

			// TODO: get clarification
			it('should set ref on targ', () => {
				before(createSingleDiv);

				$events.on('.test', 'click', () => {
					$('.test')[0].style.backgroundColor = 'red'
				}, {
					targ: 'ref:test'
				});

				triggerEvent($('.test')[0], 'click');

				expect($('.test')[0].style.backgroundColor).to.equal('red');
			});
		});

		describe('args', () => {
			it('can add injected arguments', () => {
				let state = false;

				$events.on('.test', 'click', (e, el, arg1, arg2) => {
					expect(arg1).to.equal('arg1');
					expect(arg2).to.equal('arg2');

					state = true;
				}, {
					args: ['arg1', 'arg2']
				});

				expect(state).to.equal(true);

				triggerEvent($('.test')[0], 'click');
			});
		});

		describe('scope', () => {
			it('can add change the scope of the callback', () => {
				let state = false;

				$events.on('.test', 'click', function() {
					expect(this.param).to.equal('test');
					state = true;
				}, {
					scope: {
						param: 'test'
					}
				});

				expect(state).to.equal(true);

				triggerEvent($('.test')[0], 'click');
			});
		});

		describe('delegate', () => {
			it('should delegate bound events to specified ancestor', () => {
				$events.on('.new-el', 'click', (e, el) => {
					el.style.backgroundColor = 'red';
				}, {
					delegate: 'body'
				});

				createDiv({ className: 'new-el' }, {}, true);

				triggerEvent($('.new-el')[0], 'click');
			});
		});

		describe('context', () => {
			it('should use provided context for selection', () => {
				let ctxOne = createDiv({
						className: 'context-one'
					}, {}, true);
				let ctxOneInner = createDiv({
						className: 'context-inner'
					});

				ctxOne.appendChild(ctxOneInner);

				let ctxTwo = createDiv({
						className: 'context-two'
					}, {}, true);
				let ctxTwoInner = createDiv({
						className: 'context-inner'
					});

				ctxTwo.appendChild(ctxTwoInner);

				$events.on('.context-inner', 'click', (e, el) => {
					el.style.backgroundColor = 'red';
				}, {
					context: '.context-two'
				});

				$events.trigger('.context-inner', 'click');

				expect($('.context-inner').eq(1)[0].style.backgroundColor).to.equal('red');
			});
		});

		describe('namespace', () => {
			it('should add a namespace to event', () => {
				// TODO: find the best way to test for namespace existence
				$events.on('.test', 'click', function() {
					$('.test')[0].style.backgroundColor = 'red';
				}, {
					namespace: 'namespace'
				});

				triggerEvent($('.test')[0], 'click');

				expect($('.test')[0].style.backgroundColor).to.equal('red');
			});
		});
	});

	describe('trigger', () => {
		beforeEach(createSingleDiv);
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('should trigger event for matching selection', () => {
			$events.on('.test', 'click', () => {
				$('.test')[0].style.backgroundColor = 'red';
			});

			$events.trigger('.test', 'click');

			expect($('.test')[0].style.backgroundColor).to.equal('red');
		});
	});

	describe('touch', () => {
		beforeEach(createSingleDiv);
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('should bind touch event', () => {
			$events.on('.test', 'swipeLeft', () => {
				$('.test')[0].style.backgroundColor = 'red';
			}, {
				distance: 150,
				movement: 20
			});

			$events.trigger('.test', 'swipeLeft');

			expect($('.test')[0].style.backgroundColor).to.equal('red');
		});
	});

	describe('bound', () => {
		beforeEach(createSingleDiv);
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('it should return an array of all bound events', () => {
			$events.on({
				'.test': {
					click() {
						return 'click';
					},
					mouseenter() {
						return 'mouseenter';
					}
				}
			});

			expect($events.bound()).to.be.an('array');
			expect($events.bound()[0]).to.be.an('object');
			expect($events.bound()[0].el.className).to.equal('test');
			expect($events.bound()[0].ev).to.equal('click');
			expect($events.bound()[0].evt).to.equal('click');
			expect($events.bound()[0].fn()).to.equal('click');

			expect($events.bound()[1].el.className).to.equal('test');
			expect($events.bound()[1].ev).to.equal('mouseenter');
			expect($events.bound()[1].evt).to.equal('mouseenter');
			expect($events.bound()[1].fn()).to.equal('mouseenter');
		});

		// TODO: finish this test
		// it('should check delegated selector against targeted selector', () => {
		// 	$events.on('ref:test', 'click', (e, el) => {
		// 		el.style.backgroundColor = 'red';
		// 	}, {
		// 		delegate: 'ref:test'
		// 	});
		//
		// 	createDiv({
		// 		className: 'new-el'
		// 	}, {
		// 		'data-ref': 'test'
		// 	}, true);
		//
		// 	triggerEvent($('ref:test')[0], 'click');
		// });
	});

	describe('off', () => {
		beforeEach(createSingleDiv);
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('should remove a bound element', () => {
			$events.on('.test', 'click', () => {
				$('.test')[0].style.backgroundColor = 'red';
			});

			triggerEvent($('.test')[0], 'click');

			expect($('.test')[0].style.backgroundColor).to.equal('red');

			$events.off('.test');

			expect($events.bound().length).to.equal(0);
		});

		it('should remove a bound element by namespace', () => {
			$events.on('.test', 'click.namespace', () => {
				$('.test')[0].style.backgroundColor = 'red';
			});

			triggerEvent($('.test')[0], 'click');

			expect($('.test')[0].style.backgroundColor).to.equal('red');

			$events.off(null, '.namespace');

			expect($events.bound().length).to.equal(0);
		});
	});

	describe('addEvent', () => {
		beforeEach(() => {
			createSingleDiv();
			createMultiDiv();
		});
		afterEach(() => {
			resetDOM();
			removeEvents();
		});

		it('should register custom event', () => {
			$events.addEvent('pressHold', function(el, fn, conf) {
				$events.on(el, 'mousedown.pressHold', function(e, el) {
					expect(el.className).to.equal('test');
				}, conf);

				$events.on(el, 'mouseup.pressHold', function(e, el) {
					expect(el.className).to.equal('test');
				});
			}, function(el, fn) {
				$events.off(el, 'mouseup.pressHold', fn);
			});

			$events.on('.test', 'pressHold', function(e, el) {
				$('.test')[0].style.backgroundColor = 'red';
			});

			$events.trigger('.test', 'pressHold');

			expect($('.test')[0].style.backgroundColor).to.equal('red');

			$events.off('.test', null, (e) => {
				// TODO: Find a better way to test this
			});
		});
	});

	// TODO: finish this test - line 99
	// describe('init', () => {
	// 	beforeEach(createSingleDiv);
	// 	afterEach(resetDOM);
	//
	// 	it('should fire event immediately', () => {
	// 		$events.on('.test', 'click', () => {
	// 			$('.test')[0].style.backgroundColor = 'red';
	// 		}, {
	// 			init: true
	// 		});
	//
	// 		triggerEvent($('.test')[0], 'click');
	//
	// 		expect($('.test')[0].style.backgroundColor).to.equal('red');
	// 	});
	// });
});<|endoftext|>


<commit_before>var peer = new Peer({
  key: key_,
});

var connected_peers = {};
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
navigator.getUserMedia({audio: true, video: false},
        function(stream){
          console.log("navigator");
          window.localStream = stream;
        },
        function(){console.log("navigator error");});

/**
 * peer イベント
 */
peer.on('open', function(id){
  $('#pid').text(id);
});

peer.on('connection', connect);

peer.on('call', audioCall);

peer.on('error', function(err){
  alert(err.message);
});

/**
 * チャットとファイル通信
 */
function connect(c) {
  if (c.label === 'chat') {
    var member_box = $('#member');
    var messages = $('#messages');
    messages.append('
' + c.peer + ': connect
');
    connected_peers[c.peer] = 1;

    c.on('data', function(data) {
      messages.append('
' + c.peer + ': ' + data + '
');
    });
    c.on('close', function() {
      delete connected_peers[c.peer];
    });
  } else if (c.label === 'file') {
    c.on('data', function(data) {
      if (data.constructor === ArrayBuffer) {
        var dataView = new Uint8Array(data);
        var dataBlob = new Blob([dataView]);
        var url = window.URL.createObjectURL(dataBlob);
        $('#messages').append('
' +
            c.peer + 'がfileを送信しました
');
      }
    });
  }
}

/**
 * 音声データ通信接続時（されたとき）
 */
function audioCall(call) {
  call.answer(window.localStream);
  setOnCall(call);
}

/**
 * call のイベント発生時の動作を設定
 */
function setOnCall(call) {
  call.on('stream', function(stream){
    console.log("call.on('stream', function(stream)");
    $('#audio_sec').append('<audio class="' + call.id + '" src="' + URL.createObjectURL(stream) + '" autoplay></audio>');
  });
}

$(document).ready(function() {
  name = $('#user_name').text();
  var box = $('#file_box');
  box.on('dragenter', doNothing);
  box.on('dragover', doNothing);
  box.on('drop', function(e){
    e.originalEvent.preventDefault();
    var file = e.originalEvent.dataTransfer.files[0];
    eachActiveConnection(function(c, $c) {
      if (c.label === 'file') {
        c.send(file);
        $('#messages').append('
You sent a file.
');
      }
    });
  });
  function doNothing(e){
    e.preventDefault();
    e.stopPropagation();
  }

  // 他の人との peer 接続開始
  $('#connect').click(function() {
    requestedPeer = $('#rid').val();
    if (!connected_peers[requestedPeer]) {
      // chat 用
      var chat = peer.connect(requestedPeer, {
        label: 'chat',
        serialization: 'none',
      });
      chat.on('open', function() {
        connect(chat);
      });
      chat.on('error', function(err) { alert(err); });

      // file 用
      var file = peer.connect(requestedPeer, {
        label: 'file',
        reliable: true });
      file.on('open', function() {
        connect(file);
      });
      file.on('error', function(err) { alert(err); });

      // 通話用
      var call = peer.call(requestedPeer, window.localStream);
      setOnCall(call);
    }
    connected_peers[requestedPeer] = 1;
  });

  // Close a connection.
  $('#close').click(function() {
    eachActiveConnection(function(c) {
      c.close();
    });
  });

  $('#chat_form').submit(function(e) {
    e.preventDefault();
    var msg = $('#text').val();
    $('#messages').append('
You: ' + msg + '
');
    eachActiveConnection(function(c, $c) {
      if (c.label === 'chat') {
        c.send(msg);
      }
    });
    $('#text').val('');
    $('#text').focus();
  });

  function eachActiveConnection(fn) {
    var checkedIds = {};
    for(key in connected_peers) {
      console.log(key);
      if (!checkedIds[key]) {
        var conns = peer.connections[key];
        for (var i = 0, ii = conns.length; i < ii; i += 1) {
          var conn = conns[i];
          fn(conn, $(this));
        }
      }
      checkedIds[key] = 1;
    }
  }
});

window.onunload = window.onbeforeunload = function(e) {
  if (!!peer && !peer.destroyed) {
    peer.destroy();
  }
};<commit_msg>スクリーンキャプチャとれるようにした<commit_after>var peer = new Peer({
  key: key_,
});

var connected_peers = {};
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
navigator.getUserMedia(
        {video:{mandatory:{chromeMediaSource:"screen"}}},
        function(stream){
          console.log("navigator");
          window.localStream = stream;
        },
        function(){console.log("navigator error");});
/*
 navigator.getUserMedia({audio: true, video: false},
        function(stream){
          console.log("navigator");
          window.localStream = stream;
        },
        function(){console.log("navigator error");});
*/
/**
 * peer イベント
 */
peer.on('open', function(id){
  $('#pid').text(id);
});

peer.on('connection', connect);

peer.on('call', audioCall);

peer.on('error', function(err){
  alert(err.message);
});

/**
 * チャットとファイル通信
 */
function connect(c) {
  if (c.label === 'chat') {
    var member_box = $('#member');
    var messages = $('#messages');
    messages.append('
' + c.peer + ': connect
');
    connected_peers[c.peer] = 1;

    c.on('data', function(data) {
      messages.append('
' + c.peer + ': ' + data + '
');
    });
    c.on('close', function() {
      delete connected_peers[c.peer];
    });
  } else if (c.label === 'file') {
    c.on('data', function(data) {
      if (data.constructor === ArrayBuffer) {
        var dataView = new Uint8Array(data);
        var dataBlob = new Blob([dataView]);
        var url = window.URL.createObjectURL(dataBlob);
        $('#messages').append('
' +
            c.peer + 'がfileを送信しました
');
      }
    });
  }
}

/**
 * 音声データ通信接続時（されたとき）
 */
function audioCall(call) {
  call.answer(window.localStream);
  setOnCall(call);
}

/**
 * call のイベント発生時の動作を設定
 */
function setOnCall(call) {
  call.on('stream', function(stream){
    console.log("call.on('stream', function(stream)");
    $('#audio_sec').append('<video class="' + call.id + '" src="' + URL.createObjectURL(stream) + '" autoplay></video>');
  });
}

$(document).ready(function() {
  name = $('#user_name').text();
  var box = $('#file_box');
  box.on('dragenter', doNothing);
  box.on('dragover', doNothing);
  box.on('drop', function(e){
    e.originalEvent.preventDefault();
    var file = e.originalEvent.dataTransfer.files[0];
    eachActiveConnection(function(c, $c) {
      if (c.label === 'file') {
        c.send(file);
        $('#messages').append('
You sent a file.
');
      }
    });
  });
  function doNothing(e){
    e.preventDefault();
    e.stopPropagation();
  }

  // 他の人との peer 接続開始
  $('#connect').click(function() {
    requestedPeer = $('#rid').val();
    if (!connected_peers[requestedPeer]) {
      // chat 用
      var chat = peer.connect(requestedPeer, {
        label: 'chat',
        serialization: 'none',
      });
      chat.on('open', function() {
        connect(chat);
      });
      chat.on('error', function(err) { alert(err); });

      // file 用
      var file = peer.connect(requestedPeer, {
        label: 'file',
        reliable: true });
      file.on('open', function() {
        connect(file);
      });
      file.on('error', function(err) { alert(err); });

      // 通話用
      var call = peer.call(requestedPeer, window.localStream);
      setOnCall(call);
    }
    connected_peers[requestedPeer] = 1;
  });

  // Close a connection.
  $('#close').click(function() {
    eachActiveConnection(function(c) {
      c.close();
    });
  });

  $('#chat_form').submit(function(e) {
    e.preventDefault();
    var msg = $('#text').val();
    $('#messages').append('
You: ' + msg + '
');
    eachActiveConnection(function(c, $c) {
      if (c.label === 'chat') {
        c.send(msg);
      }
    });
    $('#text').val('');
    $('#text').focus();
  });

  function eachActiveConnection(fn) {
    var checkedIds = {};
    for(key in connected_peers) {
      console.log(key);
      if (!checkedIds[key]) {
        var conns = peer.connections[key];
        for (var i = 0, ii = conns.length; i < ii; i += 1) {
          var conn = conns[i];
          fn(conn, $(this));
        }
      }
      checkedIds[key] = 1;
    }
  }
});

window.onunload = window.onbeforeunload = function(e) {
  if (!!peer && !peer.destroyed) {
    peer.destroy();
  }
};<|endoftext|>


<commit_before>var canvas;
var context;
var canvasWidth = window.innerWidth - 15;
var tempHeight = window.innerHeight;
var canvasHeight = (tempHeight - 150);
var padding = 0;
var lineWidth = 8;
var clickX = [];
var clickY = [];
var clickColor = [];
var clickTool = [];
var clickSize = [];
var clickDrag = [];
var paint = false;
var curColor = '#00ff00';
var colors = ['#ff0000', '#990000', '#00ff00', '#009900', '#0000ff', '#000099'];
//size of pen
var radius = 4;
var isClear = true; // is there nothing drawn by the user on the canvas?

/**
* Creates a canvas element, loads images, adds events, and draws the canvas for the first time.
*/
function initColor()
{
	curColor = colors[Math.floor(Math.random() * colors.length)];
	var colorpicker = document.getElementById('colorpicker');
	colorpicker.setAttribute('value', curColor);
}

function prepareCanvas()
{
	//init color to random
	initColor();
	// Create the canvas (Neccessary for IE because it doesn't know what a canvas element is)
	var canvasDiv = document.getElementById('canvasDiv');
	canvas = document.createElement('canvas');
	canvas.setAttribute('width', canvasDiv.offsetWidth);
	canvas.setAttribute('height', canvasHeight);
	canvas.setAttribute('id', 'canvas');
	canvas.setAttribute('style', 'left: 0px; top: 0px; border: 1px solid #000000;');
	canvasDiv.appendChild(canvas);

	if(typeof G_vmlCanvasManager !== 'undefined') {
		canvas = G_vmlCanvasManager.initElement(canvas);
	}
	context = canvas.getContext('2d'); // Grab the 2d canvas context
	// Note: The above code is a workaround for IE 8 and lower. Otherwise we could have used:
	//     context = document.getElementById('canvas').getContext('2d');

	canvas.addEventListener('touchstart', doTouchStart, false);
	canvas.addEventListener('touchmove', doTouchMove, false);
	canvas.addEventListener('touchend', doTouchEnd, false);
	window.addEventListener('resize', resizeCanvas, false);

	// Add mouse events
	// ----------------
	$('#canvas').mousedown(function(e)
	{
		// Mouse down location
		var mouseX = e.pageX - this.offsetLeft;
		var mouseY = e.pageY - this.offsetTop;
		coords.push({x: mouseX, y: mouseY});

		paint = true;
		addClick(mouseX, mouseY, false);
		redraw();
	});

	$('#canvas').mousemove(function(e){
		if(paint===true){
			var mouseX = e.pageX - this.offsetLeft;
			var mouseY = e.pageY - this.offsetTop;
			addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
			coords.push({x: mouseX, y: mouseY});
			redraw();
		}
	});

	$('#canvas').mouseup(function(e){
		paint = false;
	  	redraw();
	});

	$('#canvas').mouseleave(function(e){
		paint = false;
	});

	resizeCanvas();
	drawHelpText();
}

function resizeCanvas() {
	console.log('resized to' + window.innerWidth + 'x' + window.innerHeight);
	var canvasDiv = document.getElementById('canvasDiv');
	var canvas = document.getElementById('canvas');
	canvasDiv.width = canvasDiv.offsetWidth;
	canvasDiv.height = window.innerHeight - 150;
	canvas.width = canvasDiv.offsetWidth;
	canvas.height = window.innerHeight - 150;
	canvasWidth = canvasDiv.offsetWidth;
	canvasHeight = window.innerHeight - 150;
	redraw();
	if (isClear){
		drawHelpText();
	}
}

function doTouchEnd(e){
	paint = false;
	redraw();
}

function doTouchStart(e){
	e.preventDefault();
	//var e = event.originalEvent;
	var mouseX = e.targetTouches[0].pageX;
	var mouseY = e.targetTouches[0].pageY;
	coords.push({x: mouseX, y: mouseY});

	paint = true;
	addClick(mouseX, mouseY, false);
	redraw();
}

function doTouchMove(e){
	e.preventDefault();
	//var e = event.originalEvent;
	if(paint===true){
			var mouseX = e.targetTouches[0].pageX;
			var mouseY = e.targetTouches[0].pageY;
			addClick(mouseX, mouseY, true);
			//$('#test').text(coords.length + ' mousex:' + mouseX + ' mousey:' + mouseY);
			coords.push({x: mouseX, y: mouseY});
			redraw();
		}
}

/**
* Adds a point to the drawing array.
* @param x
* @param y
* @param dragging
*/
function addClick(x, y, dragging)
{
	isClear = false;
	curColor = $('#colorpicker').val();
	clickX.push(x);
	clickY.push(y);
	clickDrag.push(dragging);
}

/**
* Clears the canvas.
*/

function erase()
{
	clickX = [];
	clickY = [];
	clickDrag = [];
	coords = [];
	outputNotes = [];
	clearCanvas();
	drawHelpText();
}

function clearCanvas()
{
	isClear = true;
	context.clearRect(0, 0, canvasWidth, canvasHeight);
}

/**
 * Draw instructions onto the canvas
 */
function drawHelpText()
{
	var canvas = document.getElementById('canvas');
	var context = canvas.getContext('2d');
	context.font = '48px serif';
	context.fillStyle = '#cccccc';
	context.textAlign = 'center';
	var x = canvas.width / 2;
	var y = canvas.height / 2;
	context.fillText('draw', x , y);
}

/**
* Redraws the canvas.
*/
function redraw()
{
	clearCanvas();

	var i = 0;
	for(; i < clickX.length; i++)
	{
		context.beginPath();
		if(clickDrag[i] && i){
			context.moveTo(clickX[i-1], clickY[i-1]);
		}else{
			context.moveTo(clickX[i], clickY[i]);
		}
		context.lineTo(clickX[i], clickY[i]);

		context.closePath();

		context.lineJoin = 'round';
		context.lineWidth = radius;
		//setcolor
		context.strokeStyle = curColor;
		context.stroke();

	}
	context.restore();

}

/**/
<commit_msg>change when help text appears<commit_after>var canvas;
var context;
var canvasWidth = window.innerWidth - 15;
var tempHeight = window.innerHeight;
var canvasHeight = (tempHeight - 150);
var padding = 0;
var lineWidth = 8;
var clickX = [];
var clickY = [];
var clickColor = [];
var clickTool = [];
var clickSize = [];
var clickDrag = [];
var paint = false;
var curColor = '#00ff00';
var colors = ['#ff0000', '#990000', '#00ff00', '#009900', '#0000ff', '#000099'];
//size of pen
var radius = 4;
var isClear = true; // is there nothing drawn by the user on the canvas?

/**
* Creates a canvas element, loads images, adds events, and draws the canvas for the first time.
*/
function initColor()
{
	curColor = colors[Math.floor(Math.random() * colors.length)];
	var colorpicker = document.getElementById('colorpicker');
	colorpicker.setAttribute('value', curColor);
}

function prepareCanvas()
{
	//init color to random
	initColor();
	// Create the canvas (Neccessary for IE because it doesn't know what a canvas element is)
	var canvasDiv = document.getElementById('canvasDiv');
	canvas = document.createElement('canvas');
	canvas.setAttribute('width', canvasDiv.offsetWidth);
	canvas.setAttribute('height', canvasHeight);
	canvas.setAttribute('id', 'canvas');
	canvas.setAttribute('style', 'left: 0px; top: 0px; border: 1px solid #000000;');
	canvasDiv.appendChild(canvas);

	if(typeof G_vmlCanvasManager !== 'undefined') {
		canvas = G_vmlCanvasManager.initElement(canvas);
	}
	context = canvas.getContext('2d'); // Grab the 2d canvas context
	// Note: The above code is a workaround for IE 8 and lower. Otherwise we could have used:
	//     context = document.getElementById('canvas').getContext('2d');

	canvas.addEventListener('touchstart', doTouchStart, false);
	canvas.addEventListener('touchmove', doTouchMove, false);
	canvas.addEventListener('touchend', doTouchEnd, false);
	window.addEventListener('resize', resizeCanvas, false);

	// Add mouse events
	// ----------------
	$('#canvas').mousedown(function(e)
	{
		// Mouse down location
		var mouseX = e.pageX - this.offsetLeft;
		var mouseY = e.pageY - this.offsetTop;
		coords.push({x: mouseX, y: mouseY});

		paint = true;
		addClick(mouseX, mouseY, false);
		redraw();
	});

	$('#canvas').mousemove(function(e){
		if(paint===true){
			var mouseX = e.pageX - this.offsetLeft;
			var mouseY = e.pageY - this.offsetTop;
			addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
			coords.push({x: mouseX, y: mouseY});
			redraw();
		}
	});

	$('#canvas').mouseup(function(e){
		paint = false;
	  	redraw();
	});

	$('#canvas').mouseleave(function(e){
		paint = false;
	});

	resizeCanvas();
	drawHelpText();
}

function resizeCanvas() {
	console.log('resized to' + window.innerWidth + 'x' + window.innerHeight);
	var canvasDiv = document.getElementById('canvasDiv');
	var canvas = document.getElementById('canvas');
	canvasDiv.width = canvasDiv.offsetWidth;
	canvasDiv.height = window.innerHeight - 150;
	canvas.width = canvasDiv.offsetWidth;
	canvas.height = window.innerHeight - 150;
	canvasWidth = canvasDiv.offsetWidth;
	canvasHeight = window.innerHeight - 150;
	redraw();
	if (isClear){
		drawHelpText();
	}
}

function doTouchEnd(e){
	paint = false;
	redraw();
}

function doTouchStart(e){
	e.preventDefault();
	//var e = event.originalEvent;
	var mouseX = e.targetTouches[0].pageX;
	var mouseY = e.targetTouches[0].pageY;
	coords.push({x: mouseX, y: mouseY});

	paint = true;
	addClick(mouseX, mouseY, false);
	redraw();
}

function doTouchMove(e){
	e.preventDefault();
	//var e = event.originalEvent;
	if(paint===true){
			var mouseX = e.targetTouches[0].pageX;
			var mouseY = e.targetTouches[0].pageY;
			addClick(mouseX, mouseY, true);
			//$('#test').text(coords.length + ' mousex:' + mouseX + ' mousey:' + mouseY);
			coords.push({x: mouseX, y: mouseY});
			redraw();
		}
}

/**
* Adds a point to the drawing array.
* @param x
* @param y
* @param dragging
*/
function addClick(x, y, dragging)
{
	isClear = false;
	curColor = $('#colorpicker').val();
	clickX.push(x);
	clickY.push(y);
	clickDrag.push(dragging);
}

/**
* Clears the canvas.
*/

function erase()
{
	isClear = true;
	clickX = [];
	clickY = [];
	clickDrag = [];
	coords = [];
	outputNotes = [];
	clearCanvas();
	drawHelpText();
}

function clearCanvas()
{
	context.clearRect(0, 0, canvasWidth, canvasHeight);
}

/**
 * Draw instructions onto the canvas
 */
function drawHelpText()
{
	var canvas = document.getElementById('canvas');
	var context = canvas.getContext('2d');
	context.font = '48px serif';
	context.fillStyle = '#cccccc';
	context.textAlign = 'center';
	var x = canvas.width / 2;
	var y = canvas.height / 2;
	context.fillText('draw', x , y);
}

/**
* Redraws the canvas.
*/
function redraw()
{
	clearCanvas();

	var i = 0;
	for(; i < clickX.length; i++)
	{
		context.beginPath();
		if(clickDrag[i] && i){
			context.moveTo(clickX[i-1], clickY[i-1]);
		}else{
			context.moveTo(clickX[i], clickY[i]);
		}
		context.lineTo(clickX[i], clickY[i]);

		context.closePath();

		context.lineJoin = 'round';
		context.lineWidth = radius;
		//setcolor
		context.strokeStyle = curColor;
		context.stroke();

	}
	context.restore();

}

/**/
<|endoftext|>