<commit_before>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems                */
/*                                                                            */
/* 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.                                             */
/* -------------------------------------------------------------------------- */

define(function(require) {
  /*
    DEPENDENCIES
   */

  var Locale = require('utils/locale');
  var Tips = require('utils/tips');
  var CapacityInputs = require('./general/capacity-inputs');
  var WizardFields = require('utils/wizard-fields');
  var Config = require('sunstone-config');

  /*
    TEMPLATES
   */

  var TemplateHTML = require('hbs!./general/html');

  /*
    CONSTANTS
   */

  var WIZARD_TAB_ID = require('./general/wizardTabId');

  /*
    CONSTRUCTOR
   */

  function WizardTab() {
    this.wizardTabId = WIZARD_TAB_ID;
    this.icon = 'fa-laptop';
    this.title = Locale.tr("General");
  }

  WizardTab.prototype.constructor = WizardTab;
  WizardTab.prototype.html = _html;
  WizardTab.prototype.setup = _setup;
  WizardTab.prototype.onShow = _onShow;
  WizardTab.prototype.retrieve = _retrieve;
  WizardTab.prototype.fill = _fill;

  return WizardTab;

  /*
    FUNCTION DEFINITIONS
   */

  function _html() {
    return TemplateHTML({
      'capacityInputsHTML': CapacityInputs.html(),
      'logos': Config.vmLogos
    });
  }

  function _onShow(context, panelForm) {
    if (panelForm.action == 'create') {
      $('#template_name_form', context).show();
      $('#template_hypervisor_form', context).removeClass("left");
      $('#NAME', context).removeAttr('disabled');
      $('#NAME', context).attr("required", "");
    } else if (panelForm.action == 'update') {
      $('#template_name_form', context).hide();
      $('#template_hypervisor_form', context).addClass("left");
      $('#NAME', context).attr("disabled", "disabled");
      $('#NAME', context).removeAttr("required");
    }

    context.foundation('slider', 'reflow');
  }

  function _setup(context) {
    $(document).on('click', "[href='#" + this.wizardTabId + "']", function(){
      context.foundation('slider', 'reflow');
    });

    context.on("change", "#LOGO", function() {
      $("#template_create_logo", context).show();
      $("#template_create_logo", context).html('' +
          '' +
        '');
    });

    context.on("change", "input[name='hypervisor']", function() {
      // TODO define context (for example: this.closest('form'))
      $(".hypervisor").hide();
      $(".only_" + this.value).show();

      // There is another listener in context.js setup
    });

    CapacityInputs.setup(context);
  }

  function _retrieve(context) {
    var templateJSON = WizardFields.retrieve(context);

    if (templateJSON["HYPERVISOR"] == 'vcenter') {
      templateJSON["VCENTER_PUBLIC_CLOUD"] = {
        'TYPE': 'vcenter',
        'VM_TEMPLATE': $("#vcenter_template_uuid", context).val()
      };

      templateJSON["KEEP_DISKS_ON_DONE"] = $("#KEEP_DISKS", context).is(':checked')?"YES":"NO"
    }

    var sunstone_template = {};
    if ($('#sunstone_capacity_select:checked', context).length > 0) {
      sunstone_template["CAPACITY_SELECT"] = "NO"
    }

    if ($('#sunstone_network_select:checked', context).length > 0) {
      sunstone_template["NETWORK_SELECT"] = "NO"
    }

    if (!$.isEmptyObject(sunstone_template)) {
      templateJSON['SUNSTONE'] = sunstone_template;
    }

    return templateJSON;
  }

  function _fill(context, templateJSON) {
    var sunstone_template = templateJSON.SUNSTONE;
    if (sunstone_template &&
        sunstone_template["CAPACITY_SELECT"] &&
        sunstone_template["CAPACITY_SELECT"].toUpperCase() == "NO") {
      $("#sunstone_capacity_select", context).attr("checked", "checked");
    }

    delete sunstone_template["CAPACITY_SELECT"];

    if (sunstone_template &&
        sunstone_template["NETWORK_SELECT"] &&
        sunstone_template["NETWORK_SELECT"].toUpperCase() == "NO") {
      $("#sunstone_network_select", context).attr("checked", "checked");
    }

    delete sunstone_template["NETWORK_SELECT"];

    if (templateJSON["HYPERVISOR"] == 'vcenter' &&
      templateJSON["KEEP_DISKS_ON_DONE"] &&
        templateJSON["KEEP_DISKS_ON_DONE"].toLowerCase() == "yes" ) {
      $("#KEEP_DISKS", context).attr("checked", "checked");
    }

    delete templateJSON["KEEP_DISKS_ON_DONE"];

    if (templateJSON["HYPERVISOR"] == 'vcenter') {
      var publicClouds = templateJSON["PUBLIC_CLOUD"];

      if (publicClouds != undefined) {
        if (!$.isArray(publicClouds)){
          publicClouds = [publicClouds];
        }

        $.each(publicClouds, function(){
          if(this["TYPE"] == "vcenter"){
            $("#vcenter_template_uuid", context).val(this["VM_TEMPLATE"]);
            return false;
          }
        });
      }
    }

    if (templateJSON["HYPERVISOR"]) {
      $("input[name='hypervisor'][value='"+templateJSON["HYPERVISOR"]+"']", context).trigger("click")
      delete templateJSON["HYPERVISOR"];
    }

    WizardFields.fill(context, templateJSON);
  }
});
<commit_msg>feature #3671: Check if SUNSTONE vector is defined in the VM template<commit_after>/* -------------------------------------------------------------------------- */
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems                */
/*                                                                            */
/* 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.                                             */
/* -------------------------------------------------------------------------- */

define(function(require) {
  /*
    DEPENDENCIES
   */

  var Locale = require('utils/locale');
  var Tips = require('utils/tips');
  var CapacityInputs = require('./general/capacity-inputs');
  var WizardFields = require('utils/wizard-fields');
  var Config = require('sunstone-config');

  /*
    TEMPLATES
   */

  var TemplateHTML = require('hbs!./general/html');

  /*
    CONSTANTS
   */

  var WIZARD_TAB_ID = require('./general/wizardTabId');

  /*
    CONSTRUCTOR
   */

  function WizardTab() {
    this.wizardTabId = WIZARD_TAB_ID;
    this.icon = 'fa-laptop';
    this.title = Locale.tr("General");
  }

  WizardTab.prototype.constructor = WizardTab;
  WizardTab.prototype.html = _html;
  WizardTab.prototype.setup = _setup;
  WizardTab.prototype.onShow = _onShow;
  WizardTab.prototype.retrieve = _retrieve;
  WizardTab.prototype.fill = _fill;

  return WizardTab;

  /*
    FUNCTION DEFINITIONS
   */

  function _html() {
    return TemplateHTML({
      'capacityInputsHTML': CapacityInputs.html(),
      'logos': Config.vmLogos
    });
  }

  function _onShow(context, panelForm) {
    if (panelForm.action == 'create') {
      $('#template_name_form', context).show();
      $('#template_hypervisor_form', context).removeClass("left");
      $('#NAME', context).removeAttr('disabled');
      $('#NAME', context).attr("required", "");
    } else if (panelForm.action == 'update') {
      $('#template_name_form', context).hide();
      $('#template_hypervisor_form', context).addClass("left");
      $('#NAME', context).attr("disabled", "disabled");
      $('#NAME', context).removeAttr("required");
    }

    context.foundation('slider', 'reflow');
  }

  function _setup(context) {
    $(document).on('click', "[href='#" + this.wizardTabId + "']", function(){
      context.foundation('slider', 'reflow');
    });

    context.on("change", "#LOGO", function() {
      $("#template_create_logo", context).show();
      $("#template_create_logo", context).html('' +
          '' +
        '');
    });

    context.on("change", "input[name='hypervisor']", function() {
      // TODO define context (for example: this.closest('form'))
      $(".hypervisor").hide();
      $(".only_" + this.value).show();

      // There is another listener in context.js setup
    });

    CapacityInputs.setup(context);
  }

  function _retrieve(context) {
    var templateJSON = WizardFields.retrieve(context);

    if (templateJSON["HYPERVISOR"] == 'vcenter') {
      templateJSON["VCENTER_PUBLIC_CLOUD"] = {
        'TYPE': 'vcenter',
        'VM_TEMPLATE': $("#vcenter_template_uuid", context).val()
      };

      templateJSON["KEEP_DISKS_ON_DONE"] = $("#KEEP_DISKS", context).is(':checked')?"YES":"NO"
    }

    var sunstone_template = {};
    if ($('#sunstone_capacity_select:checked', context).length > 0) {
      sunstone_template["CAPACITY_SELECT"] = "NO"
    }

    if ($('#sunstone_network_select:checked', context).length > 0) {
      sunstone_template["NETWORK_SELECT"] = "NO"
    }

    if (!$.isEmptyObject(sunstone_template)) {
      templateJSON['SUNSTONE'] = sunstone_template;
    }

    return templateJSON;
  }

  function _fill(context, templateJSON) {
    var sunstone_template = templateJSON.SUNSTONE;
    if (sunstone_template) {
      if (sunstone_template["CAPACITY_SELECT"] &&
          sunstone_template["CAPACITY_SELECT"].toUpperCase() == "NO") {
        $("#sunstone_capacity_select", context).attr("checked", "checked");
      }

      delete sunstone_template["CAPACITY_SELECT"];

      if (sunstone_template["NETWORK_SELECT"] &&
          sunstone_template["NETWORK_SELECT"].toUpperCase() == "NO") {
        $("#sunstone_network_select", context).attr("checked", "checked");
      }

      delete sunstone_template["NETWORK_SELECT"];
    }

    if (templateJSON["HYPERVISOR"] == 'vcenter' &&
      templateJSON["KEEP_DISKS_ON_DONE"] &&
        templateJSON["KEEP_DISKS_ON_DONE"].toLowerCase() == "yes" ) {
      $("#KEEP_DISKS", context).attr("checked", "checked");
    }

    delete templateJSON["KEEP_DISKS_ON_DONE"];

    if (templateJSON["HYPERVISOR"] == 'vcenter') {
      var publicClouds = templateJSON["PUBLIC_CLOUD"];

      if (publicClouds != undefined) {
        if (!$.isArray(publicClouds)){
          publicClouds = [publicClouds];
        }

        $.each(publicClouds, function(){
          if(this["TYPE"] == "vcenter"){
            $("#vcenter_template_uuid", context).val(this["VM_TEMPLATE"]);
            return false;
          }
        });
      }
    }

    if (templateJSON["HYPERVISOR"]) {
      $("input[name='hypervisor'][value='"+templateJSON["HYPERVISOR"]+"']", context).trigger("click")
      delete templateJSON["HYPERVISOR"];
    }

    WizardFields.fill(context, templateJSON);
  }
});
<|endoftext|>


