<commit_before>
/**
 * @module server
 * @requires module:utils~Formatter
 */

(/** @lends module:server */function(){

var fs      = require('fs');
var restify = require('restify');
var http    = require('http');
var fmt     = require('../utils/formatter');
var filter  = require('./logfilter');

var name = 'server';

var defAddress    = '127.0.0.1';
var defHostname   = 'localhost';
var defOpenPort   = 8080;
var defSecurePort = 8081;

/**
 * Constructs a restify based HTTP server.
 *
 * @constructor
 * @param {Object} config                  - a server configuration object
 * @param {String} config.basedir          - the base directory of the server
 * @param {String} [config.address]        - IP address to bind
 * @param {String} [config.hostname]       - hostname to bind
 * @param {String} [config.open_port]      - tcp port to bind
 * @param {String} [config.secure_port]    - tls port to bind
 * @param {Object} [config.https]          - https configuration object
 * @param {String} config.https.key        - location of https private key
 * @param {String} config.https.cert       - location of https certificate
 * @param {String} config.static.directory - location of static content
 */

function Server(config, logger) {
  var that = this;

  // Grab a configuration if present ...
  // ... otherwise supply a default configuration
  this.config = config[name] || {
    address:     defAddress,
    hostname:    defHostname,
    open_port:   defOpenPort,
    secure_port: defSecurePort
  };

  this.logger = logger.addLog(name);

  // Set default values in case where passed config is deficient
  this.config.address     = this.config.address     || defAddress;
  this.config.hostname    = this.config.hostname    || defHostname;
  this.config.open_port   = this.config.open_port   || defOpenPort;
  this.config.secure_port = this.config.secure_port || defSecurePort;
  this.config.protocol    = this.config.https ? 'https' : 'http';

  // Load credential information if present
  if(this.config.https) {
    this.creds = {
      key: fs.readFileSync(this.config.https.key),
      certificate: fs.readFileSync(this.config.https.cert)
    };

    // redirect all http requests to the https port
    this.http = http.createServer(
      function(req, res) {
        res.writeHead(301, {
          Location: 'https://' + that.config.hostname + ':' +
                    that.config.secure_port + '/'
        });
        res.end();
      }
    );
  } else {
    this.creds = {};
  }

  // Create and configure a server instance
  this.server = restify.createServer(this.creds)
    .use(restify.jsonp())
    .use(restify.gzipResponse())
    .use(restify.bodyParser());

  this.running = false;
}
exports.Server = Server;

/**
 * @callback httpCallback
 * @param {Object} req    - nodejs HTTP request object
 * @param {Object} res    - nodejs HTTP response object
 * @param {Function} next - function to envoke next http handler in chain
 */

/**
 * Registers a handler with the server to use for all HTTP reqeuests
 * where the method and path match their respective parts from the
 * request-url.
 *
 * @param {String} method        - HTTP method to catpure
 * @param {String} path          - the relative path of the handler
 * @param {httpCallback} handler - HTTP request handler to call
 * @returns {Server} a reference to the object instance
 */
Server.prototype.addHandler = function(method, path, handler) {
  this.logger.info('Adding Handler: %s %s', method, path);
  switch(method) {
    case 'post':
    case 'get':
    case 'put':
    case 'delete':
      this.server[method](this.rootPath() + path, handler);
      break;
    case '*':
      this.server.use(handler);
      break;
    default:
      throw 'Bad server handler: ' + method + ' ' + path + ' ' + handler;
  }
  return this;
};

Server.prototype.addModule = function(mod) {
  mod.load(this);
  return this;
};

/**
 * Returns the base url for the running server.
 *
 * @returns {String} protocol://hostname:port
 */
Server.prototype.baseUrl = function() {
  var bp = this.https ? this.config.secure_port : this.config.open_port;
  return this.config.protocol + '://' + this.config.hostname + ':' + bp;
};

/**
 * Returns the path root of the server
 *
 * @returns {String} path root of server
 */
Server.prototype.rootPath = function() {
  return this.config.root + '/';
};

/**
 * Starts the server
 *
 * @returns {Server} returns a self reference
 */
Server.prototype.run = function() {
  var notFound;

  this.server.on('after', filter.auditLogger({
    log: this.logger,
    body: true
  }));

  this.server.on('NotFound', function(req, res) {
    var body = JSON.stringify({ error: {
      message: 'Bad request',
      details: req.method + ' ' + req.url
    }});
    res.end(body);
  });

  if(this.config.static) {
    this.server.get(this.config.static.mount+'.*', restify.serveStatic(
      {
        directory: this.config.static.directory,
        default: 'index.html'
      }
    ));
  }

  // start the http redirector if needed
  if(this.http) {
    this.http.listen(this.config.open_port, this.config.address);
  }
  // start the primary server
  this.server.listen(this.http ? this.config.secure_port : this.config.open_port, this.config.address);

  this.running = true;
  this.logger.info('Started Flowsim');
  return this;
};

/**
 * A formatter implementation for the Server.
 *
 * @param {module:utils~Formatter} f - formatter object to use
 * @returns {module:utils~Formatter} a reference to the active formatter
 */
Server.prototype.toFormatter = function(f) {
  f.begin('Server');
  f.addPair('Address', this.config.address);
  f.addPair('Hostname', this.config.hostname);
  f.addPair('TCP Port', this.config.open_port);
  if(this.config.https) {
    f.addPair('TLS Port', this.config.secure_port);
  }
  f.addPair('Protocol', this.config.protocol);
  if(this.config.https) {
    f.addPair('Key', this.config.https.key);
    f.addPair('Cert', this.config.https.cert);
  }
  if(this.config.static) {
    f.addPair('Static', this.config.static.directory);
  }
  f.addPair('Running', this.running);
  f.end();
  return f;
};

/**
 * Attach the basic formatter.toString funcitonality.
 *
 * @returns {String} a stringified version of the Server.
 */
Server.prototype.toString = fmt.toString;

})();
<commit_msg>latest<commit_after>
/**
 * @module server
 * @requires module:utils~Formatter
 */

(/** @lends module:server */function(){

var fs      = require('fs');
var restify = require('restify');
var http    = require('http');
var fmt     = require('../utils/formatter');
var filter  = require('./logfilter');

var name = 'server';

var defAddress    = '127.0.0.1';
var defHostname   = 'localhost';
var defOpenPort   = 8080;
var defSecurePort = 8081;

/**
 * Constructs a restify based HTTP server.
 *
 * @constructor
 * @param {Object} config                  - a server configuration object
 * @param {String} config.basedir          - the base directory of the server
 * @param {String} [config.address]        - IP address to bind
 * @param {String} [config.hostname]       - hostname to bind
 * @param {String} [config.open_port]      - tcp port to bind
 * @param {String} [config.secure_port]    - tls port to bind
 * @param {Object} [config.https]          - https configuration object
 * @param {String} config.https.key        - location of https private key
 * @param {String} config.https.cert       - location of https certificate
 * @param {String} config.static.directory - location of static content
 */

function Server(config, logger) {
  var that = this;

  // Grab a configuration if present ...
  // ... otherwise supply a default configuration
  this.config = config[name] || {
    address:     defAddress,
    hostname:    defHostname,
    open_port:   defOpenPort,
    secure_port: defSecurePort
  };

  this.logger = logger.addLog(name);

  // Set default values in case where passed config is deficient
  this.config.address     = this.config.address     || defAddress;
  this.config.hostname    = this.config.hostname    || defHostname;
  this.config.open_port   = this.config.open_port   || defOpenPort;
  this.config.secure_port = this.config.secure_port || defSecurePort;
  this.config.protocol    = this.config.https ? 'https' : 'http';

  // Load credential information if present
  if(this.config.https) {
    this.creds = {
      key: fs.readFileSync(this.config.https.key),
      certificate: fs.readFileSync(this.config.https.cert)
    };

    // redirect all http requests to the https port
    this.http = http.createServer(
      function(req, res) {
        res.writeHead(301, {
          Location: 'https://' + that.config.hostname + ':' +
                    that.config.secure_port + '/'
        });
        res.end();
      }
    );
  } else {
    this.creds = {};
  }

  // Create and configure a server instance
  this.server = restify.createServer(this.creds)
    .use(restify.jsonp())
    .use(restify.gzipResponse())
    .use(restify.bodyParser());

  this.running = false;
}
exports.Server = Server;

/**
 * @callback httpCallback
 * @param {Object} req    - nodejs HTTP request object
 * @param {Object} res    - nodejs HTTP response object
 * @param {Function} next - function to envoke next http handler in chain
 */

/**
 * Registers a handler with the server to use for all HTTP reqeuests
 * where the method and path match their respective parts from the
 * request-url.
 *
 * @param {String} method        - HTTP method to catpure
 * @param {String} path          - the relative path of the handler
 * @param {httpCallback} handler - HTTP request handler to call
 * @returns {Server} a reference to the object instance
 */
Server.prototype.addHandler = function(method, path, handler) {
  this.logger.info('Adding Handler: %s %s', method, path);
  switch(method) {
    case 'post':
    case 'get':
    case 'put':
    case 'delete':
      this.server[method](this.rootPath() + path, handler);
      break;
    case '*':
      this.server.use(handler);
      break;
    default:
      throw 'Bad server handler: ' + method + ' ' + path + ' ' + handler;
  }
  return this;
};

Server.prototype.addModule = function(mod) {
  mod.load(this);
  return this;
};

/**
 * Returns the base url for the running server.
 *
 * @returns {String} protocol://hostname:port
 */
Server.prototype.baseUrl = function() {
  var bp = this.https ? this.config.secure_port : this.config.open_port;
  return this.config.protocol + '://' + this.config.hostname;// + ':' + bp;
};

/**
 * Returns the path root of the server
 *
 * @returns {String} path root of server
 */
Server.prototype.rootPath = function() {
  return this.config.root + '/';
};

/**
 * Starts the server
 *
 * @returns {Server} returns a self reference
 */
Server.prototype.run = function() {
  var notFound;

  this.server.on('after', filter.auditLogger({
    log: this.logger,
    body: true
  }));

  this.server.on('NotFound', function(req, res) {
    var body = JSON.stringify({ error: {
      message: 'Bad request',
      details: req.method + ' ' + req.url
    }});
    res.end(body);
  });

  if(this.config.static) {
    this.server.get(this.config.static.mount+'.*', restify.serveStatic(
      {
        directory: this.config.static.directory,
        default: 'index.html'
      }
    ));
  }

  // start the http redirector if needed
  if(this.http) {
    this.http.listen(this.config.open_port, this.config.address);
  }
  // start the primary server
  this.server.listen(this.http ? this.config.secure_port : this.config.open_port, this.config.address);

  this.running = true;
  this.logger.info('Started Flowsim');
  return this;
};

/**
 * A formatter implementation for the Server.
 *
 * @param {module:utils~Formatter} f - formatter object to use
 * @returns {module:utils~Formatter} a reference to the active formatter
 */
Server.prototype.toFormatter = function(f) {
  f.begin('Server');
  f.addPair('Address', this.config.address);
  f.addPair('Hostname', this.config.hostname);
  f.addPair('TCP Port', this.config.open_port);
  if(this.config.https) {
    f.addPair('TLS Port', this.config.secure_port);
  }
  f.addPair('Protocol', this.config.protocol);
  if(this.config.https) {
    f.addPair('Key', this.config.https.key);
    f.addPair('Cert', this.config.https.cert);
  }
  if(this.config.static) {
    f.addPair('Static', this.config.static.directory);
  }
  f.addPair('Running', this.running);
  f.end();
  return f;
};

/**
 * Attach the basic formatter.toString funcitonality.
 *
 * @returns {String} a stringified version of the Server.
 */
Server.prototype.toString = fmt.toString;

})();
<|endoftext|>


