<commit_before>/*!
 * Dialogs Manager v2.1.0
 * https://github.com/cobicarmel/dialogs-manager/
 *
 * Copyright Kobi Zaltzberg
 * Released under the MIT license
 * https://github.com/cobicarmel/dialogs-manager/blob/master/LICENSE.txt
 */

(function ($, global) {
	'use strict';

	/*
	 * Dialog Manager
	 */
	var DialogsManager = {
		widgetsTypes: {},
		createWidgetType: function (typeName, properties, Parent) {
			if (!Parent) {
				Parent = this.Widget;
			}

			var WidgetType = function () {

				Parent.apply(this, arguments);
			};

			var prototype = WidgetType.prototype = new Parent(typeName);

			$.extend(prototype, properties);

			prototype.constructor = WidgetType;

			WidgetType.extend = function (typeName, properties) {

				return DialogsManager.createWidgetType(typeName, properties, WidgetType);
			};

			return WidgetType;
		},
		addWidgetType: function (typeName, properties, Parent) {

			if (properties && properties.prototype instanceof this.Widget) {
				return this.widgetsTypes[typeName] = properties;
			}

			return this.widgetsTypes[typeName] = this.createWidgetType(typeName, properties, Parent);
		},
		getWidgetType: function (widgetType) {

			return this.widgetsTypes[widgetType];
		}
	};

	/*
	 * Dialog Manager instances constructor
	 */
	DialogsManager.Instance = function () {

		var self = this,
			components = {},
			settings = {};

		var initComponents = function () {

			components.$body = $('body');
		};

		var initSettings = function (options) {

			var defaultSettings = {
				classPrefix: 'dialog',
				effects: {
					show: 'fadeIn',
					hide: 'fadeOut'
				}
			};

			settings = $.extend(defaultSettings, options);
		};

		this.createWidget = function (widgetType, properties) {

			var WidgetTypeConstructor = DialogsManager.getWidgetType(widgetType),
				widget = new WidgetTypeConstructor(widgetType);

			properties = properties || {};

			widget.init(self, properties);

			widget.setMessage(properties.message);

			if (properties.linkedElement) {
				widget.linkElement(properties.linkedElement, widget);
			}

			return widget;
		};

		this.getSettings = function (property) {

			if (property) {
				return settings[property];
			}

			return Object.create(settings);
		};

		this.init = function (settings) {

			initSettings(settings);

			initComponents();

			return self;
		};

		self.init();
	};

	/*
	 * Widget types constructor
	 */
	DialogsManager.Widget = function (widgetName) {

		var self = this,
			settings = {},
			events = {},
			components = {
				$element: 0
			};

		var callEffect = function (intent) {

			var effect = settings.effects[intent],
				$widget = components.$widget;

			if ($.isFunction(effect)) {
				effect.call($widget);
			}
			else {

				if ($widget[effect]) {
					$widget[effect]();
				}
				else {
					throw 'Reference Error: The effect ' + effect + ' not found';
				}
			}
		};

		var initComponents = function () {

			self.addComponent('widget');

			self.addComponent('message');

			var id = self.getSettings('id');

			if (id) {

				self.getComponents('widget').attr('id', id);
			}
		};

		var initSettings = function (parent, userSettings) {

			var parentSettings = parent.getSettings();

			settings = self.getDefaultSettings();

			settings.effects = parentSettings.effects;

			var prefix = parentSettings.classPrefix + '-' + widgetName;

			settings.classes = {
				globalPrefix: parentSettings.classPrefix,
				prefix: prefix,
				widget: 'dialog-widget',
				linkedActive: prefix + '-linked-active'
			};

			$.extend(true, settings, userSettings);

			initSettingsEvents();
		};

		var initSettingsEvents = function () {

			var settings = self.getSettings();

			$.each( settings, function (settingKey) {

				var eventName = settingKey.match(/^on([A-Z].*)/);

				if (!eventName) {
					return;
				}

				eventName = eventName[1].charAt(0).toLowerCase() + eventName[1].slice(1);

				self.on(eventName, this);
			} );
		};

		var normalizeClassName = function (name) {

			return name.replace(/([a-z])([A-Z])/g, function () {
				return arguments[1] + '-' + arguments[2].toLowerCase();
			});
		};

		this.addComponent = function (name, component, type) {

			var $newComponent = components['$' + name] = $(component || '<div>'),
				className = settings.classes.prefix + '-';

			name = normalizeClassName(name);

			className += name;

			if (!type) {
				type = name;
			}

			className += ' ' + settings.classes.globalPrefix + '-' + type;

			$newComponent.addClass(className);

			return $newComponent;
		};

		this.getSettings = function (setting) {

			var copy = Object.create(settings);

			if (setting) {
				return copy[setting];
			}

			return copy;
		};

		this.init = function (parent, properties) {

			if (!(parent instanceof DialogsManager.Instance)) {
				throw 'The ' + self.widgetName + ' must to be initialized from an instance of DialogsManager.Instance';
			}

			self.trigger('init', properties);

			initSettings(parent, properties);

			initComponents();

			self.buildWidget();

			if (self.attachEvents) {
				self.attachEvents();
			}

			self.trigger('ready');

			return self;
		};

		this.getComponents = function (item) {

			return item ? components['$' + item] : components;
		};

		this.hide = function () {

			callEffect('hide');

			if (components.$element.length) {
				components.$element.removeClass(settings.classes.linkedActive);
			}

			self.trigger('hide');

			return self;
		};

		this.linkElement = function (element) {

			this.addComponent('element', element);

			return self;
		};

		this.on = function (eventName, callback) {
			if (!events[eventName]) {
				events[eventName] = [];
			}

			events[eventName].push(callback);

			return self;
		};

		this.setMessage = function (message) {

			components.$message.html(message);

			return self;
		};

		this.show = function (e, userSettings) {

			if (e) {
				e.stopPropagation();
			}

			components.$widget.appendTo('body');

			callEffect('show');

			if (components.$element.length) {
				components.$element.addClass(settings.classes.linkedActive);
			}

			self.trigger('show', userSettings);

			return self;
		};

		this.trigger = function (eventName, params) {

			var methodName = 'on' + eventName[0].toUpperCase() + eventName.slice(1);

			if (self[methodName]) {
				self[methodName](params);
			}

			var callbacks = events[eventName];

			if (!callbacks) {
				return;
			}

			$.each(callbacks, function (index, callback) {
				callback.call(self, params);
			});
		};
	};

	// Inheritable widget methods
	DialogsManager.Widget.prototype.buildWidget = function () {

		var components = this.getComponents();

		components.$widget.html(components.$message);
	};

	DialogsManager.Widget.prototype.getDefaultSettings = function () {

		return {};
	};

	DialogsManager.Widget.prototype.onHide = function () {
	};

	DialogsManager.Widget.prototype.onShow = function () {
	};

	DialogsManager.Widget.prototype.onInit = function () {
	};

	DialogsManager.Widget.prototype.onReady = function () {
	};

	/*
	 * Default basic widget types
	 */
	DialogsManager.addWidgetType('tool-tip', {
		onShow: function () {

			var components = this.getComponents();

			if (components.$element.length) {

				components.$widget.position({
					at: 'left top-5',
					my: 'left+10 bottom',
					of: components.$element,
					collision: 'none none'
				});

				components.$element.focus();
			}

			setTimeout(this.hide, 5000);
		}
	});

	DialogsManager.addWidgetType('options', {
		activeKeyUp: function (event) {

			var TAB_KEY = 9;

			if (event.which === TAB_KEY) {

				event.preventDefault();
			}

			if (this.hotKeys[event.which]) {
				this.hotKeys[event.which](this);
			}
		},
		activeKeyDown: function (event) {

			var TAB_KEY = 9;

			if (event.which === TAB_KEY) {
				event.preventDefault();

				var currentButtonIndex = this.focusedButton.index(),
					nextButtonIndex;

				if (event.shiftKey) {

					nextButtonIndex = currentButtonIndex - 1;

					if (nextButtonIndex < 0) {
						nextButtonIndex = this.buttons.length - 1;
					}
				} else {

					nextButtonIndex = currentButtonIndex + 1;

					if (nextButtonIndex >= this.buttons.length) {
						nextButtonIndex = 0;
					}
				}

				this.focusedButton = this.buttons[nextButtonIndex].focus();
			}
		},
		addButton: function (options) {

			var self = this,
				$button = self.addComponent(options.name, $('<button>').text(options.text));

			self.buttons.push($button);

			var buttonFn = function () {

				self.hide();

				if ($.isFunction(options.callback)) {
					options.callback.call(this, self);
				}
			};

			$button.on('click', buttonFn);

			if (options.hotKey) {
				this.hotKeys[options.hotKey] = buttonFn;
			}

			this.getComponents('buttonsWrapper').append($button);

			if (options.focus) {
				this.focusedButton = $button;
			}

			return self;
		},
		bindHotKeys: function () {
			var self = this;

			self.bindKeyUpEvents = function (event) {

				self.activeKeyUp(event);
			};

			self.bindKeyDownEvents = function (event) {

				self.activeKeyDown(event);
			};

			$(window).on({
				keyup: self.bindKeyUpEvents,
				keydown: self.bindKeyDownEvents
			});
		},
		buildWidget: function () {

			var $widgetHeader = this.addComponent('widgetHeader'),
				$widgetContent = this.addComponent('widgetContent'),
				$buttonsWrapper = this.addComponent('buttonsWrapper');

			var components = this.getComponents();

			$widgetContent.append($widgetHeader, components.$message, $buttonsWrapper);

			components.$widget.html($widgetContent);
		},
		getDefaultSettings: function () {

			return {
				position: {
					my: 'center',
					at: 'center center-100'
				},
				headerMessage: ''
			};
		},
		onHide: function () {

			this.unbindHotKeys();
		},
		onInit: function () {

			this.buttons = [];

			this.hotKeys = {};

			this.focusedButton = null;
		},
		onReady: function(){

			this.setHeaderMessage(this.getSettings('headerMessage'));
		},
		onShow: function (userSettings) {

			var components = this.getComponents(),
				position = this.getSettings('position');

			position.of = components.$widget;

			if (userSettings) {
				$.extend(position, userSettings);
			}

			components.$widgetContent.position(position);

			this.bindHotKeys();

			if (!this.focusedButton) {
				this.focusedButton = this.buttons[0];
			}

			if (this.focusedButton) {
				this.focusedButton.focus();
			}
		},
		setHeaderMessage: function (message) {

			this.getComponents('widgetHeader').html(message);

			return this;
		},
		unbindHotKeys: function () {

			$(window).off({
				keyup: this.bindKeyUpEvents,
				keydown: this.bindKeyDownEvents
			});
		}
	});

	DialogsManager.addWidgetType('confirm', DialogsManager.getWidgetType('options').extend('confirm', {
		onReady: function () {

			DialogsManager.getWidgetType('options').prototype.onReady.apply(this, arguments);

			var strings = this.getSettings('strings'),
				ESC_KEY = 27,
				isDefaultCancel = this.getSettings('defaultOption') === 'cancel';

			this.addButton({
				name: 'cancel',
				text: strings.cancel,
				callback: function (widget) {

					widget.trigger('cancel');
				},
				hotKey: ESC_KEY,
				focus: isDefaultCancel
			});

			this.addButton({
				name: 'ok',
				text: strings.confirm,
				callback: function (widget) {

					widget.trigger('confirm');
				},
				focus: !isDefaultCancel
			});
		},
		getDefaultSettings: function () {

			var settings = DialogsManager.getWidgetType('options').prototype.getDefaultSettings.apply(this, arguments);

			settings.strings = {
				confirm: 'OK',
				cancel: 'Cancel'
			};

			settings.defaultOption = 'cancel';

			return settings;
		}
	}));

	DialogsManager.addWidgetType('alert', DialogsManager.getWidgetType('options').extend('alert', {
		onReady: function () {

			DialogsManager.getWidgetType('options').prototype.onReady.apply(this, arguments);

			var strings = this.getSettings('strings');

			this.addButton({
				name: 'ok',
				text: strings.confirm,
				callback: function (widget) {

					widget.trigger('confirm');
				}
			});
		},
		getDefaultSettings: function () {
			var settings = DialogsManager.getWidgetType('options').prototype.getDefaultSettings.apply(this, arguments);

			settings.strings = {
				confirm: 'OK'
			};

			return settings;
		}
	}));

	DialogsManager.addWidgetType('popup', {
		getDefaultSettings: function () {

			return {
				position: {
					my: 'center',
					at: 'center',
					of: window
				},
				hide: {
					delay: 5000
				}
			};
		},
		onShow: function () {

			var $widgetMessage = this.getComponents('message');

			$widgetMessage.position(this.getSettings('position'));

			setTimeout(this.hide, this.getSettings('hide').delay);
		}
	});

	// Exporting the DialogsManager variable to global
	global.DialogsManager = DialogsManager;
})('function' === typeof require ? require('jquery') : jQuery, 'undefined' !== typeof module && module.exports || window);<commit_msg>Allow to disable auto-hide on button click<commit_after>/*!
 * Dialogs Manager v2.1.0
 * https://github.com/cobicarmel/dialogs-manager/
 *
 * Copyright Kobi Zaltzberg
 * Released under the MIT license
 * https://github.com/cobicarmel/dialogs-manager/blob/master/LICENSE.txt
 */