<commit_before>var path = require('path');
var fs = require('fs');
var _ = require('lodash');
var util = require('util');

/**
   generate namespace automatically, first by trying to read the name attribute from your `package.json` file,
	 if the name includes '-' it takes the first letter of each separated word, otherwise it will just take the first ? 3 letters.
	 If for some reason the name could be generated from `package.json` file, the name space will be 'APP'.
 */
function getNamespace() {
	var ns = '';
	var fileExists = fs.existsSync(path.dirname(require.main.filename) + '/package.json');
	if(fileExists) {
		var projectName = require(path.dirname(require.main.filename) + '/package.json').name;
		if(projectName.indexOf('-') !== -1) {
			var splitName = projectName.split('-');
			var len = splitName.length >= 3 ? 3 : splitName.length;
			for(var i = 0; i < len; i++) {
					ns += splitName[i][0];
			}
		}
		else {
			ns = projectName.slice(0, 3);
		}
	}
	else {
		ns = 'app'
	}
	return ns.toUpperCase();
}
/**
 * The name that will prefix the unique errorCode. the namespace should be 3 chars long and uppercase.
 * @private
 */
var namespace;
/**
 * An object that define possible errors and their related message.
 * @private
 */
var	errorsMap;
/**
 * A character for separating the error codes.
 * @private
 */
var	errorDelimiter;
/**
 * A character for separating the errors messages.
 * @private
 */
var	messageDelimiter;
/**
 * A boolean. filter duplicate codes from the response errorCode
 * @private
 */
var	distinctCodes;
/**
 * An object for storing the current added errors.
 * @private
 */
var	errorsLog;
/**
 * The current http status code.
 * @private
 */
var	currentStatus;

/**
 * The Error Coder Object.
 * @constructor
 * @param  {Object} errsMap.
 * @param  {Object} options set of configuration options.
 */
function ErrorCoder(errsMap, options) {

	namespace = (options && options.namespace) ? options.namespace : getNamespace();
	errorsMap = errsMap;
	errorDelimiter = (options && options.errorDelimiter) ? options.errorDelimiter : '_';
	messageDelimiter = (options && options.messageDelimiter) ? options.messageDelimiter : '
';
	distinctCodes = (options && options.distinctCodes) ? options.distinctCodes : false;
	errorsLog = {};
	currentStatus = 0;

	// validations
	if(_.isUndefined(errorsMap)) {
		throw new Error('errorsMap is required');
	}
	if(!_.isObject(errorsMap)) {
		throw new Error('errorsMap should be an object');
	}
	if(!_.isString(namespace)) {
		throw new Error('namespace should be a string');
	}
	if(!_.isString(errorDelimiter)) {
		throw new Error('error delimiter should be a string');
	}
	if(!_.isString(messageDelimiter)) {
		throw new Error('message delimiter should be a string');
	}

	// enforce namespace standard
	namespace = namespace.slice(0,3).toUpperCase();

}
/**
 * Sets new status code.
 * @param  {Number} status - the actual status code of the http response.
 * @return {ErrorCoder} the current ErrorCoder instance
 */
ErrorCoder.prototype.setStatus = function(status) {
	if(_.isUndefined(status)) {
		throw new Error('status code is required');
	}
	if(!_.isNumber(status) || _.isNaN(status) || (_.isNumber(status) && !_.inRange(status, 100, 600))) {
		throw new Error('status code should be a valid http status code according to http specification, RFC 2616 section 6.1.1');
	}
  if(_.isUndefined(errorsMap[status])) {
		throw new Error(util.format('status code "%s" is not defined in the errors map', status));
	}

	currentStatus = status;

	return this;
};
/**
 * Adds new child error to the current error object.
 * @param  {Number|String} errorCode.
 * @param  {...*} arguments optional error message variables.
 * @return {ErrorCoder} the current ErrorCoder instance
 */
ErrorCoder.prototype.add = function(errorCode) {

	if(_.isUndefined(errorCode)) {
		throw new Error('error code is required');
	}
	var hasMapEntry = !_.isUndefined(errorsMap[currentStatus][errorCode]);

	if(!hasMapEntry) {
		throw new Error(util.format('errors map Error: the status code property "%s" does not contain error code with the name "%s"', currentStatus, errorCode));
	}

	var msgArgs = [errorsMap[currentStatus][errorCode]];

	for(var i = 1, len = arguments.length; i < len; i++) {
		msgArgs.push(arguments[i]);
	}

	var msg = util.format.apply(this, msgArgs);

	if(!errorsLog.hasOwnProperty(currentStatus)) {
		errorsLog[currentStatus] = {
			status: currentStatus,
			errorCode: namespace + currentStatus + errorDelimiter + errorCode,
			errorMessages: msg + messageDelimiter
		}
	}
	else {
		errorsLog[currentStatus].errorCode += (errorDelimiter + errorCode);
		errorsLog[currentStatus].errorMessages += (msg + messageDelimiter);
	}

	return this;
};
/**
 * Sends the current errors
 * @param  {Object} [response] http.response or express.js response object.
 * @return {Object} returns either errors object or http.response (express.js or node.js native response
 * @api public
 */
ErrorCoder.prototype.send = function(response) {
	if(errorsLog[currentStatus]) {

		var errCode = errorsLog[currentStatus].errorCode;

		if(distinctCodes) {
			var errCodeArray = errCode.split(errorDelimiter);
			errCode = errCodeArray[0] + errorDelimiter + _.uniq(errCodeArray.slice(1)).join(errorDelimiter);
		}

		var resObj = {
			status: currentStatus,
			errorCode: errCode,
			errorMessages: errorsLog[currentStatus].errorMessages
		};

		if(response) {
			// express support
			if(response.status && response.json) {
				response.status(currentStatus).json(resObj);
			}
			// support node.js native response.
			else if(response.writeHead && response.end) {
				response.writeHead(currentStatus, {'Content-Type':'application/json'});
				var json = JSON.stringify(resObj);
				response.end(json);
			}
			// unsupported response object
			else {
				throw new Error('unsupported response object');
			}
		}
		// the caller will handle the response, so just send back the error object.
		else {
			return resObj;
		}
	}
};

/**
 * Get the current error map.
 * @return {Object} the errors map object
 */
ErrorCoder.prototype.getErrorsMap = function() {
	return errorsMap;
};

module.exports = ErrorCoder;
<commit_msg>reset error messages after send with response. bump minor version to 0.2.4<commit_after>var path = require('path');
var fs = require('fs');
var _ = require('lodash');
var util = require('util');

/**
   generate namespace automatically, first by trying to read the name attribute from your `package.json` file,
	 if the name includes '-' it takes the first letter of each separated word, otherwise it will just take the first ? 3 letters.
	 If for some reason the name could be generated from `package.json` file, the name space will be 'APP'.
 */
function getNamespace() {
	var ns = '';
	var fileExists = fs.existsSync(path.dirname(require.main.filename) + '/package.json');
	if(fileExists) {
		var projectName = require(path.dirname(require.main.filename) + '/package.json').name;
		if(projectName.indexOf('-') !== -1) {
			var splitName = projectName.split('-');
			var len = splitName.length >= 3 ? 3 : splitName.length;
			for(var i = 0; i < len; i++) {
					ns += splitName[i][0];
			}
		}
		else {
			ns = projectName.slice(0, 3);
		}
	}
	else {
		ns = 'app'
	}
	return ns.toUpperCase();
}
/**
 * The name that will prefix the unique errorCode. the namespace should be 3 chars long and uppercase.
 * @private
 */