<commit_before>/* Blast - JavaScript Two-Way databinding library
 * Copyright Angel Todorov (attodorov@gmail.com)
 * Licensed under BSD
 */
"use strict";
(function (window, document) {
	var blast = window.blast = window.blast || {}, doc = document;
	var _arrextend = ["pop", "push", "reverse", "shift", "sort", "splice", "unshift"];
	blast.observable = function (val) {
		var current = val;
		var ret = function (retVal) {
			if (!undef(retVal) && retVal !== ret._val) {
				//notify subscribers
				ret.notify(false);
				current = retVal;
				ret.notify(true);
				return ret;
			}
			return current;
		};
		ret.notify = function (end, action) {
			for (var i = 0; i < ret.subs.length; i++) {
				ret.subs[i](current, !end ? true : false, action);
			}
		};
		ret.subs = [];
		ret._val = val;
		ret.__bo = true; //mark it as a Blast observable
		ret(val);
		return ret;
	};
	blast.observableArray = function (arr) {
		arr = arr || [];
		var i;
		var observableArr = blast.observable(arr);
		var _compilefn = function (fn) {
			return function () {
				observableArr.notify(false, fn);
				var ret = observableArr._val[fn].apply(observableArr._val, arguments);
				observableArr.notify(true, fn);
				return ret;
			};
		};
		for (i = 0; i < _arrextend.length; i++) {
			observableArr[_arrextend[i]] = _compilefn(_arrextend[i]);
		}
		return observableArr;
	};
	blast.link = function (elem, meta, data) { // DOM => observables
		var key = meta.key;
		if (data[key].__bo) {
			data[key].subs.push(function (val, beforeEvent) {
				if (!beforeEvent) {
					setval(elem, val);
				}
			});
		}
		elem.addEventListener(meta.event ? meta.event : "change", function () {
			var newVal = getval(elem);
			if (data[key].__bo) { // assume observable
				data[key](newVal);
			} else {
				data[key] = newVal;
			}
		}, false); //don't bubble
		if (undef(meta) || (meta && meta.init !== false)) {
			setval(elem, data[key].__bo ? data[key]() : data[key]); // init
		}
	};
	blast.linkAll = function (prop, meta, model) {
		var elems = elem(prop, meta.parent);
		for (var i = 0; i < elems.length; i++) {
			meta.key = prop;
			blast.link(elems[i], meta, model);
		}
	};
	blast.observe = function (data) { // data is a plain js object/array
		if (undef(data)) {
			return null;
		}
		if (Array.isArray(data)) {
			var observed = [];
			for (var i = 0; i < data.length; i++) {
				var observedObj = observeObj(data[i]);
				observed.push(observeObj(data[i]));
			}
			return observed;
		}
		return observeObj(data);
	};
	blast.bind = function (model, meta) { //two-way: HTML <=> Model
		var m = undef(meta) ? {} : meta;
		var addItem = function (parent, tmpl, meta, prepend) {
			var item = tmpl.cloneNode(true);
			if (prepend) {
				parent.insertBefore(item, parent.firstChild);
			} else {
				parent.appendChild(item);
			}
			meta.parent = item;
		};
		for (var p in model) {
			if (model.hasOwnProperty(p)) { //TODO: handle scope
				var prop = model[p];
				if (Array.isArray(prop) || (prop.__bo && Array.isArray(prop()))) { //also recurse
					var dom = elem(p)[0];//TODO elem() returning > 1
					var tmpl = (dom.firstElementChild || dom.children[0]).cloneNode(true);
					clear(dom);
					if (prop.__bo) { // listen for array notifications
						prop.subs.push(function (arr, before, action) {
							if (!before) { // transaction log, order, batch, etc. ?
								switch (action) {
									case "push":
										addItem(dom, tmpl, m);
										blast.bind(arr[arr.length - 1], m);
										break;
									case "pop":
										dom.removeChild(dom.lastChild);
										break;
									case "shift":
										dom.removeChild(dom.firstChild);
										break;
									case "unshift":
										addItem(dom, tmpl, m, true);
										blast.bind(arr[0], m);
										break;
									case "splice":
										//TODO: check how many items have been added (by comparing prev.length to new.length) & do add
										break;
									case "sort":
										// rebind the whole array
										break;
									default:
										break;
								}
							}
						});
						prop = prop();
					}
					for (var i = 0; i < prop.length; i++) {
						addItem(dom, tmpl, m);
						blast.bind(prop[i], m);
					}
				} else {
					blast.linkAll(p, m, model);
				}
			}
		}
	};
	// convert model to plain js objects
	blast.json = function (model) {
		if (undef(model)) {
			return null;
		}
		if (Array.isArray(model)) {
			var d = [];
			for (var i = 0; i < model.length; i++) {
				d.push(toObj(model[i]));
			}
			return d;
		}
		return toObj(model);
	};
	function observeObj(o) {
		var observed = {}, prop = null;
		for (prop in o) {
			if (o.hasOwnProperty(prop)) {
				observed[prop] = blast.observable(o[prop]);
			}
		}
		return observed;
	}
	function toObj(observable) {
		var obj = {};
		for (var p in observable) {
			if (observable.hasOwnProperty(p)) {
				obj[p] = observable[p]();
			}
		}
		return obj;
	}
	function setval(elem, val) {
		if (elem instanceof window.HTMLInputElement) {
			elem.value = val;
		} else {
			elem.innerHTML = val;
		}
	}
	function getval(elem) {
		if (elem instanceof window.HTMLInputElement) {
			return elem.value;
		}
		return elem.innerHTML; //TODO: parse inner content
	}
	function elem(prop, parent) {
		var root = parent ? parent : doc;
		return root.querySelectorAll("[data-bind=" + prop + "]");
	}
	function clear(elem) {
		while (elem.firstChild) {
			elem.removeChild(elem.firstChild);
		}
	}
	function undef(val) {
		return val === null || typeof (val) === "undefined";
	}
}) (window, document);
//Support for AMD (RequireJS)
if (typeof define === "function" && define.amd) {
    define( "blast", [], function () {
        return window.blast;
    });
}
// support for CommonJS (Node)
if (typeof module !== "undefined" && module.exports) {
	module.exports = window.blast; // works only if window is defined (JSDOM, etc.)
}<commit_msg>fixing<commit_after>/* Blast - JavaScript Two-Way databinding library
 * Copyright Angel Todorov (attodorov@gmail.com)
 * Licensed under BSD
 */
"use strict";
(function (window, document) {
	var blast = window.blast = window.blast || {}, doc = document;
	var _arrextend = ["pop", "push", "reverse", "shift", "sort", "splice", "unshift"];
	blast.observable = function (val) {
		var current = val;
		var ret = function (retVal) {
			if (!undef(retVal) && retVal !== ret._val) {
				//notify subscribers
				ret.notify(false);
				current = retVal;
				ret.notify(true);
				return ret;
			}
			return current;
		};
		ret.notify = function (end, action) {
			for (var i = 0; i < ret.subs.length; i++) {
				ret.subs[i](current, !end ? true : false, action);
			}
		};
		ret.subs = [];
		ret._val = val;
		ret.__bo = true; //mark it as a Blast observable
		ret(val);
		return ret;
	};
	blast.observableArray = function (arr) {
		arr = arr || [];
		var i;
		var observableArr = blast.observable(arr);
		var _compilefn = function (fn) {
			return function () {
				observableArr.notify(false, fn);
				var ret = observableArr._val[fn].apply(observableArr._val, arguments);
				observableArr.notify(true, fn);
				return ret;
			};
		};
		for (i = 0; i < _arrextend.length; i++) {
			observableArr[_arrextend[i]] = _compilefn(_arrextend[i]);
		}
		return observableArr;
	};
	blast.link = function (elem, meta, data) { // DOM => observables
		var key = meta.key;
		if (data[key].__bo) {
			data[key].subs.push(function (val, beforeEvent) {
				if (!beforeEvent) {
					setval(elem, val);
				}
			});
		}
		elem.addEventListener(meta.event ? meta.event : "change", function () {
			var newVal = getval(elem);
			if (data[key].__bo) { // assume observable
				data[key](newVal);
			} else {
				data[key] = newVal;
			}
		}, false); //don't bubble
		if (undef(meta) || (meta && meta.init !== false)) {
			setval(elem, data[key].__bo ? data[key]() : data[key]); // init
		}
	};
	blast.linkAll = function (prop, meta, model) {
		var elems = elem(prop, meta.parent);
		for (var i = 0; i < elems.length; i++) {
			meta.key = prop;
			blast.link(elems[i], meta, model);
		}
	};
	blast.observe = function (data) { // data is a plain js object/array
		if (undef(data)) {
			return null;
		}
		if (Array.isArray(data)) {
			var observed = [];
			for (var i = 0; i < data.length; i++) {
				observed.push(observeObj(data[i]));
			}
			return observed;
		}
		return observeObj(data);
	};
	blast.bind = function (model, meta) { //two-way: HTML <=> Model
		var m = undef(meta) ? {} : meta;
		var addItem = function (parent, tmpl, meta, prepend) {
			var item = tmpl.cloneNode(true);
			if (prepend) {
				parent.insertBefore(item, parent.firstChild);
			} else {
				parent.appendChild(item);
			}
			meta.parent = item;
		};
		for (var p in model) {
			if (model.hasOwnProperty(p)) { //TODO: handle scope
				var prop = model[p];
				if (Array.isArray(prop) || (prop.__bo && Array.isArray(prop()))) { //also recurse
					var dom = elem(p)[0];//TODO elem() returning > 1
					var tmpl = (dom.firstElementChild || dom.children[0]).cloneNode(true);
					clear(dom);
					if (prop.__bo) { // listen for array notifications
						prop.subs.push(function (arr, before, action) {
							if (!before) { // transaction log, order, batch, etc. ?
								switch (action) {
									case "push":
										addItem(dom, tmpl, m);
										blast.bind(arr[arr.length - 1], m);
										break;
									case "pop":
										dom.removeChild(dom.lastChild);
										break;
									case "shift":
										dom.removeChild(dom.firstChild);
										break;
									case "unshift":
										addItem(dom, tmpl, m, true);
										blast.bind(arr[0], m);
										break;
									case "splice":
										//TODO: check how many items have been added (by comparing prev.length to new.length) & do add
										break;
									case "sort":
										// rebind the whole array
										break;
									default:
										break;
								}
							}
						});
						prop = prop();
					}
					for (var i = 0; i < prop.length; i++) {
						addItem(dom, tmpl, m);
						blast.bind(prop[i], m);
					}
				} else {
					blast.linkAll(p, m, model);
				}
			}
		}
	};
	// convert model to plain js objects
	blast.json = function (model) {
		if (undef(model)) {
			return null;
		}
		if (Array.isArray(model)) {
			var d = [];
			for (var i = 0; i < model.length; i++) {
				d.push(toObj(model[i]));
			}
			return d;
		}
		return toObj(model);
	};
	function observeObj(o) {
		var observed = {}, prop = null;
		for (prop in o) {
			if (o.hasOwnProperty(prop)) {
				observed[prop] = blast.observable(o[prop]);
			}
		}
		return observed;
	}
	function toObj(observable) {
		var obj = {};
		for (var p in observable) {
			if (observable.hasOwnProperty(p)) {
				obj[p] = observable[p]();
			}
		}
		return obj;
	}
	function setval(elem, val) {
		if (elem instanceof window.HTMLInputElement) {
			elem.value = val;
		} else {
			elem.innerHTML = val;
		}
	}
	function getval(elem) {
		if (elem instanceof window.HTMLInputElement) {
			return elem.value;
		}
		return elem.innerHTML; //TODO: parse inner content
	}
	function elem(prop, parent) {
		var root = parent ? parent : doc;
		return root.querySelectorAll("[data-bind=" + prop + "]");
	}
	function clear(elem) {
		while (elem.firstChild) {
			elem.removeChild(elem.firstChild);
		}
	}
	function undef(val) {
		return val === null || typeof (val) === "undefined";
	}
}) (window, document);
//Support for AMD (RequireJS)
if (typeof define === "function" && define.amd) {
    define( "blast", [], function () {
        return window.blast;
    });
}
// support for CommonJS (Node)
if (typeof module !== "undefined" && module.exports) {
	module.exports = window.blast; // works only if window is defined (JSDOM, etc.)
}<|endoftext|>