(function ($, global) {
	'use strict';

	/*
	 * Dialog Manager
	 */
	var DialogsManager = {
		widgetsTypes: {},
		createWidgetType: function (typeName, properties, Parent) {
			if (!Parent) {
				Parent = this.Widget;
			}

			var WidgetType = function () {

				Parent.apply(this, arguments);
			};

			var prototype = WidgetType.prototype = new Parent(typeName);

			$.extend(prototype, properties);

			prototype.constructor = WidgetType;

			WidgetType.extend = function (typeName, properties) {

				return DialogsManager.createWidgetType(typeName, properties, WidgetType);
			};

			return WidgetType;
		},
		addWidgetType: function (typeName, properties, Parent) {

			if (properties && properties.prototype instanceof this.Widget) {
				return this.widgetsTypes[typeName] = properties;
			}

			return this.widgetsTypes[typeName] = this.createWidgetType(typeName, properties, Parent);
		},
		getWidgetType: function (widgetType) {

			return this.widgetsTypes[widgetType];
		}
	};

	/*
	 * Dialog Manager instances constructor
	 */
	DialogsManager.Instance = function () {

		var self = this,
			components = {},
			settings = {};

		var initComponents = function () {

			components.$body = $('body');
		};

		var initSettings = function (options) {

			var defaultSettings = {
				classPrefix: 'dialog',
				effects: {
					show: 'fadeIn',
					hide: 'fadeOut'
				}
			};

			settings = $.extend(defaultSettings, options);
		};

		this.createWidget = function (widgetType, properties) {

			var WidgetTypeConstructor = DialogsManager.getWidgetType(widgetType),
				widget = new WidgetTypeConstructor(widgetType);

			properties = properties || {};

			widget.init(self, properties);

			widget.setMessage(properties.message);

			if (properties.linkedElement) {
				widget.linkElement(properties.linkedElement, widget);
			}

			return widget;
		};

		this.getSettings = function (property) {

			if (property) {
				return settings[property];
			}

			return Object.create(settings);
		};

		this.init = function (settings) {

			initSettings(settings);

			initComponents();

			return self;
		};

		self.init();
	};

	/*
	 * Widget types constructor
	 */
	DialogsManager.Widget = function (widgetName) {

		var self = this,
			settings = {},
			events = {},
			components = {
				$element: 0
			};

		var callEffect = function (intent) {

			var effect = settings.effects[intent],
				$widget = components.$widget;

			if ($.isFunction(effect)) {
				effect.call($widget);
			}
			else {

				if ($widget[effect]) {
					$widget[effect]();
				}
				else {
					throw 'Reference Error: The effect ' + effect + ' not found';
				}
			}
		};

		var initComponents = function () {

			self.addComponent('widget');

			self.addComponent('message');

			var id = self.getSettings('id');

			if (id) {

				self.getComponents('widget').attr('id', id);
			}
		};

		var initSettings = function (parent, userSettings) {

			var parentSettings = parent.getSettings();

			settings = self.getDefaultSettings();

			settings.effects = parentSettings.effects;

			var prefix = parentSettings.classPrefix + '-' + widgetName;

			settings.classes = {
				globalPrefix: parentSettings.classPrefix,
				prefix: prefix,
				widget: 'dialog-widget',
				linkedActive: prefix + '-linked-active'
			};

			$.extend(true, settings, userSettings);

			initSettingsEvents();
		};

		var initSettingsEvents = function () {

			var settings = self.getSettings();

			$.each( settings, function (settingKey) {

				var eventName = settingKey.match(/^on([A-Z].*)/);

				if (!eventName) {
					return;
				}

				eventName = eventName[1].charAt(0).toLowerCase() + eventName[1].slice(1);

				self.on(eventName, this);
			} );
		};

		var normalizeClassName = function (name) {

			return name.replace(/([a-z])([A-Z])/g, function () {
				return arguments[1] + '-' + arguments[2].toLowerCase();
			});
		};

		this.addComponent = function (name, component, type) {

			var $newComponent = components['$' + name] = $(component || '<div>'),
				className = settings.classes.prefix + '-';

			name = normalizeClassName(name);

			className += name;

			if (!type) {
				type = name;
			}

			className += ' ' + settings.classes.globalPrefix + '-' + type;

			$newComponent.addClass(className);

			return $newComponent;
		};

		this.getSettings = function (setting) {

			var copy = Object.create(settings);

			if (setting) {
				return copy[setting];
			}

			return copy;
		};

		this.init = function (parent, properties) {

			if (!(parent instanceof DialogsManager.Instance)) {
				throw 'The ' + self.widgetName + ' must to be initialized from an instance of DialogsManager.Instance';
			}

			self.trigger('init', properties);

			initSettings(parent, properties);

			initComponents();

			self.buildWidget();

			if (self.attachEvents) {
				self.attachEvents();
			}

			self.trigger('ready');

			return self;
		};

		this.getComponents = function (item) {

			return item ? components['$' + item] : components;
		};

		this.hide = function () {

			callEffect('hide');

			if (components.$element.length) {
				components.$element.removeClass(settings.classes.linkedActive);
			}

			self.trigger('hide');

			return self;
		};

		this.linkElement = function (element) {

			this.addComponent('element', element);

			return self;
		};

		this.on = function (eventName, callback) {
			if (!events[eventName]) {
				events[eventName] = [];
			}

			events[eventName].push(callback);

			return self;
		};

		this.setMessage = function (message) {

			components.$message.html(message);

			return self;
		};

		this.show = function (e, userSettings) {

			if (e) {
				e.stopPropagation();
			}

			components.$widget.appendTo('body');

			callEffect('show');

			if (components.$element.length) {
				components.$element.addClass(settings.classes.linkedActive);
			}

			self.trigger('show', userSettings);

			return self;
		};

		this.trigger = function (eventName, params) {

			var methodName = 'on' + eventName[0].toUpperCase() + eventName.slice(1);

			if (self[methodName]) {
				self[methodName](params);
			}

			var callbacks = events[eventName];

			if (!callbacks) {
				return;
			}

			$.each(callbacks, function (index, callback) {
				callback.call(self, params);
			});
		};
	};

	// Inheritable widget methods
	DialogsManager.Widget.prototype.buildWidget = function () {

		var components = this.getComponents();

		components.$widget.html(components.$message);
	};

	DialogsManager.Widget.prototype.getDefaultSettings = function () {

		return {};
	};

	DialogsManager.Widget.prototype.onHide = function () {
	};

	DialogsManager.Widget.prototype.onShow = function () {
	};

	DialogsManager.Widget.prototype.onInit = function () {
	};

	DialogsManager.Widget.prototype.onReady = function () {
	};

	/*
	 * Default basic widget types
	 */
	DialogsManager.addWidgetType('tool-tip', {
		onShow: function () {

			var components = this.getComponents();

			if (components.$element.length) {

				components.$widget.position({
					at: 'left top-5',
					my: 'left+10 bottom',
					of: components.$element,
					collision: 'none none'
				});

				components.$element.focus();
			}

			setTimeout(this.hide, 5000);
		}
	});

	DialogsManager.addWidgetType('options', {
		activeKeyUp: function (event) {

			var TAB_KEY = 9;

			if (event.which === TAB_KEY) {

				event.preventDefault();
			}

			if (this.hotKeys[event.which]) {
				this.hotKeys[event.which](this);
			}
		},
		activeKeyDown: function (event) {

			var TAB_KEY = 9;

			if (event.which === TAB_KEY) {
				event.preventDefault();

				var currentButtonIndex = this.focusedButton.index(),
					nextButtonIndex;

				if (event.shiftKey) {

					nextButtonIndex = currentButtonIndex - 1;

					if (nextButtonIndex < 0) {
						nextButtonIndex = this.buttons.length - 1;
					}
				} else {

					nextButtonIndex = currentButtonIndex + 1;

					if (nextButtonIndex >= this.buttons.length) {
						nextButtonIndex = 0;
					}
				}

				this.focusedButton = this.buttons[nextButtonIndex].focus();
			}
		},
		addButton: function (options) {

			var self = this,
				$button = self.addComponent(options.name, $('<button>').text(options.text));

			self.buttons.push($button);

			var buttonFn = function () {

				if (self.getSettings('hideOnButtonClick')) {
					self.hide();
				}

				if ($.isFunction(options.callback)) {
					options.callback.call(this, self);
				}
			};

			$button.on('click', buttonFn);

			if (options.hotKey) {
				this.hotKeys[options.hotKey] = buttonFn;
			}

			this.getComponents('buttonsWrapper').append($button);

			if (options.focus) {
				this.focusedButton = $button;
			}

			return self;
		},
		bindHotKeys: function () {
			var self = this;

			self.bindKeyUpEvents = function (event) {

				self.activeKeyUp(event);
			};

			self.bindKeyDownEvents = function (event) {

				self.activeKeyDown(event);
			};

			$(window).on({
				keyup: self.bindKeyUpEvents,
				keydown: self.bindKeyDownEvents
			});
		},
		buildWidget: function () {

			var $widgetHeader = this.addComponent('widgetHeader'),
				$widgetContent = this.addComponent('widgetContent'),
				$buttonsWrapper = this.addComponent('buttonsWrapper');

			var components = this.getComponents();

			$widgetContent.append($widgetHeader, components.$message, $buttonsWrapper);

			components.$widget.html($widgetContent);
		},
		getDefaultSettings: function () {

			return {
				position: {
					my: 'center',
					at: 'center center-100'
				},
				headerMessage: '',
				hideOnButtonClick: true
			};
		},
		onHide: function () {

			this.unbindHotKeys();
		},
		onInit: function () {

			this.buttons = [];

			this.hotKeys = {};

			this.focusedButton = null;
		},
		onReady: function(){

			this.setHeaderMessage(this.getSettings('headerMessage'));
		},
		onShow: function (userSettings) {

			var components = this.getComponents(),
				position = this.getSettings('position');

			position.of = components.$widget;

			if (userSettings) {
				$.extend(position, userSettings);
			}

			components.$widgetContent.position(position);

			this.bindHotKeys();

			if (!this.focusedButton) {
				this.focusedButton = this.buttons[0];
			}

			if (this.focusedButton) {
				this.focusedButton.focus();
			}
		},
		setHeaderMessage: function (message) {

			this.getComponents('widgetHeader').html(message);

			return this;
		},
		unbindHotKeys: function () {

			$(window).off({
				keyup: this.bindKeyUpEvents,
				keydown: this.bindKeyDownEvents
			});
		}
	});

	DialogsManager.addWidgetType('confirm', DialogsManager.getWidgetType('options').extend('confirm', {
		onReady: function () {

			DialogsManager.getWidgetType('options').prototype.onReady.apply(this, arguments);

			var strings = this.getSettings('strings'),
				ESC_KEY = 27,
				isDefaultCancel = this.getSettings('defaultOption') === 'cancel';

			this.addButton({
				name: 'cancel',
				text: strings.cancel,
				callback: function (widget) {

					widget.trigger('cancel');
				},
				hotKey: ESC_KEY,
				focus: isDefaultCancel
			});

			this.addButton({
				name: 'ok',
				text: strings.confirm,
				callback: function (widget) {

					widget.trigger('confirm');
				},
				focus: !isDefaultCancel
			});
		},
		getDefaultSettings: function () {

			var settings = DialogsManager.getWidgetType('options').prototype.getDefaultSettings.apply(this, arguments);

			settings.strings = {
				confirm: 'OK',
				cancel: 'Cancel'
			};

			settings.defaultOption = 'cancel';

			return settings;
		}
	}));

	DialogsManager.addWidgetType('alert', DialogsManager.getWidgetType('options').extend('alert', {
		onReady: function () {

			DialogsManager.getWidgetType('options').prototype.onReady.apply(this, arguments);

			var strings = this.getSettings('strings');

			this.addButton({
				name: 'ok',
				text: strings.confirm,
				callback: function (widget) {

					widget.trigger('confirm');
				}
			});
		},
		getDefaultSettings: function () {
			var settings = DialogsManager.getWidgetType('options').prototype.getDefaultSettings.apply(this, arguments);

			settings.strings = {
				confirm: 'OK'
			};

			return settings;
		}
	}));

	DialogsManager.addWidgetType('popup', {
		getDefaultSettings: function () {

			return {
				position: {
					my: 'center',
					at: 'center',
					of: window
				},
				hide: {
					delay: 5000
				}
			};
		},
		onShow: function () {

			var $widgetMessage = this.getComponents('message');

			$widgetMessage.position(this.getSettings('position'));

			setTimeout(this.hide, this.getSettings('hide').delay);
		}
	});

	// Exporting the DialogsManager variable to global
	global.DialogsManager = DialogsManager;
})('function' === typeof require ? require('jquery') : jQuery, 'undefined' !== typeof module && module.exports || window);<|endoftext|>


