<commit_before>// pre-defined list of full time developers and contributors. overrides
// the list generated with the `update-contributors` task in `gulpfile.js`

// Full Time Developers
var full_time_developers = [{
  github_id: "vietj",
  name: "Julien Viet",
  role: "Project lead",
  avatar: "http://www.gravatar.com/avatar/cb52062fbd7e159b54e3c298d622fe72?s=80",
  homepage: "http://blog.julienviet.com",
  github: "https://github.com/vietj",
  twitter: "https://twitter.com/julienviet"
}, {
  github_id: "pmlopes",
  name: "Paulo Lopes",
  role: "Core developer",
  avatar: "http://www.gravatar.com/avatar/e948f0816514cc90a10bbe9ca1060d60?s=80",
  homepage: "http://pmlopes.svbtle.com/",
  github: "https://github.com/pmlopes",
  twitter: "https://twitter.com/jetdrone"
}, {
  github_id: "cescoffier",
  name: "Clement Escoffier",
  role: "Core developer",
  avatar: "http://gravatar.com/avatar/ab937f7df990a673446f1e30fd9ccfba?s=80",
  homepage: "http://escoffier.me/",
  github: "https://github.com/cescoffier",
  twitter: "https://twitter.com/clementplop"
}, {
  github_id: "tsegismont",
  name: "Thomas Segismont",
  role: "Core developer",
  avatar: "https://avatars1.githubusercontent.com/u/1500598?v=3&s=80",
  homepage: "http://tsegismont.blogspot.fr",
  github: "https://github.com/tsegismont",
  twitter: "https://twitter.com/tsegismont"
}, {
  github_id: "jponge",
  name: "Julien Ponge",
  role: "Core developer",
  avatar: "https://avatars.githubusercontent.com/u/25961?v=3&s=80",
  github: "https://github.com/jponge",
  twitter: "https://twitter.com/jponge",
  homepage: "https://julien.ponge.org/"
}];

// Component maintainers
var maintainers = [{
  github_id: "michel-kraemer",
  name: "Michel Krämer",
  contribution: "Web-site",
  avatar: "http://www.gravatar.com/avatar/bdcf8af7892cb0147cb22828d37e872f?s=80",
  homepage: "http://www.michel-kraemer.com",
  github: "https://github.com/michel-kraemer",
  google_plus: "https://plus.google.com/115526316201910245712"
}, {
  github_id: "alexlehm",
  avatar: "https://avatars.githubusercontent.com/u/156144?v=3&s=80",
  github: "https://github.com/alexlehm",
  name: "Alexander Lehmann",
  contribution: "SMTP client",
  twitter: "https://twitter.com/alexlehm",
  homepage: "https://about.me/alexlehm"
}, {
  github_id: "fmarinelli",
  avatar: "https://avatars.githubusercontent.com/u/790571?v=3&s=80",
  github: "https://github.com/fmarinelli",
  name: "Fabio Marinelli",
  contribution: "JGroups Cluster Manager"
}, {
  github_id: "jstrachan",
  avatar: "https://avatars.githubusercontent.com/u/30140?v=3&s=80",
  github: "https://github.com/jstrachan",
  name: "James Strachan",
  homepage: "http://macstrac.blogspot.com/",
  contribution: "Kubernetes/Fabric8"
}, {
  github_id: "Narigo",
  avatar: "https://avatars.githubusercontent.com/u/1767865?v=3&s=80",
  github: "https://github.com/Narigo",
  name: "Joern Bernhardt",
  homepage: "http://www.campudus.com/",
  contribution: "MySQL/PostgreSQL"
}, {
  github_id: "johnoliver",
  avatar: "https://avatars.githubusercontent.com/u/1615532?v=3&s=80",
  github: "https://github.com/johnoliver",
  name: "John Oliver",
  contribution: "MongoDB client"
}, {
  github_id: "kuujo",
  avatar: "https://avatars.githubusercontent.com/u/823318?v=3&s=80",
  github: "https://github.com/kuujo",
  name: "Jordan Halterman",
  homepage: "http://atomix.io",
  contribution: "Python"
}, {
  github_id: "codepitbull",
  avatar: "https://pbs.twimg.com/profile_images/1900844895/rec_400x400.jpg",
  github: "https://github.com/codepitbull",
  homepage: "http://codepitbull.de/",
  name: "Jochen Mader",
  contribution: "Scala"
}, {
  github_id: "karianna",
  avatar: "https://avatars.githubusercontent.com/u/180840?v=3&s=80",
  github: "https://github.com/karianna",
  name: "Martijn Verburg",
  homepage: "http://martijnverburg.blogspot.com",
  contribution: "MongoDB client"
}, {
  github_id: "gemmellr",
  avatar: "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/3/005/063/2a2/3a921c5.jpg",
  github: "https://github.com/gemmellr",
  name: "Robbie Gemmell",
  contribution: "AMQP bridge, Proton"
}, {
  github_id: "ppatierno",
  avatar: "https://avatars2.githubusercontent.com/u/5842311?v=3&s=140",
  github: "https://github.com/ppatierno",
  homepage: "https://paolopatierno.wordpress.com/",
  twitter: "https://twitter.com/ppatierno",
  name: "Paolo Patierno",
  contribution: "MQTT server & client, Kafka client"
}, {
  github_id: "maeste",
  name: "Stefano Maestri",
  avatar: "https://avatars.githubusercontent.com/u/74194?v=3&s=80",
  github: "https://github.com/maeste",
  homepage: "http://www.javalinux.it/",
  contribution: "JCA Adapter"
}, {
  github_id: "davsclaus",
  name: "Claus Ibsen",
  avatar: "https://avatars.githubusercontent.com/u/477100?v=3&s=80",
  github: "https://github.com/davsclaus",
  homepage: "http://davsclaus.com/",
  contribution: "Camel bridge"
}, {
  github_id: "agura",
  name: "Andrey Gura",
  avatar: "https://avatars.githubusercontent.com/u/1387185?v=3&s=80",
  github: "https://github.com/agura",
  homepage: "https://github.com/agura",
  contribution: "Apache Ignite Cluster Manager"
}, {
  github_id: "poiuytrez",
  name: "Guillaume Charhon",
  avatar: "https://avatars.githubusercontent.com/u/1167433?v=3&s=80",
  github: "https://github.com/poiuytrez",
  homepage: "https://github.com/poiuytrez",
  contribution: "RabbitMQ client"
}, {
  github_id: "stream1984",
  name: "Stream Liu",
  contribution: "Zookeeper Cluster Manager",
  avatar: "https://s.gravatar.com/avatar/421414eb861cf22a469d90ff8c8de980?s=80",
  homepage: "http://www.streamis.me",
  github: "https://github.com/stream1984"
}, {
  github_id: "ruslansennov",
  name: "Ruslan Sennov",
  contribution: "Consul Client",
  avatar: "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/4/000/175/035/229e194.jpg",
  homepage: "http://ruslan-sennov.blogspot.fr/",
  github: "https://github.com/ruslansennov"
}, {
  github_id: "fromage",
  name: "Stéphane Épardaud",
  contribution: "Ceylon language",
  avatar: "https://avatars0.githubusercontent.com/u/179265?v=3&u=545a452f4ae4d1d3d77b2a4e84e40ebaad54c8cf&s=400",
  homepage: "http://stephane.epardaud.fr/",
  github: "https://github.com/fromage"
}];

// Contributors
var contributors = [{
  github_id: "jotschi",
  name: "Johannes Schüth",
  avatar: "http://www.gravatar.com/avatar/1e57b87157678193e7a0faf22ae3e958?s=80",
  homepage: "http://www.jotschi.de",
  github: "https://github.com/jotschi",
  twitter: "https://twitter.com/jotschi"
}, {
  github_id: "msoute",
  name: "Marcel Soute",
  avatar: "http://www.gravatar.com/avatar/4fe2cb46fafbdfd35b32be964b0b1597?s=80",
  github: "https://github.com/msoute",
  twitter: "https://twitter.com/marcelsoute"
}, {
  github_id: "InfoSec812",
  name: "Deven Phillips",
  contribution: "Examples/Tests/Docs",
  avatar: "https://en.gravatar.com/userimage/30123434/0b6e8988b6f3ad4e127c8cd0fc9a99c7.jpg?size=80",
  homepage: "http://blog.zanclus.com/",
  github: "https://github.com/InfoSec812",
  google_plus: "https://plus.google.com/+DevenPhillips",
  twitter: "https://twitter.com/InfoSec812"
}, {
  github_id: "sisqbates",
  name: "Ferran Puig",
  avatar: "http://www.gravatar.com/avatar/1490b5d8f7be9ccf0c056ff58ba95e0e?s=80",
  github: "https://github.com/sisqbates",
  twitter: "https://twitter.com/sisqbates"
}, {
  github_id: "millross",
  name: "Jez Prime",
  avatar: "https://avatars2.githubusercontent.com/u/1318862?v=3&s=80",
  github: "https://github.com/millross",
  twitter: "https://twitter.com/jezprime"
}, {
  github_id: "stream1984",
  name: "Stream Liu",
  contribution: "Clojure/Zookeeper",
  avatar: "https://s.gravatar.com/avatar/421414eb861cf22a469d90ff8c8de980?s=80",
  homepage: "http://www.streamis.me",
  github: "https://github.com/stream1984"
}, {
  github_id: "nmcl",
  name: "Mark Little",
  avatar: "https://avatars1.githubusercontent.com/u/580667?v=3&s=80",
  google_plus: "https://plus.google.com/u/0/+MarkLittleJBossCTO/",
  homepage: "http://markclittle.blogspot.co.uk",
  github: "https://github.com/nmcl"
}];

module.exports = {
  full_time_developers: full_time_developers,
  maintainers: maintainers,
  contributors: contributors
};
<commit_msg>Daniel Petisme added as Vert.X Starter maintainer<commit_after>// pre-defined list of full time developers and contributors. overrides
// the list generated with the `update-contributors` task in `gulpfile.js`

// Full Time Developers
var full_time_developers = [{
  github_id: "vietj",
  name: "Julien Viet",
  role: "Project lead",
  avatar: "http://www.gravatar.com/avatar/cb52062fbd7e159b54e3c298d622fe72?s=80",
  homepage: "http://blog.julienviet.com",
  github: "https://github.com/vietj",
  twitter: "https://twitter.com/julienviet"
}, {
  github_id: "pmlopes",
  name: "Paulo Lopes",
  role: "Core developer",
  avatar: "http://www.gravatar.com/avatar/e948f0816514cc90a10bbe9ca1060d60?s=80",
  homepage: "http://pmlopes.svbtle.com/",
  github: "https://github.com/pmlopes",
  twitter: "https://twitter.com/jetdrone"
}, {
  github_id: "cescoffier",
  name: "Clement Escoffier",
  role: "Core developer",
  avatar: "http://gravatar.com/avatar/ab937f7df990a673446f1e30fd9ccfba?s=80",
  homepage: "http://escoffier.me/",
  github: "https://github.com/cescoffier",
  twitter: "https://twitter.com/clementplop"
}, {
  github_id: "tsegismont",
  name: "Thomas Segismont",
  role: "Core developer",
  avatar: "https://avatars1.githubusercontent.com/u/1500598?v=3&s=80",
  homepage: "http://tsegismont.blogspot.fr",
  github: "https://github.com/tsegismont",
  twitter: "https://twitter.com/tsegismont"
}, {
  github_id: "jponge",
  name: "Julien Ponge",
  role: "Core developer",
  avatar: "https://avatars.githubusercontent.com/u/25961?v=3&s=80",
  github: "https://github.com/jponge",
  twitter: "https://twitter.com/jponge",
  homepage: "https://julien.ponge.org/"
}];