<commit_before>var Board = {
  init : function(options){

    this.canvas = document.createElement("canvas");
    document.body.appendChild(this.canvas);
    this.context = this.canvas.getContext('2d');
    document.body.style.cssText = "padding: 0px;margin: 0px;overflow: hidden;";
    this.setInitValue(options||{});
    this.resize();
    this.bind();

  },
  setInitValue : function(options){
    this.cursorPath = options.cursorPath || "../img/eraser.png";
    this.lineColor = options.lineColor||"#ffffff";
    this.lineWidth = options.lineWidth||10;
    this.currentLineWidth = this.lineWidth;
    this.backgroundColor = options.backgroundColor||"#000";
    this.canvas.style.backgroundColor = this.backgroundColor;
  },
  fontSize : function(num){
    this.lineWidth = this.lineWidth + num;
  },
  color : function(color){
    this.lineColor = color;
  },
  mode : function(){
    if(this.canvas.style.cursor != ""){
      this.lineWidth = this.currentLineWidth;
      this.draw();
    }else{
      this.currentLineWidth = this.lineWidth;
      this.lineWidth = 30;
      this.eraser();
    }
  },
  eraser : function(){
    this.oldLineColor = this.lineColor;
    this.oldLineWidth = this.lineWidth;
    this.color(this.backgroundColor);
    this.canvas.style.cursor =  "url("+this.cursorPath+") 0 15, auto";
  },
  draw : function(){
    this.color(this.oldLineColor);
    this.canvas.style.cursor =  "";
  },
  bind : function(){
    this.canvas.addEventListener("mousedown",this.mousedown.bind(this));
    this.mousemoveForBind = this.mousemove.bind(this);
    this.mouseupForBind = this.mouseup.bind(this);
  },
  mousedown : function(e){
    this.canvas.addEventListener("mousemove",this.mousemoveForBind);
    this.canvas.addEventListener("mouseup",this.mouseupForBind);

    this.context.beginPath();
    this.context.moveTo(e.pageX, e.pageY);
  },
  mousemove : function(e){
    var context = this.context;
    context.lineTo(e.pageX, e.pageY);
    context.strokeStyle = this.lineColor;
    context.lineWidth = this.lineWidth;
    context.stroke();
  },
  mouseup : function(e){
    this.canvas.removeEventListener("mousemove",this.mousemoveForBind);
    this.canvas.removeEventListener("mouseup",this.mouseupForBind);
  },
  resize : function(){
    this.canvas.width = document.documentElement.clientWidth;
    this.canvas.height = document.documentElement.clientHeight;
  }
};

<commit_msg>test1<commit_after>var Board = {
  init : function(options){

    this.canvas = document.createElement("canvas");
    document.body.appendChild(this.canvas);
    this.context = this.canvas.getContext('2d');
    document.body.style.cssText = "padding: 0px;margin: 0px;overflow: hidden;";
    this.setInitValue(options||{});
    this.resize();
    this.bind();

  },
  setInitValue : function(options){

    this.cursorPath = options.cursorPath || "../img/eraser.png";
    this.lineColor = options.lineColor||"#ffffff";
    this.lineWidth = options.lineWidth||10;
    this.currentLineWidth = this.lineWidth;
    this.backgroundColor = options.backgroundColor||"#000";
    this.canvas.style.backgroundColor = this.backgroundColor;
  },
  fontSize : function(num){
    this.lineWidth = this.lineWidth + num;
  },
  color : function(color){
    this.lineColor = color;
  },
  mode : function(){
    if(this.canvas.style.cursor != ""){
      this.lineWidth = this.currentLineWidth;
      this.draw();
    }else{
      this.currentLineWidth = this.lineWidth;
      this.lineWidth = 30;
      this.eraser();
    }
  },
  eraser : function(){
    this.oldLineColor = this.lineColor;
    this.oldLineWidth = this.lineWidth;
    this.color(this.backgroundColor);
    this.canvas.style.cursor =  "url("+this.cursorPath+") 0 15, auto";
  },
  draw : function(){
    this.color(this.oldLineColor);
    this.canvas.style.cursor =  "";
  },
  bind : function(){
    this.canvas.addEventListener("mousedown",this.mousedown.bind(this));
    this.mousemoveForBind = this.mousemove.bind(this);
    this.mouseupForBind = this.mouseup.bind(this);
  },
  mousedown : function(e){
    this.canvas.addEventListener("mousemove",this.mousemoveForBind);
    this.canvas.addEventListener("mouseup",this.mouseupForBind);

    this.context.beginPath();
    this.context.moveTo(e.pageX, e.pageY);
  },
  mousemove : function(e){
    var context = this.context;
    context.lineTo(e.pageX, e.pageY);
    context.strokeStyle = this.lineColor;
    context.lineWidth = this.lineWidth;
    context.stroke();
  },
  mouseup : function(e){
    this.canvas.removeEventListener("mousemove",this.mousemoveForBind);
    this.canvas.removeEventListener("mouseup",this.mouseupForBind);
  },
  resize : function(){
    this.canvas.width = document.documentElement.clientWidth;
    this.canvas.height = document.documentElement.clientHeight;
  }
};

<|endoftext|>


<commit_before>/* eslint-env browser */

import './lib/displayProjectsGraph';

// TODO: Hook this up to the log out button on the graph view. It is currently not hooked up to anything,
// but functions properly
document.addEventListener('DOMContentLoaded', () => {
  document.getElementById('logOut').addEventListener('click', () => {
    document.location.href = '/logout';
  });
});

document.addEventListener('DOMContentLoaded', () => {
  document.getElementById('projectList').addEventListener('click', event => {
    if (event.target.nodeName === 'A') {
      let selectedProject = event.target.getAttributeNode('data-id').nodeValue;
      let hierarchy = getHierarchyRequest('/hierarchy', selectedProject);
      let graph = getGraphRequest('/graph', selectedProject);
      // Temporary statement for linter
      console.log(graph + hierarchy);
      // TODO: change query parameter (dependent on hierarchy endpoint story)
    }
  });
});

/**
 * Makes an AJAX request to the provided endpoint for the item hierarchy tree.
 *
 * @param url
 * @param projectId
 * @returns {*}
 */
function getHierarchyRequest (url, projectId) {
  let hierarchy = {};
  let httpRequest = new XMLHttpRequest();
  httpRequest.onreadystatechange = () => {
    if (httpRequest.readyState === XMLHttpRequest.DONE) {
      if (httpRequest.status === 200) {
        hierarchy = JSON.parse(httpRequest.responseText);
        console.log(httpRequest.responseText);
      } else {
        console.log('There was a problem requesting to the hierarchy endpoint.');
      }
    }
  };
  httpRequest.open('GET', url);
  httpRequest.send('project=' + projectId);
  return hierarchy;
}

/**
 * Makes an AJAX request to the provided endpoint for the project graph.
 *
 * @param url
 * @param projectId
 * @returns {*}
 */
function getGraphRequest (url, projectId) {
  let graph = {};
  let httpRequest = new XMLHttpRequest();
  httpRequest.onreadystatechange = () => {
    if (httpRequest.readyState === XMLHttpRequest.DONE) {
      if (httpRequest.status === 200) {
        graph = JSON.parse(httpRequest.responseText);
        console.log(httpRequest.responseText);
      } else {
        console.log('There was a problem requesting to the graph endpoint.');
      }
    }
  };
  httpRequest.open('GET', url);
  httpRequest.send('project=' + projectId);
  return graph;
}
<commit_msg>Refactor project click handler<commit_after>/* eslint-env browser */

import './lib/displayProjectsGraph';

// TODO: Hook this up to the log out button on the graph view. It is currently not hooked up to anything,
// but functions properly
document.addEventListener('DOMContentLoaded', () => {
  document.getElementById('logOut').addEventListener('click', () => {
    document.location.href = '/logout';
  });
});