<commit_before>/* Norwegian LANGUAGE
================================================== */
if(typeof VMM != 'undefined') {
	VMM.Language = {
		lang: "no",
		api: {
			wikipedia: "no"
		},
		date: {
			month: ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"],
			month_abbr: ["Jan.", "Feb.", "Mars", "Apr.", "Mai", "Juni", "Juli", "Aug.", "Sep.", "Okt.", "Nov.", "Des."],
			day: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"],
			day_abbr: ["Søn.", "Man.", "Tir.", "Ons.", "Tor.", "Fre.", "Lør."]
		},
		dateformats: {
			year: "yyyy",
			month_short: "mmm",
			month: "mmmm yyyy",
			full_short: "d. mmm",
			full: "d. mmmm',' yyyy",
			time_short: "HH:MM:ss",
			time_no_seconds_short: "HH:MM",
			time_no_seconds_small_date: "HH:MM'
'd. mmmm',' yyyy''",
			full_long: "dddd',' d. mmm',' yyyy 'kl.' HH:MM",
			full_long_small_date: "HH:MM'
'dddd',' d. mmm',' yyyy''"
		},
		messages: {
			loading_timeline: "Laster timeline... ",
			return_to_title: "Tilbake til tittel",
			expand_timeline: "Utvid timeline",
			contract_timeline: "Krymp timeline",
			wikipedia: "Fra Wikipedia, den frie encyklopedi",
			loading_content: "Laster innhold",
			loading: "Laster"
		}
	}
}
<commit_msg>s/timeline/tidslinje - closes NUKnightLab/StoryJS-Core#40 thanks @tbaschim<commit_after>/* Norwegian LANGUAGE
================================================== */
if(typeof VMM != 'undefined') {
	VMM.Language = {
		lang: "no",
		api: {
			wikipedia: "no"
		},
		date: {
			month: ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"],
			month_abbr: ["Jan.", "Feb.", "Mars", "Apr.", "Mai", "Juni", "Juli", "Aug.", "Sep.", "Okt.", "Nov.", "Des."],
			day: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"],
			day_abbr: ["Søn.", "Man.", "Tir.", "Ons.", "Tor.", "Fre.", "Lør."]
		},
		dateformats: {
			year: "yyyy",
			month_short: "mmm",
			month: "mmmm yyyy",
			full_short: "d. mmm",
			full: "d. mmmm',' yyyy",
			time_short: "HH:MM:ss",
			time_no_seconds_short: "HH:MM",
			time_no_seconds_small_date: "HH:MM'
'd. mmmm',' yyyy''",
			full_long: "dddd',' d. mmm',' yyyy 'kl.' HH:MM",
			full_long_small_date: "HH:MM'
'dddd',' d. mmm',' yyyy''"
		},
		messages: {
			loading_timeline: "Laster tidslinje... ",
			return_to_title: "Tilbake til tittel",
			expand_timeline: "Utvid tidslinje",
			contract_timeline: "Krymp tidslinje",
			wikipedia: "Fra Wikipedia, den frie encyklopedi",
			loading_content: "Laster innhold",
			loading: "Laster"
		}
	}
}<|endoftext|>


<commit_before>/*!
  * Stickyfill – `position: sticky` polyfill
  * v. 2.0.5 | https://github.com/wilddeer/stickyfill
  * MIT License
  */

'use strict';

/*
 * 1. Check if the browser supports `position: sticky` natively or is too old to run the polyfill.
 *    If either of these is the case set `seppuku` flag. It will be checked later to disable key features
 *    of the polyfill, but the API will remain functional to avoid breaking things.
 */
let seppuku = false;

// The polyfill cant’t function properly without `getComputedStyle`.
if (!window.getComputedStyle) seppuku = true;
// Dont’t get in a way if the browser supports `position: sticky` natively.
else {
    const testNode = document.createElement('div');

    if (
        ['', '-webkit-', '-moz-', '-ms-'].some(prefix => {
            try {
                testNode.style.position = prefix + 'sticky';
            }
            catch(e) {}

            return testNode.style.position != '';
        })
    ) seppuku = true;
}

/*
 * 2. “Global” vars used across the polyfill
 */

// Check if Shadow Root constructor exists to make further checks simpler
const shadowRootExists = typeof ShadowRoot !== 'undefined';

// Last saved scroll position
const scroll = {
    top: null,
    left: null
};

// Array of created Sticky instances
const stickies = [];

/*
 * 3. Utility functions
 */
function extend (targetObj, sourceObject) {
    for (var key in sourceObject) {
        if (sourceObject.hasOwnProperty(key)) {
            targetObj[key] = sourceObject[key];
        }
    }
}

function parseNumeric (val) {
    return parseFloat(val) || 0;
}

function getDocOffsetTop (node) {
    let docOffsetTop = 0;

    while (node) {
        docOffsetTop += node.offsetTop;
        node = node.offsetParent;
    }

    return docOffsetTop;
}