// Component maintainers
var maintainers = [{
  github_id: "michel-kraemer",
  name: "Michel Krämer",
  contribution: "Web-site",
  avatar: "http://www.gravatar.com/avatar/bdcf8af7892cb0147cb22828d37e872f?s=80",
  homepage: "http://www.michel-kraemer.com",
  github: "https://github.com/michel-kraemer",
  google_plus: "https://plus.google.com/115526316201910245712"
}, {
  github_id: "alexlehm",
  avatar: "https://avatars.githubusercontent.com/u/156144?v=3&s=80",
  github: "https://github.com/alexlehm",
  name: "Alexander Lehmann",
  contribution: "SMTP client",
  twitter: "https://twitter.com/alexlehm",
  homepage: "https://about.me/alexlehm"
}, {
  github_id: "fmarinelli",
  avatar: "https://avatars.githubusercontent.com/u/790571?v=3&s=80",
  github: "https://github.com/fmarinelli",
  name: "Fabio Marinelli",
  contribution: "JGroups Cluster Manager"
}, {
  github_id: "jstrachan",
  avatar: "https://avatars.githubusercontent.com/u/30140?v=3&s=80",
  github: "https://github.com/jstrachan",
  name: "James Strachan",
  homepage: "http://macstrac.blogspot.com/",
  contribution: "Kubernetes/Fabric8"
}, {
  github_id: "Narigo",
  avatar: "https://avatars.githubusercontent.com/u/1767865?v=3&s=80",
  github: "https://github.com/Narigo",
  name: "Joern Bernhardt",
  homepage: "http://www.campudus.com/",
  contribution: "MySQL/PostgreSQL"
}, {
  github_id: "johnoliver",
  avatar: "https://avatars.githubusercontent.com/u/1615532?v=3&s=80",
  github: "https://github.com/johnoliver",
  name: "John Oliver",
  contribution: "MongoDB client"
}, {
  github_id: "kuujo",
  avatar: "https://avatars.githubusercontent.com/u/823318?v=3&s=80",
  github: "https://github.com/kuujo",
  name: "Jordan Halterman",
  homepage: "http://atomix.io",
  contribution: "Python"
}, {
  github_id: "codepitbull",
  avatar: "https://pbs.twimg.com/profile_images/1900844895/rec_400x400.jpg",
  github: "https://github.com/codepitbull",
  homepage: "http://codepitbull.de/",
  name: "Jochen Mader",
  contribution: "Scala"
}, {
  github_id: "karianna",
  avatar: "https://avatars.githubusercontent.com/u/180840?v=3&s=80",
  github: "https://github.com/karianna",
  name: "Martijn Verburg",
  homepage: "http://martijnverburg.blogspot.com",
  contribution: "MongoDB client"
}, {
  github_id: "gemmellr",
  avatar: "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/3/005/063/2a2/3a921c5.jpg",
  github: "https://github.com/gemmellr",
  name: "Robbie Gemmell",
  contribution: "AMQP bridge, Proton"
}, {
  github_id: "ppatierno",
  avatar: "https://avatars2.githubusercontent.com/u/5842311?v=3&s=140",
  github: "https://github.com/ppatierno",
  homepage: "https://paolopatierno.wordpress.com/",
  twitter: "https://twitter.com/ppatierno",
  name: "Paolo Patierno",
  contribution: "MQTT server & client, Kafka client"
}, {
  github_id: "maeste",
  name: "Stefano Maestri",
  avatar: "https://avatars.githubusercontent.com/u/74194?v=3&s=80",
  github: "https://github.com/maeste",
  homepage: "http://www.javalinux.it/",
  contribution: "JCA Adapter"
}, {
  github_id: "davsclaus",
  name: "Claus Ibsen",
  avatar: "https://avatars.githubusercontent.com/u/477100?v=3&s=80",
  github: "https://github.com/davsclaus",
  homepage: "http://davsclaus.com/",
  contribution: "Camel bridge"
}, {
  github_id: "agura",
  name: "Andrey Gura",
  avatar: "https://avatars.githubusercontent.com/u/1387185?v=3&s=80",
  github: "https://github.com/agura",
  homepage: "https://github.com/agura",
  contribution: "Apache Ignite Cluster Manager"
}, {
  github_id: "poiuytrez",
  name: "Guillaume Charhon",
  avatar: "https://avatars.githubusercontent.com/u/1167433?v=3&s=80",
  github: "https://github.com/poiuytrez",
  homepage: "https://github.com/poiuytrez",
  contribution: "RabbitMQ client"
}, {
  github_id: "stream1984",
  name: "Stream Liu",
  contribution: "Zookeeper Cluster Manager",
  avatar: "https://s.gravatar.com/avatar/421414eb861cf22a469d90ff8c8de980?s=80",
  homepage: "http://www.streamis.me",
  github: "https://github.com/stream1984"
}, {
  github_id: "ruslansennov",
  name: "Ruslan Sennov",
  contribution: "Consul Client",
  avatar: "https://media.licdn.com/mpr/mpr/shrinknp_400_400/p/4/000/175/035/229e194.jpg",
  homepage: "http://ruslan-sennov.blogspot.fr/",
  github: "https://github.com/ruslansennov"
}, {
  github_id: "fromage",
  name: "Stéphane Épardaud",
  contribution: "Ceylon language",
  avatar: "https://avatars0.githubusercontent.com/u/179265?v=3&u=545a452f4ae4d1d3d77b2a4e84e40ebaad54c8cf&s=400",
  homepage: "http://stephane.epardaud.fr/",
  github: "https://github.com/fromage"
}, {
  github_id: "danielpetisme",
  name: "Daniel Petisme",
  contribution: "Vert.x Starter",
  avatar: "https://avatars.githubusercontent.com/u/593564?v=3&s=80",
  homepage: "http://danielpetisme.com",
  github: "https://github.com/danielpetisme",
  twitter: "https://twitter.com/danielpetisme"
}];

// Contributors
var contributors = [{
  github_id: "jotschi",
  name: "Johannes Schüth",
  avatar: "http://www.gravatar.com/avatar/1e57b87157678193e7a0faf22ae3e958?s=80",
  homepage: "http://www.jotschi.de",
  github: "https://github.com/jotschi",
  twitter: "https://twitter.com/jotschi"
}, {
  github_id: "msoute",
  name: "Marcel Soute",
  avatar: "http://www.gravatar.com/avatar/4fe2cb46fafbdfd35b32be964b0b1597?s=80",
  github: "https://github.com/msoute",
  twitter: "https://twitter.com/marcelsoute"
}, {
  github_id: "InfoSec812",
  name: "Deven Phillips",
  contribution: "Examples/Tests/Docs",
  avatar: "https://en.gravatar.com/userimage/30123434/0b6e8988b6f3ad4e127c8cd0fc9a99c7.jpg?size=80",
  homepage: "http://blog.zanclus.com/",
  github: "https://github.com/InfoSec812",
  google_plus: "https://plus.google.com/+DevenPhillips",
  twitter: "https://twitter.com/InfoSec812"
}, {
  github_id: "sisqbates",
  name: "Ferran Puig",
  avatar: "http://www.gravatar.com/avatar/1490b5d8f7be9ccf0c056ff58ba95e0e?s=80",
  github: "https://github.com/sisqbates",
  twitter: "https://twitter.com/sisqbates"
}, {
  github_id: "millross",
  name: "Jez Prime",
  avatar: "https://avatars2.githubusercontent.com/u/1318862?v=3&s=80",
  github: "https://github.com/millross",
  twitter: "https://twitter.com/jezprime"
}, {
  github_id: "stream1984",
  name: "Stream Liu",
  contribution: "Clojure/Zookeeper",
  avatar: "https://s.gravatar.com/avatar/421414eb861cf22a469d90ff8c8de980?s=80",
  homepage: "http://www.streamis.me",
  github: "https://github.com/stream1984"
}, {
  github_id: "nmcl",
  name: "Mark Little",
  avatar: "https://avatars1.githubusercontent.com/u/580667?v=3&s=80",
  google_plus: "https://plus.google.com/u/0/+MarkLittleJBossCTO/",
  homepage: "http://markclittle.blogspot.co.uk",
  github: "https://github.com/nmcl"
}];

module.exports = {
  full_time_developers: full_time_developers,
  maintainers: maintainers,
  contributors: contributors
};
<|endoftext|>