/**
 * Query the page for a set of elements given a CSS selector.
 *
 * @param selector CSS selector
 * @returns {*} Array of matched elements
 */
function querySelectorAll(selector) {
  return Array.prototype.slice.call(document.querySelectorAll(selector));
}

document.addEventListener('DOMContentLoaded', () => {
  querySelectorAll('#projects a').forEach(projectAnchor => {
    projectAnchor.addEventListener('click', event => {

      let selectedProject = event.target.getAttribute('data-id');
      let hierarchy = getHierarchyRequest('/hierarchy', selectedProject);
      let graph = getGraphRequest('/graph', selectedProject);
      // Temporary statement for linter
      console.log(graph + hierarchy);
      // TODO: change query parameter (dependent on hierarchy endpoint story)
    });
  });
});

/**
 * Makes an AJAX request to the provided endpoint for the item hierarchy tree.
 *
 * @param url
 * @param projectId
 * @returns {*}
 */
function getHierarchyRequest (url, projectId) {
  let hierarchy = {};
  // TODO: Refactor to use the request module
  let httpRequest = new XMLHttpRequest();
  httpRequest.onreadystatechange = () => {
    if (httpRequest.readyState === XMLHttpRequest.DONE) {
      if (httpRequest.status === 200) {
        hierarchy = JSON.parse(httpRequest.responseText);
        console.log(httpRequest.responseText);
      } else {
        console.log('There was a problem requesting to the hierarchy endpoint.');
      }
    }
  };
  httpRequest.open('GET', url);
  httpRequest.send('project=' + projectId);
  return hierarchy;
}

/**
 * Makes an AJAX request to the provided endpoint for the project graph.
 *
 * @param url
 * @param projectId
 * @returns {*}
 */
function getGraphRequest (url, projectId) {
  let graph = {};
  // TODO: Refactor to use the request module
  let httpRequest = new XMLHttpRequest();
  httpRequest.onreadystatechange = () => {
    if (httpRequest.readyState === XMLHttpRequest.DONE) {
      if (httpRequest.status === 200) {
        graph = JSON.parse(httpRequest.responseText);
        console.log(httpRequest.responseText);
      } else {
        console.log('There was a problem requesting to the graph endpoint.');
      }
    }
  };
  httpRequest.open('GET', url);
  httpRequest.send('project=' + projectId);
  return graph;
}
<|endoftext|>


<commit_before>var UID = "_U_";
var MULTI_TYPE = "_multi";

var STATUS = {
  UNKNOWN : 'UNKNOWN',
  PENDING : 'PENDING',
  RUNNING : 'RUNNING',
  DONE : 'DONE',
  FAILED : 'FAILED'
};

// *** Node *******************************************************************
function Node(id, name, type, status) {
  if (typeof (name) === 'undefined') {
    name = id;
  }
  if (typeof (type) === 'undefined') {
    type = 'analysis';
  }
  if (typeof (status) === 'undefined') {
    status = STATUS.UNKNOWN;
  }
  if (typeof STATUS[status] === 'undefined') {
    throw Error("Unknown status '" + status + "' for node " + name + "(id="
        + id + ")");
  }
  this.id = id;
  this.name = name;
  this.isMulti = (type.search(/_multi$/) >= 0);
  this.type = this.isMulti ? type.substr(0, type.length - MULTI_TYPE.length)
      : type;
  this.status = status;
}

Node.prototype.isMdo = function() {
  return this.type === "mdo";
};

Node.prototype.getScenarioId = function() {
  if (this.isMdo()) {
    var idxscn = this.name.indexOf("_scn-");
    if (idxscn === -1) {
      console.log("Warning: MDO Scenario not found. "
          + "Bad type or name for node: " + JSON.stringify(this));
      return null;
    }
    return this.name.substr(idxscn + 1);
  }
  return null;
};

// *** Edge *******************************************************************
function Edge(from, to, nameOrVars, row, col, isMulti) {
  this.id = "link_" + from + "_" + to;
  if (typeof (nameOrVars) === "string") {
    this.name = nameOrVars;
    this.vars = {};
    let vars = this.name.split(',');
    vars.forEach((n, i) => this.vars[i] = n.trim());
  } else { // vars = {id: name, ...}
    this.vars = nameOrVars;
    let names = [];
    for (let k in this.vars) {
      names.push(this.vars[k]);
    }
    this.name = names.join(", ")
  }
  this.row = row;
  this.col = col;
  this.iotype = row < col ? "in" : "out";
  this.io = {
    fromU : (from === UID),
    toU : (to === UID),
  };
  this.isMulti = isMulti;
}

Edge.prototype.isIO = function() {
  return this.io.fromU || this.io.toU;
};

Edge.prototype.addVar = function(nameOrVar) {
  if (typeof(nameOrVar) === "string") {
    if (this.name==="") {
      this.name=nameOrVar;
    } else {
      this.name+=", "+nameOrVar;
    }
    this.vars[this.vars.length] = nameOrVar;
  } else {
    for (let k in nameOrVar) {
      this.vars[k] = nameOrVar[k];
      let names = [];
      for (let k in this.vars) {
        names.push(this.vars[k]);
      }
      this.name = names.join(", ")
    }
  }
}

Edge.prototype.removeVar = function(nameOrId) {
  let found = false;
  for (k in this.nameOrVars) {
    if (k === nameOrId) {
      this.nameOrVars.delete(k);
      found = true;
    }
  }
  if (!found) {
    for (k in this.nameOrVars) {
      if (this.nameOrVars[k] === nameOrId) {
        this.nameOrVars.delete(k);
        found = true;
      }
    }
  }
  if (found) {
    let names = [];
    for (let k in this.vars) {
      names.push(this.vars[k]);
    }
    this.name = names.join(", ");
  }
}

// *** Graph ******************************************************************
function Graph(mdo, refname) {
  this.nodes = [ new Node(UID, UID, "user") ];
  this.edges = [];
  this.chains = [];
  this.refname = refname || "";
  this._newNodeCount = 0;

  var numbering = Graph.number(mdo.workflow);
  var numPrefixes = numbering.toNum;
  this.nodesByStep = numbering.toNode;

  mdo.nodes.forEach(function(item) {
    var num = numPrefixes[item.id];
    this.nodes.push(new Node(item.id, num ? num + ":" + item.name : item.name,
        item.type, item.status));
  }, this);

  if (mdo.edges) {
    mdo.edges.forEach(function(item) {
      this.addEdge(item.from, item.to, item.vars?item.vars:item.name);
    }, this);
  }

  if (mdo.workflow) {
    this._makeChaining(mdo.workflow);
  }
}

Graph.NODE_STATUS = STATUS;

Graph.prototype._makeChaining = function(workflow) {
  var echain = Graph.expand(workflow);
  echain.forEach(function(leafChain) {
    if (leafChain.length < 2) {
      throw new Error("Bad process chain (" + leafChain.length + "elt)");
    } else {
      this.chains.push([]);
      var ids = this.nodes.map(function(elt) {
        return elt.id;
      });
      leafChain.forEach(function(item, j) {
        if (j !== 0) {
          var idA = ids.indexOf(leafChain[j - 1]);
          if (idA < 0) {
            throw new Error("Process chain element (" + leafChain[j - 1]
                + ") not found");
          }
          var idB = ids.indexOf(leafChain[j]);
          if (idB < 0) {
            throw new Error("Process chain element (" + leafChain[j]
                + ") not found");
          }
          if (idA !== idB) {
            this.chains[this.chains.length - 1].push([ idA, idB ]);
          }
        }
      }, this);
    }
  }, this);
};

Graph.prototype.idxOf = function(nodeId) {
  return this.nodes.map(function(elt) {
    return elt.id;
  }).indexOf(nodeId);
};

Graph.prototype.getNode = function(nodeId) {
  var theNode;
  this.nodes.forEach(function(node) {
    if (node.id === nodeId) {
      theNode = node;
    }
  }, this);
  return theNode;
};

Graph.prototype.getNodeFromIndex = function(idx) {
  var node;
  if (idx >= 0 && idx < this.nodes.length) {
    node = this.nodes[idx];
  } else {
    throw Error("Index out of range : " + idx + " not in [0, "
        + (this.nodes.length - 1) + "]");
  }
  return node;
}

Graph.prototype.addNode = function(nodeName) {
  this._newNodeCount += 1;
  this.nodes
      .push(new Node("NewNode" + this._newNodeCount, nodeName, "analysis"));
};

Graph.prototype.removeNode = function(index) {
  var self = this;
  // Update edges
  var edges = this.findEdgesOf(index);
  edges.toRemove.forEach(function(edge) {
    var idx = self.edges.indexOf(edge);
    if (idx > -1) {
      self.edges.splice(idx, 1);
    }
  }, this);
  edges.toShift.forEach(function(edge) {
    if (edge.row > 1) {
      edge.row -= 1;
    }
    if (edge.col > 1) {
      edge.col -= 1;
    }
  }, this);

  // Update nodes
  this.nodes.splice(index, 1);
};

Graph.prototype.moveLeft = function(index) {
  if (index>1) {
    let tmp = this.nodes[index-1];
    this.nodes[index-1] = this.nodes[index];
    this.nodes[index] = tmp;
  }
};

Graph.prototype.moveRight = function(index) {
  if (index<this.nodes.length-1) {
    let tmp = this.nodes[index+1];
    this.nodes[index+1] = this.nodes[index];
    this.nodes[index] = tmp;
  }
};

Graph.prototype.addEdge = function(nodeIdFrom, nodeIdTo, nameOrVar) {
  var idA = this.idxOf(nodeIdFrom);
  var idB = this.idxOf(nodeIdTo);
  var isMulti = this.nodes[idA].isMulti || this.nodes[idB].isMulti;
  this.edges
      .push(new Edge(nodeIdFrom, nodeIdTo, nameOrVar, idA, idB, isMulti));
}

Graph.prototype.removeEdge = function(nodeIdFrom, nodeIdTo) {
  let edge = this.findEdge(nodeIdFrom, nodeIdTo);
  this.edges.splice(edge.index, 1);
}

Graph.prototype.addEdgeVar = function(nodeIdFrom, nodeIdTo, nameOrVar) {
  let edge = this.findEdge(nodeIdFrom, nodeIdTo).element;
  if (edge) {
    edge.addVar(nameOrVar);
  } else {
    this.addEdge(nodeIdFrom, nodeIdTo, nameOrVar)
  }
}