/*
 * 4. Sticky class
 */
class Sticky {
    constructor (node) {
        if (!(node instanceof HTMLElement))
            throw new Error('First argument must be HTMLElement');
        if (stickies.some(sticky => sticky._node === node))
            throw new Error('Stickyfill is already applied to this node');

        this._node = node;
        this._stickyMode = null;
        this._active = false;

        stickies.push(this);

        this.refresh();
    }

    refresh () {
        if (seppuku || this._removed) return;
        if (this._active) this._deactivate();

        const node = this._node;

        /*
         * 1. Save node computed props
         */
        const nodeComputedStyle = getComputedStyle(node);
        const nodeComputedProps = {
            top: nodeComputedStyle.top,
            display: nodeComputedStyle.display,
            marginTop: nodeComputedStyle.marginTop,
            marginBottom: nodeComputedStyle.marginBottom,
            marginLeft: nodeComputedStyle.marginLeft,
            marginRight: nodeComputedStyle.marginRight,
            cssFloat: nodeComputedStyle.cssFloat
        };

        /*
         * 2. Check if the node can be activated
         */
        if (
            isNaN(parseFloat(nodeComputedProps.top)) ||
            nodeComputedProps.display == 'table-cell' ||
            nodeComputedProps.display == 'none'
        ) return;

        this._active = true;

        /*
         * 3. Get necessary node parameters
         */
        const referenceNode = node.parentNode;
        const parentNode = shadowRootExists && referenceNode instanceof ShadowRoot? referenceNode.host: referenceNode;
        const nodeWinOffset = node.getBoundingClientRect();
        const parentWinOffset = parentNode.getBoundingClientRect();
        const parentComputedStyle = getComputedStyle(parentNode);

        this._parent = {
            node: parentNode,
            styles: {
                position: parentNode.style.position
            },
            offsetHeight: parentNode.offsetHeight
        };
        this._offsetToWindow = {
            left: nodeWinOffset.left,
            right: document.documentElement.clientWidth - nodeWinOffset.right
        };
        this._offsetToParent = {
            top: nodeWinOffset.top - parentWinOffset.top - parseNumeric(parentComputedStyle.borderTopWidth),
            left: nodeWinOffset.left - parentWinOffset.left - parseNumeric(parentComputedStyle.borderLeftWidth),
            right: -nodeWinOffset.right + parentWinOffset.right - parseNumeric(parentComputedStyle.borderRightWidth)
        };
        this._styles = {
            position: node.style.position,
            top: node.style.top,
            bottom: node.style.bottom,
            left: node.style.left,
            right: node.style.right,
            width: node.style.width,
            marginTop: node.style.marginTop,
            marginLeft: node.style.marginLeft,
            marginRight: node.style.marginRight
        };

        const nodeTopValue = parseNumeric(nodeComputedProps.top);
        this._limits = {
            start: nodeWinOffset.top + window.pageYOffset - nodeTopValue,
            end: parentWinOffset.top + window.pageYOffset + parentNode.offsetHeight -
                parseNumeric(parentComputedStyle.borderBottomWidth) - node.offsetHeight -
                nodeTopValue - parseNumeric(nodeComputedProps.marginBottom)
        };

        /*
         * 4. Ensure that the node will be positioned relatively to the parent node
         */
        const parentPosition = parentComputedStyle.position;

        if (
            parentPosition != 'absolute' &&
            parentPosition != 'relative'
        ) {
            parentNode.style.position = 'relative';
        }

        /*
         * 5. Recalc node position.
         *    It’s important to do this before clone injection to avoid scrolling bug in Chrome.
         */
        this._recalcPosition();

        /*
         * 6. Create a clone
         */
        const clone = this._clone = {};
        clone.node = document.createElement('div');

        // Apply styles to the clone
        extend(clone.node.style, {
            width: nodeWinOffset.right - nodeWinOffset.left + 'px',
            height: nodeWinOffset.bottom - nodeWinOffset.top + 'px',
            marginTop: nodeComputedProps.marginTop,
            marginBottom: nodeComputedProps.marginBottom,
            marginLeft: nodeComputedProps.marginLeft,
            marginRight: nodeComputedProps.marginRight,
            cssFloat: nodeComputedProps.cssFloat,
            padding: 0,
            border: 0,
            borderSpacing: 0,
            fontSize: '1em',
            position: 'static'
        });

        referenceNode.insertBefore(clone.node, node);
        clone.docOffsetTop = getDocOffsetTop(clone.node);
    }

    _recalcPosition () {
        if (!this._active || this._removed) return;

        const stickyMode = scroll.top <= this._limits.start? 'start': scroll.top >= this._limits.end? 'end': 'middle';

        if (this._stickyMode == stickyMode) return;

        switch (stickyMode) {
            case 'start':
                extend(this._node.style, {
                    position: 'absolute',
                    left: this._offsetToParent.left + 'px',
                    right: this._offsetToParent.right + 'px',
                    top: this._offsetToParent.top + 'px',
                    bottom: 'auto',
                    width: 'auto',
                    marginLeft: 0,
                    marginRight: 0,
                    marginTop: 0
                });
                break;

            case 'middle':
                extend(this._node.style, {
                    position: 'fixed',
                    left: this._offsetToWindow.left + 'px',
                    right: this._offsetToWindow.right + 'px',
                    top: this._styles.top,
                    bottom: 'auto',
                    width: 'auto',
                    marginLeft: 0,
                    marginRight: 0,
                    marginTop: 0
                });
                break;

            case 'end':
                extend(this._node.style, {
                    position: 'absolute',
                    left: this._offsetToParent.left + 'px',
                    right: this._offsetToParent.right + 'px',
                    top: 'auto',
                    bottom: 0,
                    width: 'auto',
                    marginLeft: 0,
                    marginRight: 0
                });
                break;
        }

        this._stickyMode = stickyMode;
    }

    _fastCheck () {
        if (!this._active || this._removed) return;

        if (
            Math.abs(getDocOffsetTop(this._clone.node) - this._clone.docOffsetTop) > 1 ||
            Math.abs(this._parent.node.offsetHeight - this._parent.offsetHeight) > 1
        ) this.refresh();
    }

    _deactivate () {
        if (!this._active || this._removed) return;

        this._clone.node.parentNode.removeChild(this._clone.node);
        delete this._clone;

        extend(this._node.style, this._styles);
        delete this._styles;

        // Check whether element’s parent node is used by other stickies.
        // If not, restore parent node’s styles.
        if (!stickies.some(sticky => sticky !== this && sticky._parent && sticky._parent.node === this._parent.node)) {
            extend(this._parent.node.style, this._parent.styles);
        }
        delete this._parent;

        this._stickyMode = null;
        this._active = false;

        delete this._offsetToWindow;
        delete this._offsetToParent;
        delete this._limits;
    }

    remove () {
        this._deactivate();

        stickies.some((sticky, index) => {
            if (sticky._node === this._node) {
                stickies.splice(index, 1);
                return true;
            }
        });

        this._removed = true;
    }
}

/*
 * 5. Stickyfill API
 */
const Stickyfill = {
    stickies,
    Sticky,

    addOne (node) {
        // Check whether it’s a node
        if (!(node instanceof HTMLElement)) {
            // Maybe it’s a node list of some sort?
            // Take first node from the list then
            if (node.length && node[0]) node = node[0];
            else return;
        }

        // Check if Stickyfill is already applied to the node
        // and return existing sticky
        for (var i = 0; i < stickies.length; i++) {
            if (stickies[i]._node === node) return stickies[i];
        }

        // Create and return new sticky
        return new Sticky(node);
    },

    add (nodeList) {
        // If it’s a node make an array of one node
        if (nodeList instanceof HTMLElement) nodeList = [nodeList];
        // Check if the argument is an iterable of some sort
        if (!nodeList.length) return;

        // Add every element as a sticky and return an array of created Sticky instances
        const addedStickies = [];

        for (let i = 0; i < nodeList.length; i++) {
            const node = nodeList[i];

            // If it’s not an HTMLElement – create an empty element to preserve 1-to-1
            // correlation with input list
            if (!(node instanceof HTMLElement)) {
                addedStickies.push(void 0);
                continue;
            }

            // If Stickyfill is already applied to the node
            // add existing sticky
            if (stickies.some(sticky => {
                if (sticky._node === node) {
                    addedStickies.push(sticky);
                    return true;
                }
            })) continue;

            // Create and add new sticky
            addedStickies.push(new Sticky(node));
        }

        return addedStickies;
    },

    refreshAll () {
        stickies.forEach(sticky => sticky.refresh());
    },

    removeOne (node) {
        // Check whether it’s a node
        if (!(node instanceof HTMLElement)) {
            // Maybe it’s a node list of some sort?
            // Take first node from the list then
            if (node.length && node[0]) node = node[0];
            else return;
        }

        // Remove the stickies bound to the nodes in the list
        stickies.some(sticky => {
            if (sticky._node === node) {
                sticky.remove();
                return true;
            }
        });
    },

    remove (nodeList) {
        // If it’s a node make an array of one node
        if (nodeList instanceof HTMLElement) nodeList = [nodeList];
        // Check if the argument is an iterable of some sort
        if (!nodeList.length) return;

        // Remove the stickies bound to the nodes in the list
        for (let i = 0; i < nodeList.length; i++) {
            const node = nodeList[i];

            stickies.some(sticky => {
                if (sticky._node === node) {
                    sticky.remove();
                    return true;
                }
            });
        }
    },

    removeAll () {
        while (stickies.length) stickies[0].remove();
    }
};

/*
 * 6. Setup events (unless the polyfill was disabled)
 */