<commit_before>	thymol.makeContext = function(contextNameParam, varAccessorParam) {

		var jsonDeclSpec = "(?:\\W*([\\'][A-Za-z]+(?:\\w|[$])*[\\'])\\s*[:])?\\s*([#][A-Za-z]+(?:\\w|[$])*)(?:\\W|[^$])*", jsonDeclExpr = new RegExp(jsonDeclSpec), context = new Array();

		context.contextName = contextNameParam;
		context.varAccessor = varAccessorParam;
		context.varStore = [];
		context.varNamePrefix = "";

		if (typeof varAccessorParam === "undefined") {
			context.varAccessor = new ThVarsAccessor(context.varStore, "varStore");
		}
		context.varNamePrefix = context.varAccessor.arrayName + "[";

		context.getJSONView = function(param, rootVal) {
			var pType = typeof param, view = "", objType;
			if (pType === 'string') {
				view = view + "'" + param + "'";
			}
			else if (pType === 'number' || pType === 'boolean') {
				view = view + param;
			}
			else if (pType === 'object') {
				if (param instanceof Object) {
					objType = Object.prototype.toString.call(param);
					if ("[object Array]" === objType) {
						view = this.getJSONViewArray(param, false);
					}
					else if ("[object Object]" === objType) {
						view = this.getJSONViewObject(param, false);
					}
					view = '#' + view;
				}
			}
			return view;
		};

		context.init = function() {
			var persisted = top.name, paramRow, paramName, params, i, iLimit, paramValue;
			if (persisted && persisted !== "") {
				params = this.javascriptify(persisted);
				if (params && params.length > 0) {
					for (i = 0, iLimit = params.length; i < iLimit; i++) {
						paramRow = params[i];
						if (paramRow) {
							paramName = paramRow[0];
							if (paramName) {
								paramValue = paramRow[1];
								this.createVariable(paramName, paramValue);
							}
						}
					}
				}
			}
		};

		context.getJSONViewObject = function(param, rootVal) {
			var isRoot = true, key = null, view = "{", value, identifier, definition, suffix, instanceNamePrefix, isTaken, i, iLimit, instanceValue;
			if (typeof rootVal === "boolean") {
				isRoot = rootVal;
			}
			for (key in param) {
				if (key) {
					value = param[key];
					if (typeof value !== "function") {
						if (view != "{") {
							view = view + ",";
						}
						identifier = this.getJSONView(key, false);
						definition = this.getJSONView(value, false);
						view = view + identifier + ":";
						if (!isRoot && typeof value === "object") {
							suffix = 1;
							instanceNamePrefix = key + "$";
							instanceName = null;
							isTaken = false;
							do {
								instanceName = instanceNamePrefix + suffix++;
								instanceValue = context[instanceName];
								if (instanceValue === null || typeof instanceValue === "undefined") {
									isTaken = false;
									for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
										if (instanceName === varStore[i][0]) {
											isTaken = true;
											break;
										}
									}
									if (!isTaken) {
										this.addAttribute(instanceName, definition);
									}
								}
							} while (isTaken);
							if (instanceName !== null) {
								view = view + "#" + instanceName;
							}
						}
						else {
							view = view + definition;
						}
					}
				}
			}
			view = view + "}";
			return view;
		};

		context.getJSONViewArray = function(param, rootVal) {
			var view = "[", i;
			for (i = 0; i < param.length; i++) {
				view = view + this.getJSONView(param[i], false);
				if (i < param.length - 1) {
					view = view + ",";
				}
			}
			view = view + "]";
			return view;
		};

		context.getAttribute = function(name) {
			return context[name];
		};

		context.addAttribute = function(name, value) {
			var entry = [];
			entry[0] = name;
			entry[1] = value;
			varStore.push(entry);
		};

		context.serialise = function() {
			varStore = [];
			var serialised = "[", key = null, value, cn, view, name, i, iLimit;
			for (key in context) {
				if (key) {
					value = context[key];
					if (value != null && typeof value === "object") {
						cn = Object.prototype.toString.call(value);
						if ("[object Array]" !== cn && !(value instanceof ThClass) && !(value instanceof ThVarsAccessor)) {
							if (serialised !== "[") {
								serialised = serialised + ",";
							}
							view = this.getJSONView(value, true);
							serialised = serialised + "[";
							serialised = serialised + "\"" + key + "\"";
							serialised = serialised + ",";
							serialised = serialised + "\"" + view + "\"";
							serialised = serialised + "]";
						}
					}
				}
			}
			for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
				name = varStore[i][0];
				view = varStore[i][1];
				serialised = serialised + ",[";
				serialised = serialised + "\"" + name + "\"";
				serialised = serialised + ",";
				serialised = serialised + "\"" + view + "\"";
				serialised = serialised + "]";
			}
			serialised = serialised + "]";
			return serialised;
		};

		context.javascriptify = function(fn) {
			return new Function('return ' + fn)();
		};

		context.createVariable = function(name, valParam, isReq) {
			var value = valParam, param, tt, literalBoolean, strValue, initial, existing, newArray;
			param = value;
			if (!(value instanceof ThParam)) {
				tt = (typeof valParam);
				if (tt !== "function" && tt !== "object") {
					if (tt === "string") {
						value = decodeURIComponent(value);
					}
					if (tt === "boolean" || tt === "number") {
						param = new ThParam(value);
					}
					else if (value || value === "") {
						literalBoolean = ThUtils.testLiteralFalse(value);
						if (literalBoolean) {
							param = false;
						}
						else {
							strValue = new String(value);
							initial = strValue.trim();
							if (initial.charAt(0) === '#') {
								initial = initial.substring(1);
								try {
									param = this.createJSONVariable(initial);
								}
								catch (err) {
									if (err instanceof ReferenceError) {
										// Do nothing
									}
									if (err instanceof EvalError) {
										// Do nothing
									}
									if (param == null) {
										param = new ThParam(value); // Just save it
									}
								}
							}
							else {
								param = new ThParam(strValue.toString());
							}
						}
					}
				}
			}
			if (isReq) { // Handle multi-valued request parameters
				existing = context[name];
				if (typeof existing !== "undefined" && existing !== null) {
					if (Object.prototype.toString.call(existing) === '[object Array]') {
						existing.push(param);
					}
					else {
						if (thymol.debug) {
							window.alert("request parameters should be of type string array \"" + name + "\"");
						}
					}
				}
				else {
					newArray = new Array();
					newArray["class"] = {};
					newArray["class"]["name"] = "[Thymol.ThParam]";
					newArray.push(param);
					context[name] = newArray;

				}
			}
			else {
				context[name] = param;
			}
			return param;
		};

		context.createJSONVariable = function(initial) {
			var current = initial.trim(), parts = " ", substIndex, token, re, vName, obj, result;
			substIndex = this.varAccessor.length() + 1;
			while (parts) {
				parts = current.match(jsonDeclExpr);
				if (parts && parts.length > 2) {
					token = parts[2];
					token = token.replace(/[\']/g, "[\']").replace(/[$]/g, "[$]");
					re = new RegExp(token);
					vName = this.varNamePrefix + substIndex + "]";
					obj = new Object();
					obj.name = parts[2].substring(1);
					this.varAccessor.set(substIndex, obj);
					substIndex = substIndex + 1;
					current = current.replace(re, "'" + vName + "'", "g");
				}
			}
			current = current.replace(/[\']/g, "\"");
			result = $.parseJSON(current);
			if ("[object Array]" !== Object.prototype.toString.call(result)) {
				result = new ThObject(result);
			}
			return result;
		};

		context.resolveJSONReferences = function() {
			var key = null, param, prop = null, val, ref, subst;
			for (key in context) {
				if (key) {
					param = context[key];
					if (param != null && typeof param === "object") {
						if (!(param instanceof ThVarsAccessor) && !(param instanceof ThClass)) {
							if (!(param instanceof ThParam)) {
								for (prop in param) {
									if (prop) {
										val = param[prop];
										if (typeof val === "string") {
											if (val.indexOf(this.varNamePrefix) == 0) {
												subst = null;
												if (prop.match(/\d*/)) { // Array index!
													ref = val.substring(this.varNamePrefix.length, val.length - 1);
													ref = this.varAccessor.get(ref);
													subst = context[ref.name];
												}
												else {
													subst = context[prop];
												}
												param[prop] = subst;
											}
										}
									}
								}
							}
							else if (typeof param.value === "string" && param.value.charAt(0) == '#') {
								subst = context[param.value.substring(1)];
								context[key] = subst;
							}
						}
					}
				}
			}
		};

		return context;

	};
<commit_msg>Fixed issue with decoding of parameters from request. Added resolveJSONReferences call for request derived parameters.<commit_after>	thymol.makeContext = function(contextNameParam, varAccessorParam) {

		var jsonDeclSpec = "(?:\\W*([\\'][A-Za-z]+(?:\\w|[$])*[\\'])\\s*[:])?\\s*([#][A-Za-z]+(?:\\w|[$])*)(?:\\W|[^$])*", jsonDeclExpr = new RegExp(jsonDeclSpec), context = new Array();

		context.contextName = contextNameParam;
		context.varAccessor = varAccessorParam;
		context.varStore = [];
		context.varNamePrefix = "";

		if (typeof varAccessorParam === "undefined") {
			context.varAccessor = new ThVarsAccessor(context.varStore, "varStore");
		}
		context.varNamePrefix = context.varAccessor.arrayName + "[";

		context.getJSONView = function(param, rootVal) {
			var pType = typeof param, view = "", objType;
			if (pType === 'string') {
				view = view + "'" + param + "'";
			}
			else if (pType === 'number' || pType === 'boolean') {
				view = view + param;
			}
			else if (pType === 'object') {
				if (param instanceof Object) {
					objType = Object.prototype.toString.call(param);
					if ("[object Array]" === objType) {
						view = this.getJSONViewArray(param, false);
					}
					else if ("[object Object]" === objType) {
						view = this.getJSONViewObject(param, false);
					}
					view = '#' + view;
				}
			}
			return view;
		};

		context.init = function() {
			var persisted = top.name, paramRow, paramName, params, i, iLimit, paramValue;
			if (persisted && persisted !== "") {
				params = this.javascriptify(persisted);
				if (params && params.length > 0) {
					for (i = 0, iLimit = params.length; i < iLimit; i++) {
						paramRow = params[i];
						if (paramRow) {
							paramName = paramRow[0];
							if (paramName) {
								paramValue = paramRow[1];
								this.createVariable(paramName, paramValue);
							}
						}
					}
				}
			}
		};

		context.getJSONViewObject = function(param, rootVal) {
			var isRoot = true, key = null, view = "{", value, identifier, definition, suffix, instanceNamePrefix, isTaken, i, iLimit, instanceValue;
			if (typeof rootVal === "boolean") {
				isRoot = rootVal;
			}
			for (key in param) {
				if (key) {
					value = param[key];
					if (typeof value !== "function") {
						if (view != "{") {
							view = view + ",";
						}
						identifier = this.getJSONView(key, false);
						definition = this.getJSONView(value, false);
						view = view + identifier + ":";
						if (!isRoot && typeof value === "object") {
							suffix = 1;
							instanceNamePrefix = key + "$";
							instanceName = null;
							isTaken = false;
							do {
								instanceName = instanceNamePrefix + suffix++;
								instanceValue = context[instanceName];
								if (instanceValue === null || typeof instanceValue === "undefined") {
									isTaken = false;
									for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
										if (instanceName === varStore[i][0]) {
											isTaken = true;
											break;
										}
									}
									if (!isTaken) {
										this.addAttribute(instanceName, definition);
									}
								}
							} while (isTaken);
							if (instanceName !== null) {
								view = view + "#" + instanceName;
							}
						}
						else {
							view = view + definition;
						}
					}
				}
			}
			view = view + "}";
			return view;
		};

		context.getJSONViewArray = function(param, rootVal) {
			var view = "[", i;
			for (i = 0; i < param.length; i++) {
				view = view + this.getJSONView(param[i], false);
				if (i < param.length - 1) {
					view = view + ",";
				}
			}
			view = view + "]";
			return view;
		};

		context.getAttribute = function(name) {
			return context[name];
		};

		context.addAttribute = function(name, value) {
			var entry = [];
			entry[0] = name;
			entry[1] = value;
			varStore.push(entry);
		};

		context.serialise = function() {
			varStore = [];
			var serialised = "[", key = null, value, cn, view, name, i, iLimit;
			for (key in context) {
				if (key) {
					value = context[key];
					if (value != null && typeof value === "object") {
						cn = Object.prototype.toString.call(value);
						if ("[object Array]" !== cn && !(value instanceof ThClass) && !(value instanceof ThVarsAccessor)) {
							if (serialised !== "[") {
								serialised = serialised + ",";
							}
							view = this.getJSONView(value, true);
							serialised = serialised + "[";
							serialised = serialised + "\"" + key + "\"";
							serialised = serialised + ",";
							serialised = serialised + "\"" + view + "\"";
							serialised = serialised + "]";
						}
					}
				}
			}
			for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
				name = varStore[i][0];
				view = varStore[i][1];
				serialised = serialised + ",[";
				serialised = serialised + "\"" + name + "\"";
				serialised = serialised + ",";
				serialised = serialised + "\"" + view + "\"";
				serialised = serialised + "]";
			}
			serialised = serialised + "]";
			return serialised;
		};

		context.javascriptify = function(fn) {
			return new Function('return ' + fn)();
		};

		context.createVariable = function(name, valParam, isReq) {
			var value = valParam, param, tt, literalBoolean, strValue, initial, existing, newArray;
			param = value;
			if (!(value instanceof ThParam)) {
				tt = (typeof valParam);
				if (tt !== "function" && tt !== "object") {
					if (tt === "string") {
						try {
							value = isReq ? decodeURIComponent(value): decodeURI(value);
						}
						catch(err) {
							value = "";
						}
					}
					if (tt === "boolean" || tt === "number") {
						param = new ThParam(value);
					}
					else if (value || value === "") {
						literalBoolean = ThUtils.testLiteralFalse(value);
						if (literalBoolean) {
							param = false;
						}
						else {
							strValue = new String(value);
							initial = strValue.trim();
							if (initial.charAt(0) === '#') {
								initial = initial.substring(1);
								try {
									param = this.createJSONVariable(initial);
								}
								catch (err) {
									if (err instanceof ReferenceError) {
										// Do nothing
									}
									if (err instanceof EvalError) {
										// Do nothing
									}
									if (param == null || isReq) {
										param = new ThParam(value); // Just save it
									}
								}
							}
							else {
								param = new ThParam(strValue.toString());
							}
						}
					}
				}
			}
			if (isReq) { // Handle multi-valued request parameters
				existing = context[name];
				if (typeof existing !== "undefined" && existing !== null) {
					if (Object.prototype.toString.call(existing) === '[object Array]') {
						existing.push(param);
					}
					else {
						if (thymol.debug) {
							window.alert("request parameters should be of type string array \"" + name + "\"");
						}
					}
				}
				else {
					newArray = new Array();
					newArray["class"] = {};
					newArray["class"]["name"] = "[Thymol.ThParam]";
					newArray.push(param);
					context[name] = newArray;

				}
			}
			else {
				context[name] = param;
			}
			return param;
		};

		context.createJSONVariable = function(initial) {
			var current = initial.trim(), parts = " ", substIndex, token, re, vName, obj, result;
			substIndex = this.varAccessor.length() + 1;
			while (parts) {
				parts = current.match(jsonDeclExpr);
				if (parts && parts.length > 2) {
					token = parts[2];
					token = token.replace(/[\']/g, "[\']").replace(/[$]/g, "[$]");
					re = new RegExp(token);
					vName = this.varNamePrefix + substIndex + "]";
					obj = new Object();
					obj.name = parts[2].substring(1);
					this.varAccessor.set(substIndex, obj);
					substIndex = substIndex + 1;
					current = current.replace(re, "'" + vName + "'", "g");
				}
			}
			current = current.replace(/[\']/g, "\"");
			result = $.parseJSON(current);
			if ("[object Array]" !== Object.prototype.toString.call(result)) {
				result = new ThObject(result);
			}
			return result;
		};

		context.resolveJSONReferences = function() {
			var key = null, param, prop = null, val, ref, subst, isReq = ("request" === this.contextName );
			for (key in context) {
				if (key) {
					param = context[key];
					if (param != null && typeof param === "object") {
						if (!(param instanceof ThVarsAccessor) && !(param instanceof ThClass)) {
							if (!(param instanceof ThParam)) {
								if ( isReq && Object.prototype.toString.call(param) === '[object Array]') {
									for( var i = 0, iLimit = param.length; i < iLimit; i++ ) {
										var pi = param[i];
										if ( !!pi && typeof pi.value === "string" && pi.value.charAt(0) == '#') {
											var pv = ThUtils.getParameter( pi.value.substring(1) );
											param[i] = pv;
										}
									}
								}
								else {
									for (prop in param) {
										if (prop) {
											val = param[prop];
											if (typeof val === "string") {
												if (val.indexOf(this.varNamePrefix) == 0) {
													subst = null;
													if (prop.match(/\d*/)) { // Array index!
														ref = val.substring(this.varNamePrefix.length, val.length - 1);
														ref = this.varAccessor.get(ref);
														subst = context[ref.name];
													}
													else {
														subst = context[prop];
													}
													param[prop] = subst;
												}
											}
										}
									}

								}
							}
							else if (typeof param.value === "string" && param.value.charAt(0) == '#') {
								subst = context[param.value.substring(1)];
								context[key] = subst;
							}
						}
					}
				}
			}
		};

		return context;

	};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import JSONClientSingleton from './util/JSONClientSingleton'

class RoomplanSelector extends Component {

  constructor(props) {
    super(props);
    this.state = {
      names: [],
      idx: [],
      sceneIds: []
    };
    this.json = new JSONClientSingleton();
  }

  componentDidMount() {
    this.json.get({
      type: 'plans',
      order: 'name',
      used: 'true'
    }, (data) => {
      if (data.status !== "OK") {
        alert("Unable to get floor plans.");
        return;
      }
      if (!data.result) {
        return;
      }
      const names = [];
      const idx = [];
      for (let i = 0 ; i < data.result.length; i++) {
        names.push(data.result[i]['Name']);
        idx.push(data.result[i]['idx']);
      }
      this.setState({names: names, idx: idx});
    });
    this.json.getAllScenes((data) => {
      if (data.status !== "OK") {
        alert("Unable to get scenes status.");
        return;
      }
      const scenes = data.result;
      const sceneIds = [];
      for (let i = 0; i < scenes.length; i++) {
        const scene = scenes[i];
        const fullId = (scene.Type === 'Group' ? 'g' : 's') + '|' + scene.idx;
        sceneIds.push(fullId);
      }
      this.setState({sceneIds: sceneIds});
    });
  }

  getUid(device) {
    if (device.type === 1) {
      const sceneId = 's|' + device.devidx;
      if (this.state.sceneIds.indexOf(sceneId) >= 0) {
        return sceneId;
      }
      const groupId = 'g|' + device.devidx;
      if (this.state.sceneIds.indexOf(groupId) >= 0) {
        return groupId;
      }
      alert('Unknown scene id: ' + device.devidx);
    }
    return 'd|' + device.devidx;
  }

  handleSelect = (event) => {
    if (event.target.value === "none") {
      return;
    }
    if (this.props.needConfirm &&
      !confirm('Replace current selection with the devices of this room ?')) {
      return;
    }
    // Force-reset layout.
    this.props.onWhitelistChange([]);
    const message = {
      type: 'command',
      param: 'getplandevices',
      idx: event.target.value
    };
    this.json.get(message, (data) => {
      const whitelist = [];
      if (data.result) {
        for (let i = 0 ; i < data.result.length; i++) {
          whitelist.push(this.getUid(data.result[i]));
        }
      }
      this.props.onWhitelistChange(whitelist);
    });
  }

  render() {
    const options = [];
    if (this.state.idx.length) {
      options.push(<option key='nofp' value='none'>select by room plan</option>);
      for (let i = 0; i < this.state.idx.length; i++) {
        const id = this.state.idx[i];
        options.push(
          <option key={'fp' + id} value={id}>{this.state.names[i]}</option>
        );
      };
    }
    return (

        {options.length ? , or <select value="none" onChange={this.handleSelect}>{options}</select> : ''}

    );
  }

}

export default RoomplanSelector
<commit_msg>Fix error when no scene have been defined in Domoticz (#58)<commit_after>import React, { Component } from 'react';
import JSONClientSingleton from './util/JSONClientSingleton'

class RoomplanSelector extends Component {

  constructor(props) {
    super(props);
    this.state = {
      names: [],
      idx: [],
      sceneIds: []
    };
    this.json = new JSONClientSingleton();
  }

  componentDidMount() {
    this.json.get({
      type: 'plans',
      order: 'name',
      used: 'true'
    }, (data) => {
      if (data.status !== "OK") {
        alert("Unable to get floor plans.");
        return;
      }
      if (!data.result) {
        return;
      }
      const names = [];
      const idx = [];
      for (let i = 0 ; i < data.result.length; i++) {
        names.push(data.result[i]['Name']);
        idx.push(data.result[i]['idx']);
      }
      this.setState({names: names, idx: idx});
    });
    this.json.getAllScenes((data) => {
      if (data.status !== "OK") {
        alert("Unable to get scenes status.");
        return;
      }
      if (!data.result) {
        return;
      }
      const scenes = data.result;
      const sceneIds = [];
      for (let i = 0; i < scenes.length; i++) {
        const scene = scenes[i];
        const fullId = (scene.Type === 'Group' ? 'g' : 's') + '|' + scene.idx;
        sceneIds.push(fullId);
      }
      this.setState({sceneIds: sceneIds});
    });
  }

  getUid(device) {
    if (device.type === 1) {
      const sceneId = 's|' + device.devidx;
      if (this.state.sceneIds.indexOf(sceneId) >= 0) {
        return sceneId;
      }
      const groupId = 'g|' + device.devidx;
      if (this.state.sceneIds.indexOf(groupId) >= 0) {
        return groupId;
      }
      alert('Unknown scene id: ' + device.devidx);
    }
    return 'd|' + device.devidx;
  }

  handleSelect = (event) => {
    if (event.target.value === "none") {
      return;
    }
    if (this.props.needConfirm &&
      !confirm('Replace current selection with the devices of this room ?')) {
      return;
    }
    // Force-reset layout.
    this.props.onWhitelistChange([]);
    const message = {
      type: 'command',
      param: 'getplandevices',
      idx: event.target.value
    };
    this.json.get(message, (data) => {
      const whitelist = [];
      if (data.result) {
        for (let i = 0 ; i < data.result.length; i++) {
          whitelist.push(this.getUid(data.result[i]));
        }
      }
      this.props.onWhitelistChange(whitelist);
    });
  }

  render() {
    const options = [];
    if (this.state.idx.length) {
      options.push(<option key='nofp' value='none'>select by room plan</option>);
      for (let i = 0; i < this.state.idx.length; i++) {
        const id = this.state.idx[i];
        options.push(
          <option key={'fp' + id} value={id}>{this.state.names[i]}</option>
        );
      };
    }
    return (

        {options.length ? , or <select value="none" onChange={this.handleSelect}>{options}</select> : ''}

    );
  }

}

export default RoomplanSelector
<|endoftext|>


<commit_before>/**
 * <TextareaAutosize />
 */

import React from 'react';
import emptyFunction from 'react/lib/emptyFunction';
import calculateNodeHeight from './calculateNodeHeight';

export default class TextareaAutosize extends React.Component {

  static propTypes = {
    /**
     * Current textarea value.
     */
    value: React.PropTypes.string,

    /**
     * Callback on value change.
     */
    onChange: React.PropTypes.func,

    /**
     * Try to cache DOM measurements performed by component so that we don't
     * touch DOM when it's not needed.
     *
     * This optimization doesn't work if we dynamically style <textarea />
     * component.
     */
    useCacheForDOMMeasurements: React.PropTypes.bool
  }

  static defaultProps = {
    onChange: emptyFunction,
    useCacheForDOMMeasurements: false
  }

  constructor(props) {
    super(props);
    this.state = {height: null};
    this._onChange = this._onChange.bind(this);
    this._resizeComponent = this._resizeComponent.bind(this);
  }

  render() {
    let {valueLink, onChange, ...props} = this.props;
    if (typeof valueLink === 'object') {
      props.value = this.props.valueLink.value;
    }
    props.style = {
      ...props.style,
      overflow: 'hidden',
      height: this.state.height
    };
    return <textarea {...props} onChange={this._onChange} />;
  }

  componentDidMount() {
    this._resizeComponent();
  }

  componentWillReceiveProps() {
    // Re-render with the new content then recalculate the height as required.
    onNextFrame(this._resizeComponent);
  }

  _onChange(e) {
    this._resizeComponent();
    let {valueLink, onChange} = this.props;
    if (valueLink) {
      valueLink.requestChange(e.target.value);
    } else {
      onChange(e);
    }
  }

  _resizeComponent() {
    let {useCacheForDOMMeasurements} = this.props;
    let height = calculateNodeHeight(
      React.findDOMNode(this),
      useCacheForDOMMeasurements,
      this.props.rows);
    this.setState({height});
  }

  /**
   * Read the current value of <textarea /> from DOM.
   */
  get value(): string {
    return React.findDOMNode(this).value;
  }

  /**
   * Put focus on a <textarea /> DOM element.
   */
  focus() {
    React.findDOMNode(this).focus();
  }

}

function onNextFrame(cb) {
  if (window.requestAnimationFrame) {
    window.requestAnimationFrame(cb);
  } else {
    window.setTimeout(cb, 1);
  }
}
<commit_msg>Do not set overflow: hidden only if we past maxHeight<commit_after>/**
 * <TextareaAutosize />
 */

import React from 'react';
import emptyFunction from 'react/lib/emptyFunction';
import calculateNodeHeight from './calculateNodeHeight';

export default class TextareaAutosize extends React.Component {

  static propTypes = {
    /**
     * Current textarea value.
     */
    value: React.PropTypes.string,

    /**
     * Callback on value change.
     */
    onChange: React.PropTypes.func,

    /**
     * Try to cache DOM measurements performed by component so that we don't
     * touch DOM when it's not needed.
     *
     * This optimization doesn't work if we dynamically style <textarea />
     * component.
     */
    useCacheForDOMMeasurements: React.PropTypes.bool
  }

  static defaultProps = {
    onChange: emptyFunction,
    useCacheForDOMMeasurements: false
  }

  constructor(props) {
    super(props);
    this.state = {height: null};
    this._onChange = this._onChange.bind(this);
    this._resizeComponent = this._resizeComponent.bind(this);
  }

  render() {
    let {valueLink, onChange, ...props} = this.props;
    props = {...props};
    if (typeof valueLink === 'object') {
      props.value = this.props.valueLink.value;
    }
    props.style = {
      ...props.style,
      height: this.state.height
    };
    if (!props.style.maxHeight || props.style.maxHeight > props.style.height) {
      props.style.overflow = 'hidden';
    }
    return <textarea {...props} onChange={this._onChange} />;
  }

  componentDidMount() {
    this._resizeComponent();
  }

  componentWillReceiveProps() {
    // Re-render with the new content then recalculate the height as required.
    onNextFrame(this._resizeComponent);
  }

  _onChange(e) {
    this._resizeComponent();
    let {valueLink, onChange} = this.props;
    if (valueLink) {
      valueLink.requestChange(e.target.value);
    } else {
      onChange(e);
    }
  }

  _resizeComponent() {
    let {useCacheForDOMMeasurements} = this.props;
    let height = calculateNodeHeight(
      React.findDOMNode(this),
      useCacheForDOMMeasurements,
      this.props.rows);
    this.setState({height});
  }

  /**
   * Read the current value of <textarea /> from DOM.
   */
  get value(): string {
    return React.findDOMNode(this).value;
  }

  /**
   * Put focus on a <textarea /> DOM element.
   */
  focus() {
    React.findDOMNode(this).focus();
  }

}

function onNextFrame(cb) {
  if (window.requestAnimationFrame) {
    window.requestAnimationFrame(cb);
  } else {
    window.setTimeout(cb, 1);
  }
}
<|endoftext|>


<commit_before>import PTT from '../PTT';

class TimerFetch {

  _defaultParams() {
    const uId = PTT.get('user').id;
    return '?per_page=100&author='+uId;
  }

  /**
   * Retrieve a taxonomy from premise time tracker.
   *
   * @param  {String}   slug     the taxonomy slug (wihtout 'premise_time_tracker_')
   * @param  {Function} callback a callback to be called with the taxonomy found
   * @return {Void}              does not return anything. call the callbcak passed.
   */
  loadTaxonomy( slug, callback ) {
    slug = slug || null;

    if ( ! slug ) return false;

    fetch( PTT.get( 'site' ).url
      + '/wp-json/wp/v2/premise_time_tracker_'
      + slug
      + '/'
      + this._defaultParams() )
    .then( response => {
      response.json()
      .then( _terms => {
        callback( _terms );
      });
    });
  }

  /**
   * Retrieve a taxonomy from premise time tracker.
   *
   * @param  {String} slug the taxonomy slug (wihtout 'premise_time_tracker_')
   * @return {Promise}     Promise for the taxonomy object
   */
  getTaxonomy( slug ) {
    slug = slug || null;

    if ( ! slug ) return false;

    const url = PTT.get( 'site' ).url
    + '/wp-json/wp/v2/premise_time_tracker_'
    + slug
    + this._defaultParams();

    // console.log(url);

    const tax = fetch( url )
    .then( response => {
      return response.json();
    });

    return tax;
  }

  /**
   * Search timers.
   *
   * @param  {String}  Search term.
   * @return {Promise} Promise for the results object
   */
  searchTimers( searchTerm ) {
    searchTerm = searchTerm || null;

    if ( ! searchTerm ) return false;

    const url = PTT.get( 'endpoint' )
    + this._defaultParams()
    + '&search='
    + encodeURIComponent( searchTerm );

    // console.log(url);

    const results = fetch( url )
    .then( response => {
      return response.json();
    });

    return results;
  }

  /**
   * Get timers by term.
   *
   * @param  {Integer}  Term ID.
   * @param  {String}  Taxonomy.
   * @return {Promise} Promise for the timers object
   */
  getTimersByTerm( termId, taxonomy ) {
    taxonomy = taxonomy || null;

    if ( ! termId ) return false;
    if ( ! taxonomy ) return false;

    const url = this.timersByTermUrl( termId, taxonomy );

    // console.log(url);

    const timers = fetch( url )
    .then( response => {
      return response.json();
    });

    return timers;
  }

  /**
   * Get timers by term URL.
   *
   * @param  {Integer}  Term ID.
   * @param  {String}  Taxonomy.
   * @return {String}  Wordpress API URL.
   */
  timersByTermUrl( termId, taxonomy ) {
    taxonomy = 'premise_time_tracker_' + taxonomy;

    return PTT.get( 'endpoint' )
    + this._defaultParams()
    + '&'
    + encodeURIComponent( taxonomy )
    + '[]=' + encodeURIComponent( termId );
  }

  /**
   * Get timers by term, filtered by date.
   *
   * @param  {Integer}  Term ID.
   * @param  {String}   Taxonomy.
   * @param  {String}   Timers before date (ISO8601 compliant date).
   * @param  {String}   Timers before date (ISO8601 compliant date).
   * @return {Promise}  Promise for the timers object
   */
  getTimersByTermFilterByDate( termId, taxonomy, before, after ) {
    taxonomy = taxonomy || null;

    if ( ! termId ) return false;
    if ( ! taxonomy ) return false;

    if ( ! before && ! after ) {
      return this.getTimersByTerm( termId, taxonomy );
    }

    let url = this.timersByTermUrl( termId, taxonomy );

    if ( after ) {
      url += '&after=' + encodeURIComponent( after );
    }

    if ( before ) {
      url += '&before=' + encodeURIComponent( before );
    }

    console.log(url);

    const timers = fetch( url )
    .then( response => {
      return response.json();
    });

    return timers;
  }

  /**
   * Retrieve a post from premise time tracker.
   *
   * @param  {Integer} id      the id for the post we want to retrieve
   * @param  {Object}  options params to add to the query as a javascript object
   * @return {Object}          the post object for the post found.
   */
  getPost( id, options ) {
    id = id || null;
    options = options || null;

    if ( ! id ) return false;

    // Parse options as params.
    // BETA not fully tested
    if ( options ) {
      var _options = '';
      for ( var i in options ) {
        if ( options.hasOwnProperty( i ) ) {
          _options += '&' + i + '=' + options[i];
        }
      }
      // console.log(_options);
    }

    // Fetch the post and return promise.
    var post = fetch( PTT.get( 'endpoint' ) + '/' + id + '?' + _options + '/' )
    .then( response => {
      return response.json();
    });
    return post;
  }
}

// Export new singleton class!
// http://stackoverflow.com/questions/33550380/react-flux-dispatcher-as-singleton-in-typescript#34377957
export default new TimerFetch();
<commit_msg>new function otheEndpoint<commit_after>import PTT from '../PTT';
import $ from 'jquery';

class TimerFetch {

  _defaultParams() {
    let _params = '?per_page=100';

    _params += PTT.get('user').id
    ? '&author=' + PTT.get('user').id
    : '';

    return _params;
  }

  /**
   * Retrieve a taxonomy from premise time tracker.
   *
   * @param  {String}   slug     the taxonomy slug (wihtout 'premise_time_tracker_')
   * @param  {Function} callback a callback to be called with the taxonomy found
   * @return {Void}              does not return anything. call the callbcak passed.
   */
  loadTaxonomy( slug, callback ) {
    slug = slug || null;

    if ( ! slug ) return false;

    fetch( PTT.get( 'endpoint' )
      + '_' + slug
      + '/'
      + this._defaultParams() )
    .then( response => {
      response.json()
      .then( _terms => {
        callback( _terms );
      });
    });
  }

  /**
   * Retrieve a taxonomy from premise time tracker.
   *
   * @param  {String} slug the taxonomy slug (wihtout 'premise_time_tracker_')
   * @return {Promise}     Promise for the taxonomy object
   */
  getTaxonomy( slug ) {
    slug = slug || null;

    if ( ! slug ) return false;

    const url = PTT.get( 'endpoint' )
    + '_' + slug
    + this._defaultParams();

    // console.log(url);

    const tax = fetch( url )
    .then( response => {
      return response.json();
    });

    return tax;
  }

  /**
   * Search timers.
   *
   * @param  {String}  Search term.
   * @return {Promise} Promise for the results object
   */
  searchTimers( searchTerm ) {
    searchTerm = searchTerm || null;

    if ( ! searchTerm ) return false;

    const url = PTT.get( 'endpoint' )
    + this._defaultParams()
    + '&search='
    + encodeURIComponent( searchTerm );

    // console.log(url);

    const results = fetch( url )
    .then( response => {
      return response.json();
    });

    return results;
  }

  /**
   * Get timers by term.
   *
   * @param  {Integer}  Term ID.
   * @param  {String}  Taxonomy.
   * @return {Promise} Promise for the timers object
   */
  getTimersByTerm( termId, taxonomy ) {
    taxonomy = taxonomy || null;

    if ( ! termId ) return false;
    if ( ! taxonomy ) return false;

    const url = this.timersByTermUrl( termId, taxonomy );

    // console.log(url);

    const timers = fetch( url )
    .then( response => {
      return response.json();
    });

    return timers;
  }

  /**
   * Get timers by term URL.
   *
   * @param  {Integer}  Term ID.
   * @param  {String}  Taxonomy.
   * @return {String}  Wordpress API URL.
   */
  timersByTermUrl( termId, taxonomy ) {
    taxonomy = 'premise_time_tracker_' + taxonomy;

    return PTT.get( 'endpoint' )
    + this._defaultParams()
    + '&'
    + encodeURIComponent( taxonomy )
    + '[]=' + encodeURIComponent( termId );
  }

  /**
   * Get timers by term, filtered by date.
   *
   * @param  {Integer}  Term ID.
   * @param  {String}   Taxonomy.
   * @param  {String}   Timers before date (ISO8601 compliant date).
   * @param  {String}   Timers before date (ISO8601 compliant date).
   * @return {Promise}  Promise for the timers object
   */
  getTimersByTermFilterByDate( termId, taxonomy, before, after ) {
    taxonomy = taxonomy || null;

    if ( ! termId ) return false;
    if ( ! taxonomy ) return false;

    if ( ! before && ! after ) {
      return this.getTimersByTerm( termId, taxonomy );
    }

    let url = this.timersByTermUrl( termId, taxonomy );

    if ( after ) {
      url += '&after=' + encodeURIComponent( after );
    }

    if ( before ) {
      url += '&before=' + encodeURIComponent( before );
    }

    console.log(url);

    const timers = fetch( url )
    .then( response => {
      return response.json();
    });

    return timers;
  }

  /**
   * Retrieve a post from premise time tracker.
   *
   * @param  {Integer} id      the id for the post we want to retrieve
   * @param  {Object}  options params to add to the query as a javascript object
   * @return {Object}          the post object for the post found.
   */
  getPost( id, options ) {
    id = id || null;
    options = options || null;

    if ( ! id ) return false;

    let _url = PTT.get( 'endpoint' )
    + '/' + id;

    // Parse options as params.
    // BETA not fully tested
    if ( options ) {
      var _options = '';
      for ( var i in options ) {
        if ( options.hasOwnProperty( i ) ) {
          _options += '&' + i + '=' + options[i];
        }
      }
      _url += '?' + _options + '/';
    }

    // Fetch the post and return promise.
    return fetch( _url )
    .then( response => {
      return response.json();
    });
  }

  otherEndpoint( endpoint ) {
    const url = PTT.get( 'site' ).url
    + '/wp-json/'
    + endpoint;

    return $.ajax({
        method:     'GET',
        beforeSend: PTT.get( 'auth' ).ajaxBeforeSend,
        url: url,
    });
  }
}

// Export new singleton class!
// http://stackoverflow.com/questions/33550380/react-flux-dispatcher-as-singleton-in-typescript#34377957
export default new TimerFetch();
<|endoftext|>


<commit_before>/*
	UILanguagePicker.js
	Copyright (c) 2014-2020 dangered wolf, et al
	Released under the MIT licence
*/

import { make } from "./Utils.js";
import { I18n } from "./I18n.js";
import DataI18n from "./DataI18n.js";
import { UIModal } from "./UIModal.js";
import { getPref, setPref } from "./StoragePreferences.js";
import { getFullLanguage, getMainLanguage } from "./I18n.js";
import unsupportedCodeTable from "./DataUnsupportedLanguage.js";
import inaccuraciesCodeTable from "./DataTranslationsMayBeInaccurate.js";
import languageText from "./DataTextThatSaysLanguage.js";

import languageData from "./DataI18n.js";

export class UILanguagePicker extends UIModal {
	constructor() {
		super();
		window.languageData = languageData;

		this.hasMadeChange = false;

		this.element = make("div").addClass("mdl mtd-alert mtd-language-picker");
		this.alertTitle = make("h2").addClass("mtd-alert-title").html("language" + (languageText[navigator.language.substr(0,2)] || languageText["en"]));
		this.alertButton = make("button").addClass("btn-primary btn mtd-alert-button hidden").html("OK");
		this.inaccuracy = make("div").addClass("mtd-unsupported-lang mtd-lang-inaccuracies").html(((DataI18n[navigator.language.substr(0,2)] && DataI18n[navigator.language.substr(0,2)]["Translations may be incomplete or inaccurate."] ? DataI18n[navigator.language.substr(0,2)]["Translations may be incomplete or inaccurate."] : (inaccuraciesCodeTable[navigator.language.substr(0,2)] || inaccuraciesCodeTable["en"]) ))+ " translate.moderndeck.org")

		this.selectLanguage = make("select").attr("id","mtd_language_select").append(
			make("option").val("default").html("-").attr("selected","true").attr("disabled","true"),
			make("option").val("bg").html("български"),
			make("option").val("cs").html("čeština"),
			make("option").val("de").html("Deutsche"),
			make("option").val("en_CA").html("English (Canada)"),
			make("option").val("en_US").html("English (United States)"),
			make("option").val("en_GB").html("English (United Kingdom)"),
			make("option").val("es_ES").html("Español (España)"),
			make("option").val("es_US").html("Español (Estados Unidos)"),
			make("option").val("es_419").html("Español (México)"),
			make("option").val("fr_CA").html("Français (Canada)"),
			make("option").val("fr_FR").html("Français (France)"),
			make("option").val("hr").html("Hrvatski"),
			make("option").val("no").html("norsk"),
			make("option").val("pl").html("Polskie"),
			make("option").val("pt_BR").html("Português (Brasil)"),
			make("option").val("ja").html("日本語"),
			make("option").val("ru").html("русский"),
			make("option").val("zh_CN").html("简体中文")
		).change(() => {
			this.alertTitle.html("language " + (languageData.Language[this.selectLanguage.val()] || languageData.Language[this.selectLanguage.val().substr(0,2)] || "broken"));

			this.hasMadeChange = true;

			this.alertButton.html(languageData.OK[this.selectLanguage.val()] || languageData.OK[this.selectLanguage.val().substr(0,2)] || "OK");
			this.alertButton.removeClass("hidden");

			this.inaccuracy.html(((DataI18n[this.selectLanguage.val().substr(0,2)] && DataI18n[this.selectLanguage.val().substr(0,2)]["Translations may be incomplete or inaccurate."] ? DataI18n[this.selectLanguage.val().substr(0,2)]["Translations may be incomplete or inaccurate."] : (inaccuraciesCodeTable[this.selectLanguage.val().substr(0,2)] || inaccuraciesCodeTable["en"]) ))+ " translate.moderndeck.org")
		});

		setTimeout(() => {
			let mainLang = $("#mtd_language_select>option[value=\"" + navigator.language.substr(0,2) + "\"]");
			if (mainLang.length > 0) {
				mainLang.attr("selected","true");
				this.selectLanguage.trigger("change");
			}

			let localLang = $("#mtd_language_select>option[value=\"" + navigator.language.replace(/\-/g,"_") + "\"]");

			if (localLang.length > 0) {
				localLang.attr("selected","true");
				this.selectLanguage.trigger("change");
			}

			this.hasMadeChange = false;

			setTimeout(() => {
				this.hasMadeChange = false;
			})
		})

		window.inaccuraciesCodeTable = inaccuraciesCodeTable;
		this.alertBody = make("p").addClass("mtd-alert-body").append(this.selectLanguage);
		this.alertButtonContainer = make("div").addClass("mtd-alert-button-container");
		this.unsupportedLang = make("div").addClass("mtd-unsupported-lang").html((unsupportedCodeTable[navigator.language.substr(0,2)] || unsupportedCodeTable["en"]) + " translate.moderndeck.org")

		this.alertButtonContainer.append(this.alertButton);

		this.alertButton.click(() => {
			setPref("mtd_last_lang", navigator.language);
			setPref("mtd_lang", this.selectLanguage.val());

			if (getFullLanguage() !== this.selectLanguage.val() && getMainLanguage() !== this.selectLanguage.val()) {
				setTimeout(() => {
					if (typeof require !== "undefined") {
						const { ipcRenderer } = require("electron");
						ipcRenderer.send("restartApp");
					} else {
						location.reload();
					}
				}, 200);
			} else {
				this.dismiss();
			}

			if (window.isInWelcome) {
				setTimeout(() => new window.UIWelcome, 100)
			}
		});

		this.element.append(this.alertTitle, this.alertBody, this.alertButtonContainer);

		if (!DataI18n.GIF[navigator.language.substr(0,2)]) {
			this.element.append(this.unsupportedLang);
		} else {
			this.element.append(this.inaccuracy);
		}

		// if ($("#splash-modal").length < 1) {
		// 	this.modalRoot = ".login-container";
		// } else {
			this.modalRoot = "#splash-modal";
		// }

		$(this.modalRoot).attr("style", "display: block;").append(this.element)
	}
}
<commit_msg>Added Korean and Estonian<commit_after>/*
	UILanguagePicker.js
	Copyright (c) 2014-2020 dangered wolf, et al
	Released under the MIT licence
*/

import { make } from "./Utils.js";
import { I18n } from "./I18n.js";
import DataI18n from "./DataI18n.js";
import { UIModal } from "./UIModal.js";
import { getPref, setPref } from "./StoragePreferences.js";
import { getFullLanguage, getMainLanguage } from "./I18n.js";
import unsupportedCodeTable from "./DataUnsupportedLanguage.js";
import inaccuraciesCodeTable from "./DataTranslationsMayBeInaccurate.js";
import languageText from "./DataTextThatSaysLanguage.js";

import languageData from "./DataI18n.js";

export class UILanguagePicker extends UIModal {
	constructor() {
		super();
		window.languageData = languageData;

		this.hasMadeChange = false;

		this.element = make("div").addClass("mdl mtd-alert mtd-language-picker");
		this.alertTitle = make("h2").addClass("mtd-alert-title").html("language" + (languageText[navigator.language.substr(0,2)] || languageText["en"]));
		this.alertButton = make("button").addClass("btn-primary btn mtd-alert-button hidden").html("OK");
		this.inaccuracy = make("div").addClass("mtd-unsupported-lang mtd-lang-inaccuracies").html(((DataI18n[navigator.language.substr(0,2)] && DataI18n[navigator.language.substr(0,2)]["Translations may be incomplete or inaccurate."] ? DataI18n[navigator.language.substr(0,2)]["Translations may be incomplete or inaccurate."] : (inaccuraciesCodeTable[navigator.language.substr(0,2)] || inaccuraciesCodeTable["en"]) ))+ " translate.moderndeck.org")

		this.selectLanguage = make("select").attr("id","mtd_language_select").append(
			make("option").val("default").html("-").attr("selected","true").attr("disabled","true"),
			make("option").val("bg").html("български"),
			make("option").val("cs").html("čeština"),
			make("option").val("de").html("Deutsche"),
			make("option").val("et").html("Eesti"),
			make("option").val("en_CA").html("English (Canada)"),
			make("option").val("en_US").html("English (United States)"),
			make("option").val("en_GB").html("English (United Kingdom)"),
			make("option").val("es_ES").html("Español (España)"),
			make("option").val("es_US").html("Español (Estados Unidos)"),
			make("option").val("es_419").html("Español (México)"),
			make("option").val("fr_CA").html("Français (Canada)"),
			make("option").val("fr_FR").html("Français (France)"),
			make("option").val("zh_CN").html("简体中文"),
			make("option").val("ko").html("한국어"),
			make("option").val("hr").html("Hrvatski"),
			make("option").val("ja").html("日本語"),
			make("option").val("no").html("norsk"),
			make("option").val("pl").html("Polskie"),
			make("option").val("pt_BR").html("Português (Brasil)"),
			make("option").val("ru").html("русский")
		).change(() => {
			this.alertTitle.html("language " + (languageData.Language[this.selectLanguage.val()] || languageData.Language[this.selectLanguage.val().substr(0,2)] || "broken"));

			this.hasMadeChange = true;

			this.alertButton.html(languageData.OK[this.selectLanguage.val()] || languageData.OK[this.selectLanguage.val().substr(0,2)] || "OK");
			this.alertButton.removeClass("hidden");

			this.inaccuracy.html(((DataI18n[this.selectLanguage.val().substr(0,2)] && DataI18n[this.selectLanguage.val().substr(0,2)]["Translations may be incomplete or inaccurate."] ? DataI18n[this.selectLanguage.val().substr(0,2)]["Translations may be incomplete or inaccurate."] : (inaccuraciesCodeTable[this.selectLanguage.val().substr(0,2)] || inaccuraciesCodeTable["en"]) ))+ " translate.moderndeck.org")
		});

		setTimeout(() => {
			let mainLang = $("#mtd_language_select>option[value=\"" + navigator.language.substr(0,2) + "\"]");
			if (mainLang.length > 0) {
				mainLang.attr("selected","true");
				this.selectLanguage.trigger("change");
			}

			let localLang = $("#mtd_language_select>option[value=\"" + navigator.language.replace(/\-/g,"_") + "\"]");

			if (localLang.length > 0) {
				localLang.attr("selected","true");
				this.selectLanguage.trigger("change");
			}

			this.hasMadeChange = false;

			setTimeout(() => {
				this.hasMadeChange = false;
			})
		})

		window.inaccuraciesCodeTable = inaccuraciesCodeTable;
		this.alertBody = make("p").addClass("mtd-alert-body").append(this.selectLanguage);
		this.alertButtonContainer = make("div").addClass("mtd-alert-button-container");
		this.unsupportedLang = make("div").addClass("mtd-unsupported-lang").html((unsupportedCodeTable[navigator.language.substr(0,2)] || unsupportedCodeTable["en"]) + " translate.moderndeck.org")

		this.alertButtonContainer.append(this.alertButton);

		this.alertButton.click(() => {
			setPref("mtd_last_lang", navigator.language);
			setPref("mtd_lang", this.selectLanguage.val());

			if (getFullLanguage() !== this.selectLanguage.val() && getMainLanguage() !== this.selectLanguage.val()) {
				setTimeout(() => {
					if (typeof require !== "undefined") {
						const { ipcRenderer } = require("electron");
						ipcRenderer.send("restartApp");
					} else {
						location.reload();
					}
				}, 200);
			} else {
				this.dismiss();
			}

			if (window.isInWelcome) {
				setTimeout(() => new window.UIWelcome, 100)
			}
		});

		this.element.append(this.alertTitle, this.alertBody, this.alertButtonContainer);

		if (!DataI18n.GIF[navigator.language.substr(0,2)]) {
			this.element.append(this.unsupportedLang);
		} else {
			this.element.append(this.inaccuracy);
		}

		// if ($("#splash-modal").length < 1) {
		// 	this.modalRoot = ".login-container";
		// } else {
			this.modalRoot = "#splash-modal";
		// }

		$(this.modalRoot).attr("style", "display: block;").append(this.element)
	}
}
<|endoftext|>


<commit_before>$(document).ready(function () {
    $('h2').each(function(){
        if ($(this).text().indexOf("扫码") != -1) {
            var url = $(this).find('a').attr('href');
            var tokens = url.split('/');
            var topic_id = tokens[tokens.length-1];
            $(this).html('
参与讨论
');
            $(this).parent().append('

');

            $('a').each(function(){
                if ($(this).text().indexOf("扫码直达讨论区") != -1) {
                    $(this).text('参与讨论');
                }
            });

            $('img').each(function(){
                if ($(this).attr('src').indexOf("qr_") != -1) {
                    $(this).hide();
                }
            });

            DiscourseEmbed = { discourseUrl: 'https://discuss.gluon.ai/', topicId: topic_id };
            (function() {
                var d = document.createElement('script'); d.type = 'text/javascript';
                d.async = true;
                d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js';
                (document.getElementsByTagName('head')[0] ||
                 document.getElementsByTagName('body')[0]).appendChild(d);
            })();
        }
    });

});
<commit_msg>discuss js anchor<commit_after>$(document).ready(function () {
    var discuss_str = '参与讨论'
    $('h2').each(function(){
        if ($(this).text().indexOf("扫码") != -1) {
            var url = $(this).find('a').attr('href');
            var tokens = url.split('/');
            var topic_id = tokens[tokens.length-1];

            $(this).html('
'.concat(discuss_str).concat('
'));
            $(this).parent().append('

');

            $('img').each(function(){
                if ($(this).attr('src').indexOf("qr_") != -1) {
                    $(this).hide();
                }
            });

            DiscourseEmbed = { discourseUrl: 'https://discuss.gluon.ai/', topicId: topic_id };
            (function() {
                var d = document.createElement('script'); d.type = 'text/javascript';
                d.async = true;
                d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js';
                (document.getElementsByTagName('head')[0] ||
                 document.getElementsByTagName('body')[0]).appendChild(d);
            })();
        }
    });

    var replaced = $('body').html().replace(/扫码直达讨论区/g, discuss_str);
    $('body').html(replaced);
});
<|endoftext|>


<commit_before>/**
 * Spatial HashMap for broad phase collision
 *
 * @author Louis Stowasser
 */

    /**@
     * #Crafty.HashMap.constructor
     * @comp Crafty.HashMap
     * @sign public void Crafty.HashMap([cellsize])
     * @param cellsize - the cell size. If omitted, `cellsize` is 64.
     *
     * Set `cellsize`.
     * And create `this.map`.
     */
    var cellsize,

        HashMap = function (cell) {
            cellsize = cell || 64;
            this.map = {};

            this.boundsDirty = false;
            this.boundsHash = {
                max: {
                    x: -Infinity,
                    y: -Infinity
                },
                min: {
                    x: Infinity,
                    y: Infinity
                }
            };
            this.boundsCoords = {
                max: {
                    x: -Infinity,
                    y: -Infinity
                },
                min: {
                    x: Infinity,
                    y: Infinity
                }
            };
        },

        SPACE = " ",
        keyHolder = {};

    HashMap.prototype = {
        /**@
         * #Crafty.map.insert
         * @comp Crafty.map
         * @sign public Object Crafty.map.insert(Object obj)
         * @param obj - An entity to be inserted.
         * @returns An object representing this object's entry in the HashMap
         *
         * `obj` is inserted in '.map' of the corresponding broad phase cells. An object of the following fields is returned.
         * ~~~
         * {
         *   keys: the object that keep track of cells
         *   obj: The inserted object
         *   map: the HashMap object
         * }
         * ~~~
         */
        insert: function (obj) {
            var keys = HashMap.key(obj),
                entry = new Entry(keys, obj, this),
                i = 0,
                j,
                hash;

            //insert into all x buckets
            for (i = keys.x1; i <= keys.x2; i++) {
                //insert into all y buckets
                for (j = keys.y1; j <= keys.y2; j++) {
                    hash = (i << 16) ^ j;
                    if (!this.map[hash]) this.map[hash] = [];
                    this.map[hash].push(obj);
                }
            }

            //mark map boundaries as dirty
            this.boundsDirty = true;

            return entry;
        },

        /**@
         * #Crafty.map.search
         * @comp Crafty.map
         * @sign public Object Crafty.map.search(Object rect[, Boolean filter])
         * @param rect - the rectangular region to search for entities.
         *               This object must contain the properties `_x`,`_y`,`_w`,`_h`.
         * @param filter - If `false`, only performs a broad-phase collision check.  The default value is `true`.
         * @return an (possibly empty) array of entities that have been found in the given region
         *
         * Search for entities in the given region, using their broadphase bounding rectangles.
         *
         * - If `filter` is `false`, just search for all the entries in the give `rect` region by broad phase collision. Entity may be returned duplicated.
         * - If `filter` is `true`, filter the above results by checking that they actually overlap `rect`.
         *
         * The easier usage is with `filter == true`. For performance reason, you may use `filter == false`, and filter the result yourself. See examples in drawing.js and collision.js.
         *
         * @example
         * ~~~
         * // search for entities located in the current visible region of the viewport
         * var results = Crafty.map.search(Crafty.viewport.rect());
         * // iterate over all those entities
         * var ent;
         * for (var i = 0, l = results.length; i < l; ++i) {
         *     // do something with an entity
         *     ent = results[i];
         *     Crafty.log('Found entity with id', ent.getId());
         * }
         * ~~~
         */

        search: function (rect, filter) {
            var keys = HashMap.key(rect, keyHolder),
                i, j, k, l, cell,
                results = [];

            if (filter === undefined) filter = true; //default filter to true

            //search in all x buckets
            for (i = keys.x1; i <= keys.x2; i++) {
                //insert into all y buckets
                for (j = keys.y1; j <= keys.y2; j++) {
                    if ((cell = this.map[(i << 16) ^ j])) {
                        for (k = 0; k < cell.length; k++)
                            results.push(cell[k]);
                    }
                }
            }

            if (filter) {
                var obj, id, finalresult = [],
                    found = {};
                //add unique elements to lookup table with the entity ID as unique key
                for (i = 0, l = results.length; i < l; i++) {
                    obj = results[i];
                    if (!obj) continue; //skip if deleted
                    id = obj[0]; //unique ID
                    obj = obj._mbr || obj;
                    //check if not added to hash and that actually intersects
                    if (!found[id] && obj._x < rect._x + rect._w && obj._x + obj._w > rect._x &&
                                      obj._y < rect._y + rect._h && obj._y + obj._h > rect._y)
                        found[id] = results[i];
                }

                //loop over lookup table and copy to final array
                for (obj in found) finalresult.push(found[obj]);

                return finalresult;
            } else {
                return results;
            }
        },

        /**@
         * #Crafty.map.remove
         * @comp Crafty.map
         * @sign public void Crafty.map.remove(Entry entry)
         * @param entry - An entry to remove from the hashmap
         *
         * Remove an entry from the broad phase map.
         *
         * @example
         * ~~~
         * Crafty.map.remove(e);
         * ~~~
         */
        remove: function (entry) {
            var keys = entry.keys;
            var obj = entry.obj;
            var i = 0,
                j, hash;

            //search in all x buckets
            for (i = keys.x1; i <= keys.x2; i++) {
                //insert into all y buckets
                for (j = keys.y1; j <= keys.y2; j++) {
                    hash = (i << 16) ^ j;

                    if (this.map[hash]) {
                        var cell = this.map[hash],
                            m, n = cell.length;
                        //loop over objs in cell and delete
                        for (m = 0; m < n; m++)
                            if (cell[m] && cell[m][0] === obj[0])
                                cell.splice(m, 1);
                    }
                }
            }

            //mark map boundaries as dirty
            this.boundsDirty = true;
        },

        /**@
         * #Crafty.map.refresh
         * @comp Crafty.map
         * @sign public void Crafty.map.refresh(Entry entry)
         * @param entry - An entry to update
         *
         * Update an entry's keys, and its position in the broad phrase map.
         *
         * @example
         * ~~~
         * Crafty.map.refresh(e);
         * ~~~
         */
        refresh: function (entry) {
            var keys = entry.keys;
            var obj = entry.obj;
            var cell, i, j, m, n;

            //First delete current object from appropriate cells
            for (i = keys.x1; i <= keys.x2; i++) {
                for (j = keys.y1; j <= keys.y2; j++) {
                    cell = this.map[(i << 16) ^ j];
                    if (cell) {
                        n = cell.length;
                        //loop over objs in cell and delete
                        for (m = 0; m < n; m++)
                            if (cell[m] && cell[m][0] === obj[0])
                                cell.splice(m, 1);
                    }
                }
            }

            //update keys
            HashMap.key(obj, keys);

            //insert into all rows and columns
            for (i = keys.x1; i <= keys.x2; i++) {
                for (j = keys.y1; j <= keys.y2; j++) {
                    cell = this.map[(i << 16) ^ j];
                    if (!cell) cell = this.map[(i << 16) ^ j] = [];
                    cell.push(obj);
                }
            }

            //mark map boundaries as dirty
            this.boundsDirty = true;

            return entry;
        },

        /**@
         * #Crafty.map.boundaries
         * @comp Crafty.map
         * @sign public Object Crafty.map.boundaries()
         * @returns An object with the following structure, which represents an MBR which contains all entities
         *
         * Note that the returned object is a reference to the internally used object.
         * Use `Crafty.clone` to get a copy instead.
         *
         * ~~~
         * {
         *   min: {
         *     x: val_x,
         *     y: val_y
         *   },
         *   max: {
         *     x: val_x,
         *     y: val_y
         *   }
         * }
         * ~~~
         */
        boundaries: function() {
            this._updateBoundaries();
            return this.boundsCoords;
        },

        /**
         * #Crafty.map._keyBoundaries
         * @comp Crafty.map
         * @sign private Object Crafty.map._keyBoundaries()
         * @returns An object with the following structure, which represents an MBR which contains all hash keys
         *
         * Find boundaries of row/col cell grid keys instead of actual x/y pixel coordinates.
         *
         * ~~~
         * {
         *   min: {
         *     x: val_x,
         *     y: val_y
         *   },
         *   max: {
         *     x: val_x,
         *     y: val_y
         *   }
         * }
         * ~~~
         */
        _keyBoundaries: function() {
            this._updateBoundaries();
            return this.boundsHash;
        },

        _updateBoundaries: function() {
            // update map boundaries if they were changed
            if (!this.boundsDirty) return;

            var hash = this.boundsHash;
            hash.max.x = -Infinity;
            hash.max.y = -Infinity;
            hash.min.x = Infinity;
            hash.min.y = Infinity;

            var coords = this.boundsCoords;
            coords.max.x = -Infinity;
            coords.max.y = -Infinity;
            coords.min.x = Infinity;
            coords.min.y = Infinity;

            var k, ent;
            //Using broad phase hash to speed up the computation of boundaries.
            for (var h in this.map) {
                if (!this.map[h].length) continue;

                //broad phase coordinate
                var i = h >> 16,
                    j = (h << 16) >> 16;
                if (j < 0) {
                    i = i ^ -1;
                }
                if (i >= hash.max.x) {
                    hash.max.x = i;
                    for (k in this.map[h]) {
                        ent = this.map[h][k];
                        //make sure that this is a Crafty entity
                        if (typeof ent === 'object' && 'requires' in ent) {
                            coords.max.x = Math.max(coords.max.x, ent.x + ent.w);
                        }
                    }
                }
                if (i <= hash.min.x) {
                    hash.min.x = i;
                    for (k in this.map[h]) {
                        ent = this.map[h][k];
                        if (typeof ent === 'object' && 'requires' in ent) {
                            coords.min.x = Math.min(coords.min.x, ent.x);
                        }
                    }
                }
                if (j >= hash.max.y) {
                    hash.max.y = j;
                    for (k in this.map[h]) {
                        ent = this.map[h][k];
                        if (typeof ent === 'object' && 'requires' in ent) {
                            coords.max.y = Math.max(coords.max.y, ent.y + ent.h);
                        }
                    }
                }
                if (j <= hash.min.y) {
                    hash.min.y = j;
                    for (k in this.map[h]) {
                        ent = this.map[h][k];
                        if (typeof ent === 'object' && 'requires' in ent) {
                            coords.min.y = Math.min(coords.min.y, ent.y);
                        }
                    }
                }
            }

            // mark map boundaries as clean
            this.boundsDirty = false;
        }

    };

    /**@
     * #Crafty.HashMap
     * @category 2D
     * Broad-phase collision detection engine. See background information at
     *
     * - [N Tutorial B - Broad-Phase Collision](http://www.metanetsoftware.com/technique/tutorialB.html)
     * - [Broad-Phase Collision Detection with CUDA](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch32.html)
     * @see Crafty.map
     */

    /**@
     * #Crafty.HashMap.key
     * @comp Crafty.HashMap
     * @sign public Object Crafty.HashMap.key(Object obj)
     * @param obj - an Object that has .mbr() or _x, _y, _w and _h.
     *
     * Get the rectangular region (in terms of the grid, with grid size `cellsize`), where the object may fall in. This region is determined by the object's bounding box.
     * The `cellsize` is 64 by default.
     *
     * @see Crafty.HashMap.constructor
     */
    HashMap.key = function (obj, keys) {
        if (obj._mbr) {
            obj = obj._mbr;
        }
        if (!keys) {
            keys = {};
        }

        keys.x1 = Math.floor(obj._x / cellsize);
        keys.y1 = Math.floor(obj._y / cellsize);
        keys.x2 = Math.floor((obj._w + obj._x) / cellsize);
        keys.y2 = Math.floor((obj._h + obj._y) / cellsize);
        return keys;
    };

    HashMap.hash = function (keys) {
        return keys.x1 + SPACE + keys.y1 + SPACE + keys.x2 + SPACE + keys.y2;
    };

    function Entry(keys, obj, map) {
        this.keys = keys;
        this.map = map;
        this.obj = obj;
    }

    Entry.prototype = {
        update: function (rect) {
            //check if buckets change
            if (HashMap.hash(HashMap.key(rect, keyHolder)) !== HashMap.hash(this.keys)) {
                this.map.refresh(this);
            }
        }
    };

    module.exports = HashMap;
<commit_msg>Add cbr as main bounds in spatial map<commit_after>/**
 * Spatial HashMap for broad phase collision
 *
 * @author Louis Stowasser
 */

    /**@
     * #Crafty.HashMap.constructor
     * @comp Crafty.HashMap
     * @sign public void Crafty.HashMap([cellsize])
     * @param cellsize - the cell size. If omitted, `cellsize` is 64.
     *
     * Set `cellsize`.
     * And create `this.map`.
     */
    var cellsize,

        HashMap = function (cell) {
            cellsize = cell || 64;
            this.map = {};

            this.boundsDirty = false;
            this.boundsHash = {
                max: {
                    x: -Infinity,
                    y: -Infinity
                },
                min: {
                    x: Infinity,
                    y: Infinity
                }
            };
            this.boundsCoords = {
                max: {
                    x: -Infinity,
                    y: -Infinity
                },
                min: {
                    x: Infinity,
                    y: Infinity
                }
            };
        },

        SPACE = " ",
        keyHolder = {};

    HashMap.prototype = {
        /**@
         * #Crafty.map.insert
         * @comp Crafty.map
         * @sign public Object Crafty.map.insert(Object obj)
         * @param obj - An entity to be inserted.
         * @returns An object representing this object's entry in the HashMap
         *
         * `obj` is inserted in '.map' of the corresponding broad phase cells. An object of the following fields is returned.
         * ~~~
         * {
         *   keys: the object that keep track of cells
         *   obj: The inserted object
         *   map: the HashMap object
         * }
         * ~~~
         */
        insert: function (obj) {
            var keys = HashMap.key(obj),
                entry = new Entry(keys, obj, this),
                i = 0,
                j,
                hash;

            //insert into all x buckets
            for (i = keys.x1; i <= keys.x2; i++) {
                //insert into all y buckets
                for (j = keys.y1; j <= keys.y2; j++) {
                    hash = (i << 16) ^ j;
                    if (!this.map[hash]) this.map[hash] = [];
                    this.map[hash].push(obj);
                }
            }

            //mark map boundaries as dirty
            this.boundsDirty = true;

            return entry;
        },

        /**@
         * #Crafty.map.search
         * @comp Crafty.map
         * @sign public Object Crafty.map.search(Object rect[, Boolean filter])
         * @param rect - the rectangular region to search for entities.
         *               This object must contain the properties `_x`,`_y`,`_w`,`_h`.
         * @param filter - If `false`, only performs a broad-phase collision check.  The default value is `true`.
         * @return an (possibly empty) array of entities that have been found in the given region
         *
         * Search for entities in the given region, using their broadphase bounding rectangles.
         *
         * - If `filter` is `false`, just search for all the entries in the give `rect` region by broad phase collision. Entity may be returned duplicated.
         * - If `filter` is `true`, filter the above results by checking that they actually overlap `rect`.
         *
         * The easier usage is with `filter == true`. For performance reason, you may use `filter == false`, and filter the result yourself. See examples in drawing.js and collision.js.
         *
         * @example
         * ~~~
         * // search for entities located in the current visible region of the viewport
         * var results = Crafty.map.search(Crafty.viewport.rect());
         * // iterate over all those entities
         * var ent;
         * for (var i = 0, l = results.length; i < l; ++i) {
         *     // do something with an entity
         *     ent = results[i];
         *     Crafty.log('Found entity with id', ent.getId());
         * }
         * ~~~
         */

        search: function (rect, filter) {
            var keys = HashMap.key(rect, keyHolder),
                i, j, k, l, cell,
                results = [];

            if (filter === undefined) filter = true; //default filter to true

            //search in all x buckets
            for (i = keys.x1; i <= keys.x2; i++) {
                //insert into all y buckets
                for (j = keys.y1; j <= keys.y2; j++) {
                    if ((cell = this.map[(i << 16) ^ j])) {
                        for (k = 0; k < cell.length; k++)
                            results.push(cell[k]);
                    }
                }
            }

            if (filter) {
                var obj, id, finalresult = [],
                    found = {};
                //add unique elements to lookup table with the entity ID as unique key
                for (i = 0, l = results.length; i < l; i++) {
                    obj = results[i];
                    if (!obj) continue; //skip if deleted
                    id = obj[0]; //unique ID
                    obj = obj._cbr || obj._mbr || obj;
                    //check if not added to hash and that actually intersects
                    if (!found[id] && obj._x < rect._x + rect._w && obj._x + obj._w > rect._x &&
                                      obj._y < rect._y + rect._h && obj._y + obj._h > rect._y)
                        found[id] = results[i];
                }

                //loop over lookup table and copy to final array
                for (obj in found) finalresult.push(found[obj]);

                return finalresult;
            } else {
                return results;
            }
        },

        /**@
         * #Crafty.map.remove
         * @comp Crafty.map
         * @sign public void Crafty.map.remove(Entry entry)
         * @param entry - An entry to remove from the hashmap
         *
         * Remove an entry from the broad phase map.
         *
         * @example
         * ~~~
         * Crafty.map.remove(e);
         * ~~~
         */
        remove: function (entry) {
            var keys = entry.keys;
            var obj = entry.obj;
            var i = 0,
                j, hash;

            //search in all x buckets
            for (i = keys.x1; i <= keys.x2; i++) {
                //insert into all y buckets
                for (j = keys.y1; j <= keys.y2; j++) {
                    hash = (i << 16) ^ j;

                    if (this.map[hash]) {
                        var cell = this.map[hash],
                            m, n = cell.length;
                        //loop over objs in cell and delete
                        for (m = 0; m < n; m++)
                            if (cell[m] && cell[m][0] === obj[0])
                                cell.splice(m, 1);
                    }
                }
            }

            //mark map boundaries as dirty
            this.boundsDirty = true;
        },

        /**@
         * #Crafty.map.refresh
         * @comp Crafty.map
         * @sign public void Crafty.map.refresh(Entry entry)
         * @param entry - An entry to update
         *
         * Update an entry's keys, and its position in the broad phrase map.
         *
         * @example
         * ~~~
         * Crafty.map.refresh(e);
         * ~~~
         */
        refresh: function (entry) {
            var keys = entry.keys;
            var obj = entry.obj;
            var cell, i, j, m, n;

            //First delete current object from appropriate cells
            for (i = keys.x1; i <= keys.x2; i++) {
                for (j = keys.y1; j <= keys.y2; j++) {
                    cell = this.map[(i << 16) ^ j];
                    if (cell) {
                        n = cell.length;
                        //loop over objs in cell and delete
                        for (m = 0; m < n; m++)
                            if (cell[m] && cell[m][0] === obj[0])
                                cell.splice(m, 1);
                    }
                }
            }

            //update keys
            HashMap.key(obj, keys);

            //insert into all rows and columns
            for (i = keys.x1; i <= keys.x2; i++) {
                for (j = keys.y1; j <= keys.y2; j++) {
                    cell = this.map[(i << 16) ^ j];
                    if (!cell) cell = this.map[(i << 16) ^ j] = [];
                    cell.push(obj);
                }
            }

            //mark map boundaries as dirty
            this.boundsDirty = true;

            return entry;
        },

        /**@
         * #Crafty.map.boundaries
         * @comp Crafty.map
         * @sign public Object Crafty.map.boundaries()
         * @returns An object with the following structure, which represents an MBR which contains all entities
         *
         * Note that the returned object is a reference to the internally used object.
         * Use `Crafty.clone` to get a copy instead.
         *
         * ~~~
         * {
         *   min: {
         *     x: val_x,
         *     y: val_y
         *   },
         *   max: {
         *     x: val_x,
         *     y: val_y
         *   }
         * }
         * ~~~
         */
        boundaries: function() {
            this._updateBoundaries();
            return this.boundsCoords;
        },

        /**
         * #Crafty.map._keyBoundaries
         * @comp Crafty.map
         * @sign private Object Crafty.map._keyBoundaries()
         * @returns An object with the following structure, which represents an MBR which contains all hash keys
         *
         * Find boundaries of row/col cell grid keys instead of actual x/y pixel coordinates.
         *
         * ~~~
         * {
         *   min: {
         *     x: val_x,
         *     y: val_y
         *   },
         *   max: {
         *     x: val_x,
         *     y: val_y
         *   }
         * }
         * ~~~
         */
        _keyBoundaries: function() {
            this._updateBoundaries();
            return this.boundsHash;
        },

        _updateBoundaries: function() {
            // update map boundaries if they were changed
            if (!this.boundsDirty) return;

            var hash = this.boundsHash;
            hash.max.x = -Infinity;
            hash.max.y = -Infinity;
            hash.min.x = Infinity;
            hash.min.y = Infinity;

            var coords = this.boundsCoords;
            coords.max.x = -Infinity;
            coords.max.y = -Infinity;
            coords.min.x = Infinity;
            coords.min.y = Infinity;

            var k, ent;
            //Using broad phase hash to speed up the computation of boundaries.
            for (var h in this.map) {
                if (!this.map[h].length) continue;

                //broad phase coordinate
                var i = h >> 16,
                    j = (h << 16) >> 16;
                if (j < 0) {
                    i = i ^ -1;
                }
                if (i >= hash.max.x) {
                    hash.max.x = i;
                    for (k in this.map[h]) {
                        ent = this.map[h][k];
                        //make sure that this is a Crafty entity
                        if (typeof ent === 'object' && 'requires' in ent) {
                            coords.max.x = Math.max(coords.max.x, ent.x + ent.w);
                        }
                    }
                }
                if (i <= hash.min.x) {
                    hash.min.x = i;
                    for (k in this.map[h]) {
                        ent = this.map[h][k];
                        if (typeof ent === 'object' && 'requires' in ent) {
                            coords.min.x = Math.min(coords.min.x, ent.x);
                        }
                    }
                }
                if (j >= hash.max.y) {
                    hash.max.y = j;
                    for (k in this.map[h]) {
                        ent = this.map[h][k];
                        if (typeof ent === 'object' && 'requires' in ent) {
                            coords.max.y = Math.max(coords.max.y, ent.y + ent.h);
                        }
                    }
                }
                if (j <= hash.min.y) {
                    hash.min.y = j;
                    for (k in this.map[h]) {
                        ent = this.map[h][k];
                        if (typeof ent === 'object' && 'requires' in ent) {
                            coords.min.y = Math.min(coords.min.y, ent.y);
                        }
                    }
                }
            }

            // mark map boundaries as clean
            this.boundsDirty = false;
        }

    };

    /**@
     * #Crafty.HashMap
     * @category 2D
     * Broad-phase collision detection engine. See background information at
     *
     * - [N Tutorial B - Broad-Phase Collision](http://www.metanetsoftware.com/technique/tutorialB.html)
     * - [Broad-Phase Collision Detection with CUDA](http://http.developer.nvidia.com/GPUGems3/gpugems3_ch32.html)
     * @see Crafty.map
     */

    /**@
     * #Crafty.HashMap.key
     * @comp Crafty.HashMap
     * @sign public Object Crafty.HashMap.key(Object obj)
     * @param obj - an Object that has .mbr() or _x, _y, _w and _h.
     *
     * Get the rectangular region (in terms of the grid, with grid size `cellsize`), where the object may fall in. This region is determined by the object's bounding box.
     * The `cellsize` is 64 by default.
     *
     * @see Crafty.HashMap.constructor
     */
    HashMap.key = function (obj, keys) {
        obj = obj._cbr || obj._mbr || obj;
        keys = keys || {};

        keys.x1 = Math.floor(obj._x / cellsize);
        keys.y1 = Math.floor(obj._y / cellsize);
        keys.x2 = Math.floor((obj._w + obj._x) / cellsize);
        keys.y2 = Math.floor((obj._h + obj._y) / cellsize);
        return keys;
    };

    HashMap.hash = function (keys) {
        return keys.x1 + SPACE + keys.y1 + SPACE + keys.x2 + SPACE + keys.y2;
    };

    function Entry(keys, obj, map) {
        this.keys = keys;
        this.map = map;
        this.obj = obj;
    }

    Entry.prototype = {
        update: function (rect) {
            //check if buckets change
            if (HashMap.hash(HashMap.key(rect, keyHolder)) !== HashMap.hash(this.keys)) {
                this.map.refresh(this);
            }
        }
    };

    module.exports = HashMap;
<|endoftext|>