var namespace;
/**
 * An object that define possible errors and their related message.
 * @private
 */
var	errorsMap;
/**
 * A character for separating the error codes.
 * @private
 */
var	errorDelimiter;
/**
 * A character for separating the errors messages.
 * @private
 */
var	messageDelimiter;
/**
 * A boolean. filter duplicate codes from the response errorCode
 * @private
 */
var	distinctCodes;
/**
 * An object for storing the current added errors.
 * @private
 */
var	errorsLog;
/**
 * The current http status code.
 * @private
 */
var	currentStatus;

/**
 * The Error Coder Object.
 * @constructor
 * @param  {Object} errsMap.
 * @param  {Object} options set of configuration options.
 */
function ErrorCoder(errsMap, options) {

	namespace = (options && options.namespace) ? options.namespace : getNamespace();
	errorsMap = errsMap;
	errorDelimiter = (options && options.errorDelimiter) ? options.errorDelimiter : '_';
	messageDelimiter = (options && options.messageDelimiter) ? options.messageDelimiter : '
';
	distinctCodes = (options && options.distinctCodes) ? options.distinctCodes : false;
	errorsLog = {};
	currentStatus = 0;

	// validations
	if(_.isUndefined(errorsMap)) {
		throw new Error('errorsMap is required');
	}
	if(!_.isObject(errorsMap)) {
		throw new Error('errorsMap should be an object');
	}
	if(!_.isString(namespace)) {
		throw new Error('namespace should be a string');
	}
	if(!_.isString(errorDelimiter)) {
		throw new Error('error delimiter should be a string');
	}
	if(!_.isString(messageDelimiter)) {
		throw new Error('message delimiter should be a string');
	}

	// enforce namespace standard
	namespace = namespace.slice(0,3).toUpperCase();

}
/**
 * Sets new status code.
 * @param  {Number} status - the actual status code of the http response.
 * @return {ErrorCoder} the current ErrorCoder instance
 */
ErrorCoder.prototype.setStatus = function(status) {
	if(_.isUndefined(status)) {
		throw new Error('status code is required');
	}
	if(!_.isNumber(status) || _.isNaN(status) || (_.isNumber(status) && !_.inRange(status, 100, 600))) {
		throw new Error('status code should be a valid http status code according to http specification, RFC 2616 section 6.1.1');
	}
  if(_.isUndefined(errorsMap[status])) {
		throw new Error(util.format('status code "%s" is not defined in the errors map', status));
	}

	currentStatus = status;

	return this;
};
/**
 * Adds new child error to the current error object.
 * @param  {Number|String} errorCode.
 * @param  {...*} arguments optional error message variables.
 * @return {ErrorCoder} the current ErrorCoder instance
 */
ErrorCoder.prototype.add = function(errorCode) {

	if(_.isUndefined(errorCode)) {
		throw new Error('error code is required');
	}
	var hasMapEntry = !_.isUndefined(errorsMap[currentStatus][errorCode]);

	if(!hasMapEntry) {
		throw new Error(util.format('errors map Error: the status code property "%s" does not contain error code with the name "%s"', currentStatus, errorCode));
	}

	var msgArgs = [errorsMap[currentStatus][errorCode]];

	for(var i = 1, len = arguments.length; i < len; i++) {
		msgArgs.push(arguments[i]);
	}

	var msg = util.format.apply(this, msgArgs);

	if(!errorsLog.hasOwnProperty(currentStatus)) {
		errorsLog[currentStatus] = {
			status: currentStatus,
			errorCode: namespace + currentStatus + errorDelimiter + errorCode,
			errorMessages: msg + messageDelimiter
		}
	}
	else {
		errorsLog[currentStatus].errorCode += (errorDelimiter + errorCode);
		errorsLog[currentStatus].errorMessages += (msg + messageDelimiter);
	}

	return this;
};
/**
 * Sends the current errors
 * @param  {Object} [response] http.response or express.js response object.
 * @return {Object} returns either errors object or http.response (express.js or node.js native response
 * @api public
 */
ErrorCoder.prototype.send = function(response) {
	if(errorsLog[currentStatus]) {

		var errCode = errorsLog[currentStatus].errorCode;

		if(distinctCodes) {
			var errCodeArray = errCode.split(errorDelimiter);
			errCode = errCodeArray[0] + errorDelimiter + _.uniq(errCodeArray.slice(1)).join(errorDelimiter);
		}

		var resObj = {
			status: currentStatus,
			errorCode: errCode,
			errorMessages: errorsLog[currentStatus].errorMessages
		};

		if(response) {
			// express support
			if(response.status && response.json) {
				response.status(currentStatus).json(resObj);
				errorsLog[currentStatus].errorMessages = '';
			}
			// support node.js native response.
			else if(response.writeHead && response.end) {
				response.writeHead(currentStatus, {'Content-Type':'application/json'});
				var json = JSON.stringify(resObj);
				response.end(json);
				errorsLog[currentStatus].errorMessages = '';
			}
			// unsupported response object
			else {
				throw new Error('unsupported response object');
			}
		}
		// the caller will handle the response, so just send back the error object.
		else {
			return resObj;
		}
	}
};

/**
 * Get the current error map.
 * @return {Object} the errors map object
 */
ErrorCoder.prototype.getErrorsMap = function() {
	return errorsMap;
};

module.exports = ErrorCoder;
<|endoftext|>


<commit_before>/**
 * The original intention of this module was to translate
 * using the Google Translate API, but it's a paid service.
 * Hence, this pale imitation.
 */
var jp = require( 'japanese' );

module.exports = {
	events: {
		message: function ( bot, nick, to, text ) {
			// http://stackoverflow.com/a/15034560/1875784
			if ( text.match( /[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf]/ ) ) {
				bot.shout( to, '\u000314' + jp.romanize( text ) );
			}
		}
	}
};

<commit_msg>Only spout Romaji when there is Romaji to spout<commit_after>/**
 * The original intention of this module was to translate
 * using the Google Translate API, but it's a paid service.
 * Hence, this pale imitation.
 */
var jp = require( 'japanese' );

module.exports = {
	events: {
		message: function ( bot, nick, to, text ) {
			// http://stackoverflow.com/a/15034560/1875784
			if ( text.match( /[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf]/ ) ) {
				var romaji = jp.romanize( text );
				if ( romaji ) {
					bot.shout( to, '\u000314' + romaji );
				}
			}
		}
	}
};

<|endoftext|>