function init () {
    // Watch for scroll position changes and trigger recalc/refresh if needed
    function checkScroll () {
        if (window.pageXOffset != scroll.left) {
            scroll.top = window.pageYOffset;
            scroll.left = window.pageXOffset;

            Stickyfill.refreshAll();
        }
        else if (window.pageYOffset != scroll.top) {
            scroll.top = window.pageYOffset;
            scroll.left = window.pageXOffset;

            // recalc position for all stickies
            stickies.forEach(sticky => sticky._recalcPosition());
        }
    }

    checkScroll();
    window.addEventListener('scroll', checkScroll);

    // Watch for window resizes and device orientation changes and trigger refresh
    window.addEventListener('resize', Stickyfill.refreshAll);
    window.addEventListener('orientationchange', Stickyfill.refreshAll);

    //Fast dirty check for layout changes every 500ms
    let fastCheckTimer;

    function startFastCheckTimer () {
        fastCheckTimer = setInterval(function () {
            stickies.forEach(sticky => sticky._fastCheck());
        }, 500);
    }

    function stopFastCheckTimer () {
        clearInterval(fastCheckTimer);
    }

    let docHiddenKey;
    let visibilityChangeEventName;

    if ('hidden' in document) {
        docHiddenKey = 'hidden';
        visibilityChangeEventName = 'visibilitychange';
    }
    else if ('webkitHidden' in document) {
        docHiddenKey = 'webkitHidden';
        visibilityChangeEventName = 'webkitvisibilitychange';
    }

    if (visibilityChangeEventName) {
        if (!document[docHiddenKey]) startFastCheckTimer();

        document.addEventListener(visibilityChangeEventName, () => {
            if (document[docHiddenKey]) {
                stopFastCheckTimer();
            }
            else {
                startFastCheckTimer();
            }
        });
    }
    else startFastCheckTimer();
}

if (!seppuku) init();

/*
 * 7. Expose Stickyfill
 */
if (typeof module != 'undefined' && module.exports) {
    module.exports = Stickyfill;
}
else {
    window.Stickyfill = Stickyfill;
}

<commit_msg>Delete stickyfill.es6.js<commit_after><|endoftext|>


<commit_before>var image_cache = [];
var curr_image = 0;
var slideshow_running = 0;

function preview() {
	var images = document.getElementById("images").value;
	if(images.indexOf(",") >= 0)
		images = images.split(",");
	else
		images = [images];
	image_cache = images;
	document.getElementById("preview").innerHTML = "";
	for(i in images) {
		var img = document.createElement("IMG");
		img.src = images[i];
		img.height="100";
		document.getElementById("preview").appendChild(img);
	}
}

function fullscreen() {
    var elem = document.body;
    if (elem.requestFullscreen)
        elem.requestFullscreen();
    else if (elem.msRequestFullscreen)
        elem.msRequestFullscreen();
    else if (elem.mozRequestFullScreen)
        elem.mozRequestFullScreen();
    else if (elem.webkitRequestFullscreen)
        elem.webkitRequestFullscreen();

}

function view() {
	preview();
	//lockdown the editor
	document.getElementById("editor").hidden = true;
	//unlock presentation board
	document.getElementById("board").hidden = false;
	document.getElementById("bg").src = image_cache[0];
	document.getElementById("fg").src = image_cache[0];
	slideshow_running = 1;
}

function changeImage(src) {
	document.getElementById("bg").src = src;
	document.getElementById("fg").src = src;
}

function next() {
	var max = image_cache.length - 1;
	if(curr_image + 1 > max) {
		curr_image = 0;
	} else {
		curr_image++;
	}
	var src = image_cache[curr_image];
	changeImage(src);
}

function previous() {
	if(curr_image - 1 < 0) {
		curr_image = image_cache.length - 1;
	} else {
		curr_image--;
	}
	var src = image_cache[curr_image];
	changeImage(src);
}

function saveProfile() {
	preview();
	document.getElementById("preview").innerHTML = "";
	var name = document.getElementById("save-profile-name").value;
	var images = document.getElementById("images").value;
	var brightness = document.getElementById("bg-dimmer").value;

	localStorage.setItem(name+"-brightness", brightness);
	localStorage.setItem(name+"-images", image);
}

function changeBGBrightness() {
	document.getElementById("bg-dimmer-output").innerHTML = document.getElementById("bg-dimmer").value + "%";
	document.getElementById("bg").style.opacity = parseInt(document.getElementById("bg-dimmer").value)/100;

}

function loadProfile() {
	var name = document.getElementById("load-profile-name").value;
	var images = localStorage.getItem(name+"-images");
	var brightness = localStorage.getItem(name+"-brightness");

	document.getElementById("save-profile-name").value = name;
	document.getElementById("images").value = images;
	document.getElementById("bg-dimmer").value = name;
	changeBGBrightness();
}

$(document).ready(function() {
	$(document).keydown(function(e) {
		if(slideshow_running) {
			switch(e.which) {
				case 37: //left
					previous();
				break;

				case 39: //right
					next();
				break;

				default:
					return 0;
			}
			e.preventDefault();
		}
	});

	//settings the brightness of the background
	$("#bg-dimmer").change(changeBGBrightness);
});
<commit_msg>Fixed profiles issues<commit_after>var image_cache = [];
var curr_image = 0;
var slideshow_running = 0;

function preview() {
	var images = document.getElementById("images").value;
	if(images.indexOf(",") >= 0)
		images = images.split(",");
	else
		images = [images];
	image_cache = images;
	document.getElementById("preview").innerHTML = "";
	for(i in images) {
		var img = document.createElement("IMG");
		img.src = images[i];
		img.height="100";
		document.getElementById("preview").appendChild(img);
	}
}

function fullscreen() {
    var elem = document.body;
    if (elem.requestFullscreen)
        elem.requestFullscreen();
    else if (elem.msRequestFullscreen)
        elem.msRequestFullscreen();
    else if (elem.mozRequestFullScreen)
        elem.mozRequestFullScreen();
    else if (elem.webkitRequestFullscreen)
        elem.webkitRequestFullscreen();

}

function view() {
	preview();
	//lockdown the editor
	document.getElementById("editor").hidden = true;
	//unlock presentation board
	document.getElementById("board").hidden = false;
	document.getElementById("bg").src = image_cache[0];
	document.getElementById("fg").src = image_cache[0];
	slideshow_running = 1;
}

function changeImage(src) {
	document.getElementById("bg").src = src;
	document.getElementById("fg").src = src;
}

function next() {
	var max = image_cache.length - 1;
	if(curr_image + 1 > max) {
		curr_image = 0;
	} else {
		curr_image++;
	}
	var src = image_cache[curr_image];
	changeImage(src);
}

function previous() {
	if(curr_image - 1 < 0) {
		curr_image = image_cache.length - 1;
	} else {
		curr_image--;
	}
	var src = image_cache[curr_image];
	changeImage(src);
}

function saveProfile() {
	preview();
	document.getElementById("preview").innerHTML = "";
	var name = document.getElementById("save-profile-name").value;
	var images = document.getElementById("images").value;
	var brightness = document.getElementById("bg-dimmer").value;

	localStorage.setItem(name+"-brightness", brightness);
	localStorage.setItem(name+"-images", images);
}

function changeBGBrightness() {
	document.getElementById("bg-dimmer-output").innerHTML = document.getElementById("bg-dimmer").value + "%";
	document.getElementById("bg").style.opacity = parseInt(document.getElementById("bg-dimmer").value)/100;

}

function loadProfile() {
	var name = document.getElementById("load-profile-name").value;
	var images = localStorage.getItem(name+"-images");
	var brightness = localStorage.getItem(name+"-brightness");

	document.getElementById("save-profile-name").value = name;
	document.getElementById("images").value = images;
	document.getElementById("bg-dimmer").value = name;
	changeBGBrightness();
}

$(document).ready(function() {
	$(document).keydown(function(e) {
		if(slideshow_running) {
			switch(e.which) {
				case 37: //left
					previous();
				break;

				case 39: //right
					next();
				break;

				default:
					return 0;
			}
			e.preventDefault();
		}
	});

	//settings the brightness of the background
	$("#bg-dimmer").change(changeBGBrightness);
});
<|endoftext|>


<commit_before>//# Encapsulate the cable connection held by the consumer. This is an internal class not intended for direct user manipulation.
import ActionCable from '../Logger';

let slice = [].slice;
let indexOf = [].indexOf;

let MessageTypes = {
  welcome: 'welcome',
  ping: 'ping',
  confirmation: 'confirm_subscription',
  rejection: 'reject_subscription'
}

class Connection {
  constructor(consumer) {
    this.reopenDelay = 500;
    this.consumer = consumer;
    let _this = this;
    this.events = {
      message: (event) => {
        var identifier, message, ref, type;
        ref = JSON.parse(event.data), identifier = ref.identifier, message = ref.message, type = ref.type;
        switch (type) {
          case MessageTypes.welcome:
            return _this.consumer.connectionMonitor.connected();
          case MessageTypes.ping:
            return _this.consumer.connectionMonitor.ping();
          case MessageTypes.confirmation:
            return _this.consumer.subscriptions.notify(identifier, "connected");
          case MessageTypes.rejection:
            return _this.consumer.subscriptions.reject(identifier);
          default:
            if (identifier === MessageTypes.ping) {
              return _this.consumer.connectionMonitor.ping();
            }
            return _this.consumer.subscriptions.notify(identifier, "received", message);
        }
      },
      open: () => {
        ActionCable.log("WebSocket onopen event");
        _this.disconnected = false;
        return _this.consumer.subscriptions.reload();
      },
      close: () => {
        ActionCable.log("WebSocket onclose event");
        return _this.disconnect();
      },
      error: () => {
        ActionCable.log("WebSocket onerror event");
        return _this.disconnect();
      }
    }
    this.open();
  }

  send(data) {
    if (this.isOpen()) {
      this.webSocket.send(JSON.stringify(data));
      return true;
    } else {
      return false;
    }
  }

  open() {
    if (this.isAlive()) {
      ActionCable.log("Attemped to open WebSocket, but existing socket is " + (this.getState()));
      throw new Error("Existing connection must be closed before opening");
    } else {
      ActionCable.log("Opening WebSocket, current state is " + (this.getState()));
      if (this.webSocket != null) {
        this.uninstallEventHandlers();
      }
      //allow people to pass in their own method to create websockets
      if(this.consumer.options.createWebsocket) {
        this.webSocket = this.consumer.options.createWebsocket();
      } else {
        this.webSocket = new WebSocket(this.consumer.url);
      }
      this.installEventHandlers();
      return true;
    }
  }

  close() {
    var ref;
    return (ref = this.webSocket) != null ? ref.close() : void 0;
  }

  reopen() {
    ActionCable.log("Reopening WebSocket, current state is " + (this.getState()));
    if (this.isAlive()) {
      try {
        return this.close();
      } catch (error) {
        return ActionCable.log("Failed to reopen WebSocket", error);
      } finally {
        ActionCable.log("Reopening WebSocket in " + this.reopenDelay + "ms");
        setTimeout(this.open.bind(this), this.reopenDelay);
      }
    } else {
      return this.open();
    }
  }