Graph.prototype.findEdgesOf = function(nodeIdx) {
  var toRemove = [];
  var toShift = [];
  this.edges.forEach(function(edge) {
    if ((edge.row === nodeIdx) || (edge.col === nodeIdx)) {
      toRemove.push(edge);
    } else if ((edge.row > nodeIdx) || (edge.col > nodeIdx)) {
      toShift.push(edge);
    }
  }, this);
  return {
    toRemove : toRemove,
    toShift : toShift
  };
};

Graph.prototype.findEdge = function(nodeIdFrom, nodeIdTo) {
  let element, index;
  let idxFrom = this.idxOf(nodeIdFrom);
  let idxTo = this.idxOf(nodeIdTo);
  this.edges.some(function(edge, i) {
    if ((edge.row === idxFrom) && (edge.col === idxTo)) {
      if (element) {
        throw Error('edge have be uniq between two nodes, but got: '+
            JSON.stringify(element)+ ' and '+JSON.stringify(edge))
      }
      element = edge;
      index = i;
      return true;
    }
  }, this);
  return {element, index};
}

function _expand(workflow) {
  var ret = [];
  var prev;
  workflow.forEach(function(item) {
    if (item instanceof Array) {
      if (item[0].hasOwnProperty('parallel')) {
        if (prev) {
          ret = ret.slice(0, ret.length - 1).concat(
              item[0].parallel.map(function(elt) {
                return [ prev ].concat(_expand([ elt ]), prev);
              }));
        } else {
          throw new Error("Bad workflow structure : "
              + "cannot parallel loop without previous starting point.");
        }
      } else if (prev) {
        ret = ret.concat(_expand(item), prev);
      } else {
        ret = ret.concat(_expand(item));
      }
      prev = ret[ret.length - 1];
    } else if (item.hasOwnProperty('parallel')) {
      if (prev) {
        ret = ret.slice(0, ret.length - 1).concat(
            item.parallel.map(function(elt) {
              return [ prev ].concat(_expand([ elt ]));
            }));
      } else {
        ret = ret.concat(item.parallel.map(function(elt) {
          return _expand([ elt ]);
        }));
      }
      prev = undefined;
    } else {
      var i = ret.length - 1;
      var flagParallel = false;
      while (i >= 0 && (ret[i] instanceof Array)) {
        ret[i] = ret[i].concat(item);
        i -= 1;
        flagParallel = true;
      }
      if (!flagParallel) {
        ret.push(item);
      }
      prev = item;
    }
  });
  return ret;
}

Graph._isPatchNeeded = function(toBePatched) {
  var lastElts = toBePatched.map(function(arr) {
    return arr[arr.length - 1];
  });
  var lastElt = lastElts[0];
  for (var i = 0; i < lastElts.length; i++) {
    if (lastElts[i] !== lastElt) {
      return true;
    }
  }
  return false;
};

Graph._patchParallel = function(expanded) {
  var toBePatched = [];
  expanded.forEach(function(elt) {
    if (elt instanceof Array) {
      toBePatched.push(elt);
    } else if (Graph._isPatchNeeded(toBePatched)) {
      toBePatched.forEach(function(arr) {
        arr.push(elt);
      }, this);
    }
  }, this);
};

Graph.expand = function(item) {
  var expanded = _expand(item);
  var result = [];
  var current = [];
  // first pass to add missing 'end link' in case of parallel branches at the
  // end of a loop
  // [a, [b, d], [b, c], a] -> [a, [b, d, a], [b, c, a], a]
  Graph._patchParallel(expanded);
  // [a, aa, [b, c], d] -> [[a, aa, b], [b,c], [c, d]]
  expanded.forEach(function(elt) {
    if (elt instanceof Array) {
      if (current.length > 0) {
        current.push(elt[0]);
        result.push(current);
        current = [];
      }
      result.push(elt);
    } else {
      if (result.length > 0 && current.length === 0) {
        var lastChain = result[result.length - 1];
        var lastElt = lastChain[lastChain.length - 1];
        current.push(lastElt);
      }
      current.push(elt);
    }
  }, this);
  if (current.length > 0) {
    result.push(current);
  }
  return result;
};

Graph.number = function(workflow, num) {
  num = (typeof num === 'undefined') ? 0 : num;
  var toNum = {};
  var toNode = [];

  function setStep(step, nodeId) {
    if (step in toNode) {
      toNode[step].push(nodeId);
    } else {
      toNode[step] = [ nodeId ];
    }
  }

  function setNum(nodeId, beg, end) {
    if (end === undefined) {
      num = String(beg);
      setStep(beg, nodeId);
    } else {
      num = end + "-" + beg;
      setStep(end, nodeId);
    }
    if (nodeId in toNum) {
      toNum[nodeId] += "," + num;
    } else {
      toNum[nodeId] = num;
    }
  }

  function _number(wks, num) {
    var ret = 0;
    if (wks instanceof Array) {
      if (wks.length === 0) {
        ret = num;
      } else if (wks.length === 1) {
        ret = _number(wks[0], num);
      } else {
        var head = wks[0];
        var tail = wks.slice(1);
        var beg = _number(head, num);
        if (tail[0] instanceof Array) {
          var end = _number(tail[0], beg);
          setNum(head, beg, end);
          beg = end + 1;
          tail.shift();
        }
        ret = _number(tail, beg);
      }
    } else if ((wks instanceof Object) && 'parallel' in wks) {
      var nums = wks.parallel.map(function(branch) {
        return _number(branch, num);
      });
      ret = Math.max.apply(null, nums);
    } else {
      setNum(wks, num);
      ret = num + 1;
    }
    return ret;
  }

  _number(workflow, num);
  // console.log('toNodes=', JSON.stringify(toNode));
  // console.log('toNum=',JSON.stringify(toNum));
  return {
    toNum : toNum,
    toNode : toNode
  };
};

module.exports = Graph;
<commit_msg>raise error on bad indexOf<commit_after>var UID = "_U_";
var MULTI_TYPE = "_multi";

var STATUS = {
  UNKNOWN : 'UNKNOWN',
  PENDING : 'PENDING',
  RUNNING : 'RUNNING',
  DONE : 'DONE',
  FAILED : 'FAILED'
};

// *** Node *******************************************************************
function Node(id, name, type, status) {
  if (typeof (name) === 'undefined') {
    name = id;
  }
  if (typeof (type) === 'undefined') {
    type = 'analysis';
  }
  if (typeof (status) === 'undefined') {
    status = STATUS.UNKNOWN;
  }
  if (typeof STATUS[status] === 'undefined') {
    throw Error("Unknown status '" + status + "' for node " + name + "(id="
        + id + ")");
  }
  this.id = id;
  this.name = name;
  this.isMulti = (type.search(/_multi$/) >= 0);
  this.type = this.isMulti ? type.substr(0, type.length - MULTI_TYPE.length)
      : type;
  this.status = status;
}

Node.prototype.isMdo = function() {
  return this.type === "mdo";
};

Node.prototype.getScenarioId = function() {
  if (this.isMdo()) {
    var idxscn = this.name.indexOf("_scn-");
    if (idxscn === -1) {
      console.log("Warning: MDO Scenario not found. "
          + "Bad type or name for node: " + JSON.stringify(this));
      return null;
    }
    return this.name.substr(idxscn + 1);
  }
  return null;
};

// *** Edge *******************************************************************
function Edge(from, to, nameOrVars, row, col, isMulti) {
  this.id = "link_" + from + "_" + to;
  if (typeof (nameOrVars) === "string") {
    this.name = nameOrVars;
    this.vars = {};
    let vars = this.name.split(',');
    vars.forEach((n, i) => this.vars[i] = n.trim());
  } else { // vars = {id: name, ...}
    this.vars = nameOrVars;
    let names = [];
    for (let k in this.vars) {
      names.push(this.vars[k]);
    }
    this.name = names.join(", ")
  }
  this.row = row;
  this.col = col;
  this.iotype = row < col ? "in" : "out";
  this.io = {
    fromU : (from === UID),
    toU : (to === UID),
  };
  this.isMulti = isMulti;
}

Edge.prototype.isIO = function() {
  return this.io.fromU || this.io.toU;
};

Edge.prototype.addVar = function(nameOrVar) {
  if (typeof(nameOrVar) === "string") {
    if (this.name==="") {
      this.name=nameOrVar;
    } else {
      this.name+=", "+nameOrVar;
    }
    this.vars[this.vars.length] = nameOrVar;
  } else {
    for (let k in nameOrVar) {
      this.vars[k] = nameOrVar[k];
      let names = [];
      for (let k in this.vars) {
        names.push(this.vars[k]);
      }
      this.name = names.join(", ")
    }
  }
}

Edge.prototype.removeVar = function(nameOrId) {
  let found = false;
  for (k in this.nameOrVars) {
    if (k === nameOrId) {
      this.nameOrVars.delete(k);
      found = true;
    }
  }
  if (!found) {
    for (k in this.nameOrVars) {
      if (this.nameOrVars[k] === nameOrId) {
        this.nameOrVars.delete(k);
        found = true;
      }
    }
  }
  if (found) {
    let names = [];
    for (let k in this.vars) {
      names.push(this.vars[k]);
    }
    this.name = names.join(", ");
  }
}

// *** Graph ******************************************************************
function Graph(mdo, refname) {
  this.nodes = [ new Node(UID, UID, "user") ];
  this.edges = [];
  this.chains = [];
  this.refname = refname || "";
  this._newNodeCount = 0;

  var numbering = Graph.number(mdo.workflow);
  var numPrefixes = numbering.toNum;
  this.nodesByStep = numbering.toNode;

  mdo.nodes.forEach(function(item) {
    var num = numPrefixes[item.id];
    this.nodes.push(new Node(item.id, num ? num + ":" + item.name : item.name,
        item.type, item.status));
  }, this);

  if (mdo.edges) {
    mdo.edges.forEach(function(item) {
      this.addEdge(item.from, item.to, item.vars?item.vars:item.name);
    }, this);
  }

  if (mdo.workflow) {
    this._makeChaining(mdo.workflow);
  }
}

Graph.NODE_STATUS = STATUS;

Graph.prototype._makeChaining = function(workflow) {
  var echain = Graph.expand(workflow);
  echain.forEach(function(leafChain) {
    if (leafChain.length < 2) {
      throw new Error("Bad process chain (" + leafChain.length + "elt)");
    } else {
      this.chains.push([]);
      var ids = this.nodes.map(function(elt) {
        return elt.id;
      });
      leafChain.forEach(function(item, j) {
        if (j !== 0) {
          var idA = ids.indexOf(leafChain[j - 1]);
          if (idA < 0) {
            throw new Error("Process chain element (" + leafChain[j - 1]
                + ") not found");
          }
          var idB = ids.indexOf(leafChain[j]);
          if (idB < 0) {
            throw new Error("Process chain element (" + leafChain[j]
                + ") not found");
          }
          if (idA !== idB) {
            this.chains[this.chains.length - 1].push([ idA, idB ]);
          }
        }
      }, this);
    }
  }, this);
};