<commit_before>
define([
    'flight/lib/component',
    '../withPopover',
    'service/vertex',
    'util/formatters',
    'configuration/plugins/visibility/visibilityEditor',
    'util/withFormFieldErrors'
], function(
    defineComponent,
    withPopover,
    VertexService,
    formatters,
    VisibilityEditor,
    withFormFieldErrors) {
    'use strict';

    return defineComponent(FileImport, withPopover, withFormFieldErrors);

    function FileImport() {

        var vertexService = new VertexService();

        this.defaultAttrs({
            importSelector: '.btn-primary',
            cancelSelector: '.btn-default',
            checkboxSelector: '.checkbox',
            visibilityInputSelector: '.visibility'
        });

        this.after('teardown', function() {
            if (this.request) {
                this.request.abort();
            }
        });

        this.before('initialize', function(node, config) {
            config.template = 'fileImport/template';
            config.rolledUp = [{
                name: config.files.length === 1 ?
                    config.files[0].name :
                    formatters.string.plural(config.files.length, 'file'),
                size: formatters.bytes.pretty(
                    _.chain(config.files)
                        .map(_.property('size'))
                        .reduce(function(memo, num) {
                            return memo + num;
                        }, 0)
                        .value()
                ),
                index: 'collapsed'
            }];
            config.multipleFiles = config.files.length > 1;
            config.formattedFiles = _.map(config.files, function(f, i) {
                return {
                    name: f.name,
                    size: formatters.bytes.pretty(f.size, 0),
                    index: i
                };
            })
            config.pluralString = formatters.string.plural(config.files.length, 'file');

            this.after('setupWithTemplate', function() {
                var self = this;

                this.visibilitySource = null;
                this.visibilitySources = new Array(config.files.length);

                this.on(this.popover, 'visibilitychange', this.onVisibilityChange);

                VisibilityEditor.attachTo(this.popover.find('.visibility'));

                this.on(this.popover, 'click', {
                    importSelector: this.onImport,
                    cancelSelector: this.onCancel
                });

                this.on(this.popover, 'change', {
                    checkboxSelector: this.onCheckboxCopy
                })

                this.on(this.popover, 'keyup', {
                    visibilityInputSelector: function(e) {
                        if ($(e.target).closest('.single').length &&
                            e.which === $.ui.keyCode.ENTER) {
                            this.onImport();
                        }
                    }
                })

                window.focus();
                _.defer(function() {
                    self.popover.find('.visibility input').focus();
                })
            })
        });

        this.onCheckboxCopy = function(e) {
            var $checkbox = $(e.target),
                checked = $checkbox.is(':checked');

            this.popover.toggleClass('collapseVisibility', checked);
            this.popover.find('.errors').empty();
            _.delay(this.positionDialog.bind(this), 50);
        };

        this.onVisibilityChange = function(event, data) {
            var index = $(event.target)
                .data('visibility', data)
                .data('fileIndex');

            if (index === 'collapsed') {
                this.visibilitySource = data;
            } else {
                this.visibilitySources[index] = data;
            }
        };

        this.checkValid = function() {
            var collapsed = this.isVisibilityCollapsed(),
                isValid = collapsed ?
                    (this.visibilitySource && this.visibilitySource.valid) :
                    _.every(this.visibilitySources, _.property('valid'));

            if (isValid) {
                this.popover.find('button').removeAttr('disabled');
            } else {
                this.popover.find('button').attr('disabled', true);
            }

            return isValid;
        };

        this.isVisibilityCollapsed = function() {
            return this.popover.find('.checkbox input').is(':checked');
        };

        this.onCancel = function() {
            this.teardown();
        };

        this.onImport = function() {
            if (!this.checkValid()) {
                return false;
            }

            var self = this,
                button = this.popover.find('.btn-primary')
                    .text('Importing...')
                    .attr('disabled', true),
                cancelButton = this.popover.find('.btn-default').show(),
                collapsed = this.isVisibilityCollapsed(),
                visibilityValue = collapsed ?
                    this.visibilitySource.value :
                    _.map(this.visibilitySources, _.property('value'));

            this.attr.teardownOnTap = false;

            this.request = vertexService.importFiles(this.attr.files, visibilityValue)
                .progress(function(complete) {
                    var percent = Math.round(complete * 100);
                    button.text(percent + '% Importing...');
                })
                .fail(function(xhr, m, error) {
                    self.attr.teardownOnTap = true;
                    self.markFieldErrors(error, self.popover);
                    cancelButton.hide();
                    button.text('Import')
                        .removeClass('loading')
                        .removeAttr('disabled')

                    _.defer(self.positionDialog.bind(self));
                })
                .done(function(result) {

                    vertexService.getMultiple(result.vertexIds)
                        .done(function(result) {
                            self.trigger('addVertices', {
                                vertices: result.vertices,
                                options: {
                                    fileDropPosition: self.attr.anchorTo.page
                                }
                            });

                            self.teardown();
                        });
                });
        }
    }
});
<commit_msg>Fix issue where importing 1 file wouldn't send visiblility<commit_after>
define([
    'flight/lib/component',
    '../withPopover',
    'service/vertex',
    'util/formatters',
    'configuration/plugins/visibility/visibilityEditor',
    'util/withFormFieldErrors'
], function(
    defineComponent,
    withPopover,
    VertexService,
    formatters,
    VisibilityEditor,
    withFormFieldErrors) {
    'use strict';

    return defineComponent(FileImport, withPopover, withFormFieldErrors);

    function FileImport() {

        var vertexService = new VertexService();

        this.defaultAttrs({
            importSelector: '.btn-primary',
            cancelSelector: '.btn-default',
            checkboxSelector: '.checkbox',
            visibilityInputSelector: '.visibility'
        });

        this.after('teardown', function() {
            if (this.request) {
                this.request.abort();
            }
        });

        this.before('initialize', function(node, config) {
            config.template = 'fileImport/template';
            config.rolledUp = [{
                name: config.files.length === 1 ?
                    config.files[0].name :
                    formatters.string.plural(config.files.length, 'file'),
                size: formatters.bytes.pretty(
                    _.chain(config.files)
                        .map(_.property('size'))
                        .reduce(function(memo, num) {
                            return memo + num;
                        }, 0)
                        .value()
                ),
                index: 'collapsed'
            }];
            config.multipleFiles = config.files.length > 1;
            config.formattedFiles = _.map(config.files, function(f, i) {
                return {
                    name: f.name,
                    size: formatters.bytes.pretty(f.size, 0),
                    index: i
                };
            })
            config.pluralString = formatters.string.plural(config.files.length, 'file');

            this.after('setupWithTemplate', function() {
                var self = this;

                this.visibilitySource = null;
                this.visibilitySources = new Array(config.files.length);

                this.on(this.popover, 'visibilitychange', this.onVisibilityChange);

                VisibilityEditor.attachTo(this.popover.find('.visibility'));

                this.on(this.popover, 'click', {
                    importSelector: this.onImport,
                    cancelSelector: this.onCancel
                });

                this.on(this.popover, 'change', {
                    checkboxSelector: this.onCheckboxCopy
                })

                this.on(this.popover, 'keyup', {
                    visibilityInputSelector: function(e) {
                        if ($(e.target).closest('.single').length &&
                            e.which === $.ui.keyCode.ENTER) {
                            this.onImport();
                        }
                    }
                })

                window.focus();
                _.defer(function() {
                    self.popover.find('.visibility input').focus();
                })
            })
        });

        this.onCheckboxCopy = function(e) {
            var $checkbox = $(e.target),
                checked = $checkbox.is(':checked');

            this.popover.toggleClass('collapseVisibility', checked);
            this.popover.find('.errors').empty();
            _.delay(this.positionDialog.bind(this), 50);
        };

        this.onVisibilityChange = function(event, data) {
            var index = $(event.target)
                .data('visibility', data)
                .data('fileIndex');

            if (index === 'collapsed') {
                this.visibilitySource = data;
            } else {
                this.visibilitySources[index] = data;
            }

            this.checkValid();
        };

        this.checkValid = function() {
            var collapsed = this.isVisibilityCollapsed(),
                isValid = collapsed ?
                    (this.visibilitySource && this.visibilitySource.valid) :
                    _.every(this.visibilitySources, _.property('valid'));

            if (isValid) {
                this.popover.find('button').removeAttr('disabled');
            } else {
                this.popover.find('button').attr('disabled', true);
            }

            return isValid;
        };

        this.isVisibilityCollapsed = function() {
            var checkbox = this.popover.find('.checkbox input');

            return checkbox.length === 0 || checkbox.is(':checked');
        };

        this.onCancel = function() {
            this.teardown();
        };

        this.onImport = function() {
            if (!this.checkValid()) {
                return false;
            }

            var self = this,
                button = this.popover.find('.btn-primary')
                    .text('Importing...')
                    .attr('disabled', true),
                cancelButton = this.popover.find('.btn-default').show(),
                collapsed = this.isVisibilityCollapsed(),
                visibilityValue = collapsed ?
                    this.visibilitySource.value :
                    _.map(this.visibilitySources, _.property('value'));

            this.attr.teardownOnTap = false;

            this.request = vertexService.importFiles(this.attr.files, visibilityValue)
                .progress(function(complete) {
                    var percent = Math.round(complete * 100);
                    button.text(percent + '% Importing...');
                })
                .fail(function(xhr, m, error) {
                    self.attr.teardownOnTap = true;
                    self.markFieldErrors(error, self.popover);
                    cancelButton.hide();
                    button.text('Import')
                        .removeClass('loading')
                        .removeAttr('disabled')

                    _.defer(self.positionDialog.bind(self));
                })
                .done(function(result) {

                    vertexService.getMultiple(result.vertexIds)
                        .done(function(result) {
                            self.trigger('addVertices', {
                                vertices: result.vertices,
                                options: {
                                    fileDropPosition: self.attr.anchorTo.page
                                }
                            });

                            self.teardown();
                        });
                });
        }
    }
});
<|endoftext|>