  isOpen() {
    return this.isState("open");
  }

  isAlive() {
    return (this.webSocket != null) && !this.isState("closing", "closed");
  }

  isState() {
    var ref, states;
    states = 1 <= arguments.length ? slice.call(arguments, 0) : [];
    return ref = this.getState(), indexOf.call(states, ref) >= 0;
  }

  getState() {
    var ref, state, value;
    for (state in WebSocket) {
      value = WebSocket[state];
      if (value === ((ref = this.webSocket) != null ? ref.readyState : void 0)) {
        return state.toLowerCase();
      }
    }
    return null;
  }

  installEventHandlers() {
    var eventName, handler;
    for (eventName in this.events) {
      handler = this.events[eventName].bind(this);
      this.webSocket["on" + eventName] = handler;
    }
  };

  uninstallEventHandlers() {
    var eventName;
    for (eventName in this.events) {
      this.webSocket["on" + eventName] = () => {};
    }
  };

  disconnect() {
    if (this.disconnected) {
      return;
    }
    this.disconnected = true;
    this.consumer.connectionMonitor.disconnected();
    return this.consumer.subscriptions.notifyAll("disconnected");
  }

  toJSON() {
    return {
      state: this.getState()
    };
  }
}

export default Connection;
<commit_msg>getState changes from mattheworiordan<commit_after>//# Encapsulate the cable connection held by the consumer. This is an internal class not intended for direct user manipulation.
import ActionCable from '../Logger';

let slice = [].slice;
let indexOf = [].indexOf;

let MessageTypes = {
  welcome: 'welcome',
  ping: 'ping',
  confirmation: 'confirm_subscription',
  rejection: 'reject_subscription'
}

class Connection {
  constructor(consumer) {
    this.reopenDelay = 500;
    this.consumer = consumer;
    let _this = this;
    this.events = {
      message: (event) => {
        var identifier, message, ref, type;
        ref = JSON.parse(event.data), identifier = ref.identifier, message = ref.message, type = ref.type;
        switch (type) {
          case MessageTypes.welcome:
            return _this.consumer.connectionMonitor.connected();
          case MessageTypes.ping:
            return _this.consumer.connectionMonitor.ping();
          case MessageTypes.confirmation:
            return _this.consumer.subscriptions.notify(identifier, "connected");
          case MessageTypes.rejection:
            return _this.consumer.subscriptions.reject(identifier);
          default:
            if (identifier === MessageTypes.ping) {
              return _this.consumer.connectionMonitor.ping();
            }
            return _this.consumer.subscriptions.notify(identifier, "received", message);
        }
      },
      open: () => {
        ActionCable.log("WebSocket onopen event");
        _this.disconnected = false;
        return _this.consumer.subscriptions.reload();
      },
      close: () => {
        ActionCable.log("WebSocket onclose event");
        return _this.disconnect();
      },
      error: () => {
        ActionCable.log("WebSocket onerror event");
        return _this.disconnect();
      }
    }
    this.open();
  }

  send(data) {
    if (this.isOpen()) {
      this.webSocket.send(JSON.stringify(data));
      return true;
    } else {
      return false;
    }
  }

  open() {
    if (this.isAlive()) {
      ActionCable.log("Attemped to open WebSocket, but existing socket is " + (this.getState()));
      throw new Error("Existing connection must be closed before opening");
    } else {
      ActionCable.log("Opening WebSocket, current state is " + (this.getState()));
      if (this.webSocket != null) {
        this.uninstallEventHandlers();
      }
      //allow people to pass in their own method to create websockets
      if(this.consumer.options.createWebsocket) {
        this.webSocket = this.consumer.options.createWebsocket();
      } else {
        this.webSocket = new WebSocket(this.consumer.url);
      }
      this.installEventHandlers();
      return true;
    }
  }

  close() {
    var ref;
    return (ref = this.webSocket) != null ? ref.close() : void 0;
  }

  reopen() {
    ActionCable.log("Reopening WebSocket, current state is " + (this.getState()));
    if (this.isAlive()) {
      try {
        return this.close();
      } catch (error) {
        return ActionCable.log("Failed to reopen WebSocket", error);
      } finally {
        ActionCable.log("Reopening WebSocket in " + this.reopenDelay + "ms");
        setTimeout(this.open.bind(this), this.reopenDelay);
      }
    } else {
      return this.open();
    }
  }

  isOpen() {
    return this.isState("open");
  }

  isAlive() {
    return (this.webSocket != null) && !this.isState("closing", "closed");
  }

  isState() {
    var ref, states;
    states = 1 <= arguments.length ? slice.call(arguments, 0) : [];
    return ref = this.getState(), indexOf.call(states, ref) >= 0;
  }

  getState() {
    var ref, state, value;
    var states = ['connecting','open','closing','closed'];
    if (this.webSocket) {
      return states[this.webSocket.readyState];
    }
  }

  installEventHandlers() {
    var eventName, handler;
    for (eventName in this.events) {
      handler = this.events[eventName].bind(this);
      this.webSocket["on" + eventName] = handler;
    }
  };

  uninstallEventHandlers() {
    var eventName;
    for (eventName in this.events) {
      this.webSocket["on" + eventName] = () => {};
    }
  };

  disconnect() {
    if (this.disconnected) {
      return;
    }
    this.disconnected = true;
    this.consumer.connectionMonitor.disconnected();
    return this.consumer.subscriptions.notifyAll("disconnected");
  }

  toJSON() {
    return {
      state: this.getState()
    };
  }
}

export default Connection;
<|endoftext|>