Graph.prototype.idxOf = function(nodeId) {
  let idx = this.nodes.map(function(elt) {
    return elt.id;
  }).indexOf(nodeId);
  if (idx<0) {
    throw new Error("Graph.idxOf: "+nodeId+" not found in "+JSON.stringify(this.nodes));
  }
  return idx;
};

Graph.prototype.getNode = function(nodeId) {
  var theNode;
  this.nodes.forEach(function(node) {
    if (node.id === nodeId) {
      theNode = node;
    }
  }, this);
  return theNode;
};

Graph.prototype.getNodeFromIndex = function(idx) {
  var node;
  if (idx >= 0 && idx < this.nodes.length) {
    node = this.nodes[idx];
  } else {
    throw new Error("Index out of range : " + idx + " not in [0, "
        + (this.nodes.length - 1) + "]");
  }
  return node;
}

Graph.prototype.addNode = function(nodeName) {
  this._newNodeCount += 1;
  this.nodes
      .push(new Node("NewNode" + this._newNodeCount, nodeName, "analysis"));
};

Graph.prototype.removeNode = function(index) {
  var self = this;
  // Update edges
  var edges = this.findEdgesOf(index);
  edges.toRemove.forEach(function(edge) {
    var idx = self.edges.indexOf(edge);
    if (idx > -1) {
      self.edges.splice(idx, 1);
    }
  }, this);
  edges.toShift.forEach(function(edge) {
    if (edge.row > 1) {
      edge.row -= 1;
    }
    if (edge.col > 1) {
      edge.col -= 1;
    }
  }, this);

  // Update nodes
  this.nodes.splice(index, 1);
};

Graph.prototype.moveLeft = function(index) {
  if (index>1) {
    let tmp = this.nodes[index-1];
    this.nodes[index-1] = this.nodes[index];
    this.nodes[index] = tmp;
  }
};

Graph.prototype.moveRight = function(index) {
  if (index<this.nodes.length-1) {
    let tmp = this.nodes[index+1];
    this.nodes[index+1] = this.nodes[index];
    this.nodes[index] = tmp;
  }
};

Graph.prototype.addEdge = function(nodeIdFrom, nodeIdTo, nameOrVar) {
  var idA = this.idxOf(nodeIdFrom);
  var idB = this.idxOf(nodeIdTo);
  var isMulti = this.nodes[idA].isMulti || this.nodes[idB].isMulti;
  this.edges
      .push(new Edge(nodeIdFrom, nodeIdTo, nameOrVar, idA, idB, isMulti));
}

Graph.prototype.removeEdge = function(nodeIdFrom, nodeIdTo) {
  let edge = this.findEdge(nodeIdFrom, nodeIdTo);
  this.edges.splice(edge.index, 1);
}

Graph.prototype.addEdgeVar = function(nodeIdFrom, nodeIdTo, nameOrVar) {
  let edge = this.findEdge(nodeIdFrom, nodeIdTo).element;
  if (edge) {
    edge.addVar(nameOrVar);
  } else {
    this.addEdge(nodeIdFrom, nodeIdTo, nameOrVar)
  }
}

Graph.prototype.findEdgesOf = function(nodeIdx) {
  var toRemove = [];
  var toShift = [];
  this.edges.forEach(function(edge) {
    if ((edge.row === nodeIdx) || (edge.col === nodeIdx)) {
      toRemove.push(edge);
    } else if ((edge.row > nodeIdx) || (edge.col > nodeIdx)) {
      toShift.push(edge);
    }
  }, this);
  return {
    toRemove : toRemove,
    toShift : toShift
  };
};

Graph.prototype.findEdge = function(nodeIdFrom, nodeIdTo) {
  let element, index;
  let idxFrom = this.idxOf(nodeIdFrom);
  let idxTo = this.idxOf(nodeIdTo);
  this.edges.some(function(edge, i) {
    if ((edge.row === idxFrom) && (edge.col === idxTo)) {
      if (element) {
        throw Error('edge have be uniq between two nodes, but got: '+
            JSON.stringify(element)+ ' and '+JSON.stringify(edge))
      }
      element = edge;
      index = i;
      return true;
    }
  }, this);
  return {element, index};
}

function _expand(workflow) {
  var ret = [];
  var prev;
  workflow.forEach(function(item) {
    if (item instanceof Array) {
      if (item[0].hasOwnProperty('parallel')) {
        if (prev) {
          ret = ret.slice(0, ret.length - 1).concat(
              item[0].parallel.map(function(elt) {
                return [ prev ].concat(_expand([ elt ]), prev);
              }));
        } else {
          throw new Error("Bad workflow structure : "
              + "cannot parallel loop without previous starting point.");
        }
      } else if (prev) {
        ret = ret.concat(_expand(item), prev);
      } else {
        ret = ret.concat(_expand(item));
      }
      prev = ret[ret.length - 1];
    } else if (item.hasOwnProperty('parallel')) {
      if (prev) {
        ret = ret.slice(0, ret.length - 1).concat(
            item.parallel.map(function(elt) {
              return [ prev ].concat(_expand([ elt ]));
            }));
      } else {
        ret = ret.concat(item.parallel.map(function(elt) {
          return _expand([ elt ]);
        }));
      }
      prev = undefined;
    } else {
      var i = ret.length - 1;
      var flagParallel = false;
      while (i >= 0 && (ret[i] instanceof Array)) {
        ret[i] = ret[i].concat(item);
        i -= 1;
        flagParallel = true;
      }
      if (!flagParallel) {
        ret.push(item);
      }
      prev = item;
    }
  });
  return ret;
}

Graph._isPatchNeeded = function(toBePatched) {
  var lastElts = toBePatched.map(function(arr) {
    return arr[arr.length - 1];
  });
  var lastElt = lastElts[0];
  for (var i = 0; i < lastElts.length; i++) {
    if (lastElts[i] !== lastElt) {
      return true;
    }
  }
  return false;
};

Graph._patchParallel = function(expanded) {
  var toBePatched = [];
  expanded.forEach(function(elt) {
    if (elt instanceof Array) {
      toBePatched.push(elt);
    } else if (Graph._isPatchNeeded(toBePatched)) {
      toBePatched.forEach(function(arr) {
        arr.push(elt);
      }, this);
    }
  }, this);
};

Graph.expand = function(item) {
  var expanded = _expand(item);
  var result = [];
  var current = [];
  // first pass to add missing 'end link' in case of parallel branches at the
  // end of a loop
  // [a, [b, d], [b, c], a] -> [a, [b, d, a], [b, c, a], a]
  Graph._patchParallel(expanded);
  // [a, aa, [b, c], d] -> [[a, aa, b], [b,c], [c, d]]
  expanded.forEach(function(elt) {
    if (elt instanceof Array) {
      if (current.length > 0) {
        current.push(elt[0]);
        result.push(current);
        current = [];
      }
      result.push(elt);
    } else {
      if (result.length > 0 && current.length === 0) {
        var lastChain = result[result.length - 1];
        var lastElt = lastChain[lastChain.length - 1];
        current.push(lastElt);
      }
      current.push(elt);
    }
  }, this);
  if (current.length > 0) {
    result.push(current);
  }
  return result;
};

Graph.number = function(workflow, num) {
  num = (typeof num === 'undefined') ? 0 : num;
  var toNum = {};
  var toNode = [];

  function setStep(step, nodeId) {
    if (step in toNode) {
      toNode[step].push(nodeId);
    } else {
      toNode[step] = [ nodeId ];
    }
  }

  function setNum(nodeId, beg, end) {
    if (end === undefined) {
      num = String(beg);
      setStep(beg, nodeId);
    } else {
      num = end + "-" + beg;
      setStep(end, nodeId);
    }
    if (nodeId in toNum) {
      toNum[nodeId] += "," + num;
    } else {
      toNum[nodeId] = num;
    }
  }

  function _number(wks, num) {
    var ret = 0;
    if (wks instanceof Array) {
      if (wks.length === 0) {
        ret = num;
      } else if (wks.length === 1) {
        ret = _number(wks[0], num);
      } else {
        var head = wks[0];
        var tail = wks.slice(1);
        var beg = _number(head, num);
        if (tail[0] instanceof Array) {
          var end = _number(tail[0], beg);
          setNum(head, beg, end);
          beg = end + 1;
          tail.shift();
        }
        ret = _number(tail, beg);
      }
    } else if ((wks instanceof Object) && 'parallel' in wks) {
      var nums = wks.parallel.map(function(branch) {
        return _number(branch, num);
      });
      ret = Math.max.apply(null, nums);
    } else {
      setNum(wks, num);
      ret = num + 1;
    }
    return ret;
  }

  _number(workflow, num);
  // console.log('toNodes=', JSON.stringify(toNode));
  // console.log('toNum=',JSON.stringify(toNum));
  return {
    toNum : toNum,
    toNode : toNode
  };
};

module.exports = Graph;
<|endoftext|>