<commit_before>window.chat_ex = {
	cmd_start: "/!",
	cmds: {
		"test": function(args){
			chat_ex.sendMessage("Response");
		},
		"help": function(args){
			var helptext="Commands: help";
			for(var cmdf in chat_ex.cmds){
				if(cmdf!="help"){
					helptext+=", "+cmdf;
				}
			}
			chat_ex.sendMessage(helptext);
		}
	},
	sendMessage: function(msgtext, roomid){
		if(!roomid){
			roomid=CHAT.CURRENT_ROOM_ID;
		}
		$.ajax({ "type": "POST",
			"url": ("http://"+document.domain+"/chats/"+roomid+"/messages/new"),
			"data": fkey({ "text": msgtext }),
			"dataType": "json", async:false
			});
	},
	getMessages: function(roomid){
		if(!roomid){
			roomid=CHAT.CURRENT_ROOM_ID;
		}
		return $.ajax({ "type": "POST",
			"url": ("http://"+document.domain+"/chats/"+roomid+"/events/"),
			"data": fkey({ "mode": "messages", "msgCount": "5" }),
			"contentType":"application/json; charset=utf-8",
			"dataType": "json", async:false
			}).responseText;
	},
	parseMessages: function(msgsjson){
		var evts = JSON.parse(msgsjson).events;
		for(var i=0;i<evts.length;++i){
			this.parseMessage(evts[i]);
		}
	},
	parseMessage: function(msgjson){
		var event_type = msgjson.event_type;
		var time_stamp = msgjson.time_stamp;
		var room_id    = msgjson.room_id;
		var user_id    = msgjson.user_id;
		var user_name  = msgjson.user_name;
		var msg_id     = msgjson.message_id;
		var msg_text   = msgjson.content;

		if(!msg_text || !msg_text.startsWith(this.cmd_start) || this.procash.arr.indexOf(msg_id)>=0 || user_id==CHAT.CURRENT_USER_ID){
			return;
		}
		// comd = [command, args]
		var comd=msg_text.match(/\/!\S*/g)[0].substring(2).split(" ",2);
		if(!this.cmds[comd[0]]){
			this.sendMessage(":"+msg_id+" Invalid command.");
		}
		else{
			this.cmds[comd]();
		}
		this.procash.add(msg_id);
	},
	procash: {
		cashpos: 0,
		arr:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
		add: function(theval){
			if(this.cashpos>=this.arr.length){
				this.cashpos=0;
			}
			this.arr[this.cashpos++]=theval;
		}
	}
}
if (!String.prototype.startsWith) {
	String.prototype.startsWith = function( str ) {
		return str.length > 0 && this.substring( 0, str.length ) === str;
	}
}
window.setInterval(function(){chat_ex.parseMessages(chat_ex.getMessages())}, 1000)
<commit_msg>update<commit_after>window.chat_ex = {
	cmd_start: "/!",
	cmds: {
		"test": function(args){
			chat_ex.sendMessage("Response");
		},
		"help": function(args){
			var helptext="Commands: help";
			for(var cmdf in chat_ex.cmds){
				if(cmdf!="help"){
					helptext+=", "+cmdf;
				}
			}
			chat_ex.sendMessage(helptext);
		}
	},
	sendMessage: function(msgtext, roomid){
		if(!roomid){
			roomid=CHAT.CURRENT_ROOM_ID;
		}
		$.ajax({ "type": "POST",
			"url": ("http://"+document.domain+"/chats/"+roomid+"/messages/new"),
			"data": fkey({ "text": msgtext }),
			"dataType": "json", async:true
			});
	},
	getMessages: function(roomid){
		if(!roomid){
			roomid=CHAT.CURRENT_ROOM_ID;
		}
		return $.ajax({ "type": "POST",
			"url": ("http://"+document.domain+"/chats/"+roomid+"/events/"),
			"data": fkey({ "since": mn, "mode": "Messages", "msgCount": "5" }),
			"contentType":"application/json; charset=utf-8",
			"dataType": "json",
			async:true,
			'success': function(roomid){
				var evts = JSON.parse(msgsjson).events;
				for(var i=0;i<evts.length;++i){
					this.parseMessage(evts[i]);
				}
			}).responseText;
	},
	parseMessages:
	},
	parseMessage: function(msgjson){
		var event_type = msgjson.event_type;
		var time_stamp = msgjson.time_stamp;
		var room_id    = msgjson.room_id;
		var user_id    = msgjson.user_id;
		var user_name  = msgjson.user_name;
		var msg_id     = msgjson.message_id;
		var msg_text   = msgjson.content;

		if(!msg_text || !msg_text.startsWith(this.cmd_start) || this.procash.arr.indexOf(msg_id)>=0 || user_id==CHAT.CURRENT_USER_ID){
			return;
		}
		// comd = [command, args]
		var comd=msg_text.match(/\/!\S*/g)[0].substring(2).split(" ",2);
		if(!this.cmds[comd[0]]){
			this.sendMessage(":"+msg_id+" Invalid command.");
		}
		else{
			this.cmds[comd]();
		}
		this.procash.add(msg_id);
	},
	procash: {
		cashpos: 0,
		arr:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
		add: function(theval){
			if(this.cashpos>=this.arr.length){
				this.cashpos=0;
			}
			this.arr[this.cashpos++]=theval;
		}
	}
}
if (!String.prototype.startsWith) {
	String.prototype.startsWith = function( str ) {
		return str.length > 0 && this.substring( 0, str.length ) === str;
	}
}
window.setInterval(function(){chat_ex.parseMessages(chat_ex.getMessages())}, 1000)
<|endoftext|>


<commit_before>const E2eHelpers = require('platform/testing/e2e/helpers');
const Timeouts = require('platform/testing/e2e/timeouts.js');

const inputs = require('./utils/inputs.json');
const DrcE2eHelpers = require('./drc-helpers.js');

const drcPagePath = '/disability/about-disability-ratings/';