<commit_before>define(function (require, exports, module) {
    "use strict";
    var invariant = require("../modules/invariant");
    var eventEmitter = require("../modules/events/eventEmitter");
    var serializable = require("../modules/serialization/serializable");
    var tools = require("../modules/tools");
    var Tlke = require("Tlke");
    var extend = tools.extend;
    var isFunction = tools.isFunction;

    function TlecBuilder(factory) {
        invariant(factory, "Can be constructed only with factory");
        invariant(isFunction(factory.createTlec), "factory must have createTlec() method");
        invariant(isFunction(factory.createRoute), "factory must have createRoute() method");
        invariant(isFunction(factory.createTlkeBuilder), "factory must have createTlkeBuilder() method");
        invariant(isFunction(factory.createTlhtBuilder), "factory must have createTlhtBuilder() method");

        this._defineEvent("changed");
        this._defineEvent("done");
        this._defineEvent("message");
        this._defineEvent("offer");
        this._defineEvent("auth");
        this._defineEvent("openAddrIn");
        this._defineEvent("closeAddrIn");
        this._defineEvent("networkPacket");

        this._factory = factory;
        this._tlec = null;
        this._route = null;
        this._tlkeBuilder = null;
        this._tlhtBuilder = null;
        this.status = null;

    }

    extend(TlecBuilder.prototype, eventEmitter, serializable, {
        build: function () {
            this.status = TlecBuilder.STATUS_NOT_STARTED;
            var factory = this._factory;
            this._tlkeBuilder = factory.createTlkeBuilder();
            this._tlkeBuilder.build();
            this._tlhtBuilder = factory.createTlhtBuilder();
            this._tlec = this._factory.createTlec();
            this._route = this._factory.createRoute();
            this._linkBuilders();
            this._link();
            this._onChanged();
        },

        enterOffer: function (offer) {
            this._tlkeBuilder.enterOffer(offer);
        },

        enterAuth: function (auth) {
            this._tlkeBuilder.enterAuth(auth);
        },

        generateOffer: function () {
            this._tlkeBuilder.generate();
        },

        sendMessage: function (msg) {
            if (!this._tlec) {
                throw new Error("tlec is not yet built");
            }
            this._tlec.sendMessage(msg);
        },

        processNetworkPacket: function (packet) {
            console.log("TlecBuilder got networkPacket: status = " + this.status, packet);
            if (this._route) {
                this._route.processNetworkPacket(packet);
            }
            if (this._tlhtBuilder) {
                this._tlhtBuilder.processNetworkPacket(packet);
            }
            if (this._tlkeBuilder) {
                this._tlkeBuilder.processNetworkPacket(packet);
            }
        },

        serialize: function (packet, context) {
            packet.setData({status: this.status});
            packet.setLink("_tlkeBuilder", context.getPacket(this._tlkeBuilder));
            packet.setLink("_tlhtBuilder", context.getPacket(this._tlhtBuilder));
            packet.setLink("_tlec", context.getPacket(this._tlec));
            packet.setLink("_route", context.getPacket(this._route));
        },
        deserialize: function (packet, context) {
            var factory = this._factory;
            var data = packet.getData();
            this.status = data.status;
            this._tlkeBuilder = context.deserialize(packet.getLink("_tlkeBuilder"), factory.createTlkeBuilder, factory);
            this._tlhtBuilder = context.deserialize(packet.getLink("_tlhtBuilder"), factory.createTlhtBuilder, factory);
            this._tlec = context.deserialize(packet.getLink("_tlec"), factory.createTlec, factory);
            this._route = context.deserialize(packet.getLink("_route"), factory.createRoute, factory);
            this._link();
            this._linkBuilders();
        },

        _link: function () {
            var tlec = this._tlec;
            var route = this._route;

            if (route && tlec) {
                route.on("packet", tlec.processPacket, tlec);
                route.on("networkPacket", this._onNetworkPacket, this);
                route.on("openAddrIn", this._onRouteAddrIn, this);
                route.on("closeAddrIn", this._onRouteCloseAddrIn, this);
                tlec.on("packet", route.processPacket, route);
                tlec.on("message", this._onMessage, this);
            }
        },

        _unlink: function () {
            var tlec = this._tlec;
            var route = this._route;

            if (route && tlec) {
                route.off("packet", tlec.processPacket, tlec);
                route.off("networkPacket", this._onNetworkPacket, this);
                route.off("openAddrIn", this._onRouteAddrIn, this);
                route.off("closeAddrIn", this._onRouteCloseAddrIn, this);
                tlec.off("packet", route.processPacket, route);
            }
        },
        _onRouteAddrIn: function (args) {
            this.fire("openAddrIn", args);
        },
        _onRouteCloseAddrIn: function (args) {
            this.fire("closeAddrIn", args);
        },
        _onNetworkPacket: function (packet) {
            console.log("Sending some packet: ", packet);
            this.fire("networkPacket", packet);
        },
        _onMessage: function (msg) {
            this.fire("message", msg);
        },

        _linkBuilders: function () {
            if (this._tlkeBuilder && this._tlhtBuilder) {
                this._tlkeBuilder.on("offer", this._onOffer, this);
                this._tlkeBuilder.on("auth", this._onAuth, this);
                this._tlkeBuilder.on("done", this._tlhtBuilder.build, this._tlhtBuilder);
                this._tlkeBuilder.on("changed", this._onTlkeBuilderChanged, this);
                this._tlhtBuilder.on("done", this._initTlec, this);
                this._tlkeBuilder.on("networkPacket", this._onNetworkPacket, this);
                this._tlkeBuilder.on("openAddrIn", this._onRouteAddrIn, this);
                this._tlkeBuilder.on("closeAddrIn", this._onRouteCloseAddrIn, this);
                this._tlhtBuilder.on("networkPacket", this._onNetworkPacket, this);
                this._tlhtBuilder.on("openAddrIn", this._onRouteAddrIn, this);
                this._tlhtBuilder.on("closeAddrIn", this._onRouteCloseAddrIn, this);
            }
        },

        _unlinkBuilders: function () {
            if (this._tlkeBuilder && this._tlhtBuilder) {
                this._tlkeBuilder.off("offer", this._onOffer, this);
                this._tlkeBuilder.off("auth", this._onAuth, this);
                this._tlkeBuilder.off("done", this._tlhtBuilder.build, this._tlhtBuilder);
                this._tlkeBuilder.off("changed", this._onTlkeBuilderChanged, this);
                this._tlhtBuilder.off("done", this._initTlec, this);
                this._tlkeBuilder.off("networkPacket", this._onNetworkPacket, this);
                this._tlkeBuilder.off("openAddrIn", this._onRouteAddrIn, this);
                this._tlkeBuilder.off("closeAddrIn", this._onRouteCloseAddrIn, this);
                this._tlhtBuilder.off("networkPacket", this._onNetworkPacket, this);
                this._tlhtBuilder.off("openAddrIn", this._onRouteAddrIn, this);
                this._tlhtBuilder.off("closeAddrIn", this._onRouteCloseAddrIn, this);
            }
        },

        _onOffer: function (offer) {
            this.fire("offer", offer);
        },
        _onAuth: function (auth) {
            this.fire("auth", auth);
        },

        _initTlec: function (args) {
            this._tlec.init(args);
            this._route.setAddr(args);
            this._tlkeBuilder.destroy();
            this._tlhtBuilder.destroy();
            this._unlinkBuilders();
            this._tlhtBuilder = null;
            this._tlkeBuilder = null;
            this.status = TlecBuilder.STATUS_ESTABLISHED;
            this._onChanged();
            this.fire("done", this);
        },

        _onChanged: function () {
            this.fire("changed");
        },

        _onTlkeBuilderChanged: function () {
            switch (this._tlkeBuilder.getTlkeState()) {
            case Tlke.STATE_AWAITING_OFFER_RESPONSE:
                this.status = TlecBuilder.STATUS_OFFER_GENERATED;
                break;
            case Tlke.STATE_AWAITING_AUTH_RESPONSE:
                this.status = TlecBuilder.STATUS_AUTH_GENERATED;
                break;
            case Tlke.STATE_AWAITING_AUTH:
                this.status = TlecBuilder.STATUS_AUTH_NEEDED;
                break;
            case Tlke.STATE_AWAITING_OFFERDATA:
                this.status = TlecBuilder.STATUS_OFFERDATA_NEEDED;
                break;
            case Tlke.STATE_AWAITING_AUTHDATA:
                this.status = TlecBuilder.STATUS_AUTHDATA_NEEDED;
                break;
            case Tlke.STATE_CONNECTION_ESTABLISHED:
                this.status = TlecBuilder.STATUS_HT_EXCHANGE;
                break;
            case Tlke.STATE_CONNECTION_FAILED:
                this.status = TlecBuilder.STATUS_AUTH_ERROR;
                break;
            }
            this._onChanged();
        },

        destroy: function () {
            if (this._route) { this._route.destroy(); }
            if (this._tlhtBuilder) { this._tlhtBuilder.destroy(); }
            if (this._tlkeBuilder) { this._tlkeBuilder.destroy(); }
            this._unlink();
            this._unlinkBuilders();
            this._tlec = null;
            this._route = null;
            this._tlhtBuilder = null;
            this._tlkeBuilder = null;
        }

    });

    TlecBuilder.STATUS_NOT_STARTED = 0;

    // tlke A
    TlecBuilder.STATUS_OFFER_GENERATED = 1;
    TlecBuilder.STATUS_AUTH_GENERATED = 2;
    TlecBuilder.STATUS_AUTH_ERROR = -1;

    // tlke B
    TlecBuilder.STATUS_OFFERDATA_NEEDED = 4;
    TlecBuilder.STATUS_AUTHDATA_NEEDED = 5;
    TlecBuilder.STATUS_AUTH_NEEDED = 6;

    // tlht both
    TlecBuilder.STATUS_HT_EXCHANGE = 3;

    // can send messages now
    TlecBuilder.STATUS_ESTABLISHED = 10;

    module.exports = TlecBuilder;
});<commit_msg>fix import in TlecBuilder<commit_after>define(function (require, exports, module) {
    "use strict";
    var invariant = require("../modules/invariant");
    var eventEmitter = require("../modules/events/eventEmitter");
    var serializable = require("../modules/serialization/serializable");
    var tools = require("../modules/tools");
    var Tlke = require("../modules/channels/Tlke");
    var extend = tools.extend;
    var isFunction = tools.isFunction;

    function TlecBuilder(factory) {
        invariant(factory, "Can be constructed only with factory");
        invariant(isFunction(factory.createTlec), "factory must have createTlec() method");
        invariant(isFunction(factory.createRoute), "factory must have createRoute() method");
        invariant(isFunction(factory.createTlkeBuilder), "factory must have createTlkeBuilder() method");
        invariant(isFunction(factory.createTlhtBuilder), "factory must have createTlhtBuilder() method");

        this._defineEvent("changed");
        this._defineEvent("done");
        this._defineEvent("message");
        this._defineEvent("offer");
        this._defineEvent("auth");
        this._defineEvent("openAddrIn");
        this._defineEvent("closeAddrIn");
        this._defineEvent("networkPacket");

        this._factory = factory;
        this._tlec = null;
        this._route = null;
        this._tlkeBuilder = null;
        this._tlhtBuilder = null;
        this.status = null;

    }

    extend(TlecBuilder.prototype, eventEmitter, serializable, {
        build: function () {
            this.status = TlecBuilder.STATUS_NOT_STARTED;
            var factory = this._factory;
            this._tlkeBuilder = factory.createTlkeBuilder();
            this._tlkeBuilder.build();
            this._tlhtBuilder = factory.createTlhtBuilder();
            this._tlec = this._factory.createTlec();
            this._route = this._factory.createRoute();
            this._linkBuilders();
            this._link();
            this._onChanged();
        },

        enterOffer: function (offer) {
            this._tlkeBuilder.enterOffer(offer);
        },

        enterAuth: function (auth) {
            this._tlkeBuilder.enterAuth(auth);
        },

        generateOffer: function () {
            this._tlkeBuilder.generate();
        },

        sendMessage: function (msg) {
            if (!this._tlec) {
                throw new Error("tlec is not yet built");
            }
            this._tlec.sendMessage(msg);
        },

        processNetworkPacket: function (packet) {
            console.log("TlecBuilder got networkPacket: status = " + this.status, packet);
            if (this._route) {
                this._route.processNetworkPacket(packet);
            }
            if (this._tlhtBuilder) {
                this._tlhtBuilder.processNetworkPacket(packet);
            }
            if (this._tlkeBuilder) {
                this._tlkeBuilder.processNetworkPacket(packet);
            }
        },

        serialize: function (packet, context) {
            packet.setData({status: this.status});
            packet.setLink("_tlkeBuilder", context.getPacket(this._tlkeBuilder));
            packet.setLink("_tlhtBuilder", context.getPacket(this._tlhtBuilder));
            packet.setLink("_tlec", context.getPacket(this._tlec));
            packet.setLink("_route", context.getPacket(this._route));
        },
        deserialize: function (packet, context) {
            var factory = this._factory;
            var data = packet.getData();
            this.status = data.status;
            this._tlkeBuilder = context.deserialize(packet.getLink("_tlkeBuilder"), factory.createTlkeBuilder, factory);
            this._tlhtBuilder = context.deserialize(packet.getLink("_tlhtBuilder"), factory.createTlhtBuilder, factory);
            this._tlec = context.deserialize(packet.getLink("_tlec"), factory.createTlec, factory);
            this._route = context.deserialize(packet.getLink("_route"), factory.createRoute, factory);
            this._link();
            this._linkBuilders();
        },

        _link: function () {
            var tlec = this._tlec;
            var route = this._route;

            if (route && tlec) {
                route.on("packet", tlec.processPacket, tlec);
                route.on("networkPacket", this._onNetworkPacket, this);
                route.on("openAddrIn", this._onRouteAddrIn, this);
                route.on("closeAddrIn", this._onRouteCloseAddrIn, this);
                tlec.on("packet", route.processPacket, route);
                tlec.on("message", this._onMessage, this);
            }
        },

        _unlink: function () {
            var tlec = this._tlec;
            var route = this._route;

            if (route && tlec) {
                route.off("packet", tlec.processPacket, tlec);
                route.off("networkPacket", this._onNetworkPacket, this);
                route.off("openAddrIn", this._onRouteAddrIn, this);
                route.off("closeAddrIn", this._onRouteCloseAddrIn, this);
                tlec.off("packet", route.processPacket, route);
            }
        },
        _onRouteAddrIn: function (args) {
            this.fire("openAddrIn", args);
        },
        _onRouteCloseAddrIn: function (args) {
            this.fire("closeAddrIn", args);
        },
        _onNetworkPacket: function (packet) {
            console.log("Sending some packet: ", packet);
            this.fire("networkPacket", packet);
        },
        _onMessage: function (msg) {
            this.fire("message", msg);
        },

        _linkBuilders: function () {
            if (this._tlkeBuilder && this._tlhtBuilder) {
                this._tlkeBuilder.on("offer", this._onOffer, this);
                this._tlkeBuilder.on("auth", this._onAuth, this);
                this._tlkeBuilder.on("done", this._tlhtBuilder.build, this._tlhtBuilder);
                this._tlkeBuilder.on("changed", this._onTlkeBuilderChanged, this);
                this._tlhtBuilder.on("done", this._initTlec, this);
                this._tlkeBuilder.on("networkPacket", this._onNetworkPacket, this);
                this._tlkeBuilder.on("openAddrIn", this._onRouteAddrIn, this);
                this._tlkeBuilder.on("closeAddrIn", this._onRouteCloseAddrIn, this);
                this._tlhtBuilder.on("networkPacket", this._onNetworkPacket, this);
                this._tlhtBuilder.on("openAddrIn", this._onRouteAddrIn, this);
                this._tlhtBuilder.on("closeAddrIn", this._onRouteCloseAddrIn, this);
            }
        },

        _unlinkBuilders: function () {
            if (this._tlkeBuilder && this._tlhtBuilder) {
                this._tlkeBuilder.off("offer", this._onOffer, this);
                this._tlkeBuilder.off("auth", this._onAuth, this);
                this._tlkeBuilder.off("done", this._tlhtBuilder.build, this._tlhtBuilder);
                this._tlkeBuilder.off("changed", this._onTlkeBuilderChanged, this);
                this._tlhtBuilder.off("done", this._initTlec, this);
                this._tlkeBuilder.off("networkPacket", this._onNetworkPacket, this);
                this._tlkeBuilder.off("openAddrIn", this._onRouteAddrIn, this);
                this._tlkeBuilder.off("closeAddrIn", this._onRouteCloseAddrIn, this);
                this._tlhtBuilder.off("networkPacket", this._onNetworkPacket, this);
                this._tlhtBuilder.off("openAddrIn", this._onRouteAddrIn, this);
                this._tlhtBuilder.off("closeAddrIn", this._onRouteCloseAddrIn, this);
            }
        },

        _onOffer: function (offer) {
            this.fire("offer", offer);
        },
        _onAuth: function (auth) {
            this.fire("auth", auth);
        },

        _initTlec: function (args) {
            this._tlec.init(args);
            this._route.setAddr(args);
            this._tlkeBuilder.destroy();
            this._tlhtBuilder.destroy();
            this._unlinkBuilders();
            this._tlhtBuilder = null;
            this._tlkeBuilder = null;
            this.status = TlecBuilder.STATUS_ESTABLISHED;
            this._onChanged();
            this.fire("done", this);
        },

        _onChanged: function () {
            this.fire("changed");
        },

        _onTlkeBuilderChanged: function () {
            switch (this._tlkeBuilder.getTlkeState()) {
            case Tlke.STATE_AWAITING_OFFER_RESPONSE:
                this.status = TlecBuilder.STATUS_OFFER_GENERATED;
                break;
            case Tlke.STATE_AWAITING_AUTH_RESPONSE:
                this.status = TlecBuilder.STATUS_AUTH_GENERATED;
                break;
            case Tlke.STATE_AWAITING_AUTH:
                this.status = TlecBuilder.STATUS_AUTH_NEEDED;
                break;
            case Tlke.STATE_AWAITING_OFFERDATA:
                this.status = TlecBuilder.STATUS_OFFERDATA_NEEDED;
                break;
            case Tlke.STATE_AWAITING_AUTHDATA:
                this.status = TlecBuilder.STATUS_AUTHDATA_NEEDED;
                break;
            case Tlke.STATE_CONNECTION_ESTABLISHED:
                this.status = TlecBuilder.STATUS_HT_EXCHANGE;
                break;
            case Tlke.STATE_CONNECTION_FAILED:
                this.status = TlecBuilder.STATUS_AUTH_ERROR;
                break;
            }
            this._onChanged();
        },

        destroy: function () {
            if (this._route) { this._route.destroy(); }
            if (this._tlhtBuilder) { this._tlhtBuilder.destroy(); }
            if (this._tlkeBuilder) { this._tlkeBuilder.destroy(); }
            this._unlink();
            this._unlinkBuilders();
            this._tlec = null;
            this._route = null;
            this._tlhtBuilder = null;
            this._tlkeBuilder = null;
        }

    });

    TlecBuilder.STATUS_NOT_STARTED = 0;

    // tlke A
    TlecBuilder.STATUS_OFFER_GENERATED = 1;
    TlecBuilder.STATUS_AUTH_GENERATED = 2;
    TlecBuilder.STATUS_AUTH_ERROR = -1;

    // tlke B
    TlecBuilder.STATUS_OFFERDATA_NEEDED = 4;
    TlecBuilder.STATUS_AUTHDATA_NEEDED = 5;
    TlecBuilder.STATUS_AUTH_NEEDED = 6;

    // tlht both
    TlecBuilder.STATUS_HT_EXCHANGE = 3;

    // can send messages now
    TlecBuilder.STATUS_ESTABLISHED = 10;

    module.exports = TlecBuilder;
});<|endoftext|>