<commit_before>(function (angular, moment) {
    angular.module('pk-pass-display').component('pkApplePassField', {
        controller: ["$sce", "$element", PKApplePassFieldController],
        templateUrl:"apple-pass-field.html",
        bindings: {
            field: '<',
            lang: '<'
        }
    });

    function PKApplePassFieldController($sce, $element) {
        var ctrl = this;

        ctrl.$onChanges = onChanges;

        function onChanges(changesObj) {
            if (changesObj.hasOwnProperty("field") && ctrl.field != undefined) {
                fieldChange(ctrl.field);
            }
            if (changesObj.hasOwnProperty("lang") && ctrl.lang != undefined) {
                languageChange(ctrl.lang);
            }
        }

        //scope funcs
        ctrl.getValue = getValue;

        var TextAlignmentMap = {
            "PKTextAlignmentLeft":"left",
            "PKTextAlignmentCenter":"center",
            "PKTextAlignmentRight":"right",
            "PKTextAlignmentNatural":"justify"
        };

        var DateStyleMap = {
            "PKDateStyleNone":"none",
            "PKDateStyleShort":"short",
            "PKDateStyleMedium":"medium",
            "PKDateStyleLong":"long",
            "PKDateStyleFull":"full"
        };

        var CurrencyMap = {"AED":"د.إ.","AFN":"؋","ALL":"Lek","AMD":"դր.","ANG":false,"AOA":false,"ARS":"$","AUD":"$","AWG":false,"AZN":"man.","BAM":"KM","BBD":false,"BDT":"৳","BGN":"лв.","BHD":"د.ب.","BIF":false,"BMD":false,"BND":"$","BOB":"Bs","BOV":false,"BRL":"R$","BSD":false,"BTN":"Nu.","BWP":"P","BYR":"","BZD":"$","CAD":"$","CDF":false,"CHE":false,"CHF":"Fr.","CHW":false,"CLF":false,"CLP":"$","CNY":"￥","COP":"$","COU":false,"CRC":"₡","CUC":false,"CUP":false,"CVE":false,"CZK":"Kč","DJF":"Fdj","DKK":"kr","DOP":"RD$","DZD":"د.ج.","EGP":"ج.م.","ERN":"Nfk","ETB":false,"EUR":"€","FJD":false,"FKP":false,"GBP":"£","GEL":"","GHS":"GH₵","GIP":false,"GMD":false,"GNF":false,"GTQ":"Q","GYD":false,"HKD":"$","HNL":"L","HRK":"kn","HTG":false,"HUF":"Ft","IDR":"Rp","ILS":"₪","INR":"रु.","IQD":"د.ع.","IRR":"﷼","ISK":"kr","JMD":"$","JOD":"د.أ.","JPY":"￥","KES":false,"KGS":"сом","KHR":"៛","KMF":false,"KPW":false,"KRW":"₩","KWD":"د.ك.","KYD":false,"KZT":false,"LAK":"₭","LBP":"ل.ل.","LKR":"SL Re","LRD":false,"LSL":false,"LTL":"Lt","LVL":"Ls","LYD":"د.ل.","MAD":"د.م.","MDL":"","MGA":false,"MKD":"","MMK":"K","MNT":"₮","MOP":"MOP$","MRO":false,"MUR":false,"MVR":"ރ.","MWK":"","MXN":"$","MXV":false,"MYR":"RM","MZN":false,"NAD":false,"NGN":false,"NIO":"C$","NOK":"kr","NPR":"नेरू","NZD":"$","OMR":"ر.ع.","PAB":"B/.","PEN":"S/.","PGK":false,"PHP":"₱","PKR":"روپے","PLN":"zł","PYG":false,"QAR":"ر.ق.","RON":"RON","RSD":"дин.","RUB":"руб.","RWF":"RF","SAR":"ر.س.","SBD":false,"SCR":false,"SDG":"","SEK":"kr","SGD":"$","SHP":false,"SLL":false,"SOS":false,"SRD":false,"SSP":false,"STD":false,"SYP":"ل.س.","SZL":false,"THB":"฿","TJS":"сом","TMT":false,"TND":"د.ت.","TOP":"T$","TRY":"TL","TTD":"$","TWD":"NT$","TZS":"TSh","UAH":"₴","UGX":false,"USD":"$","USN":false,"USS":false,"UYI":false,"UYU":"$","UZS":"сўм","VEF":"Bs.F.","VND":false,"VUV":false,"WST":false,"XAF":false,"XAG":false,"XAU":false,"XBA":false,"XBB":false,"XBC":false,"XBD":false,"XCD":false,"XDR":false,"XFU":false,"XOF":"CFA","XPD":false,"XPF":false,"XPT":false,"XTS":false,"XXX":false,"YER":"ر.ي.","ZAR":"R","ZMK":false,"ZWL":false,"EEK":"kr"};

        var NumberStyleMap = {
            "PKNumberStyleDecimal":"decimal",
            "PKNumberStylePercent":"percent",
            "PKNumberStyleScientific":"scientific",
            "PKNumberStyleSpellOut":"spell",
        };

        function fieldChange(val) {
            if(val != null) {
                if(val.hasOwnProperty("textAlignment")) {
                    textAlign($element,TextAlignmentMap[val.textAlignment]);
                }
                if(val.hasOwnProperty("dateStyle")) {
                    /*
                        `json:"dateStyle,omitempty"`
                        `json:"ignoresTimeZone,omitempty"`
                        `json:"isRelative,omitempty"`
                        `json:"timeStyle,omitempty"`
                    */
                    ctrl.field.value = timeFormatValue(val.value, DateStyleMap[val.dateStyle]);
                }
                if(val.hasOwnProperty("currencyCode")) {
                    if(CurrencyMap[val.currencyCode]) {
                        ctrl.field.value = CurrencyMap[val.currencyCode] + val.value;
                    } else {
                        ctrl.field.value = val.currencyCode + val.value;
                    }
                }
                if(val.hasOwnProperty("numberStyle")) {
                    ctrl.field.value = numberFormat(val.value, NumberStyleMap[val.numberStyle]);
                }
            }
        }

        function languageChange(val) {
            if(val != null) {
                if(val.hasOwnProperty('text')) {
                    for (var key in val.text) {
                        if (val.text.hasOwnProperty(key) && typeof ctrl.field !== "undefined") {
                            if(ctrl.field.hasOwnProperty("value")) {
                                ctrl.field.value = replaceAll(ctrl.field.value, key, val.text[key]);
                            }
                            if(ctrl.field.hasOwnProperty("label")) {
                                ctrl.field.label = replaceAll(ctrl.field.label, key, val.text[key]);
                            }
                            if(ctrl.field.hasOwnProperty("attributedValue")) {
                                ctrl.field.attributedValue = replaceAll(ctrl.field.attributedValue, key, val.text[key]);
                            }
                        }
                    }
                }
            }
        }

        function getValue(field) {
            var text = "";
            if(field != null) {
                if(field.hasOwnProperty("attributedValue")) {
                    text = field.attributedValue;
                } else {
                    text = field.value;
                }
            }
            return $sce.trustAsHtml(text.toString().replace(/\n/g, "
"));
        }

        function textAlign(e,alignment) {
            e.css('text-align', alignment);
        }

        //FIXME need to implement number format switch;
        function numberFormat(value, format) {
            switch(format) {
            case 'percent':
                return value+"%";
            default:
                return value;
            }
        }

        function timeFormatValue(date, style) {
            var format;
            switch(style) {
            case 'full': // Wednesday, July 17, 2019
                format = 'LLLL';
                break;
            case 'long': // July 17, 2019
                format = 'LL';
                break;
            case 'medium': // Jul 17, 2019
                format = 'll';
                break;
            case 'short': // 7/17/19 (short)
                format = 'l';
                break;
            default:
                return date;
            }
            return moment(date).format(format);
        }

        function replaceAll(string, find, replaceString) {
            var regescaped = find.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
            return new String(string).replace(new RegExp(regescaped, 'g'), replaceString);
        }
    }
})(window.angular, window.moment);<commit_msg>sort the key of the translation object<commit_after>(function (angular, moment) {
    angular.module('pk-pass-display').component('pkApplePassField', {
        controller: ["$sce", "$element", PKApplePassFieldController],
        templateUrl:"apple-pass-field.html",
        bindings: {
            field: '<',
            lang: '<'
        }
    });

    function PKApplePassFieldController($sce, $element) {
        var ctrl = this;

        ctrl.$onChanges = onChanges;

        function onChanges(changesObj) {
            if (changesObj.hasOwnProperty("field") && ctrl.field != undefined) {
                fieldChange(ctrl.field);
            }
            if (changesObj.hasOwnProperty("lang") && ctrl.lang != undefined) {
                languageChange(ctrl.lang);
            }
        }

        //scope funcs
        ctrl.getValue = getValue;

        var TextAlignmentMap = {
            "PKTextAlignmentLeft":"left",
            "PKTextAlignmentCenter":"center",
            "PKTextAlignmentRight":"right",
            "PKTextAlignmentNatural":"justify"
        };

        var DateStyleMap = {
            "PKDateStyleNone":"none",
            "PKDateStyleShort":"short",
            "PKDateStyleMedium":"medium",
            "PKDateStyleLong":"long",
            "PKDateStyleFull":"full"
        };

        var CurrencyMap = {"AED":"د.إ.","AFN":"؋","ALL":"Lek","AMD":"դր.","ANG":false,"AOA":false,"ARS":"$","AUD":"$","AWG":false,"AZN":"man.","BAM":"KM","BBD":false,"BDT":"৳","BGN":"лв.","BHD":"د.ب.","BIF":false,"BMD":false,"BND":"$","BOB":"Bs","BOV":false,"BRL":"R$","BSD":false,"BTN":"Nu.","BWP":"P","BYR":"","BZD":"$","CAD":"$","CDF":false,"CHE":false,"CHF":"Fr.","CHW":false,"CLF":false,"CLP":"$","CNY":"￥","COP":"$","COU":false,"CRC":"₡","CUC":false,"CUP":false,"CVE":false,"CZK":"Kč","DJF":"Fdj","DKK":"kr","DOP":"RD$","DZD":"د.ج.","EGP":"ج.م.","ERN":"Nfk","ETB":false,"EUR":"€","FJD":false,"FKP":false,"GBP":"£","GEL":"","GHS":"GH₵","GIP":false,"GMD":false,"GNF":false,"GTQ":"Q","GYD":false,"HKD":"$","HNL":"L","HRK":"kn","HTG":false,"HUF":"Ft","IDR":"Rp","ILS":"₪","INR":"रु.","IQD":"د.ع.","IRR":"﷼","ISK":"kr","JMD":"$","JOD":"د.أ.","JPY":"￥","KES":false,"KGS":"сом","KHR":"៛","KMF":false,"KPW":false,"KRW":"₩","KWD":"د.ك.","KYD":false,"KZT":false,"LAK":"₭","LBP":"ل.ل.","LKR":"SL Re","LRD":false,"LSL":false,"LTL":"Lt","LVL":"Ls","LYD":"د.ل.","MAD":"د.م.","MDL":"","MGA":false,"MKD":"","MMK":"K","MNT":"₮","MOP":"MOP$","MRO":false,"MUR":false,"MVR":"ރ.","MWK":"","MXN":"$","MXV":false,"MYR":"RM","MZN":false,"NAD":false,"NGN":false,"NIO":"C$","NOK":"kr","NPR":"नेरू","NZD":"$","OMR":"ر.ع.","PAB":"B/.","PEN":"S/.","PGK":false,"PHP":"₱","PKR":"روپے","PLN":"zł","PYG":false,"QAR":"ر.ق.","RON":"RON","RSD":"дин.","RUB":"руб.","RWF":"RF","SAR":"ر.س.","SBD":false,"SCR":false,"SDG":"","SEK":"kr","SGD":"$","SHP":false,"SLL":false,"SOS":false,"SRD":false,"SSP":false,"STD":false,"SYP":"ل.س.","SZL":false,"THB":"฿","TJS":"сом","TMT":false,"TND":"د.ت.","TOP":"T$","TRY":"TL","TTD":"$","TWD":"NT$","TZS":"TSh","UAH":"₴","UGX":false,"USD":"$","USN":false,"USS":false,"UYI":false,"UYU":"$","UZS":"сўм","VEF":"Bs.F.","VND":false,"VUV":false,"WST":false,"XAF":false,"XAG":false,"XAU":false,"XBA":false,"XBB":false,"XBC":false,"XBD":false,"XCD":false,"XDR":false,"XFU":false,"XOF":"CFA","XPD":false,"XPF":false,"XPT":false,"XTS":false,"XXX":false,"YER":"ر.ي.","ZAR":"R","ZMK":false,"ZWL":false,"EEK":"kr"};

        var NumberStyleMap = {
            "PKNumberStyleDecimal":"decimal",
            "PKNumberStylePercent":"percent",
            "PKNumberStyleScientific":"scientific",
            "PKNumberStyleSpellOut":"spell",
        };

        function fieldChange(val) {
            if(val != null) {
                if(val.hasOwnProperty("textAlignment")) {
                    textAlign($element,TextAlignmentMap[val.textAlignment]);
                }
                if(val.hasOwnProperty("dateStyle")) {
                    /*
                        `json:"dateStyle,omitempty"`
                        `json:"ignoresTimeZone,omitempty"`
                        `json:"isRelative,omitempty"`
                        `json:"timeStyle,omitempty"`
                    */
                    ctrl.field.value = timeFormatValue(val.value, DateStyleMap[val.dateStyle]);
                }
                if(val.hasOwnProperty("currencyCode")) {
                    if(CurrencyMap[val.currencyCode]) {
                        ctrl.field.value = CurrencyMap[val.currencyCode] + val.value;
                    } else {
                        ctrl.field.value = val.currencyCode + val.value;
                    }
                }
                if(val.hasOwnProperty("numberStyle")) {
                    ctrl.field.value = numberFormat(val.value, NumberStyleMap[val.numberStyle]);
                }
            }
        }

        function languageChange(val) {
            if(val != null) {
                if(val.hasOwnProperty('text')) {
                    // sort the key to avoid substring is replaced before

// the whole string

                    var sortedKeys = [];
                    for (var key in val.text) {
                        if (val.text.hasOwnProperty(key)) {
                            sortedKeys.push(key);
                        }
                    }

                    // sort keys by text length to avoid substring is replaced randomly
                    sortedKeys.sort(function(a, b){
                        // ASC  -> a.length - b.length

                        // DESC -> b.length - a.length

                        return b.length - a.length;

                    });

                    sortedKeys.forEach(function(key){
                        if (val.text.hasOwnProperty(key) && typeof ctrl.field !== "undefined") {
                            if(ctrl.field.hasOwnProperty("value")) {
                                ctrl.field.value = replaceAll(ctrl.field.value, key, val.text[key]);
                            }
                            if(ctrl.field.hasOwnProperty("label")) {
                                ctrl.field.label = replaceAll(ctrl.field.label, key, val.text[key]);
                            }
                            if(ctrl.field.hasOwnProperty("attributedValue")) {
                                ctrl.field.attributedValue = replaceAll(ctrl.field.attributedValue, key, val.text[key]);
                            }
                        }
                    })
                }
            }
        }

        function getValue(field) {
            var text = "";
            if(field != null) {
                if(field.hasOwnProperty("attributedValue")) {
                    text = field.attributedValue;
                } else {
                    text = field.value;
                }
            }
            return $sce.trustAsHtml(text.toString().replace(/\n/g, "
"));
        }

        function textAlign(e,alignment) {
            e.css('text-align', alignment);
        }

        //FIXME need to implement number format switch;
        function numberFormat(value, format) {
            switch(format) {
            case 'percent':
                return value+"%";
            default:
                return value;
            }
        }

        function timeFormatValue(date, style) {
            var format;
            switch(style) {
            case 'full': // Wednesday, July 17, 2019
                format = 'LLLL';
                break;
            case 'long': // July 17, 2019
                format = 'LL';
                break;
            case 'medium': // Jul 17, 2019
                format = 'll';
                break;
            case 'short': // 7/17/19 (short)
                format = 'l';
                break;
            default:
                return date;
            }
            return moment(date).format(format);
        }

        function replaceAll(string, find, replaceString) {
            var regescaped = find.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
            return new String(string).replace(new RegExp(regescaped, 'g'), replaceString);
        }
    }
})(window.angular, window.moment);<|endoftext|>


<commit_before>/*
* Copyright (c) 2014 Stefan Marr, mail@stefan-marr.de
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// @ts-check

import { Primitives } from './Primitives.js';
import { universe } from '../vm/Universe.js';

import { SString } from '../vmobjects/SString.js';

function _concat(_frame, args) {
  const argument = args[1];
  return universe.newString(args[0].getEmbeddedString()
        + argument.getEmbeddedString());
}

function _asSymbol(_frame, args) {
  return universe.symbolFor(args[0].getEmbeddedString());
}

function _length(_frame, args) {
  return universe.newInteger(args[0].getEmbeddedString().length);
}

function _equals(_frame, args) {
  const op1 = args[1];
  const op2 = args[0];
  if (op1 instanceof SString) {
    if (op1.getEmbeddedString() === op2.getEmbeddedString()) {
      return universe.trueObject;
    }
  }
  return universe.falseObject;
}

function _substring(_frame, args) {
  const end = args[2];
  const start = args[1];

  const s = start.getEmbeddedInteger() - 1;
  const e = end.getEmbeddedInteger();
  const string = args[0].getEmbeddedString();

  if (s < 0 || s >= string.length || e > string.length || e < s) {
    return universe.newString('Error - index out of bounds');
  }
  return universe.newString(string.substring(s, e));
}

function _hashcode(_frame, args) {
  const s = args[0].getEmbeddedString();

  // hash code from: http://stackoverflow.com/a/7616484/916546
  let hash = 0; let i; let chr; let
    len;
  if (s.length === 0) {
    return universe.newInteger(hash);
  }

  for (i = 0, len = s.length; i < len; i += 1) {
    chr = s.charCodeAt(i);
    hash = ((hash << 5) - hash) + chr;
    hash |= 0; // Convert to 32bit integer
  }
  return universe.newInteger(hash);
}

function _isWhiteSpace(_frame, args) {
  const s = args[0].getEmbeddedString();

  if (s.match(/^\s+$/) !== null) {
    return universe.trueObject;
  }
  return universe.falseObject;
}

function _isLetters(_frame, args) {
  const s = args[0].getEmbeddedString();

  if (RegExp(/^\p{L}+$/, 'u').test(s)) {
    return universe.trueObject;
  }
  return universe.falseObject;
}

function _isDigits(_frame, args) {
  const s = args[0].getEmbeddedString();

  if (s.match(/^\d+$/) !== null) {
    return universe.trueObject;
  }
  return universe.falseObject;
}

class StringPrimitives extends Primitives {
  installPrimitives() {
    this.installInstancePrimitive('concatenate:', _concat);
    this.installInstancePrimitive('asSymbol', _asSymbol);
    this.installInstancePrimitive('length', _length);
    this.installInstancePrimitive('=', _equals);
    this.installInstancePrimitive('primSubstringFrom:to:', _substring);
    this.installInstancePrimitive('hashcode', _hashcode);
    this.installInstancePrimitive('isWhiteSpace', _isWhiteSpace);
    this.installInstancePrimitive('isLetters', _isLetters);
    this.installInstancePrimitive('isDigits', _isDigits);
  }
}

export const prims = StringPrimitives;
<commit_msg>Use plain regex literal<commit_after>/*
* Copyright (c) 2014 Stefan Marr, mail@stefan-marr.de
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// @ts-check

import { Primitives } from './Primitives.js';
import { universe } from '../vm/Universe.js';

import { SString } from '../vmobjects/SString.js';

function _concat(_frame, args) {
  const argument = args[1];
  return universe.newString(args[0].getEmbeddedString()
        + argument.getEmbeddedString());
}

function _asSymbol(_frame, args) {
  return universe.symbolFor(args[0].getEmbeddedString());
}

function _length(_frame, args) {
  return universe.newInteger(args[0].getEmbeddedString().length);
}

function _equals(_frame, args) {
  const op1 = args[1];
  const op2 = args[0];
  if (op1 instanceof SString) {
    if (op1.getEmbeddedString() === op2.getEmbeddedString()) {
      return universe.trueObject;
    }
  }
  return universe.falseObject;
}

function _substring(_frame, args) {
  const end = args[2];
  const start = args[1];

  const s = start.getEmbeddedInteger() - 1;
  const e = end.getEmbeddedInteger();
  const string = args[0].getEmbeddedString();

  if (s < 0 || s >= string.length || e > string.length || e < s) {
    return universe.newString('Error - index out of bounds');
  }
  return universe.newString(string.substring(s, e));
}

function _hashcode(_frame, args) {
  const s = args[0].getEmbeddedString();

  // hash code from: http://stackoverflow.com/a/7616484/916546
  let hash = 0; let i; let chr; let
    len;
  if (s.length === 0) {
    return universe.newInteger(hash);
  }

  for (i = 0, len = s.length; i < len; i += 1) {
    chr = s.charCodeAt(i);
    hash = ((hash << 5) - hash) + chr;
    hash |= 0; // Convert to 32bit integer
  }
  return universe.newInteger(hash);
}

function _isWhiteSpace(_frame, args) {
  const s = args[0].getEmbeddedString();

  if (s.match(/^\s+$/) !== null) {
    return universe.trueObject;
  }
  return universe.falseObject;
}

function _isLetters(_frame, args) {
  const s = args[0].getEmbeddedString();

  if (/^\p{L}+$/u.test(s)) {
    return universe.trueObject;
  }
  return universe.falseObject;
}

function _isDigits(_frame, args) {
  const s = args[0].getEmbeddedString();

  if (s.match(/^\d+$/) !== null) {
    return universe.trueObject;
  }
  return universe.falseObject;
}

class StringPrimitives extends Primitives {
  installPrimitives() {
    this.installInstancePrimitive('concatenate:', _concat);
    this.installInstancePrimitive('asSymbol', _asSymbol);
    this.installInstancePrimitive('length', _length);
    this.installInstancePrimitive('=', _equals);
    this.installInstancePrimitive('primSubstringFrom:to:', _substring);
    this.installInstancePrimitive('hashcode', _hashcode);
    this.installInstancePrimitive('isWhiteSpace', _isWhiteSpace);
    this.installInstancePrimitive('isLetters', _isLetters);
    this.installInstancePrimitive('isDigits', _isDigits);
  }
}

export const prims = StringPrimitives;
<|endoftext|>