module.exports = E2eHelpers.createE2eTest(client => {
  const componentSelector =
    'div[data-widget-type="disability-rating-calculator"]';
  const deleteRowBtnSelector = 'button[data-e2e=delete]';
  const inputSelector = '.ratingInput';
  const calculateBtnSelector = 'button[data-e2e=calculate]';
  const combinedRatingSelector = 'div[data-e2e="combined-rating"]';
  const clearBtnSelector = 'button[data-e2e=clearall]';
  const rowDeletionTestInput = {
    ratings: [10, 20, 30],
    combinedRating: {
      exact: 50,
      rounded: 50,
    },
  };

  // Navigate to beta-page and wait for component render.
  client
    .openUrl(`${E2eHelpers.baseUrl}${drcPagePath}`)
    .waitForElementPresent(componentSelector, Timeouts.slow);

  // Test row deletion.
  DrcE2eHelpers.fillRatings(client, rowDeletionTestInput);
  client
    .waitForElementVisible(`.row-3 ${deleteRowBtnSelector}`, Timeouts.normal)
    .click(`.row-2 ${deleteRowBtnSelector}`);
  client.elements('css selector', inputSelector, result => {
    client.assert.equal(result.value.length, 2);
  });
  client
    .waitForElementVisible(clearBtnSelector, Timeouts.normal)
    .click(clearBtnSelector);

  // Test combined-rating result/error and reset.
  for (const input of inputs) {
    client
      .waitForElementVisible('.rating.row-2', Timeouts.normal)
      .expect.element(`.rating.row-2 ${inputSelector}`).to.be.visible;

    DrcE2eHelpers.fillRatings(client, input);
    client
      .waitForElementVisible(calculateBtnSelector, Timeouts.normal)
      .click(calculateBtnSelector);

    if (DrcE2eHelpers.ratingsAreAllRounded(input.ratings)) {
      // Check calculation -- ratings are all rounded.
      client
        .waitForElementVisible(combinedRatingSelector, Timeouts.slow)
        .expect.element(combinedRatingSelector)
        .text.to.contain(input.combinedRating.rounded.toString());
    } else {
      // Check error -- ratings are not all rounded.
      client.expect
        .element('.usa-input-error-message')
        .to.be.visible.before(Timeouts.normal);
    }

    // Test reset.
    client
      .waitForElementVisible(clearBtnSelector, Timeouts.normal)
      .click(clearBtnSelector);

    if (inputs.indexOf(input) === 0) {
      client.expect
        .element(`.rating.row-1 ${inputSelector}`)
        .to.have.value.that.equals('');
      client.expect
        .element(`.rating.row-2 ${inputSelector}`)
        .to.have.value.that.equals('');
      client.expect.element('.rating.row-3').to.not.be.present;
    }
  }

  client.end();
});
<commit_msg>Perform axe check on disability calculator page (#17022)<commit_after>const E2eHelpers = require('platform/testing/e2e/helpers');
const Timeouts = require('platform/testing/e2e/timeouts.js');

const inputs = require('./utils/inputs.json');
const DrcE2eHelpers = require('./drc-helpers.js');

const drcPagePath = '/disability/about-disability-ratings/';

module.exports = E2eHelpers.createE2eTest(client => {
  const componentSelector =
    'div[data-widget-type="disability-rating-calculator"]';
  const deleteRowBtnSelector = 'button[data-e2e=delete]';
  const inputSelector = '.ratingInput';
  const calculateBtnSelector = 'button[data-e2e=calculate]';
  const combinedRatingSelector = 'div[data-e2e="combined-rating"]';
  const clearBtnSelector = 'button[data-e2e=clearall]';
  const rowDeletionTestInput = {
    ratings: [10, 20, 30],
    combinedRating: {
      exact: 50,
      rounded: 50,
    },
  };

  // Navigate to beta-page and wait for component render.
  client
    .openUrl(`${E2eHelpers.baseUrl}${drcPagePath}`)
    .waitForElementPresent(componentSelector, Timeouts.slow)
    .axeCheck();

  // Test row deletion.
  DrcE2eHelpers.fillRatings(client, rowDeletionTestInput);
  client
    .waitForElementVisible(`.row-3 ${deleteRowBtnSelector}`, Timeouts.normal)
    .click(`.row-2 ${deleteRowBtnSelector}`);
  client.elements('css selector', inputSelector, result => {
    client.assert.equal(result.value.length, 2);
  });
  client
    .waitForElementVisible(clearBtnSelector, Timeouts.normal)
    .click(clearBtnSelector);

  // Test combined-rating result/error and reset.
  for (const input of inputs) {
    client
      .waitForElementVisible('.rating.row-2', Timeouts.normal)
      .expect.element(`.rating.row-2 ${inputSelector}`).to.be.visible;

    DrcE2eHelpers.fillRatings(client, input);
    client
      .waitForElementVisible(calculateBtnSelector, Timeouts.normal)
      .click(calculateBtnSelector);

    if (DrcE2eHelpers.ratingsAreAllRounded(input.ratings)) {
      // Check calculation -- ratings are all rounded.
      client
        .waitForElementVisible(combinedRatingSelector, Timeouts.slow)
        .expect.element(combinedRatingSelector)
        .text.to.contain(input.combinedRating.rounded.toString());
    } else {
      // Check error -- ratings are not all rounded.
      client.expect
        .element('.usa-input-error-message')
        .to.be.visible.before(Timeouts.normal);
    }

    // Test reset.
    client
      .waitForElementVisible(clearBtnSelector, Timeouts.normal)
      .click(clearBtnSelector);

    if (inputs.indexOf(input) === 0) {
      client.expect
        .element(`.rating.row-1 ${inputSelector}`)
        .to.have.value.that.equals('');
      client.expect
        .element(`.rating.row-2 ${inputSelector}`)
        .to.have.value.that.equals('');
      client.expect.element('.rating.row-3').to.not.be.present;
    }
  }

  client.end();
});
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import $ from 'jquery';
import store from '../../store';
require('./SearchBox.scss');

export default class SearchBox extends Component {
  constructor() {
    super();
    this.search = this.search.bind(this);
  }
  search(event) {
    const that = this;
    const searchingFor = $(event.target).val();
    if(event.keyCode === 13) {
      $.ajax({
        url: '/search/words/' + searchingFor,
        type: 'GET',
      }).done((data) => {
        store.setSearchingFor(searchingFor);
        store.setData(data);
        that.props.update();
      }).fail((err) => {
        console.log(err);
      });
    }
  }
  render() {
    return (

        <input
        className="input-text__search"
        type="text"
        placeholder="Enter your query ..."
        onKeyDown={this.search}/>

    );
  }
}
<commit_msg>Error on enter with empty search text fixed<commit_after>import React, {Component} from 'react';
import $ from 'jquery';
import store from '../../store';
require('./SearchBox.scss');

export default class SearchBox extends Component {
  constructor() {
    super();
    this.search = this.search.bind(this);
  }
  search(event) {
    const that = this;
    const searchingFor = $(event.target).val();
    if(event.keyCode === 13 && searchingFor !== '') {
      $.ajax({
        url: '/search/words/' + searchingFor,
        type: 'GET',
      }).done((data) => {
        store.setSearchingFor(searchingFor);
        store.setData(data);
        that.props.update();
      }).fail((err) => {
        console.log(err);
      });
    }
  }
  render() {
    return (

        <input
        className="input-text__search"
        type="text"
        placeholder="Enter your query ..."
        onKeyDown={this.search}/>

    );
  }
}
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var capture = require('../capture/commandLineCapture');
var _ = require('underscore');

exports.get = function (req, res) {
    var settings = res.app.locals["settings"];
    var imagePath = capture.getImagePath(settings);
    var directory = path.dirname(imagePath);
    var extension = path.extname(imagePath)

    fs.readdir(directory, function (err, files) {
        if (err) {
            throw new Exception(err);
        }

        var imageFiles = _.filter(files, function (file) {
            var timeIndex = fileName.lastIndexOf("_");
            return timeIndex != -1 && path.dirname(imagePath) == extension;
        });

        imageFiles = _.sortBy(imageFiles, function (file) {
            var fileName = path.basename(file, extension);
            var timeIndex = fileName.lastIndexOf("_") + 1;
            var time = fileName.substring(timeIndex);

            return parseInt(timeIndex);
        });

        res.render('timelapse', { title: "Time Lapse - " + settings.Title, settings: settings, imageFiles: imageFiles });
    });
};<commit_msg>bug fix<commit_after>var fs = require('fs');
var path = require('path');
var capture = require('../capture/commandLineCapture');
var _ = require('underscore');

exports.get = function (req, res) {
    var settings = res.app.locals["settings"];
    var imagePath = capture.getImagePath(settings);
    var directory = path.dirname(imagePath);
    var extension = path.extname(imagePath)

    fs.readdir(directory, function (err, files) {
        if (err) {
            throw new Exception(err);
        }

        var imageFiles = _.filter(files, function (file) {
            var timeIndex = file.lastIndexOf("_");
            return timeIndex != -1 && path.dirname(imagePath) == extension;
        });

        imageFiles = _.sortBy(imageFiles, function (file) {
            var fileName = path.basename(file, extension);
            var timeIndex = fileName.lastIndexOf("_") + 1;
            var time = fileName.substring(timeIndex);

            return parseInt(timeIndex);
        });

        res.render('timelapse', { title: "Time Lapse - " + settings.Title, settings: settings, imageFiles: imageFiles });
    });
};<|endoftext|>


<commit_before>/**
 @filespec PatternView - the view which depicts a Pattern in the styleboard
 */
define(['appState', 'Example'], function (appState, Example) {

    var PatternView = Backbone.View.extend({

        initialize: function () {
            var view = this;

            appState.on('change:example', view.updateExampleIsActive, view);
        },

        render: function () {
            var view = this,
                pat = view.model,
                name = pat.getName();

            view.$el.mk( 'header', [ 'h2', name] );

            view.renderNodes();

            return view;
        },

        renderNodes: function () {
            var view = this,
                pat = view.model,
                examples = pat.getNodesOfType('example'),
                exampleIndex = 0;

            recursivelyRenderNodes( pat, view.$el );

            function recursivelyRenderNodes ( parent, $parent ) {
                var children = parent.getNodes(),
                    scope = { pattern: pat.getName() },
                    $section;
                scope[ parent.getType() ] = parent.getName();
                children.forEach( function (node) {
                    var key = node.getType();
                        attrs = { 'class': 'pattern-' + key },
                        example;
                    switch ( key ) {
                    case 'p':
                        $parent.mk( 'p', node.getText() );
                        break;
                    case 'html':
                        $(node.getText()).appendTo($parent);
                        break;
                    case 'example':
                        // TODO: this relies on order of traversal
                        example = examples[exampleIndex];
                        attrs.href = '#' + pat.getName() + '/' +
                            (example.getAttr('name') || exampleIndex);
                        $parent.mk( 'a.button', attrs,
                            example.getAttr('title') || "Example" )
                            .data( 'example', example );
                        exampleIndex++;
                        break;
                    case 'modifier':
                    case 'state':
                    case 'member':
                    case 'helper':
                        $section = $parent.mk(
                            'section', attrs,
                            [ 'header',
                              [ 'p.pattern-role', node.getType()],
                              [ 'h3', node.getName()]
                            ]);
                        recursivelyRenderNodes( node, $section );
                        break;
                    default:
                        // ignore
                        break;
                    }
                });
            }
        },

        updateExampleIsActive: function () {
            var view = this,
                example = appState.get('example'),
                scope = appState.get('scope'),
                $examples = view.$('.pattern-example'),
                viewOffset = view.$el.offset(),
                $pane = view.$el.closest('.pane'),
                $active = $examples.filter( function () {
                    return $(this).data('example').getNode() === example.getNode();
                }),
                activeOffset = $active.offset(),
                relativeOffset = activeOffset ?
                    ( activeOffset.top - viewOffset.top - $pane.outerHeight()/2 ) : 0;

            $examples.removeClass('is-active');
            $active.addClass('is-active');

            // scroll to current example
            $pane.animate({
                scrollTop: relativeOffset
            }, 200 );
        }

    });

    function code( text ) {
        return $.mk('code', text);
    }

    return PatternView;
});
<commit_msg>use standard heading CSS instead of pattern-specific styling<commit_after>/**
 @filespec PatternView - the view which depicts a Pattern in the styleboard
 */
define(['appState', 'Example'], function (appState, Example) {

    var PatternView = Backbone.View.extend({

        initialize: function () {
            var view = this;

            appState.on('change:example', view.updateExampleIsActive, view);
        },

        render: function () {
            var view = this,
                pat = view.model,
                name = pat.getName();

            view.$el.mk( 'header', [ 'h1', name] );

            view.renderNodes();

            return view;
        },

        renderNodes: function () {
            var view = this,
                pat = view.model,
                examples = pat.getNodesOfType('example'),
                exampleIndex = 0;

            recursivelyRenderNodes( pat, view.$el );

            function recursivelyRenderNodes ( parent, $parent ) {
                var children = parent.getNodes(),
                    scope = { pattern: pat.getName() },
                    $section;
                scope[ parent.getType() ] = parent.getName();
                children.forEach( function (node) {
                    var key = node.getType();
                        attrs = { 'class': 'pattern-' + key },
                        example;
                    switch ( key ) {
                    case 'p':
                        $parent.mk( 'p', node.getText() );
                        break;
                    case 'html':
                        $(node.getText()).appendTo($parent);
                        break;
                    case 'example':
                        // TODO: this relies on order of traversal
                        example = examples[exampleIndex];
                        attrs.href = '#' + pat.getName() + '/' +
                            (example.getAttr('name') || exampleIndex);
                        $parent.mk( 'a.button', attrs,
                            example.getAttr('title') || "Example" )
                            .data( 'example', example );
                        exampleIndex++;
                        break;
                    case 'modifier':
                    case 'state':
                    case 'member':
                    case 'helper':
                        $section = $parent.mk(
                            'section', attrs,
                            [ 'header',
                              [ 'h4', node.getType()],
                              [ 'h3', node.getName()]
                            ]);
                        recursivelyRenderNodes( node, $section );
                        break;
                    default:
                        // ignore
                        break;
                    }
                });
            }
        },

        updateExampleIsActive: function () {
            var view = this,
                example = appState.get('example'),
                scope = appState.get('scope'),
                $examples = view.$('.pattern-example'),
                viewOffset = view.$el.offset(),
                $pane = view.$el.closest('.pane'),
                $active = $examples.filter( function () {
                    return $(this).data('example').getNode() === example.getNode();
                }),
                activeOffset = $active.offset(),
                relativeOffset = activeOffset ?
                    ( activeOffset.top - viewOffset.top - $pane.outerHeight()/2 ) : 0;

            $examples.removeClass('is-active');
            $active.addClass('is-active');

            // scroll to current example
            $pane.animate({
                scrollTop: relativeOffset
            }, 200 );
        }

    });

    function code( text ) {
        return $.mk('code', text);
    }

    return PatternView;
});
<|endoftext|>


<commit_before>/*
Packetizer is great in that it builds packets, but sometimes replies don't
come in in an orderly fashion. If this happens, we need to be able to be able
to route them appropriately.
*/

var util = require('util');
var EventEmitter = require('events').EventEmitter;

/**
* Iterate each value of array and check if value contains
* a specific string.
*
* Differs from indexOf in that it performs indexOf on each
* value in the string, so only a partial match is needed.
*
* @param string, the string to search for
* @returns true if match, else false
* @note will return true at first occurrence of match
* @note will check value.indexOf(string) AND string.indexOf(value)
* @example:
*
* ['Apple', 'Pear'].indexOf('Pear') === 1
* ['Apple', 'Pear'].indexOf('Pe') === -1
* ['Apple', 'Pear'].indexOf('Pearing') === -1
*
* ['Apple', 'Pear'].softContains('Pear') === true
* ['Apple', 'Pear'].softContains('Pe') === false
* ['Apple', 'Pear'].softContains('Pearing') === true
*
*/
Array.prototype.softContains = function(searchStr) {
  for (var i = 0; i < this.length; i++) {
    // Sometimes array values could be buffers!
    if (typeof this[i] !== 'string') {
      return false;
    }
    if (searchStr.indexOf(this[i]) !== -1) {
      return true;
    }
  }
  return false;
}

function Postmaster (myPacketizer, enders, overflow, size, debug) {
  /*
  Constructor for the postmaster

  args
    myPacketizer
      A packetizer to listen to
    enders
      An Array of Strings that constitute the end of a post
    overflow
      A callback function to call when the message buffer overflows. Callback args are err and data
    size
      Size (in packets) of the buffer
    debug
      Are we in debug mode?
  */

  this.packetizer = myPacketizer;
  this.uart = myPacketizer.uart;
  this.RXQueue = [];
  this.callback = null;
  this.message = '';
  this.started = false;
  this.alternate = null;
  this.enders = enders || ['OK', 'ERROR'];
  this.debug = debug || false;
  overflow = overflow || function(err, arg) {
    if (err) {
      console.log('err: ', err);
    } else {
      console.log('overflow!\n', arg);
    }
  };
  size = size || 15;

  var self = this;

  //  When we get a packet, see if it starts or ends a message
  this.packetizer.on('packet', function(data) {
    // Wraps message as default start, which means a
    // reply packet must start with the message to be valid.
    // ex: ['AT']
    var starts = [self.message];
    var enders = self.enders;
    // If true, the values of `start` only need to exist
    // within the incoming data, instead of at the beginning of the packet.
    // Good for posts with known headers but unknown bodies
    var useSoftContains, useAlternate;

    // If true, we are using alternate starts and enders
    if (self.alternate) {
      // Array of valid start strings, ex: ['AT', 'OK', 'LETS BEGIN']
      starts = self.alternate[0];
      enders = self.alternate[1];
      // Use the alternate starts, enders
      useAlternate = true;
      // Use soft checking of start array
      useSoftContains = self.alternate[2] ? true : false;
    } else {
      useAlternate = false;
      useSoftContains = false;
    }

    self._debugPrint('postmaster got packet: ' + [data], '\nstarts:', starts, '\nenders:', enders);

    function hasCallback() {
      return self.callback !== null;
    }

    function hasStarted() {
      return self.started;
    }

    function isDataInStartArrayStrict() {
      return starts.indexOf(data) === -1 ? false : true;
    }

    // Sometimes a packet contains other characters in addition to
    // the string we want, for example:
    //   ['OK', 'ERROR'].indexOf('OK.')
    // in this case indexOf will not be truthy, while
    //   ['OK', 'ERROR'].softContains('OK.')
    // will be truthy.
    //
    // These type of responses from the SIM900 chip are common when querying
    // statuses. For example
    //   AT+CGATT?
    // will return differently based on status, for example both
    //   +CGATT: 0
    //   +CGATT: 1
    // are valid responses. By using softContains we can assure that both
    // are valid enders.
    //
    function isDataInStartArraySoft() {
      return starts.softContains(data);
    }

    self._debugPrint('---------------');
    self._debugPrint('hasCallback', hasCallback());
    self._debugPrint('hasStarted', hasStarted());
    self._debugPrint('useSoftContains', useSoftContains);
    self._debugPrint('isDataInStartArrayStrict', isDataInStartArrayStrict());
    self._debugPrint('isDataInStartArraySoft', isDataInStartArraySoft());

    // If we aren't busy,
    // or if we are busy but the first part of the reply doesn't match the message,
    // or if we are busy and we are using alternates and
    // it's unsolicited
    function isUnsolicited() {
      if(!hasCallback()) {
        self._debugPrint('---->>>>>>> Condition 1');
        return true;
      }
      if(!hasStarted() && !useSoftContains && !isDataInStartArrayStrict()) {
        self._debugPrint('---->>>>>>> Condition 2');
        return true;
      }
      if(!hasStarted() && useSoftContains && !isDataInStartArraySoft()) {
        self._debugPrint('---->>>>>>> Condition 3');
        return true;
      }
      return false;
    }

    self._debugPrint('isUnsolicited', isUnsolicited());
    self._debugPrint('---------------');

    if (isUnsolicited()) {
      self._debugPrint('->>>>>>>>>> unsolicited');
      self._debugPrint(data);
      self.emit('unsolicited', data);
    }
    else {
      self._debugPrint('adding', [data], 'to the RXQueue');
      self.started = true;
      self.RXQueue.push(data);
      //  Check to see of we've finished the post
      if (enders.indexOf(data) > -1) {
        self._debugPrint('\t---> Found '+ data + ' in enders:\n', enders, '\nEmitting a post with:\n', self.RXQueue);
        var temp = self.RXQueue;
        self.RXQueue = [];
        self.started = false;
        self.alternate = null;
        self.emit('post', null, temp);
      }
    }
    //  Check overflow
    if (self.RXQueue.length > size) {
      self.emit('overflow', null, self.RXQueue);
      self.RXQueue = [];
      self.started = false;
      self.alternate = null;
      self.message = '';
    }
  });

  this.on('overflow', overflow);
}

util.inherits(Postmaster, EventEmitter);

Postmaster.prototype.send = function (message, patience, callback, alternate, debug) {
  /*
  Send a message and add call its callback with the data from the reply

  args
    message
      What to send (String or Buffer)
    callback
      The callback function to call with the resulting data
    patience
      Miliseconds to wait before returning with an error
    alternate
      An Array of Arrays of alternate starts and ends of the reply post (Strings). Of the form [[s1, s2 ...], [e1, e2, ...]]. These values are used in place of traditional controls.
      If the third element of alternate is truth-y, then the given start values only need exist within the incoming data (good for posts with known headers but unknown bodies).
    debug
      Debug flag

  Callback parameters
    err
      Error, if applicable
    data
      An array of Strings, usually starting with the original call, usually ending with one of 'OK', '>', or 'ERROR'
  */

  var self = this;

  self.debug = debug || false;

  if (self.callback !== null) {
    callback(new Error('Postmaster busy'), []);
  } else {
    if (alternate) {
      self.alternate = alternate;
    }
    //  Set things up
    self.callback = callback;
    patience = patience || 10000;

    self.message = message;
    self.uart.write(message);
    self.uart.write('\r\n');
    self._debugPrint('sent', [message], 'on uart', [self.uart]);

    var reply = function(err, data) {
      var temp = self.callback;
      self.callback = null;
      if (temp) {
        temp(err, data);
      }
    };

    //  If we time out
    var panic = setTimeout(function() {
      self.removeListener('post', reply);
      var err = new Error('no reply after ' + patience + ' ms to message "' + message + '"');
      err.type = 'timeout';
      reply(err, []);
    }, patience);

    //  If we get something
    self.once('post', function(err, data) {
      self.removeAllListeners('post'); // WORKAROUND: see bug https://github.com/tessel/runtime/issues/226
      clearTimeout(panic);
      self._debugPrint("postmaster replying", data);
      reply(err, data);
    });
  }
};

Postmaster.prototype.forceClear = function(typ)
{
  //  Reset the postmaster to its default state, emit what you have as unsolicited
  var type = typ || 'unsolicited';
  this.emit(type, this.RXQueue);
  this.RXQueue = [];
  this.callback = null;
  this.message = '';
  this.started = false;
  this.alternate = null;
};

Postmaster.prototype._debugPrint = function (thing) {
  if (this.debug) {
    console.log(thing);
  }
}

module.exports = Postmaster;
<commit_msg>comment cleanup<commit_after>/*
Packetizer is great in that it builds packets, but sometimes replies don't
come in in an orderly fashion. If this happens, we need to be able to be able
to route them appropriately.
*/

var util = require('util');
var EventEmitter = require('events').EventEmitter;

/**
* Iterate each value of array and check if value contains
* a specific string.
*
* Differs from indexOf in that it performs indexOf on each
* value in the string, so only a partial match is needed.
*
* @param string, the string to search for
* @returns true if match, else false
* @note will return true at first occurrence of match
* @note will check value.indexOf(string) AND string.indexOf(value)
* @example:
*
* ['Apple', 'Pear'].indexOf('Pear') === 1
* ['Apple', 'Pear'].indexOf('Pe') === -1
* ['Apple', 'Pear'].indexOf('Pearing') === -1
*
* ['Apple', 'Pear'].softContains('Pear') === true
* ['Apple', 'Pear'].softContains('Pe') === false
* ['Apple', 'Pear'].softContains('Pearing') === true
*/

Array.prototype.softContains = function(searchStr) {
  for (var i = 0; i < this.length; i++) {
    // Sometimes array values could be buffers!
    if (typeof this[i] !== 'string') {
      return false;
    }
    if (searchStr.indexOf(this[i]) !== -1) {
      return true;
    }
  }
  return false;
}

function Postmaster (myPacketizer, enders, overflow, size, debug) {
  /*
  Constructor for the postmaster

  args
    myPacketizer
      A packetizer to listen to
    enders
      An Array of Strings that constitute the end of a post
    overflow
      A callback function to call when the message buffer overflows. Callback args are err and data
    size
      Size (in packets) of the buffer
    debug
      Are we in debug mode?
  */

  this.packetizer = myPacketizer;
  this.uart = myPacketizer.uart;
  this.RXQueue = [];
  this.callback = null;
  this.message = '';
  this.started = false;
  this.alternate = null;
  this.enders = enders || ['OK', 'ERROR'];
  this.debug = debug || false;
  overflow = overflow || function(err, arg) {
    if (err) {
      console.log('err: ', err);
    } else {
      console.log('overflow!\n', arg);
    }
  };
  size = size || 15;

  var self = this;

  //  When we get a packet, see if it starts or ends a message
  this.packetizer.on('packet', function(data) {
    // Wraps message as default start, which means a
    // reply packet must start with the message to be valid.
    // ex: ['AT']
    var starts = [self.message];
    var enders = self.enders;
    // If true, the values of `start` only need to exist
    // within the incoming data, instead of at the beginning of the packet.
    // Good for posts with known headers but unknown bodies
    var useSoftContains, useAlternate;

    // If true, we are using alternate starts and enders
    if (self.alternate) {
      // Array of valid start strings, ex: ['AT', 'OK', 'LETS BEGIN']
      starts = self.alternate[0];
      enders = self.alternate[1];
      // Use the alternate starts, enders
      useAlternate = true;
      // Use soft checking of start array
      useSoftContains = self.alternate[2] ? true : false;
    } else {
      useAlternate = false;
      useSoftContains = false;
    }

    self._debugPrint('postmaster got packet: ' + [data], '\nstarts:', starts, '\nenders:', enders);

    function hasCallback() {
      return self.callback !== null;
    }

    function hasStarted() {
      return self.started;
    }

    function isDataInStartArrayStrict() {
      return starts.indexOf(data) === -1 ? false : true;
    }

    // Sometimes a packet contains other characters in addition to
    // the string we want, for example:
    //   ['OK', 'ERROR'].indexOf('OK.')
    // in this case indexOf will not be truthy, while
    //   ['OK', 'ERROR'].softContains('OK.')
    // will be truthy.
    //
    // These type of responses from the SIM900 chip are common when querying
    // statuses. For example
    //   AT+CGATT?
    // will return differently based on status, for example both
    //   +CGATT: 0
    //   +CGATT: 1
    // are valid responses. By using softContains we can assure that both
    // are valid enders.

    function isDataInStartArraySoft() {
      return starts.softContains(data);
    }

    self._debugPrint('---------------');
    self._debugPrint('hasCallback', hasCallback());
    self._debugPrint('hasStarted', hasStarted());
    self._debugPrint('useSoftContains', useSoftContains);
    self._debugPrint('isDataInStartArrayStrict', isDataInStartArrayStrict());
    self._debugPrint('isDataInStartArraySoft', isDataInStartArraySoft());

    // If we aren't busy,
    // or if we are busy but the first part of the reply doesn't match the message,
    // or if we are busy and we are using alternates and
    // it's unsolicited
    function isUnsolicited() {
      if(!hasCallback()) {
        self._debugPrint('---->>>>>>> Condition 1');
        return true;
      }
      if(!hasStarted() && !useSoftContains && !isDataInStartArrayStrict()) {
        self._debugPrint('---->>>>>>> Condition 2');
        return true;
      }
      if(!hasStarted() && useSoftContains && !isDataInStartArraySoft()) {
        self._debugPrint('---->>>>>>> Condition 3');
        return true;
      }
      return false;
    }

    self._debugPrint('isUnsolicited', isUnsolicited());
    self._debugPrint('---------------');

    if (isUnsolicited()) {
      self._debugPrint('->>>>>>>>>> unsolicited');
      self._debugPrint(data);
      self.emit('unsolicited', data);
    }
    else {
      self._debugPrint('adding', [data], 'to the RXQueue');
      self.started = true;
      self.RXQueue.push(data);
      //  Check to see of we've finished the post
      if (enders.indexOf(data) > -1) {
        self._debugPrint('\t---> Found '+ data + ' in enders:\n', enders, '\nEmitting a post with:\n', self.RXQueue);
        var temp = self.RXQueue;
        self.RXQueue = [];
        self.started = false;
        self.alternate = null;
        self.emit('post', null, temp);
      }
    }
    //  Check overflow
    if (self.RXQueue.length > size) {
      self.emit('overflow', null, self.RXQueue);
      self.RXQueue = [];
      self.started = false;
      self.alternate = null;
      self.message = '';
    }
  });

  this.on('overflow', overflow);
}

util.inherits(Postmaster, EventEmitter);

Postmaster.prototype.send = function (message, patience, callback, alternate, debug) {
  /*
  Send a message and add call its callback with the data from the reply

  args
    message
      What to send (String or Buffer)
    callback
      The callback function to call with the resulting data
    patience
      Miliseconds to wait before returning with an error
    alternate
      An Array of Arrays of alternate starts and ends of the reply post (Strings). Of the form [[s1, s2 ...], [e1, e2, ...]]. These values are used in place of traditional controls.
      If the third element of alternate is truth-y, then the given start values only need exist within the incoming data (good for posts with known headers but unknown bodies).
    debug
      Debug flag

  Callback parameters
    err
      Error, if applicable
    data
      An array of Strings, usually starting with the original call, usually ending with one of 'OK', '>', or 'ERROR'
  */

  var self = this;

  self.debug = debug || false;

  if (self.callback !== null) {
    callback(new Error('Postmaster busy'), []);
  } else {
    if (alternate) {
      self.alternate = alternate;
    }
    //  Set things up
    self.callback = callback;
    patience = patience || 10000;

    self.message = message;
    self.uart.write(message);
    self.uart.write('\r\n');
    self._debugPrint('sent', [message], 'on uart', [self.uart]);

    var reply = function(err, data) {
      var temp = self.callback;
      self.callback = null;
      if (temp) {
        temp(err, data);
      }
    };

    //  If we time out
    var panic = setTimeout(function() {
      self.removeListener('post', reply);
      var err = new Error('no reply after ' + patience + ' ms to message "' + message + '"');
      err.type = 'timeout';
      reply(err, []);
    }, patience);

    //  If we get something
    self.once('post', function(err, data) {
      self.removeAllListeners('post'); // WORKAROUND: see bug https://github.com/tessel/runtime/issues/226
      clearTimeout(panic);
      self._debugPrint("postmaster replying", data);
      reply(err, data);
    });
  }
};

Postmaster.prototype.forceClear = function(typ)
{
  //  Reset the postmaster to its default state, emit what you have as unsolicited
  var type = typ || 'unsolicited';
  this.emit(type, this.RXQueue);
  this.RXQueue = [];
  this.callback = null;
  this.message = '';
  this.started = false;
  this.alternate = null;
};

Postmaster.prototype._debugPrint = function (thing) {
  if (this.debug) {
    console.log(thing);
  }
}

module.exports = Postmaster;
<|endoftext|>