<commit_before>import React, {Component} from 'react';

import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import PropTypeDescTable from '../PropTypeDescTable';
import Paper from 'src/Paper';
import Tree from 'src/Tree';
import TreeDoc from 'examples/assets/propTypes/Tree.json';

import 'sass/containers/app/modules/layout/TreeExamples.scss';

export default class TreeExamples extends Component {

    constructor(props) {

        super(props);

        this.data = {
            id: '0',
            text: 'Root',
            desc: 'Root',
            children: [{
                id: '00',
                text: 'Children 0 - 0',
                desc: 'Children 0 - 0'
            }, {
                id: '01',
                text: 'Children 0 - 1',
                desc: 'Children 0 - 1',
                children: [{
                    id: '010',
                    text: 'Children 0 - 1 - 0',
                    desc: 'Children 0 - 1 - 0'
                }, {
                    id: '011',
                    text: 'Children 0 - 1 - 1',
                    desc: 'Children 0 - 1 - 1'
                }, {
                    id: '012',
                    text: 'Children 0 - 1 - 2',
                    desc: 'Children 0 - 1 - 2'
                }]
            }, {
                id: '02',
                text: 'Children 0 - 2',
                desc: 'Children 0 - 2'
            }]
        };

        this.onChangeHandler = this::this.onChangeHandler;

    }

    onChangeHandler(value) {
        this.setState({
            value: value
        });
    }

    render() {
        return (

Tree

                    Tree can fully display the hierarchy, and has interactive functions such as
                    expansion, withdrawal and selection.

Examples

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Basic"/>

Treesimple example.

                                <Paper className="tree-wrapper">
                                    <Tree className="tree-example"
                                          data={this.data}/>
                                </Paper>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Self Define Node Renderer"/>

                                <Paper className="tree-wrapper">
                                    <Tree className="tree-example"
                                          data={this.data}
                                          collapsedIconCls="fa fa-plus-square-o"
                                          expandedIconCls="fa fa-minus-square-o"
                                          renderer={node => {
                                              return

                                                  {node.id}
                                                  {node.text}
                                                  {node.desc}

;
                                          }}/>
                                </Paper>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Single Select"/>

                                <Paper className="tree-wrapper">
                                    <Tree className="tree-example"
                                          selectMode={Tree.SelectMode.SINGLE_SELECT}
                                          data={this.data}/>
                                </Paper>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Multi Select"/>

                                <Paper className="tree-wrapper">
                                    <Tree className="tree-example"
                                          selectMode={Tree.SelectMode.MULTI_SELECT}
                                          data={this.data}/>
                                </Paper>

                </Widget>

Properties

                <PropTypeDescTable data={TreeDoc}/>

        );
    }
};<commit_msg>update Tree examples<commit_after>import React, {Component} from 'react';

import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import PropTypeDescTable from '../PropTypeDescTable';
import Paper from 'src/Paper';
import Tree from 'src/Tree';
import TreeDoc from 'examples/assets/propTypes/Tree.json';

import 'sass/containers/app/modules/layout/TreeExamples.scss';

export default class TreeExamples extends Component {

    constructor(props) {

        super(props);

        this.data = {
            id: '0',
            text: 'Root',
            desc: 'Root',
            children: [{
                id: '00',
                text: 'Children 0 - 0',
                desc: 'Children 0 - 0'
            }, {
                id: '01',
                text: 'Children 0 - 1',
                desc: 'Children 0 - 1',
                children: [{
                    id: '010',
                    text: 'Children 0 - 1 - 0',
                    desc: 'Children 0 - 1 - 0'
                }, {
                    id: '011',
                    text: 'Children 0 - 1 - 1',
                    desc: 'Children 0 - 1 - 1'
                }, {
                    id: '012',
                    text: 'Children 0 - 1 - 2',
                    desc: 'Children 0 - 1 - 2'
                }]
            }, {
                id: '02',
                text: 'Children 0 - 2',
                desc: 'Children 0 - 2'
            }]
        };

        this.changeHandler = this::this.changeHandler;

    }

    changeHandler(value) {
        console.log(value);
    }

    render() {
        return (

Tree

                    Tree can fully display the hierarchy, and has interactive functions such as
                    expansion, withdrawal and selection.

Examples

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Basic"/>

Treesimple example.

                                <Paper className="tree-wrapper">
                                    <Tree className="tree-example"
                                          data={this.data}
                                          onChange={this.changeHandler}/>
                                </Paper>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Self Define Node Renderer"/>

                                <Paper className="tree-wrapper">
                                    <Tree className="tree-example"
                                          data={this.data}
                                          collapsedIconCls="fa fa-plus-square-o"
                                          expandedIconCls="fa fa-minus-square-o"
                                          renderer={node => {
                                              return

                                                  {node.id}
                                                  {node.text}
                                                  {node.desc}

;
                                          }}/>
                                </Paper>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Single Select"/>

                                <Paper className="tree-wrapper">
                                    <Tree className="tree-example"
                                          selectMode={Tree.SelectMode.SINGLE_SELECT}
                                          data={this.data}
                                          onChange={this.changeHandler}/>
                                </Paper>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Multi Select"/>

                                <Paper className="tree-wrapper">
                                    <Tree className="tree-example"
                                          selectMode={Tree.SelectMode.MULTI_SELECT}
                                          data={this.data}
                                          onChange={this.changeHandler}/>
                                </Paper>

                </Widget>

Properties

                <PropTypeDescTable data={TreeDoc}/>

        );
    }
};<|endoftext|>