<commit_before>const absol98sk = [
	"If you're a trainer, talk with Pokemon!!"
];

const amiy = [
	"went to find people to flop on.",
	"got swallowed whole by a Snorlax."
];

const anrindas = [
	"went back to the Dragon's Den."
];

const axtheefrost = [
	"went to aliment Wobbuffet."
];

const bidoofftw = [
	"was forced onto bed by Kingdom of Tea."
];

const ctfrm = [
	"is better than Christos."
];

const christs = [
	"is everyone's favourite moderator."
];

const darklight1999 = [
	"returns back to darkness."
];

const darkshadow6 = [
	"Never Give Up"
];

const hannumikkola = [
	"is stealing your food now."
];

const indiancharizard = [
	"was struck by Dragon Slayer Anrin's dark magic."
];

const kingdomoftea = [
	"retreats to get more tea."
];

const srinator = [
	"elfs smells too much, ima leave"
];

const wolf = [
	"howls to the moon.",
	"runs off into a forest."
];

exports.commands = {
	dc: 'poof',
	disconnect: 'poof',
	disconnected: 'poof',
	cpoof: 'poof',
	poof: function (target, room, user) {
		if (Config.poofOff) return this.sendReply("Poof is currently disabled.");
		if (target && !this.can('broadcast')) return false;
		if (!this.canTalk(message)) return false;
		if (this.name.toUpperCase() === 'WOLF') {
			var message = target || wolf[Math.floor(Math.random() * wolf.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, this.name.toUpperCase());

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'ABSOL98SK') {
			var message = target || absol98sk[Math.floor(Math.random() * absol98sk.length)];

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'AMIŧY' || this.name.toUpperCase() === 'KIMISUMI') {
			var message = target || amiy[Math.floor(Math.random() * amiy.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, this.name.toUpperCase());

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'ANRIN DAS' || this.name.toUpperCase() === 'ANRIN N') {
			var message = target || anrindas[Math.floor(Math.random() * anrindas.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, this.name.toUpperCase());

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'AXTHEEFROST' || this.name.toUpperCase() === 'ANDY VENUS') {
			var message = target || axtheefrost[Math.floor(Math.random() * axtheefrost.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, this.name.toUpperCase());

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'BIDOOF FTW') {
			var message = target || bidoofftw[Math.floor(Math.random() * bidoofftw.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, this.name.toUpperCase());

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'CаѕTFоRM') {
			var message = target || ctfrm[Math.floor(Math.random() * ctfrm.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, this.name.toUpperCase());

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'CHRISTοS') {
			var message = target || christs[Math.floor(Math.random() * christs.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, this.name.toUpperCase());

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'DARK LIGHT1999') {
			var message = target || darklight1999[Math.floor(Math.random() * darklight1999.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, this.name.toUpperCase());

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'DARK SHADOW 6') {
			var message = target || darkshadow6[Math.floor(Math.random() * darkshadow6.length)];

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'HANNU MIKKOLA') {
			var message = target || hannumikkola[Math.floor(Math.random() * hannumikkola.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, this.name.toUpperCase());

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'INDIANCHARIZARD#' || this.name.toUpperCase() === 'ASTRAEA') {
			var message = target || indiancharizard[Math.floor(Math.random() * indiancharizard.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, this.name.toUpperCase());

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'KINGDOM OF TEA') {
			var message = target || kingdomoftea[Math.floor(Math.random() * kingdomoftea.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, this.name.toUpperCase());

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'SRINATOR') {
			var message = target || srinator[Math.floor(Math.random() * srinator.length)];

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else {
			user.leaveRoom(room);
		}
	},

	poofoff: 'nopoof',
	nopoof: function () {
		if (!this.can('poofoff')) return false;
		Config.poofOff = true;
		return this.sendReply("Poof is now disabled.");
	},

	poofon: function () {
		if (!this.can('poofoff')) return false;
		Config.poofOff = false;
		return this.sendReply("Poof is now enabled.");
	}
};
<commit_msg>Ignore case sensitivity for usernames<commit_after>const absol98sk = [
	"If you're a trainer, talk with Pokemon!!"
];

const amiy = [
	"went to find people to flop on.",
	"got swallowed whole by a Snorlax."
];

const anrindas = [
	"went back to the Dragon's Den."
];

const axtheefrost = [
	"went to aliment Wobbuffet."
];

const bidoofftw = [
	"was forced onto bed by Kingdom of Tea."
];

const ctfrm = [
	"is better than Christos."
];

const christs = [
	"is everyone's favourite moderator."
];

const darklight1999 = [
	"returns back to darkness."
];

const darkshadow6 = [
	"Never Give Up"
];

const hannumikkola = [
	"is stealing your food now."
];

const indiancharizard = [
	"was struck by Dragon Slayer Anrin's dark magic."
];

const kingdomoftea = [
	"retreats to get more tea."
];

const srinator = [
	"elfs smells too much, ima leave"
];

const wolf = [
	"howls to the moon.",
	"runs off into a forest."
];

exports.commands = {
	dc: 'poof',
	disconnect: 'poof',
	disconnected: 'poof',
	cpoof: 'poof',
	poof: function (target, room, user) {
		if (Config.poofOff) return this.sendReply("Poof is currently disabled.");
		if (target && !this.can('broadcast')) return false;
		if (!this.canTalk(message)) return false;
		if (this.name.toUpperCase() === 'WOLF') {
			var message = target || wolf[Math.floor(Math.random() * wolf.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, user.name);

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'ABSOL98SK') {
			var message = target || absol98sk[Math.floor(Math.random() * absol98sk.length)];

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'AMIŧY' || this.name.toUpperCase() === 'KIMISUMI') {
			var message = target || amiy[Math.floor(Math.random() * amiy.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, user.name);

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'ANRIN DAS' || this.name.toUpperCase() === 'ANRIN N') {
			var message = target || anrindas[Math.floor(Math.random() * anrindas.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, user.name);

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'AXTHEEFROST' || this.name.toUpperCase() === 'ANDY VENUS') {
			var message = target || axtheefrost[Math.floor(Math.random() * axtheefrost.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, user.name);

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'BIDOOF FTW') {
			var message = target || bidoofftw[Math.floor(Math.random() * bidoofftw.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, user.name);

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'CаѕTFоRM') {
			var message = target || ctfrm[Math.floor(Math.random() * ctfrm.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, user.name);

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'CHRISTοS') {
			var message = target || christs[Math.floor(Math.random() * christs.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, user.name);

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'DARK LIGHT1999') {
			var message = target || darklight1999[Math.floor(Math.random() * darklight1999.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, user.name);

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'DARK SHADOW 6') {
			var message = target || darkshadow6[Math.floor(Math.random() * darkshadow6.length)];

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'HANNU MIKKOLA') {
			var message = target || hannumikkola[Math.floor(Math.random() * hannumikkola.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, user.name);

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'INDIANCHARIZARD#' || this.name.toUpperCase() === 'ASTRAEA') {
			var message = target || indiancharizard[Math.floor(Math.random() * indiancharizard.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, user.name);

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'KINGDOM OF TEA') {
			var message = target || kingdomoftea[Math.floor(Math.random() * kingdomoftea.length)];
			if (message.indexOf('{{user}}') < 0)
				message = '{{user}} ' + message;
			message = message.replace(/{{user}}/g, user.name);

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else if (this.name.toUpperCase() === 'SRINATOR') {
			var message = target || srinator[Math.floor(Math.random() * srinator.length)];

			room.addRaw(Tools.escapeHTML(message));
			user.leaveRoom(room);
		} else {
			user.leaveRoom(room);
		}
	},

	poofoff: 'nopoof',
	nopoof: function () {
		if (!this.can('poofoff')) return false;
		Config.poofOff = true;
		return this.sendReply("Poof is now disabled.");
	},

	poofon: function () {
		if (!this.can('poofoff')) return false;
		Config.poofOff = false;
		return this.sendReply("Poof is now enabled.");
	}
};
<|endoftext|>


<commit_before>/**
 *
 * @fileoverview Class to handler PNaCl kernel
 *
 * This provides a class for constructing a PNaCl kernel and
 * relaying it's messages to a webview.
 */

var colab = colab || {};

/**
 * Singleton object to handle PNaCl kernel.
 *
 * @constructor
 * @param {colab.Webview} webview Webview interface used to communicate
 */
colab.Kernel = function(webview) {
  /**
   * Embed element for the PNaCl kernel
   * @type {Element}
   * @private
   */
  this.embed_ = null;

  /**
   * Listeners for embed messages
   * @type {Array.<Function>}
   * @private
   */
  this.embedListeners_ = [];

  /**
   * @type {Webview}
   * @private
   */
  this.webview_ = webview;

  this.addWebviewListeners_();
};

/**
 * Adds listeners for messages from webview
 * @private
 */
colab.Kernel.prototype.addWebviewListeners_ = function() {
  var that = this;
  this.webview_.addMessageListener('start_kernel', function(msgType, content) {
    that.start_();
  });

  this.webview_.addMessageListener('restart_kernel', function(msgType, content) {
    that.restart_();
  });

  this.webview_.addMessageListener('kill_kernel', function(msgType, content) {
    that.kill_();
  });

  this.webview_.addMessageListener('pick_file', function(msgType, content) {
    that.pickFile_();
  });

  this.webview_.addMessageListener('kernel_message', function(msgType, content) {
    if (that.embed_) {
      that.embed_.postMessage({json: content});
    }
  });

}

/**
 * Starts the kernel
 * @private
 */
colab.Kernel.prototype.start_ = function() {
  var that = this;
  var tty_prefix = 'tty';

  this.embed_ = document.createElement('object');
  this.embed_.width = 0;
  this.embed_.height = 0;
  this.embed_.data = '/pnacl/kernel.nmf';
  this.embed_.type = 'application/x-pnacl';

  function addParam(name, value) {
    var param = document.createElement('param');
    param.name = name;
    param.value = value;
    that.embed_.appendChild(param);
  }

  addParam('PS_TTY_PREFIX', tty_prefix);
  addParam('PS_TTY_RESIZE', 'tty_resize');
  addParam('PS_STDIN', '/dev/tty');
  addParam('PS_STDOUT', '/dev/tty');
  addParam('PS_STDERR', '/dev/tty');
  addParam('PS_VERBOSITY', '2');
  addParam('PS_EXIT_MESSAGE', 'exited');
  addParam('TERM', 'xterm-256color');
  addParam('NACL_DATA_URL', '/');
  addParam('PNACL_PACKAGE', 'pnacl_data.tar.gz')
  addParam('HTTPFS_OPTS', 'cache_content=true,
  addParam('HTTPFS_OPTS', 'cache_content=true,' +
                          'cache_stat=true,' +
                          'allow_cross_origin_requests=true,' +
                          'allow_credentials=false');

  var eventTypes = {'message': ['data'],
                    'progress': ['loaded', 'total'],
                    'loadend': [],
                    'crash': []};

  for (type in eventTypes) {
    var listener = (function(type) {
      return function(event) {
        var message = {'type': type};
        var fields = eventTypes[type];
        for (var i = 0; i < fields.length; i++) {
          var field = fields[i];
          message[field] = event[field];
        }
        that.webview_.postMessage('kernel_message', message);
      }
    })(type);
    that.embedListeners_.push(listener);
    that.embed_.addEventListener(type, listener);
  }

  document.body.appendChild(this.embed_);
};

/**
 * Restarts the kernel
 */
colab.Kernel.prototype.restart_ = function() {
  this.kill_();
  this.start_();
};

/**
 * Restarts the kernel
 */
colab.Kernel.prototype.kill_ = function() {
  if (!this.embed_) {
    return;
  }

  for (var i = 0; i < this.embedListeners_.length; i++) {
    this.embed_.removeEventListener(this.embedListeners_[i]);
  }
  this.embed_.embedListeners_ = [];

  document.body.removeChild(this.embed_);

  this.embed_ = null;

  this.webview_.postMessage('kernel_message', {'type': 'crash'});
};

/**
 * Picks a directory and passes that to the kernel to mount
 */
colab.Kernel.prototype.pickFile_ = function() {
  var that = this;

  if (!this.embed_) {
    return;
  }

  chrome.fileSystem.chooseEntry({type: 'openDirectory'}, function(theEntry) {
    if (!theEntry) {
      return;
    }
    that.embed_.postMessage({'filesystem_name': theEntry.fullPath,
                             'filesystem_resource': theEntry.filesystem});
  });
}
<commit_msg>Fixing typo.<commit_after>/**
 *
 * @fileoverview Class to handler PNaCl kernel
 *
 * This provides a class for constructing a PNaCl kernel and
 * relaying it's messages to a webview.
 */

var colab = colab || {};

/**
 * Singleton object to handle PNaCl kernel.
 *
 * @constructor
 * @param {colab.Webview} webview Webview interface used to communicate
 */
colab.Kernel = function(webview) {
  /**
   * Embed element for the PNaCl kernel
   * @type {Element}
   * @private
   */
  this.embed_ = null;

  /**
   * Listeners for embed messages
   * @type {Array.<Function>}
   * @private
   */
  this.embedListeners_ = [];

  /**
   * @type {Webview}
   * @private
   */
  this.webview_ = webview;

  this.addWebviewListeners_();
};

/**
 * Adds listeners for messages from webview
 * @private
 */
colab.Kernel.prototype.addWebviewListeners_ = function() {
  var that = this;
  this.webview_.addMessageListener('start_kernel', function(msgType, content) {
    that.start_();
  });

  this.webview_.addMessageListener('restart_kernel', function(msgType, content) {
    that.restart_();
  });

  this.webview_.addMessageListener('kill_kernel', function(msgType, content) {
    that.kill_();
  });

  this.webview_.addMessageListener('pick_file', function(msgType, content) {
    that.pickFile_();
  });

  this.webview_.addMessageListener('kernel_message', function(msgType, content) {
    if (that.embed_) {
      that.embed_.postMessage({json: content});
    }
  });

}

/**
 * Starts the kernel
 * @private
 */
colab.Kernel.prototype.start_ = function() {
  var that = this;
  var tty_prefix = 'tty';

  this.embed_ = document.createElement('object');
  this.embed_.width = 0;
  this.embed_.height = 0;
  this.embed_.data = '/pnacl/kernel.nmf';
  this.embed_.type = 'application/x-pnacl';

  function addParam(name, value) {
    var param = document.createElement('param');
    param.name = name;
    param.value = value;
    that.embed_.appendChild(param);
  }

  addParam('PS_TTY_PREFIX', tty_prefix);
  addParam('PS_TTY_RESIZE', 'tty_resize');
  addParam('PS_STDIN', '/dev/tty');
  addParam('PS_STDOUT', '/dev/tty');
  addParam('PS_STDERR', '/dev/tty');
  addParam('PS_VERBOSITY', '2');
  addParam('PS_EXIT_MESSAGE', 'exited');
  addParam('TERM', 'xterm-256color');
  addParam('NACL_DATA_URL', '/');
  addParam('PNACL_PACKAGE', 'pnacl_data.tar.gz')
  addParam('HTTPFS_OPTS', 'cache_content=true,' +
                          'cache_stat=true,' +
                          'allow_cross_origin_requests=true,' +
                          'allow_credentials=false');

  var eventTypes = {'message': ['data'],
                    'progress': ['loaded', 'total'],
                    'loadend': [],
                    'crash': []};

  for (type in eventTypes) {
    var listener = (function(type) {
      return function(event) {
        var message = {'type': type};
        var fields = eventTypes[type];
        for (var i = 0; i < fields.length; i++) {
          var field = fields[i];
          message[field] = event[field];
        }
        that.webview_.postMessage('kernel_message', message);
      }
    })(type);
    that.embedListeners_.push(listener);
    that.embed_.addEventListener(type, listener);
  }

  document.body.appendChild(this.embed_);
};

/**
 * Restarts the kernel
 */
colab.Kernel.prototype.restart_ = function() {
  this.kill_();
  this.start_();
};

/**
 * Restarts the kernel
 */
colab.Kernel.prototype.kill_ = function() {
  if (!this.embed_) {
    return;
  }

  for (var i = 0; i < this.embedListeners_.length; i++) {
    this.embed_.removeEventListener(this.embedListeners_[i]);
  }
  this.embed_.embedListeners_ = [];

  document.body.removeChild(this.embed_);

  this.embed_ = null;

  this.webview_.postMessage('kernel_message', {'type': 'crash'});
};

/**
 * Picks a directory and passes that to the kernel to mount
 */
colab.Kernel.prototype.pickFile_ = function() {
  var that = this;

  if (!this.embed_) {
    return;
  }

  chrome.fileSystem.chooseEntry({type: 'openDirectory'}, function(theEntry) {
    if (!theEntry) {
      return;
    }
    that.embed_.postMessage({'filesystem_name': theEntry.fullPath,
                             'filesystem_resource': theEntry.filesystem});
  });
}
<|endoftext|>


<commit_before>'use strict';

var copy             = require('es5-ext/object/copy')
  , assign           = require('es5-ext/object/assign')
  , isEmpty          = require('es5-ext/object/is-empty')
  , filter           = require('es5-ext/object/filter')
  , forEach          = require('es5-ext/object/for-each')
  , normalizeOptions = require('es5-ext/object/normalize-options')
  , isSet            = require('es6-set/is-set')
  , d                = require('d')
  , castAttribute    = require('dom-ext/element/#/cast-attribute')
  , isNestedObject   = require('dbjs/is-dbjs-nested-object')
  , PropObserv       = require('dbjs/_setup/1.property/observable')
  , DescPropObserv   = require('dbjs/_setup/3.descriptor-property/observable')
  , htmlAttributes   = require('./_html-attributes')
  , componentRender  = require('./utils/get-component-render')('div')
  , resolveOptions   = require('./utils/resolve-options')

  , toDOM = function () { return this.dom; };

var hasOwn = function (obj, desc, sKey) {
	if (desc.multiple) {
		if (typeof desc._value_ === 'function') return false;
		return obj._hasOwnMultiple_(sKey);
	}
	return obj._hasOwn_(sKey);
};

Object.defineProperties(PropObserv.prototype, {
	DOMInput: d(null),
	toDOMInput: d(function (document/*, options*/) {
		var input, options = normalizeOptions(arguments[1]), type, value, onChange, desc, isMap = false;

		desc = this.descriptor;
		if (desc.nested) {
			isMap = this.object.database.isObjectType(this.value.__descriptorPrototype__.type);
		}
		// Setup input options
		if (options.multiple == null) {
			if (isMap) {
				options.multiple = true;
			} else {
				options.multiple = desc.multiple;
			}
		}
		if (options.name == null) options.name = this.dbId;
		options.dbOptions = desc;
		options.observable = this;

		// Initialize input
		type = isMap ? this.value.__descriptorPrototype__.type : desc.type;
		options = resolveOptions(options, type);
		if (options.DOMInput) input = new options.DOMInput(document, type, options);
		else if (desc.DOMInput) input = new desc.DOMInput(document, type, options);
		else input = type.toDOMInput(document, options);
		input.observable = this;

		// Set input value
		value = this.value;
		if (isSet(value) && !options.multiple) value = value.values().next().value || null;
		if ((value === undefined) && (options.value != null)) value = options.value;
		input.value = value;

		// Attach listeners
		onChange = function () {
			var nuValue = this.value;
			if (isSet(nuValue)) {
				if (!options.multiple) nuValue = nuValue.values().next().value || null;
			}
			if ((isMap || isSet(nuValue)) && (nuValue !== value)) {
				if (value && (typeof value.off === 'function')) value.off('change', onChange);
				value = nuValue;
				if (nuValue && (typeof nuValue.on === 'function')) nuValue.on('change', onChange);
			}
			input.value = nuValue;
		}.bind(this);
		this.on('change', onChange);
		if (isMap || isSet(value)) value.on('change', onChange);

		input.once('destroy', function () {
			delete input.observable;
			if (isSet(value)) value.off('change', onChange);
			this.off('change', onChange);
		}.bind(this));

		type.emit('dominput', input);
		desc.emit('dominput', input);
		return input;
	}),
	toDOMInputComponent: d(function (document/*, options*/) {
		var options, input, inputOptions, dom, cb
		  , desc = this.ownDescriptor, db = desc.database;

		options = normalizeOptions(arguments[1], desc.type.fieldOptions, desc.fieldOptions);
		inputOptions = filter(options, function (value, name) {
			if (name === 'render') return false;
			return !htmlAttributes[name];
		});
		if (options.input) {
			assign(inputOptions, options.input);
			delete inputOptions.input;
		}
		input = this.toDOMInput(document, inputOptions);

		if (options.label === false) options.label = null;
		else if (options.label == null) options.label = desc.label;
		if (options.hint == null) options.hint = desc.inputHint;
		if (options.optionalInfo == null) options.optionalInfo = desc.inputOptionalInfo;

		dom = (options.render || componentRender)(input, options);
		if (!dom._dbjsInput) dom._dbjsInput = input;
		forEach(options, function (value, name) {
			if (htmlAttributes[name]) castAttribute.call(dom, name, value);
		}, this);

		dom.classList.add('dbjs-input-component');

		// Required
		dom.classList[desc.required ? 'add' : 'remove']('dbjs-required');
		dom.classList[desc.required ? 'remove' : 'add']('dbjs-optional');

		// Changed
		input.on('change:changed', cb = function (value) {
			dom.classList[value ? 'add' : 'remove']('changed');
			dom.classList[value ? 'remove' : 'add']('not-changed');
		});
		cb(input.changed);

		// Valid
		input.on('change:valid', cb = function (value) {
			dom.classList[value ? 'add' : 'remove']('valid');
			dom.classList[value ? 'remove' : 'add']('invalid');
		});
		cb(input.valid);

		// DBJS valid/invalid & empty/filled
		this.on('change', cb = function () {
			var isInvalid, value, isEmpty, isOwn;
			if (desc.required) {
				if (this.value == null) {
					isInvalid = true;
				} else if (db.NestedMap && isNestedObject(this.value) && (this.value.key === 'map') &&
						(this.value.owner instanceof db.NestedMap)) {
					isEmpty = isInvalid = !this.value.owner.ordered.size;
					this.value.owner.ordered._size.once('change', cb);
				} else if (db.File && (this.value instanceof db.File) && isNestedObject(this.value)) {
					isEmpty = isInvalid = !this.value.name;
					this.value._name.once('change', cb);
				} else {
					isInvalid = false;
				}
			} else {
				isInvalid = false;
			}
			dom.classList[isInvalid ? 'add' : 'remove']('dbjs-invalid');
			dom.classList[isInvalid ? 'remove' : 'add']('dbjs-valid');
			value = this.value;
			if (isEmpty == null) {
				if (isSet(value)) isEmpty = !value.size;
				else isEmpty = value == null;
			}
			dom.classList[isEmpty ? 'add' : 'remove']('dbjs-empty');
			dom.classList[isEmpty ? 'remove' : 'add']('dbjs-filled');
			if (input.isComposite) return;
			isOwn = hasOwn(this.object, this.descriptor, this.__sKey__);
			dom.classList[isOwn ? 'add' : 'remove']('dbjs-own');
			dom.classList[isOwn ? 'remove' : 'add']('dbjs-not-own');
		}.bind(this));
		desc.on('selfupdate', cb);
		cb();
		if (input.isComposite) {
			(function () {
				var defined = {};
				var update = function () {
					var isOwn = !isEmpty(defined);
					dom.classList[isOwn ? 'add' : 'remove']('dbjs-own');
					dom.classList[isOwn ? 'remove' : 'add']('dbjs-not-own');
				};
				forEach(input.items, function (input) {
					var observable = input.observable, cb, object, sKey, desc;
					if (!observable) return;
					object = observable.object;
					desc = observable.descriptor;
					sKey = observable.__sKey__;
					if (hasOwn(object, desc, sKey)) defined[sKey] = true;
					observable.on('change', cb = function (event) {
						if (hasOwn(object, desc, sKey)) defined[sKey] = true;
						else delete defined[sKey];
						update();
					});
					observable.ownDescriptor.on('selfupdate', cb);
					input.on('destroy', function () {
						observable.off('change', cb);
						observable.ownDescriptor.off('selfupdate', cb);
					});
				});
				update();
			}());
		}
		if (isSet(this.value)) this.value.on('change', cb);
		input.on('destroy', function (cb) { this.off('change', cb); }.bind(this, cb));

		return { dom: dom, input: input, toDOM: toDOM };
	})
});

Object.defineProperties(DescPropObserv.prototype, {
	DOMInput: d(null),
	toDOMInput: d(function (document/*, options*/) {
		var input, initOptions = Object(arguments[1]), options = copy(initOptions)
		  , type, onChange, descDesc = this.descriptor;

		// Setup input options
		if (options.name == null) options.name = this.dbId;

		// Initialize input
		type = descDesc.type;
		if (options.DOMInput) input = new options.DOMInput(document, type, options);
		else if (this.DOMInput) input = new this.DOMInput(document, type, options);
		else input = type.toDOMInput(document, options);
		input.observable = this;

		// Set input value
		input.value = this.value;

		// Attach listeners
		onChange = function () { input.value = this.value; }.bind(this);
		this.on('change', onChange);

		input.once('destroy', function () {
			delete input.observable;
			this.off('change', onChange);
		}.bind(this));

		type.emit('dominput', input);
		descDesc.emit('dominput', input);
		return input;
	})
});
<commit_msg>Ensure support for constrained values<commit_after>'use strict';

var copy             = require('es5-ext/object/copy')
  , assign           = require('es5-ext/object/assign')
  , isEmpty          = require('es5-ext/object/is-empty')
  , filter           = require('es5-ext/object/filter')
  , forEach          = require('es5-ext/object/for-each')
  , normalizeOptions = require('es5-ext/object/normalize-options')
  , isSet            = require('es6-set/is-set')
  , d                = require('d')
  , castAttribute    = require('dom-ext/element/#/cast-attribute')
  , isNestedObject   = require('dbjs/is-dbjs-nested-object')
  , PropObserv       = require('dbjs/_setup/1.property/observable')
  , DescPropObserv   = require('dbjs/_setup/3.descriptor-property/observable')
  , htmlAttributes   = require('./_html-attributes')
  , componentRender  = require('./utils/get-component-render')('div')
  , resolveOptions   = require('./utils/resolve-options')

  , toDOM = function () { return this.dom; };

var hasOwn = function (obj, desc, sKey) {
	if (desc.multiple) {
		if (typeof desc._value_ === 'function') return false;
		return obj._hasOwnMultiple_(sKey);
	}
	return obj._hasOwn_(sKey);
};

Object.defineProperties(PropObserv.prototype, {
	DOMInput: d(null),
	toDOMInput: d(function (document/*, options*/) {
		var input, options = normalizeOptions(arguments[1]), type, value, onChange, desc, isMap = false;

		desc = this.descriptor;
		if (desc.nested) {
			isMap = this.object.database.isObjectType(this.value.__descriptorPrototype__.type);
		}
		// Setup input options
		if (options.multiple == null) {
			if (isMap) {
				options.multiple = true;
			} else {
				options.multiple = desc.multiple;
			}
		}
		if (options.name == null) options.name = this.dbId;
		options.dbOptions = desc;
		options.observable = this;

		// Initialize input
		type = isMap ? this.value.__descriptorPrototype__.type : desc.type;
		options = resolveOptions(options, type);
		if (options.DOMInput) input = new options.DOMInput(document, type, options);
		else if (desc.DOMInput) input = new desc.DOMInput(document, type, options);
		else input = type.toDOMInput(document, options);
		input.observable = this;

		// Set input value
		value = this.value;
		if (isSet(value) && !options.multiple) value = value.values().next().value || null;
		if ((value === undefined) && (options.value != null)) value = options.value;
		input.value = value;

		// Attach listeners
		onChange = function () {
			var nuValue = this.value;
			if (isSet(nuValue)) {
				if (!options.multiple) nuValue = nuValue.values().next().value || null;
			}
			if ((isMap || isSet(nuValue)) && (nuValue !== value)) {
				if (value && (typeof value.off === 'function')) value.off('change', onChange);
				value = nuValue;
				if (nuValue && (typeof nuValue.on === 'function')) nuValue.on('change', onChange);
			}
			input.value = nuValue;
		}.bind(this);
		this.on('change', onChange);
		if (isMap || isSet(value)) value.on('change', onChange);

		input.once('destroy', function () {
			delete input.observable;
			if (isSet(value)) value.off('change', onChange);
			this.off('change', onChange);
		}.bind(this));

		type.emit('dominput', input);
		desc.emit('dominput', input);
		return input;
	}),
	toDOMInputComponent: d(function (document/*, options*/) {
		var options, input, inputOptions, dom, cb
		  , desc = this.ownDescriptor, db = desc.database;

		options = normalizeOptions(arguments[1], desc.type.fieldOptions, desc.fieldOptions);
		inputOptions = filter(options, function (value, name) {
			if (name === 'render') return false;
			return !htmlAttributes[name];
		});
		if (options.input) {
			assign(inputOptions, options.input);
			delete inputOptions.input;
		}
		input = this.toDOMInput(document, inputOptions);

		if (options.label === false) options.label = null;
		else if (options.label == null) options.label = desc.label;
		if (options.hint == null) options.hint = desc.inputHint;
		if (options.optionalInfo == null) options.optionalInfo = desc.inputOptionalInfo;

		dom = (options.render || componentRender)(input, options);
		if (!dom._dbjsInput) dom._dbjsInput = input;
		forEach(options, function (value, name) {
			if (htmlAttributes[name]) castAttribute.call(dom, name, value);
		}, this);

		dom.classList.add('dbjs-input-component');

		// Required
		dom.classList[desc.required ? 'add' : 'remove']('dbjs-required');
		dom.classList[desc.required ? 'remove' : 'add']('dbjs-optional');

		// Changed
		input.on('change:changed', cb = function (value) {
			dom.classList[value ? 'add' : 'remove']('changed');
			dom.classList[value ? 'remove' : 'add']('not-changed');
		});
		cb(input.changed);

		// Valid
		input.on('change:valid', cb = function (value) {
			dom.classList[value ? 'add' : 'remove']('valid');
			dom.classList[value ? 'remove' : 'add']('invalid');
		});
		cb(input.valid);

		// DBJS valid/invalid & empty/filled
		this.on('change', cb = function () {
			var isInvalid, value, isEmpty, isOwn;
			if (desc.required) {
				if (this.value == null) {
					isInvalid = true;
				} else if (db.NestedMap && isNestedObject(this.value) && (this.value.key === 'map') &&
						(this.value.owner instanceof db.NestedMap)) {
					isEmpty = isInvalid = !this.value.owner.ordered.size;
					this.value.owner.ordered._size.once('change', cb);
				} else if (db.File && (this.value instanceof db.File) && isNestedObject(this.value)) {
					isEmpty = isInvalid = !this.value.name;
					this.value._name.once('change', cb);
				} else if (isNestedObject(this.value) &&
						(typeof this.value.getDescriptor('resolvedValue')._value_ === 'function')) {
					isEmpty = isInvalid = (this.value.resolvedValue == null);
					this.value._resolvedValue.once('change', cb);
				} else {
					isInvalid = false;
				}
			} else {
				isInvalid = false;
			}
			dom.classList[isInvalid ? 'add' : 'remove']('dbjs-invalid');
			dom.classList[isInvalid ? 'remove' : 'add']('dbjs-valid');
			value = this.value;
			if (isEmpty == null) {
				if (isSet(value)) isEmpty = !value.size;
				else isEmpty = value == null;
			}
			dom.classList[isEmpty ? 'add' : 'remove']('dbjs-empty');
			dom.classList[isEmpty ? 'remove' : 'add']('dbjs-filled');
			if (input.isComposite) return;
			isOwn = hasOwn(this.object, this.descriptor, this.__sKey__);
			dom.classList[isOwn ? 'add' : 'remove']('dbjs-own');
			dom.classList[isOwn ? 'remove' : 'add']('dbjs-not-own');
		}.bind(this));
		desc.on('selfupdate', cb);
		cb();
		if (input.isComposite) {
			(function () {
				var defined = {};
				var update = function () {
					var isOwn = !isEmpty(defined);
					dom.classList[isOwn ? 'add' : 'remove']('dbjs-own');
					dom.classList[isOwn ? 'remove' : 'add']('dbjs-not-own');
				};
				forEach(input.items, function (input) {
					var observable = input.observable, cb, object, sKey, desc;
					if (!observable) return;
					object = observable.object;
					desc = observable.descriptor;
					sKey = observable.__sKey__;
					if (hasOwn(object, desc, sKey)) defined[sKey] = true;
					observable.on('change', cb = function (event) {
						if (hasOwn(object, desc, sKey)) defined[sKey] = true;
						else delete defined[sKey];
						update();
					});
					observable.ownDescriptor.on('selfupdate', cb);
					input.on('destroy', function () {
						observable.off('change', cb);
						observable.ownDescriptor.off('selfupdate', cb);
					});
				});
				update();
			}());
		}
		if (isSet(this.value)) this.value.on('change', cb);
		input.on('destroy', function (cb) { this.off('change', cb); }.bind(this, cb));

		return { dom: dom, input: input, toDOM: toDOM };
	})
});

Object.defineProperties(DescPropObserv.prototype, {
	DOMInput: d(null),
	toDOMInput: d(function (document/*, options*/) {
		var input, initOptions = Object(arguments[1]), options = copy(initOptions)
		  , type, onChange, descDesc = this.descriptor;

		// Setup input options
		if (options.name == null) options.name = this.dbId;

		// Initialize input
		type = descDesc.type;
		if (options.DOMInput) input = new options.DOMInput(document, type, options);
		else if (this.DOMInput) input = new this.DOMInput(document, type, options);
		else input = type.toDOMInput(document, options);
		input.observable = this;

		// Set input value
		input.value = this.value;

		// Attach listeners
		onChange = function () { input.value = this.value; }.bind(this);
		this.on('change', onChange);

		input.once('destroy', function () {
			delete input.observable;
			this.off('change', onChange);
		}.bind(this));

		type.emit('dominput', input);
		descDesc.emit('dominput', input);
		return input;
	})
});
<|endoftext|>


<commit_before>$(document).ready(function() {
  /*This function returns a tweetable string*/
  function tweetSize(quote, author) {
    var tweet = "";
    var len = quote.length + author.length +2;

    if (len > 140) {
      tweet += quote.substring(0, 133 - author.length);
      tweet += "... -" + author;
    }
    else {
      tweet += quote + " -" + author;
    }
    return escape(tweet);
  }

  /*This function calls the API, gets the quote and metadata and updates the html*/
  function getQuote() {
    $("#getQuote").html("Loading...");
    $.getJSON("http://api.forismatic.com/api/1.0/?method=getQuote&lang=en&format=jsonp&jsonp=?", function(data){
      var html = "
" + data.quoteText;
      if (data.quoteAuthor != "") {
        html += "

" + data.quoteAuthor + "" +
          "" +
          "" +
          "
";
      }
      else {
        html += "

Author Unknown
";
      }
      $(".message").html(html)
      $("#getQuote").html("New Quote");
      $("#quoteLink").attr("href", data.quoteLink);
      //http://twitter.com/home?status=Today is the tomorrow we worried about yesterday.  http://en.forismatic.com/6750845f01/ @forismatic
    });
  }

  /*Initialize*/
  getQuote(); //comment out when editing to reduce API calls

  /*the following calls getQuote() when button is pressed*/
  $("#getQuote").on("click", function(){
    getQuote();
  });
});<commit_msg>br fix<commit_after>$(document).ready(function() {
  /*This function returns a tweetable string*/
  function tweetSize(quote, author) {
    var tweet = "";
    var len = quote.length + author.length +2;

    if (len > 140) {
      tweet += quote.substring(0, 133 - author.length);
      tweet += "... -" + author;
    }
    else {
      tweet += quote + " -" + author;
    }
    return escape(tweet);
  }

  /*This function calls the API, gets the quote and metadata and updates the html*/
  function getQuote() {
    $("#getQuote").html("Loading...");
    $.getJSON("http://api.forismatic.com/api/1.0/?method=getQuote&lang=en&format=jsonp&jsonp=?", function(data){
      var html = "
" + data.quoteText;
      if (data.quoteAuthor != "") {
        html += "

" + data.quoteAuthor + "
" +
          "" +
          "" +
          "
";
      }
      else {
        html += "

Author Unknown
";
      }
      $(".message").html(html);
      $("#getQuote").html("New Quote");
      $("#quoteLink").attr("href", data.quoteLink);
      //http://twitter.com/home?status=Today is the tomorrow we worried about yesterday.  http://en.forismatic.com/6750845f01/ @forismatic
    });
  }

  /*Initialize*/
  getQuote(); //comment out when editing to reduce API calls

  /*the following calls getQuote() when button is pressed*/
  $("#getQuote").on("click", function(){
    getQuote();
  });
});<|endoftext|>


<commit_before>(function (global) {
	"use strict";

	// run search/replace for '.x' and '.y' to suit your point format
	// (its configurability would draw significant performance overhead)

	function squareDistance(p1, p2) { // square distance between 2 points

		var dx = p1.x - p2.x,
		    dy = p1.y - p2.y;

		return dx * dx + dy * dy;
	}

	function squareSegmentDistance(p, p1, p2) { // square distance from a point to a segment

		var x = p1.x,
		    y = p1.y,

		    dx = p2.x - x,
		    dy = p2.y - y,

		    t;

		if (dx !== 0 || dy !== 0) {

			t = ((p.x - x) * dx +
			     (p.y - y) * dy) /
			    (dx * dx + dy * dy);

			if (t > 1) {
				x = p2.x;
				y = p2.y;

			} else if (t > 0) {
				x += dx * t;
				y += dy * t;
			}
		}

		dx = p.x - x;
		dy = p.y - y;

		return dx * dx + dy * dy;
	}

	// replace previous functions with the following for 3D space

	/*
	function squareDistance(p1, p2) {

		var dx = p1.x - p2.x,
		    dy = p1.y - p2.y,
		    dz = p1.z - p2.z;

		return dx * dx + dy * dy + dz * dz;
	}

	function squareSegmentDistance(p, p1, p2) {

		var x = p1.x,
		    y = p1.y,
		    z = p1.z,

		    dx = p2.x - x,
		    dy = p2.y - y,
		    dz = p2.z - z,

		    t;

		if (dx !== 0 || dy !== 0) {

			t = ((p.x - x) * dx +
			     (p.y - y) * dy +
			     (p.z - z) * dz) /
			    (dx * dx + dy * dy + dz * dz);

			if (t > 1) {
				x = p2.x;
				y = p2.y;
				z = p2.z;

			} else if (t > 0) {
				x += dx * t;
				y += dy * t;
				z += dz * t;
			}
		}

		dx = p.x - x;
		dy = p.y - y;
		dz = p.z - z;

		return dx * dx + dy * dy + dz * dz;
	}
	*/

	// the rest of the code doesn't care for the point format

	// radial distance simplification

	function simplifyRadialDist(points, sqTolerance) {

		var prevPoint = points[0],
		    newPoints = [prevPoint],
		    len = points.length,
		    i,
		    point;

		for (i = 1; i < len; i += 1) {
			point = points[i];
			if (squareDistance(point, prevPoint) > sqTolerance) {
				newPoints.push(point);
				prevPoint = point;
			}
		}

		if (prevPoint !== point) {
			newPoints.push(point);
		}

		return newPoints;
	}

	// simplification using optimized Douglas-Peucker algorithm with recursion elimination

	function markPointsDP(points, markers, sqTolerance, first, last) {

		var maxSqDist,
		    i,
		    squareDistance,
		    index,
		    firstStack = [],
		    lastStack = [];

		while (last) {

			maxSqDist = 0;

			for (i = first + 1; i < last; i++) {
				squareDistance = squareSegmentDistance(points[i], points[first], points[last]);

				if (squareDistance > maxSqDist) {
					index = i;
					maxSqDist = squareDistance;
				}
			}

			if (maxSqDist > sqTolerance) {
				markers[index] = 1;

				firstStack.push(first);
				lastStack.push(index);

				firstStack.push(index);
				lastStack.push(last);
			}

			first = firstStack.pop();
			last = lastStack.pop();
		}
	}

	function simplifyDouglasPeucker(points, sqTolerance) {

		var len = points.length,
		    ArrayConstructor = typeof Uint8Array !== 'undefined' ? Uint8Array : Array,
		    markers = new ArrayConstructor(len),
		    i,
		    newPoints = [];

		markers[0] = markers[len - 1] = 1;

		markPointsDP(points, markers, sqTolerance, 0, len - 1);

		for (i = 0; i < len; i += 1) {
			if (markers[i]) {
				newPoints.push(points[i]);
			}
		}

		return newPoints;
	}

	var root = (typeof exports !== 'undefined' ? exports : global);

	root.simplify = function (points, tolerance) {

		tolerance = typeof tolerance !== 'undefined' ? tolerance : 1;

		var sqTolerance = tolerance * tolerance;

		points = simplifyRadialDist(points, sqTolerance);
		points = simplifyDouglasPeucker(points, sqTolerance);

		return points;
	};

}(this));<commit_msg>minor code styling<commit_after>(function (global) {

	"use strict";

	// run search/replace for '.x' and '.y' to suit your point format
	// (its configurability would draw significant performance overhead)

	function squareDistance(p1, p2) { // square distance between 2 points

		var dx = p1.x - p2.x,
		    dy = p1.y - p2.y;

		return dx * dx + dy * dy;
	}

	function squareSegmentDistance(p, p1, p2) { // square distance from a point to a segment

		var x = p1.x,
		    y = p1.y,

		    dx = p2.x - x,
		    dy = p2.y - y,

		    t;

		if (dx !== 0 || dy !== 0) {

			t = ((p.x - x) * dx +
			     (p.y - y) * dy) /
			    (dx * dx + dy * dy);

			if (t > 1) {
				x = p2.x;
				y = p2.y;

			} else if (t > 0) {
				x += dx * t;
				y += dy * t;
			}
		}

		dx = p.x - x;
		dy = p.y - y;

		return dx * dx + dy * dy;
	}

	// replace previous functions with the following for 3D space

	/*
	function squareDistance(p1, p2) {

		var dx = p1.x - p2.x,
		    dy = p1.y - p2.y,
		    dz = p1.z - p2.z;

		return dx * dx + dy * dy + dz * dz;
	}

	function squareSegmentDistance(p, p1, p2) {

		var x = p1.x,
		    y = p1.y,
		    z = p1.z,

		    dx = p2.x - x,
		    dy = p2.y - y,
		    dz = p2.z - z,

		    t;

		if (dx !== 0 || dy !== 0) {

			t = ((p.x - x) * dx +
			     (p.y - y) * dy +
			     (p.z - z) * dz) /
			    (dx * dx + dy * dy + dz * dz);

			if (t > 1) {
				x = p2.x;
				y = p2.y;
				z = p2.z;

			} else if (t > 0) {
				x += dx * t;
				y += dy * t;
				z += dz * t;
			}
		}

		dx = p.x - x;
		dy = p.y - y;
		dz = p.z - z;

		return dx * dx + dy * dy + dz * dz;
	}
	*/

	// the rest of the code doesn't care for the point format

	// radial distance simplification

	function simplifyRadialDist(points, sqTolerance) {

		var prevPoint = points[0],
		    newPoints = [prevPoint],
		    len = points.length,
		    i,
		    point;

		for (i = 1; i < len; i++) {
			point = points[i];
			if (squareDistance(point, prevPoint) > sqTolerance) {
				newPoints.push(point);
				prevPoint = point;
			}
		}

		if (prevPoint !== point) {
			newPoints.push(point);
		}

		return newPoints;
	}

	// simplification using optimized Douglas-Peucker algorithm with recursion elimination

	function markPointsDP(points, markers, sqTolerance, first, last) {

		var maxSqDist,
		    i,
		    squareDistance,
		    index,
		    firstStack = [],
		    lastStack = [];

		while (last) {

			maxSqDist = 0;

			for (i = first + 1; i < last; i++) {
				squareDistance = squareSegmentDistance(points[i], points[first], points[last]);

				if (squareDistance > maxSqDist) {
					index = i;
					maxSqDist = squareDistance;
				}
			}

			if (maxSqDist > sqTolerance) {
				markers[index] = 1;

				firstStack.push(first);
				lastStack.push(index);

				firstStack.push(index);
				lastStack.push(last);
			}

			first = firstStack.pop();
			last = lastStack.pop();
		}
	}

	function simplifyDouglasPeucker(points, sqTolerance) {

		var len = points.length,
		    ArrayConstructor = typeof Uint8Array !== 'undefined' ? Uint8Array : Array,
		    markers = new ArrayConstructor(len),
		    i,
		    newPoints = [];

		markers[0] = markers[len - 1] = 1;

		markPointsDP(points, markers, sqTolerance, 0, len - 1);

		for (i = 0; i < len; i++) {
			if (markers[i]) {
				newPoints.push(points[i]);
			}
		}

		return newPoints;
	}

	var root = (typeof exports !== 'undefined' ? exports : global);

	root.simplify = function (points, tolerance) {

		tolerance = (typeof tolerance !== 'undefined' ? tolerance : 1);

		var sqTolerance = tolerance * tolerance;

		points = simplifyRadialDist(points, sqTolerance);
		points = simplifyDouglasPeucker(points, sqTolerance);

		return points;
	};

}(this));<|endoftext|>


<commit_before>/**
 * The techtips object is the namespace into which we put all techtips-related
 * functionality.
 */
var techtips = function () {

    // Public
    return {
        /**
         * load_tip loads a techtip asynchronously, and then hides it if the
         * user click on the title a second time.
         */
        load_tip: function () {
            var original_href = $(this).attr('href');
            $(this).attr('href', '#');
            $(this).click(function () {
                // Load list item content asynchronously
                $(this).parent().parent().find('div.list_item_outer').load(
                    original_href + 'ajax/'
                );
                // Now redefine click handler to simple toggle
                $(this).unbind('click');
                $(this).click(function () {
                    $(this).parent().parent().find('div.list_item_outer').toggle();
                    return false;
                });

                return false;
            });
        }

    };
}();
<commit_msg>License notice added to techtips.js<commit_after>/**
 * This file is part of Tech Tip of the Day.
 *
 * Tech Tip of the Day 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.
 *
 * Tech Tip of the Day 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 Tech Tip of the Day.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * The techtips object is the namespace into which we put all techtips-related
 * functionality.
 */
var techtips = function () {

    // Public
    return {
        /**
         * load_tip loads a techtip asynchronously, and then hides it if the
         * user click on the title a second time.
         */
        load_tip: function () {
            var original_href = $(this).attr('href');
            $(this).attr('href', '#');
            $(this).click(function () {
                // Load list item content asynchronously
                $(this).parent().parent().find('div.list_item_outer').load(
                    original_href + 'ajax/'
                );
                // Now redefine click handler to simple toggle
                $(this).unbind('click');
                $(this).click(function () {
                    $(this).parent().parent().find('div.list_item_outer').toggle();
                    return false;
                });

                return false;
            });
        }

    };
}();
<|endoftext|>


<commit_before>/* globals module */
/**
 * Copyright (c) 2020 Julian Knight (Totally Information)
 * https://it.knightnet.org.uk
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/
/**
 * Template security functions for uibuilder.
 * Only used if the node.useSecurity flag is set.
 * Please replace with your own code.
 *
 * You MUST export the following functions:
 *   - userValidate - based on an id, lookup the user data to see if the user is valid.
 *                    MUST return a boolean or object of type userValidation.
 *                    Called from the server's logon process. (uiblib.js::logon)
 *
 *
 * Each function MUST at least return true/false. See each function for more details.
 *
 * NOTES & WARNINGS:
 *   1) IF there is an error in this JavaScript, it is very likely that Node-RED will terminate.
 *   2) You can use different security.js files for different instances of uibuilder.
 *      Simply, place a securiy.js file in the instances root folder (e.g ~/.node-red/uibuilder/<url>/security.js)
 *      Note, however, that this means that the security.js file can be edited using the admin Editor.
 *      You have to restart Node-RED to pick up the new file.
 */
'use strict'

/**
 * @typedef {Object} uibAuth The standard auth object used by uibuilder security. See docs for details.
 * Note that any other data may be passed from your front-end code in the uibAuth object.
 * An obvious property would be `password`.
 * @property {String} id Required. A unique user identifier.
 * @property {Object=} [authData] Optional metadata about the user.
 */
/**
 * @typedef {Object} userValidation Optional return object that is able to pass on additional use metadata back to the client.
 * @property {boolean} userValidated Required. Whether the input ID (and optional additional data from the _auth object) validated correctly or not.
 * @property {userMetadata} [authData] Optional return metadata about the user. Will be added to the output msg's _auth object
 */
/**
 * @typedef {Object} userMetadata Optional. Metadata about the user. Will be added to the output msg's _auth object.
 * This is just an example of what you might want to return, you can send anything you like.
 * @property {String} [name] Users full name or screen name.
 * @property {String} [message] A message that the front-end code could use to display to the user when they log in.
 * @property {String} [level] Users authorisation level (admin, gold, silver, reader, editor, author, ...).
 * @property {String} [location] Users location.
 * @property {Date} [passwordExpiry] Date/time the users password expires.
 * @property {Date} [subsExpiry] Date/time the users subscription expires.
 */

module.exports = {
    /** Validate user against your own user data.
     * The minimum input data is _auth.id which must represent a unique ID.
     * Called from the logon function (uiblib.js::logon) which is triggered by a uibuilder control msg from the client of type 'logon'.
     * May also be called to revalidate users at any time.
     * @param {uibAuth} _auth Required.
     * @return {boolean|userValidation} Either true/false or Object of type userValidation
     */
    userValidate: function(_auth) {
        console.log(`[uibuilder:security.js] userValidate Security from ${__filename} used. Replace this template with your own code. _auth:`, _auth)

        /** Manual "test" ID validates - this will be replaced with a suitable lookup in your code - maybe from a database or a file.
         * You will also want to pass through some kind of password to validate the user.
         */
        if ( _auth.id === 'test' ) {
            console.log(`[uibuilder:security.js] User id ${_auth.id} has been validated`)

            // Example of simple boolean return
            return true

            //Example of object return with additional data that gets passed back to the client
            // return {
            //     userValidated: true,
            //     authData: {
            //         name: 'Me',
            //         message: 'Hi you, don\'t forget to change your password :)'
            //     }
            // }
        }

        // In all other cases, fail the validation - optionally, you can include more info here by returning an object.
        return false
        // return {
        //     userValidated: false,
        //     authData: {
        //         message: `Login failed, User id ${_auth.id} not recognised.`
        //     }
        // }

    } // ---- End of userValidate ---- //

}

//EOF<commit_msg>Linting<commit_after>/* globals module */
/**
 * Copyright (c) 2020 Julian Knight (Totally Information)
 * https://it.knightnet.org.uk
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/
/**
 * Template security functions for uibuilder.
 * Only used if the node.useSecurity flag is set.
 * Please replace with your own code.
 *
 * You MUST export the following functions:
 *   - userValidate - based on an id, lookup the user data to see if the user is valid.
 *                    MUST return a boolean or object of type userValidation.
 *                    Called from the server's logon process. (uiblib.js::logon)
 *
 *
 * Each function MUST at least return true/false. See each function for more details.
 *
 * NOTES & WARNINGS:
 *   1) IF there is an error in this JavaScript, it is very likely that Node-RED will terminate.
 *   2) You can use different security.js files for different instances of uibuilder.
 *      Simply, place a securiy.js file in the instances root folder (e.g ~/.node-red/uibuilder/<url>/security.js)
 *      Note, however, that this means that the security.js file can be edited using the admin Editor.
 *      You have to restart Node-RED to pick up the new file.
 */
'use strict'

/**
 * Standard msg._auth object exchanged in msg's between front-end and server
 * @typedef {import('../../index').MsgAuth} MsgAuth
 */
/**
 * Validated user object returned by the userValidate function
 * typedef {import('./security').userValidation} userValidation
 */

const TYPEDEFS = require('../../typedefs.js')
/**
 * typedef {TYPEDEFS.MsgAuth} MsgAuth
 * @typedef {TYPEDEFS.userValidation} userValidation
 * @typedef {TYPEDEFS.userMetadata} userMetadata
 */

module.exports = {
    /** Validate user against your own user data.
     * The minimum input data is _auth.id which must represent a unique ID.
     * Called from the logon function (uiblib.js::logon) which is triggered by a uibuilder control msg from the client of type 'logon'.
     * May also be called to revalidate users at any time.
     * @param {MsgAuth} _auth Required.
     * @return {boolean|userValidation} Either true/false or Object of type userValidation
     */
    userValidate: function(_auth) {
        console.log(`[uibuilder:security.js] userValidate Security from ${__filename} used. Replace this template with your own code. _auth:`, _auth)

        /** Manual "test" ID validates - this will be replaced with a suitable lookup in your code - maybe from a database or a file.
         * You will also want to pass through some kind of password to validate the user.
         */
        if ( _auth.id === 'test' ) {
            console.log(`[uibuilder:security.js] User id ${_auth.id} has been validated`)

            // Example of simple boolean return
            return true

            //Example of object return with additional data that gets passed back to the client
            // return {
            //     userValidated: true,
            //     authData: {
            //         name: 'Me',
            //         message: 'Hi you, don\'t forget to change your password :)'
            //     }
            // }
        }

        // In all other cases, fail the validation - optionally, you can include more info here by returning an object.
        return false
        // return {
        //     userValidated: false,
        //     authData: {
        //         message: `Login failed, User id ${_auth.id} not recognised.`
        //     }
        // }

    } // ---- End of userValidate ---- //

}

//EOF<|endoftext|>


<commit_before>var debug = false;
var showDelay = 2;
var hideDelay = 2;
var customColors = true;
var foreground = "#FF0000";
var background = "#FFFFFF";

function myLog(message) {
    if (debug)
        console.log(message);
}

self.port.on("pref-init", function(prefs) {
    debug = prefs[0]
    showDelay = prefs[1];
    hideDelay = prefs[2];
    customColors = prefs[3];
    foreground = prefs[4];
    background = prefs[5];
    myLog("Initialized preferences - show:" + showDelay + " s - hide:" + hideDelay + " s - foreground:" + (customColors ? foreground : "none") + " - background:" + (customColors ? background : "none"));
});

self.port.on("pref-changed", function(prefs) {
    switch (prefs[0]) {
        case "debug":
            debug = prefs[1];
            break;
        case "showDelay":
            showDelay = prefs[1];
            break;
        case "hideDelay":
            hideDelay = prefs[1];
            break;
        case "customColors":
            customColors = prefs[1];
            break;
        case "foreground":
            foreground = prefs[1];
            break;
        case "background":
            background = prefs[1];
            break;
    }
    myLog("Updated preference " + prefs[0]);
});

function ShowPasswordField(obj) {
    var self = this;
    self.obj = obj;
    self.showed = false;
    self.hiddenWithoutExit = false;
    self.showTimer = null;
    self.hideTimer = null;

    self.foreground = self.obj.style.color;
    self.background = self.obj.style.background;

    self.log = function(message) {
        myLog("[" + self.obj.name + "] " + message);
    };

    self.onEnter = function() {
        if (self.hiddenWithoutExit) return; // Avoid re-show after an hide for blur
        self.log("Entered");
        // Cancel hide action
        if (self.hideTimer != null) {
            self.log("Entered - Cancelled hide");
            window.clearTimeout(self.hideTimer);
            self.hideTimer = null;
        }
        // Set show action
        if (self.showTimer == null) {
            self.log("Entered - Show in " + showDelay + " s");
            self.showTimer = window.setTimeout(
                function() {
                    self.showTimer = null;
                    self.show();
                },
                showDelay * 1000
            );
        }
    };
    self.onExit = function() {
        self.log("Exited");
        // Cancel show action
        if (self.showTimer != null) {
            self.log("Exited - Cancelled show");
            window.clearTimeout(self.showTimer);
            self.showTimer = null;
        }
        // Set hide action
        if (self.hideTimer == null) {
            self.log("Exited - Hide in " + hideDelay + " s");
            self.hideTimer = window.setTimeout(
                function() {
                    self.hideTimer = null;
                    self.hide();
                    self.hiddenWithoutExit = false;
                },
                hideDelay * 1000
            );
        }
    };

    self.change = function(type, fg, bg) {
        // Save selection
        var selectionStart = self.obj.selectionStart;
        var selectionEnd = self.obj.selectionEnd;

        // Apply custom colors
        if (customColors) {
            self.obj.style.color = fg;
            self.obj.style.background = bg;
        }

        // Change field type
        self.obj.type = type;

        // Restore selection
        self.obj.selectionStart = selectionStart;
        self.obj.selectionEnd = selectionEnd;
    };
    self.show = function() {
        if (!self.showed) {
            self.log("Show");
            self.change("text", foreground, background);
            self.showed = true;
        }
    };
    self.hide = function() {
        if (self.showed) {
            self.log("Hide");
            self.change("password", self.foreground, self.background);
            self.showed = false;
            self.hiddenWithoutExit = true;
        }
    };

    self.obj.addEventListener("mouseover", self.onEnter, false);
    self.obj.addEventListener("mouseout", self.onExit, false);
    self.obj.addEventListener("blur", self.hide, false);
}

var inputFields = document.getElementsByTagName("input");
var num_inputFields = inputFields.length;
var num_passwordFields = 0;
for (var i = 0; i < num_inputFields; ++i) {
    var field = inputFields[i];
    if (field.type.toLowerCase() != "password")
        continue;
    myLog("Found - " + field.name);
    new ShowPasswordField(field);
    ++num_passwordFields;
}
myLog("Setup done for " + num_passwordFields + " password fields");
<commit_msg>Avoid unneeded hide and show<commit_after>var debug = false;
var showDelay = 2;
var hideDelay = 2;
var customColors = true;
var foreground = "#FF0000";
var background = "#FFFFFF";

function myLog(message) {
    if (debug)
        console.log(message);
}

self.port.on("pref-init", function(prefs) {
    debug = prefs[0]
    showDelay = prefs[1];
    hideDelay = prefs[2];
    customColors = prefs[3];
    foreground = prefs[4];
    background = prefs[5];
    myLog("Initialized preferences - show:" + showDelay + " s - hide:" + hideDelay + " s - foreground:" + (customColors ? foreground : "none") + " - background:" + (customColors ? background : "none"));
});

self.port.on("pref-changed", function(prefs) {
    switch (prefs[0]) {
        case "debug":
            debug = prefs[1];
            break;
        case "showDelay":
            showDelay = prefs[1];
            break;
        case "hideDelay":
            hideDelay = prefs[1];
            break;
        case "customColors":
            customColors = prefs[1];
            break;
        case "foreground":
            foreground = prefs[1];
            break;
        case "background":
            background = prefs[1];
            break;
    }
    myLog("Updated preference " + prefs[0]);
});

function ShowPasswordField(obj) {
    var self = this;
    self.obj = obj;
    self.showed = false;
    self.hiddenWithoutExit = false;
    self.showTimer = null;
    self.hideTimer = null;

    self.foreground = self.obj.style.color;
    self.background = self.obj.style.background;

    self.log = function(message) {
        myLog("[" + self.obj.name + "] " + message);
    };

    self.onEnter = function() {
        if (self.hiddenWithoutExit) return; // Avoid re-show after an hide for blur
        self.log("Entered");
        // Cancel hide action
        if (self.hideTimer != null) {
            self.log("Entered - Cancelled hide");
            window.clearTimeout(self.hideTimer);
            self.hideTimer = null;
        }
        // Set show action
        if (!self.showed && self.showTimer == null) {
            self.log("Entered - Show in " + showDelay + " s");
            self.showTimer = window.setTimeout(
                function() {
                    self.showTimer = null;
                    self.show();
                },
                showDelay * 1000
            );
        }
    };
    self.onExit = function() {
        self.log("Exited");
        // Cancel show action
        if (self.showTimer != null) {
            self.log("Exited - Cancelled show");
            window.clearTimeout(self.showTimer);
            self.showTimer = null;
        }
        // Set hide action
        if (self.showed && self.hideTimer == null) {
            self.log("Exited - Hide in " + hideDelay + " s");
            self.hideTimer = window.setTimeout(
                function() {
                    self.hideTimer = null;
                    self.hide();
                    self.hiddenWithoutExit = false;
                },
                hideDelay * 1000
            );
        }
    };

    self.change = function(type, fg, bg) {
        // Save selection
        var selectionStart = self.obj.selectionStart;
        var selectionEnd = self.obj.selectionEnd;

        // Apply custom colors
        if (customColors) {
            self.obj.style.color = fg;
            self.obj.style.background = bg;
        }

        // Change field type
        self.obj.type = type;

        // Restore selection
        self.obj.selectionStart = selectionStart;
        self.obj.selectionEnd = selectionEnd;
    };
    self.show = function() {
        if (!self.showed) {
            self.log("Show");
            self.change("text", foreground, background);
            self.showed = true;
        }
    };
    self.hide = function() {
        if (self.showed) {
            self.log("Hide");
            self.change("password", self.foreground, self.background);
            self.showed = false;
            self.hiddenWithoutExit = true;
        }
    };

    self.obj.addEventListener("mouseover", self.onEnter, false);
    self.obj.addEventListener("mouseout", self.onExit, false);
    self.obj.addEventListener("blur", self.hide, false);
}

var inputFields = document.getElementsByTagName("input");
var num_inputFields = inputFields.length;
var num_passwordFields = 0;
for (var i = 0; i < num_inputFields; ++i) {
    var field = inputFields[i];
    if (field.type.toLowerCase() != "password")
        continue;
    myLog("Found - " + field.name);
    new ShowPasswordField(field);
    ++num_passwordFields;
}
myLog("Setup done for " + num_passwordFields + " password fields");
<|endoftext|>


<commit_before>/**
 * Write loading image to a container for ajax request
 *
 * @param container: a jQuery object
 * @param theme: dark or white
 */
const showLoadingImage = (container, theme = 'dark') => {
    container.empty().append(`<div class="barspinner ${theme}"><div class="rect1"></div><div class="rect2"></div><div class="rect3"></div><div class="rect4"></div><div class="rect5"></div></div>`);
};

/**
 * Returns the highest z-index in the page.
 * Accepts a jquery style selector to only check those elements,
 * uses all container tags by default
 * If no element found, returns null.
 *
 * @param selector: a jquery style selector for target elements
 * @return int|null
 */
const getHighestZIndex = (selector) => {
    if (!selector) {
        selector = 'div,p,area,nav,section,header,canvas,aside,span';
    }
    const all = [];
    const _store_zindex = function() {
        if ($(this).is(':visible')) {
            const z = $(this).css('z-index');
            if (!isNaN(z)) {
                all.push(z);
            }
        }
    };
    $(selector).each(_store_zindex);

    return all.length ? Math.max(...all) : null;
};

const downloadCSV = (csv_contents, filename) => {
    filename = filename || 'data.csv';
    if (navigator.msSaveBlob) { // IE 10+
        navigator.msSaveBlob(new Blob([csv_contents], { type: 'text/csv;charset=utf-8;' }), filename);
    } else { // Other browsers
        const csv = `data:text/csv;charset=utf-8,${csv_contents}`;
        const download_link = document.createElement('a');
        download_link.href = encodeURI(csv);
        download_link.download = filename;

        document.body.appendChild(download_link);
        download_link.click();
        document.body.removeChild(download_link);
    }
};

const template = (string, content) => string.replace(/\[_(\d+)]/g, (s, index) => content[(+index) - 1]);

const isEmptyObject = (obj) => {
    let is_empty = true;
    if (obj && obj instanceof Object) {
        Object.keys(obj).forEach((key) => {
            if (obj.hasOwnProperty(key)) is_empty = false;
        });
    }
    return is_empty;
};

const cloneObject = obj => (!isEmptyObject(obj) ? $.extend(true, Array.isArray(obj) ? [] : {}, obj) : obj);

const getPropertyValue = (obj, keys) => {
    if (!Array.isArray(keys)) keys = [keys];
    if (!isEmptyObject(obj) && keys[0] in obj && keys && keys.length > 1) {
        return getPropertyValue(obj[keys[0]], keys.slice(1));
    }
    // else return clone of object to avoid overwriting data
    return obj ? cloneObject(obj[keys[0]]) : undefined;
};

const handleHash = () => {
    const hash = window.location.hash;
    if (hash) {
        $(`a[href="${hash}"]`).click();
    }
};

const clearable = (element) => {
    element.addClass('clear');
    $(document).on('mousemove', '.clear', function(e) {
        e.stopPropagation();
        $(e.currentTarget)[toggleAddRemoveClass(this.offsetWidth - 18 < e.clientX - this.getBoundingClientRect().left)]('onClear');
    }).on('mousedown', '.onClear', function(e) {
        e.stopPropagation();
        $(e.currentTarget).attr('data-value', '');
        $(e.currentTarget).removeClass('clear onClear').val('').change();
    });
};

const toggleAddRemoveClass = condition => (condition ? 'addClass' : 'removeClass');

module.exports = {
    showLoadingImage: showLoadingImage,
    getHighestZIndex: getHighestZIndex,
    downloadCSV     : downloadCSV,
    template        : template,
    isEmptyObject   : isEmptyObject,
    getPropertyValue: getPropertyValue,
    handleHash      : handleHash,
    clearable       : clearable,
};
<commit_msg>Refactor the function<commit_after>/**
 * Write loading image to a container for ajax request
 *
 * @param $container: a jQuery object
 * @param theme: dark or white
 */
const showLoadingImage = ($container, theme = 'dark') => {
    $container.html($('<div/>', {
        class: `barspinner ${theme}`,
        html : Array.from(new Array(5)).map((x, i) => `<div class="rect${i + 1}"></div>`).join(''),
    }));
};

/**
 * Returns the highest z-index in the page.
 * Accepts a jquery style selector to only check those elements,
 * uses all container tags by default
 * If no element found, returns null.
 *
 * @param selector: a jquery style selector for target elements
 * @return int|null
 */
const getHighestZIndex = (selector) => {
    if (!selector) {
        selector = 'div,p,area,nav,section,header,canvas,aside,span';
    }
    const all = [];
    const _store_zindex = function() {
        if ($(this).is(':visible')) {
            const z = $(this).css('z-index');
            if (!isNaN(z)) {
                all.push(z);
            }
        }
    };
    $(selector).each(_store_zindex);

    return all.length ? Math.max(...all) : null;
};

const downloadCSV = (csv_contents, filename) => {
    filename = filename || 'data.csv';
    if (navigator.msSaveBlob) { // IE 10+
        navigator.msSaveBlob(new Blob([csv_contents], { type: 'text/csv;charset=utf-8;' }), filename);
    } else { // Other browsers
        const csv = `data:text/csv;charset=utf-8,${csv_contents}`;
        const download_link = document.createElement('a');
        download_link.href = encodeURI(csv);
        download_link.download = filename;

        document.body.appendChild(download_link);
        download_link.click();
        document.body.removeChild(download_link);
    }
};

const template = (string, content) => string.replace(/\[_(\d+)]/g, (s, index) => content[(+index) - 1]);

const isEmptyObject = (obj) => {
    let is_empty = true;
    if (obj && obj instanceof Object) {
        Object.keys(obj).forEach((key) => {
            if (obj.hasOwnProperty(key)) is_empty = false;
        });
    }
    return is_empty;
};

const cloneObject = obj => (!isEmptyObject(obj) ? $.extend(true, Array.isArray(obj) ? [] : {}, obj) : obj);

const getPropertyValue = (obj, keys) => {
    if (!Array.isArray(keys)) keys = [keys];
    if (!isEmptyObject(obj) && keys[0] in obj && keys && keys.length > 1) {
        return getPropertyValue(obj[keys[0]], keys.slice(1));
    }
    // else return clone of object to avoid overwriting data
    return obj ? cloneObject(obj[keys[0]]) : undefined;
};

const handleHash = () => {
    const hash = window.location.hash;
    if (hash) {
        $(`a[href="${hash}"]`).click();
    }
};

const clearable = (element) => {
    element.addClass('clear');
    $(document).on('mousemove', '.clear', function(e) {
        e.stopPropagation();
        $(e.currentTarget)[toggleAddRemoveClass(this.offsetWidth - 18 < e.clientX - this.getBoundingClientRect().left)]('onClear');
    }).on('mousedown', '.onClear', function(e) {
        e.stopPropagation();
        $(e.currentTarget).attr('data-value', '');
        $(e.currentTarget).removeClass('clear onClear').val('').change();
    });
};

const toggleAddRemoveClass = condition => (condition ? 'addClass' : 'removeClass');

module.exports = {
    showLoadingImage: showLoadingImage,
    getHighestZIndex: getHighestZIndex,
    downloadCSV     : downloadCSV,
    template        : template,
    isEmptyObject   : isEmptyObject,
    getPropertyValue: getPropertyValue,
    handleHash      : handleHash,
    clearable       : clearable,
};
<|endoftext|>


<commit_before>var client_form;
onLoad.queue(function() {
    client_form = new ClientForm({valid_loginids: page.settings.get('valid_loginids')});
});

var select_user_country = function() {
    if ($('#residence').length > 0) {
        var selected_country = $('#residence').val();
        var c_config = page.settings.get('countries_list');
        if (selected_country.length > 0) {
            if (c_config[selected_country]['gaming_company'] == 'none' && c_config[selected_country]['financial_company'] == 'none') {
                selected_country = '';
            }
            $('#residence').val(selected_country).change();
        } else {
            $.ajax({
                crossDomain: true,
                url: page.url.url_for('country'),
                async: true,
                dataType: "json"
            }).done(function(response) {
                selected_country = response.country;
                if (c_config[selected_country]['gaming_company'] == 'none' && c_config[selected_country]['financial_company'] == 'none') {
                    selected_country = '';
                }
                $('#residence').val(selected_country).change();
            });
        }
    }
};

var disable_residence = function () {
    var vr_residence = page.client.residence;
    if (vr_residence.length > 0 && vr_residence == $('#residence').val()) {
        $('#residence').attr('disabled', true);
    }
};

var enable_residence_form_submit = function () {
    $('form#openAccForm').submit(function (event) {
        var field_error = false;
        $("form#openAccForm").find('p.errorfield:visible').each(function() {
            if ($(this).text().length > 0) {
                field_error = true;
                return false;
            }
        });
        if (!field_error) {
            $('#residence').removeAttr('disabled');
        }
    });
};

pjax_config_page('new_account/real', function() {
    return {
        onLoad: function() {
            client_form.on_residence_change();
            select_user_country();
            disable_residence();
            enable_residence_form_submit();
            if (page.client.is_logged_in) {
                client_form.set_virtual_email_id(page.client.email);
            }
        }
    };
});

var upgrade_investment_disabled_field = function () {
    if (page.client.is_real) {
        var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
        fields.forEach(function (element, index, array) {
            var obj = $('#'+element);
            if (obj.length > 0) {
                $('#'+element).attr('disabled', true);
            }
        });
    } else {
        $('#residence').attr('disabled', true);
    }
};

var financial_enable_fields_form_submit = function () {
    $('form#openAccForm').submit(function (event) {
        var field_error = false;
        $("form#openAccForm").find('p.errorfield:visible').each(function() {
            if ($(this).text().length > 0) {
                field_error = true;
                return false;
            }
        });
        if (field_error) {
            return;
        }

        if (page.client.is_real) {
            var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
            fields.forEach(function (element, index, array) {
                var obj = $('#'+element);
                if (obj.length > 0) {
                    obj.removeAttr('disabled');
                }
            });
        } else {
            $('#residence').removeAttr('disabled');
        }
    });
};

var hide_account_opening_for_risk_disclaimer = function () {
    var risk_section = $('#risk_disclaimer_section');
    if (risk_section.length > 0) {
        $('.formObject fieldset').not("#risk_disclaimer_section").hide();
    }
};

pjax_config_page('new_account/maltainvest', function() {
    return {
        onLoad: function() {
            if (!page.client.is_real) {
                client_form.on_residence_change();
                select_user_country();
            }
            upgrade_investment_disabled_field();
            financial_enable_fields_form_submit();
            hide_account_opening_for_risk_disclaimer();
        }
    };
});

pjax_config_page('user/assessment', function() {
    return {
        onLoad: function() {
            hide_account_opening_for_risk_disclaimer();
        }
    };
});
<commit_msg>toggle hedging assets visibility<commit_after>var client_form;
onLoad.queue(function() {
    client_form = new ClientForm({valid_loginids: page.settings.get('valid_loginids')});
});

var select_user_country = function() {
    if ($('#residence').length > 0) {
        var selected_country = $('#residence').val();
        var c_config = page.settings.get('countries_list');
        if (selected_country.length > 0) {
            if (c_config[selected_country]['gaming_company'] == 'none' && c_config[selected_country]['financial_company'] == 'none') {
                selected_country = '';
            }
            $('#residence').val(selected_country).change();
        } else {
            $.ajax({
                crossDomain: true,
                url: page.url.url_for('country'),
                async: true,
                dataType: "json"
            }).done(function(response) {
                selected_country = response.country;
                if (c_config[selected_country]['gaming_company'] == 'none' && c_config[selected_country]['financial_company'] == 'none') {
                    selected_country = '';
                }
                $('#residence').val(selected_country).change();
            });
        }
    }
};

var disable_residence = function () {
    var vr_residence = page.client.residence;
    if (vr_residence.length > 0 && vr_residence == $('#residence').val()) {
        $('#residence').attr('disabled', true);
    }
};

var enable_residence_form_submit = function () {
    $('form#openAccForm').submit(function (event) {
        var field_error = false;
        $("form#openAccForm").find('p.errorfield:visible').each(function() {
            if ($(this).text().length > 0) {
                field_error = true;
                return false;
            }
        });
        if (!field_error) {
            $('#residence').removeAttr('disabled');
        }
    });
};

pjax_config_page('new_account/real', function() {
    return {
        onLoad: function() {
            client_form.on_residence_change();
            select_user_country();
            disable_residence();
            enable_residence_form_submit();
            if (page.client.is_logged_in) {
                client_form.set_virtual_email_id(page.client.email);
            }
        }
    };
});

var upgrade_investment_disabled_field = function () {
    if (page.client.is_real) {
        var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
        fields.forEach(function (element, index, array) {
            var obj = $('#'+element);
            if (obj.length > 0) {
                $('#'+element).attr('disabled', true);
            }
        });
    } else {
        $('#residence').attr('disabled', true);
    }
};

var financial_enable_fields_form_submit = function () {
    $('form#openAccForm').submit(function (event) {
        var field_error = false;
        $("form#openAccForm").find('p.errorfield:visible').each(function() {
            if ($(this).text().length > 0) {
                field_error = true;
                return false;
            }
        });
        if (field_error) {
            return;
        }

        if (page.client.is_real) {
            var fields = ['mrms', 'fname', 'lname', 'dobdd', 'dobmm', 'dobyy', 'residence', 'secretquestion', 'secretanswer'];
            fields.forEach(function (element, index, array) {
                var obj = $('#'+element);
                if (obj.length > 0) {
                    obj.removeAttr('disabled');
                }
            });
        } else {
            $('#residence').removeAttr('disabled');
        }
    });
};

var hide_account_opening_for_risk_disclaimer = function () {
    var risk_section = $('#risk_disclaimer_section');
    if (risk_section.length > 0) {
        $('.formObject fieldset').not("#risk_disclaimer_section").hide();
    }
};

var toggle_hedging_assets = function() {
    var trading_purpose = $('#trading_purpose');
    var hedging_assets_fields = $('.hedging_assets');

    if (trading_purpose.val() === 'Hedging') {
        hedging_assets_fields.show();
    } else {
        hedging_assets_fields.hide();
    }
};

pjax_config_page('new_account/maltainvest', function() {
    return {
        onLoad: function() {
            if (!page.client.is_real) {
                client_form.on_residence_change();
                select_user_country();
            }
            upgrade_investment_disabled_field();
            financial_enable_fields_form_submit();
            hide_account_opening_for_risk_disclaimer();
        }
    };
});

pjax_config_page('new_account/japan', function() {
    return {
        onLoad: function() {
            toggle_hedging_assets();
            $('#trading_purpose').on('change', function() {
                toggle_hedging_assets();
            });
        }
    };
});

pjax_config_page('user/assessment', function() {
    return {
        onLoad: function() {
            hide_account_opening_for_risk_disclaimer();
        }
    };
});
<|endoftext|>


<commit_before>(function() {
    // Get application context
    var app = Sammy.apps['#main'];
    var store = app.store;

    /**
     * Backup
     *
     */

    var config_hooks = [
        'system_ldap',
        'system_ssowat',
        'system_cron',
        'system_ssh',
        'system_xmpp',
        'system_mysql',
        'system_yunohost',
        'system_nginx'
    ];
    // Storage list
    app.get('#/backup', function (c) {
        var storages = [];
        var item = {
                id: 'local',
                name: y18n.t('local_archives'),
                uri: '/home/yunohost.backup/'
            };
        storages.push(item);

        c.view('backup/backup', {'storages':storages});
    });

    // Storage list
    app.get('#/storages/create', function (c) {
        c.view('backup/storage_create', {});
    });

    // Create a storage
    app.post('#/storages', function (c) {
        store.clear('slide');
        c.redirect('#/storages');
    });

    // Create a backup
    app.get('#/backup/:storage/create', function (c) {
        var data=[];
        data['storage']={
            id:c.params['storage'],
            name:y18n.t('local_archives')
        };
        c.api('/hooks/backup', function(hooks) {
            data['hooks']=c.groupHooks(hooks['hooks']);
            data['apps']={};
            c.api('/apps?with_backup', function(apps_list) {
                data['apps'] = apps_list.apps;
                c.view('backup/backup_create', data);
            });
        });
    });

    app.post('#/backup/:storage', function (c) {
        var params = c.ungroupHooks(c.params['hooks'],c.params['apps']);
        c.api('/backup', function() {
            store.clear('slide');
            c.redirect('#/backup/'+ c.params['storage']);
        }, 'POST', params);
    });

    // Restore a backup
    app.post('#/backup/:storage/:archive/restore', function (c) {
        c.confirm(
            y18n.t('backup'),
            y18n.t('confirm_restore', [c.params['archive']]),
            $.proxy(function(c){
                var params=c.ungroupHooks(c.params['hooks'],c.params['apps']);
                params['force']='';
                c.api('/backup/restore/'+c.params['archive'], function(data) {
                    store.clear('slide');
                    c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
                }, 'POST', params);
            },this,c),
            function(){
                store.clear('slide');
                c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
            }
        );
    });

    // Delete a backup
    app.get('#/backup/:storage/:archive/delete', function (c) {
        c.confirm(
            y18n.t('backup'),
            y18n.t('confirm_delete', [c.params['archive']]),
            function(){
                c.api('/backup/archives/'+c.params['archive'], function(data) {
                    c.redirect('#/backup/'+ c.params['storage']);
                }, 'DELETE');
            },
            function(){
                store.clear('slide');
                c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
            }
        );
    });

    // Download a backup
    app.get('#/backup/:storage/:archive/download', function (c) {
        c.api('/backup/'+c.params['archive']+'/download', function(data) {
            c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
        }, 'GET');
    });

    // Copy a backup
    app.get('#/backup/:storage/:archive/copy', function (c) {
        store.clear('slide');
        c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
    });

    // Upload a backup
    app.get('#/backup/:storage/:archive/upload', function (c) {
        store.clear('slide');
        c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
    });

    // Get archive info
    app.get('#/backup/:storage/:archive', function (c) {
        c.api('/backup/archives/'+c.params['archive']+'?with_details', function(data) {
            data['storage']={
                id:c.params['storage'],
                name:y18n.t('local_archives')
            };
            data['other_storages']=[];
            data['name']=c.params['archive'];
            data['hooks']=c.groupHooks(Object.keys(data['hooks']));
            data['items']=(data['hooks']!={} || data['apps']!=[]);
            c.view('backup/backup_info', data);
        });
    });

    // Archive list
    app.get('#/backup/:storage', function (c) {
        c.api('/backup/archives?with_info', function(data) {
            data['storage']={
                id:'local',
                name:y18n.t('local_archives')
            };
            data['archives2']=[];
            $.each(data['archives'], function(name, info) {
                info['name']=name;
                data['archives2'].unshift(info)
            });
            data['archives']=data['archives2'];
            c.view('backup/backup_list', data);
        });
    });

})();<commit_msg>[fix] 'hooks' key is now 'system' in backup info (#165)<commit_after>(function() {
    // Get application context
    var app = Sammy.apps['#main'];
    var store = app.store;

    /**
     * Backup
     *
     */

    var config_hooks = [
        'system_ldap',
        'system_ssowat',
        'system_cron',
        'system_ssh',
        'system_xmpp',
        'system_mysql',
        'system_yunohost',
        'system_nginx'
    ];
    // Storage list
    app.get('#/backup', function (c) {
        var storages = [];
        var item = {
                id: 'local',
                name: y18n.t('local_archives'),
                uri: '/home/yunohost.backup/'
            };
        storages.push(item);

        c.view('backup/backup', {'storages':storages});
    });

    // Storage list
    app.get('#/storages/create', function (c) {
        c.view('backup/storage_create', {});
    });

    // Create a storage
    app.post('#/storages', function (c) {
        store.clear('slide');
        c.redirect('#/storages');
    });

    // Create a backup
    app.get('#/backup/:storage/create', function (c) {
        var data=[];
        data['storage']={
            id:c.params['storage'],
            name:y18n.t('local_archives')
        };
        c.api('/hooks/backup', function(hooks) {
            data['hooks']=c.groupHooks(hooks['hooks']);
            data['apps']={};
            c.api('/apps?with_backup', function(apps_list) {
                data['apps'] = apps_list.apps;
                c.view('backup/backup_create', data);
            });
        });
    });

    app.post('#/backup/:storage', function (c) {
        var params = c.ungroupHooks(c.params['hooks'],c.params['apps']);
        c.api('/backup', function() {
            store.clear('slide');
            c.redirect('#/backup/'+ c.params['storage']);
        }, 'POST', params);
    });

    // Restore a backup
    app.post('#/backup/:storage/:archive/restore', function (c) {
        c.confirm(
            y18n.t('backup'),
            y18n.t('confirm_restore', [c.params['archive']]),
            $.proxy(function(c){
                var params=c.ungroupHooks(c.params['hooks'],c.params['apps']);
                params['force']='';
                c.api('/backup/restore/'+c.params['archive'], function(data) {
                    store.clear('slide');
                    c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
                }, 'POST', params);
            },this,c),
            function(){
                store.clear('slide');
                c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
            }
        );
    });

    // Delete a backup
    app.get('#/backup/:storage/:archive/delete', function (c) {
        c.confirm(
            y18n.t('backup'),
            y18n.t('confirm_delete', [c.params['archive']]),
            function(){
                c.api('/backup/archives/'+c.params['archive'], function(data) {
                    c.redirect('#/backup/'+ c.params['storage']);
                }, 'DELETE');
            },
            function(){
                store.clear('slide');
                c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
            }
        );
    });

    // Download a backup
    app.get('#/backup/:storage/:archive/download', function (c) {
        c.api('/backup/'+c.params['archive']+'/download', function(data) {
            c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
        }, 'GET');
    });

    // Copy a backup
    app.get('#/backup/:storage/:archive/copy', function (c) {
        store.clear('slide');
        c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
    });

    // Upload a backup
    app.get('#/backup/:storage/:archive/upload', function (c) {
        store.clear('slide');
        c.redirect('#/backup/'+ c.params['storage']+'/'+c.params['archive']);
    });

    // Get archive info
    app.get('#/backup/:storage/:archive', function (c) {
        c.api('/backup/archives/'+c.params['archive']+'?with_details', function(data) {
            data['storage']={
                id:c.params['storage'],
                name:y18n.t('local_archives')
            };
            data['other_storages']=[];
            data['name']=c.params['archive'];
            data['hooks']=c.groupHooks(Object.keys(data['system']));
            data['items']=(data['hooks']!={} || data['apps']!=[]);
            c.view('backup/backup_info', data);
        });
    });

    // Archive list
    app.get('#/backup/:storage', function (c) {
        c.api('/backup/archives?with_info', function(data) {
            data['storage']={
                id:'local',
                name:y18n.t('local_archives')
            };
            data['archives2']=[];
            $.each(data['archives'], function(name, info) {
                info['name']=name;
                data['archives2'].unshift(info)
            });
            data['archives']=data['archives2'];
            c.view('backup/backup_list', data);
        });
    });

})();
<|endoftext|>