<commit_before>"use strict";

function doClear() {
	document.getElementById("input-text").value = "";
	removeAllChildren(document.getElementById("results"));
	inputTextElem.className = "";
}

function doAnalyze() {
	var inputTextElem = document.getElementById("input-text");
	var text = inputTextElem.value;
	text = text.replace(/\n+$/g, "");  // Strip trailing newlines
	var lines = text.split("\n");

	var header = lines[0].split(",");
	var electrodeColIndex = -1;
	for (var i = 0; i < header.length; i++) {
		if (header[i] == "Electrode") {
			if (electrodeColIndex != -1) {
				alert("Error: Duplicate column \"Electrode\"");
				return;
			} else {
				electrodeColIndex = i;
			}
		}
	}

	var skippedRows = 0;
	var invalidValues = 0;
	var samples = [];
	for (var i = 1; i < lines.length; i++) {
		var columns = lines[i].split(",");
		if (columns.length != header.length) {
			skippedRows++;
		} else {
			var strValue = columns[electrodeColIndex];
			var numValue;
			if (/^[+-]?\d+(?:\.\d*)?$/.test(strValue))
				numValue = parseFloat(strValue)
			else {
				invalidValues++;
				numValue = 0;
			}
			samples.push(numValue);
		}
	}
	if (skippedRows > 0)
		alert("Warning: Skipped " + skippedRows + " rows in the input data due to invalid format");
	if (invalidValues > 0)
		alert("Warning: Replaced " + invalidValues + " invalid electrode values in the input data");
	inputTextElem.className = "minimize";

	setTimeout(function() {
		doComputation(samples);
	}, 250);
}

var SAMPLES_PER_SECOND = 512;

function doComputation(samples) {
	var resultsElem = document.getElementById("results");
	removeAllChildren(resultsElem);

	var numSeconds = Math.floor(samples.length / SAMPLES_PER_SECOND);
	for (var i = 0; i < numSeconds; i++) {
		var startIndex = (i + 0) * SAMPLES_PER_SECOND;  // Inclusive
		var endIndex   = (i + 1) * SAMPLES_PER_SECOND;  // Exclusive
		var block = samples.slice(startIndex, endIndex)
		var real = block.slice();  // Clone
		var imag = real.map(function() { return 0; });  // Same length, but all zeros
		transform(real, imag);  // FFT
		real[0] = 0;  // Cancel the DC offset coefficient
		var amplitude = [];
		for (var j = 0; j <= real.length / 2; j++)
			amplitude.push(Math.hypot(real[j], imag[j]));
		var maxAmplitude = Math.max.apply(null, amplitude);

		var h3 = createElement("h3", "Time = " + i + " seconds");
		resultsElem.appendChild(h3);

		var p = createElement("p", "Brainwave:");
		resultsElem.appendChild(p);

		var graphElem = document.createElement("div");
		graphElem.className = "wavegraph";
		var minBlock = Math.min.apply(null, block);
		var maxBlock = Math.max.apply(null, block);
		for (var j = 0; j < block.length; j++) {
			var fullHeight = 4;
			var dotOffset = (maxBlock - block[j]) / (maxBlock - minBlock) * fullHeight;
			var dotElem = document.createElement("div");
			dotElem.style.top = "calc(" + dotOffset.toFixed(3) + "em - 1px)";
			dotElem.title = (i + j / SAMPLES_PER_SECOND).toFixed(3) + " s";
			graphElem.appendChild(dotElem);
		}
		resultsElem.appendChild(graphElem);

		p = createElement("p", "Frequency spectrum:");
		resultsElem.appendChild(p);

		graphElem = document.createElement("div");
		graphElem.className = "freqgraph";
		for (var j = 0; j <= real.length / 2; j++) {
			var fullHeight = 10;
			var barHeight = amplitude[j] / maxAmplitude * fullHeight;
			var barElem = document.createElement("div");
			barElem.style.height = barHeight.toFixed(3) + "em";
			barElem.title = j + " Hz";
			graphElem.appendChild(barElem);
		}
		resultsElem.appendChild(graphElem);
	}
}

function createElement(tagName, content) {
	var result = document.createElement(tagName);
	if (typeof content == "string")
		content = document.createTextNode(content);
	result.appendChild(content);
	return result;
}

function removeAllChildren(node) {
	while (node.firstChild != null)
		node.removeChild(node.firstChild);
}

// Polyfill
if (!("hypot" in Math)) {
	Math.hypot = function(x, y) {
		return Math.sqrt(x * x + y * y);
	};
}
<commit_msg>Further simplified JavaScript code by updating the helper function.<commit_after>"use strict";

function doClear() {
	document.getElementById("input-text").value = "";
	removeAllChildren(document.getElementById("results"));
	inputTextElem.className = "";
}

function doAnalyze() {
	var inputTextElem = document.getElementById("input-text");
	var text = inputTextElem.value;
	text = text.replace(/\n+$/g, "");  // Strip trailing newlines
	var lines = text.split("\n");

	var header = lines[0].split(",");
	var electrodeColIndex = -1;
	for (var i = 0; i < header.length; i++) {
		if (header[i] == "Electrode") {
			if (electrodeColIndex != -1) {
				alert("Error: Duplicate column \"Electrode\"");
				return;
			} else {
				electrodeColIndex = i;
			}
		}
	}

	var skippedRows = 0;
	var invalidValues = 0;
	var samples = [];
	for (var i = 1; i < lines.length; i++) {
		var columns = lines[i].split(",");
		if (columns.length != header.length) {
			skippedRows++;
		} else {
			var strValue = columns[electrodeColIndex];
			var numValue;
			if (/^[+-]?\d+(?:\.\d*)?$/.test(strValue))
				numValue = parseFloat(strValue)
			else {
				invalidValues++;
				numValue = 0;
			}
			samples.push(numValue);
		}
	}
	if (skippedRows > 0)
		alert("Warning: Skipped " + skippedRows + " rows in the input data due to invalid format");
	if (invalidValues > 0)
		alert("Warning: Replaced " + invalidValues + " invalid electrode values in the input data");
	inputTextElem.className = "minimize";

	setTimeout(function() {
		doComputation(samples);
	}, 250);
}

var SAMPLES_PER_SECOND = 512;

function doComputation(samples) {
	var resultsElem = document.getElementById("results");
	removeAllChildren(resultsElem);

	var numSeconds = Math.floor(samples.length / SAMPLES_PER_SECOND);
	for (var i = 0; i < numSeconds; i++) {
		var startIndex = (i + 0) * SAMPLES_PER_SECOND;  // Inclusive
		var endIndex   = (i + 1) * SAMPLES_PER_SECOND;  // Exclusive
		var block = samples.slice(startIndex, endIndex)
		var real = block.slice();  // Clone
		var imag = real.map(function() { return 0; });  // Same length, but all zeros
		transform(real, imag);  // FFT
		real[0] = 0;  // Cancel the DC offset coefficient
		var amplitude = [];
		for (var j = 0; j <= real.length / 2; j++)
			amplitude.push(Math.hypot(real[j], imag[j]));
		var maxAmplitude = Math.max.apply(null, amplitude);

		var h3 = createElement("h3", "Time = " + i + " seconds");
		resultsElem.appendChild(h3);

		var p = createElement("p", "Brainwave:");
		resultsElem.appendChild(p);

		var graphElem = createElement("div");
		graphElem.className = "wavegraph";
		var minBlock = Math.min.apply(null, block);
		var maxBlock = Math.max.apply(null, block);
		for (var j = 0; j < block.length; j++) {
			var fullHeight = 4;
			var dotOffset = (maxBlock - block[j]) / (maxBlock - minBlock) * fullHeight;
			var dotElem = createElement("div");
			dotElem.style.top = "calc(" + dotOffset.toFixed(3) + "em - 1px)";
			dotElem.title = (i + j / SAMPLES_PER_SECOND).toFixed(3) + " s";
			graphElem.appendChild(dotElem);
		}
		resultsElem.appendChild(graphElem);

		p = createElement("p", "Frequency spectrum:");
		resultsElem.appendChild(p);

		graphElem = createElement("div");
		graphElem.className = "freqgraph";
		for (var j = 0; j <= real.length / 2; j++) {
			var fullHeight = 10;
			var barHeight = amplitude[j] / maxAmplitude * fullHeight;
			var barElem = createElement("div");
			barElem.style.height = barHeight.toFixed(3) + "em";
			barElem.title = j + " Hz";
			graphElem.appendChild(barElem);
		}
		resultsElem.appendChild(graphElem);
	}
}

function createElement(tagName, content) {
	var result = document.createElement(tagName);
	if (content != undefined) {
		if (typeof content == "string")
			content = document.createTextNode(content);
		result.appendChild(content);
	}
	return result;
}

function removeAllChildren(node) {
	while (node.firstChild != null)
		node.removeChild(node.firstChild);
}

// Polyfill
if (!("hypot" in Math)) {
	Math.hypot = function(x, y) {
		return Math.sqrt(x * x + y * y);
	};
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

function handleInstalled(details) {
    if (details.reason === "update") {
        let versions = details.previousVersion.split(".");

        // migrate from < 1.7.0
        if (Number(versions[0]) < 1 ||
            (Number(versions[0]) === 1 && Number(versions[1]) < 7) ||
            (Number(versions[0]) === 1 && Number(versions[1]) === 7) && versions[2].startsWith("0beta")) {

            let myOptionsManager = new OptionsManager(RequestControl.defaultOptions);

            myOptionsManager.loadOptions(function () {
                for (let rule of myOptionsManager.options.rules) {
                    if (rule.action === "filter" && rule.paramsFilter) {
                        let values = rule.paramsFilter;
                        rule.paramsFilter = {};
                        rule.paramsFilter.values = values;

                        let regexpChars = /[.+?^${}()|[\]\\]/g; // excluding * wildcard
                        let regexpParam = /^\/(.*)\/$/;

                        // construct regexp pattern of filter params
                        if (rule.paramsFilter.values.length > 0) {
                            let pattern = "";
                            for (let param of rule.paramsFilter.values) {
                                let testRegexp = param.match(regexpParam);
                                if (testRegexp) {
                                    pattern += "|" + testRegexp[1];
                                } else {
                                    pattern += "|" + param.replace(regexpChars, "\\$&").replace(/\*/g, ".*");
                                }
                            }
                            rule.paramsFilter.pattern = pattern.substring(1);
                            console.log(rule.paramsFilter);
                        } else {
                            delete rule.paramsFilter;
                        }
                    }
                }
                myOptionsManager.saveAllOptions();
            });
        }
    }
}

browser.runtime.onInstalled.addListener(handleInstalled);<commit_msg>Fix migrate.js<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

function handleInstalled(details) {
    if (details.reason === "update") {
        let versions = details.previousVersion.split(".");

        // migrate from < 1.7.0
        if (Number(versions[0]) < 1 ||
            (Number(versions[0]) === 1 && Number(versions[1]) < 7) ||
            (Number(versions[0]) === 1 && Number(versions[1]) === 7) && versions[2].startsWith("0beta")) {

            let myOptionsManager = new OptionsManager(RequestControl.defaultOptions);

            myOptionsManager.loadOptions(function () {
                for (let rule of myOptionsManager.options.rules) {
                    if (rule.action === "filter" && rule.paramsFilter) {
                        let newValue = {};
                        newValue.values = rule.paramsFilter;

                        let regexpChars = /[.+?^${}()|[\]\\]/g; // excluding * wildcard
                        let regexpParam = /^\/(.*)\/$/;

                        // construct regexp pattern of filter params
                        if (newValue.values.length > 0) {
                            let pattern = "";
                            for (let param of newValue.values) {
                                let testRegexp = param.match(regexpParam);
                                if (testRegexp) {
                                    pattern += "|" + testRegexp[1];
                                } else {
                                    pattern += "|" + param.replace(regexpChars, "\\$&").replace(/\*/g, ".*");
                                }
                            }
                            newValue.pattern = pattern.substring(1);
                            rule.paramsFilter = newValue;
                            console.log(rule.paramsFilter);
                        } else {
                            delete rule.paramsFilter;
                        }
                    }
                }
                myOptionsManager.saveAllOptions();
            });
        }
    }
}

browser.runtime.onInstalled.addListener(handleInstalled);<|endoftext|>


<commit_before>/**
 * When using db-migrate, the CLI should work most of the time:
 *
 * ```
 * $ db-migrate up
 * ```
 *
 * However, if the migration code calls Service and Model
 * methods directly, then we need to manually close the
 * connection. This file will take care of this for us. Instead
 * of running the `db-migrate` command, run this file instead.
 * Note: This works with multiple migrations.
 *
 * ```
 * $ node migrate.js
 * ```
 */

const DBMigrate = require('db-migrate');
const mongoose = require('mongoose');

const instance = DBMigrate.getInstance(true);

// same as running `db-migrate up`
instance.up(() => {
	mongoose.connections.forEach(conn => conn.close());
});
<commit_msg>set default env to dev for db-migrate<commit_after>/**
 * When using db-migrate, the CLI should work most of the time:
 *
 * ```
 * $ db-migrate up
 * ```
 *
 * However, if the migration code calls Service and Model
 * methods directly, then we need to manually close the
 * connection. This file will take care of this for us. Instead
 * of running the `db-migrate` command, run this file instead.
 * Note: This works with multiple migrations.
 *
 * ```
 * $ node migrate.js
 * ```
 */

const DBMigrate = require('db-migrate');
const mongoose = require('mongoose');

const options = {};

// Travis runs db-migrate without passing NODE_ENV
if (!process.env.NODE_ENV){
	options.env = 'dev';
}

const instance = DBMigrate.getInstance(true, options);

// same as running `db-migrate up`
instance.up(() => {
	mongoose.connections.forEach(conn => conn.close());
});
<|endoftext|>


<commit_before>JSM.TriangleBody = function (name)
{
	this.name = name;
	this.vertices = [];
	this.normals = [];
	this.uvs = [];
	this.triangles = [];
	this.defaultUVIndex = -1;
};

JSM.TriangleBody.prototype.SetName = function (name)
{
	this.name = name;
};

JSM.TriangleBody.prototype.GetName = function ()
{
	return this.name;
};

JSM.TriangleBody.prototype.AddVertex = function (x, y, z)
{
	this.vertices.push (new JSM.Coord (x, y, z));
	return this.vertices.length - 1;
};

JSM.TriangleBody.prototype.GetVertex = function (index)
{
	return this.vertices[index];
};

JSM.TriangleBody.prototype.SetVertex = function (index, x, y, z)
{
	this.vertices[index] = new JSM.Coord (x, y, z);
};

JSM.TriangleBody.prototype.VertexCount = function ()
{
	return this.vertices.length;
};

JSM.TriangleBody.prototype.AddNormal = function (x, y, z)
{
	this.normals.push (new JSM.Coord (x, y, z));
	return this.normals.length - 1;
};

JSM.TriangleBody.prototype.GetNormal = function (index)
{
	return this.normals[index];
};

JSM.TriangleBody.prototype.NormalCount = function ()
{
	return this.normals.length;
};

JSM.TriangleBody.prototype.AddUV = function (x, y)
{
	this.uvs.push (new JSM.Coord2D (x, y));
	return this.uvs.length - 1;
};

JSM.TriangleBody.prototype.AddDefaultUV = function ()
{
	if (this.defaultUVIndex != -1) {
		return this.defaultUVIndex;
	}

	this.defaultUVIndex = this.AddUV (0.0, 0.0);
	return this.defaultUVIndex;
};

JSM.TriangleBody.prototype.GetUV = function (index)
{
	return this.uvs[index];
};

JSM.TriangleBody.prototype.UVCount = function ()
{
	return this.uvs.length;
};

JSM.TriangleBody.prototype.AddTriangle = function (v0, v1, v2, n0, n1, n2, u0, u1, u2, mat, curve)
{
	this.triangles.push ({
		v0 : v0,
		v1 : v1,
		v2 : v2,
		n0 : n0,
		n1 : n1,
		n2 : n2,
		u0 : u0,
		u1 : u1,
		u2 : u2,
		mat : mat,
		curve : curve
	});
	return this.triangles.length - 1;
};

JSM.TriangleBody.prototype.GetTriangle = function (index)
{
	return this.triangles[index];
};

JSM.TriangleBody.prototype.TriangleCount = function ()
{
	return this.triangles.length;
};

JSM.TriangleBody.prototype.Finalize = function (model)
{
	function FinalizeTriangle (body, triangleIndex, triangleNormals, vertexToTriangles)
	{
		function AddAverageNormal (body, vertexIndex, triangleIndex, triangleNormals, vertexToTriangles)
		{
			var averageNormal = new JSM.Vector (0.0, 0.0, 0.0);
			var averageCount = 0;

			var triangle = body.GetTriangle (triangleIndex);
			var neighbourTriangles = vertexToTriangles[vertexIndex];
			var i, neighbourTriangleIndex, neighbourTriangle;
			for (i = 0; i < neighbourTriangles.length; i++) {
				neighbourTriangleIndex = neighbourTriangles[i];
				neighbourTriangle = body.GetTriangle (neighbourTriangleIndex);
				if (triangle.curve == neighbourTriangle.curve) {
					averageNormal = JSM.CoordAdd (averageNormal, triangleNormals[neighbourTriangleIndex]);
					averageCount = averageCount + 1;
				}
			}

			averageNormal = JSM.VectorMultiply (averageNormal, 1.0 / averageCount);
			averageNormal = JSM.VectorNormalize (averageNormal);
			return body.AddNormal (averageNormal.x, averageNormal.y, averageNormal.z);
		}

		var triangle = body.triangles[i];
		if (triangle.mat === undefined) {
			triangle.mat = model.GetDefaultMaterialIndex ();
		}

		var normal, normalIndex;
		if (triangle.n0 === undefined || triangle.n1 === undefined || triangle.n2 === undefined) {
			if (triangle.curve === undefined || triangle.curve === 0) {
				normal = triangleNormals[i];
				normalIndex = body.AddNormal (normal.x, normal.y, normal.z);
				triangle.n0 = normalIndex;
				triangle.n1 = normalIndex;
				triangle.n2 = normalIndex;
			} else {
				triangle.n0 = AddAverageNormal (body, triangle.v0, triangleIndex, triangleNormals, vertexToTriangles);
				triangle.n1 = AddAverageNormal (body, triangle.v1, triangleIndex, triangleNormals, vertexToTriangles);
				triangle.n2 = AddAverageNormal (body, triangle.v2, triangleIndex, triangleNormals, vertexToTriangles);
			}
		}

		if (triangle.u0 === undefined || triangle.u1 === undefined || triangle.u2 === undefined) {
			triangle.u0 = body.AddDefaultUV ();
			triangle.u1 = body.AddDefaultUV ();
			triangle.u2 = body.AddDefaultUV ();
		}
	}

	var triangleNormals = [];
	var vertexToTriangles = {};

	var i;
	for (i = 0; i < this.vertices.length; i++) {
		vertexToTriangles[i] = [];
	}

	var triangle, normal;
	for (i = 0; i < this.triangles.length; i++) {
		triangle = this.triangles[i];
		normal = JSM.CalculateTriangleNormal (this.vertices[triangle.v0], this.vertices[triangle.v1], this.vertices[triangle.v2]);
		triangleNormals.push (normal);
		vertexToTriangles[triangle.v0].push (i);
		vertexToTriangles[triangle.v1].push (i);
		vertexToTriangles[triangle.v2].push (i);
	}

	for (i = 0; i < this.triangles.length; i++) {
		FinalizeTriangle (this, i, triangleNormals, vertexToTriangles);
	}
};

JSM.TriangleBody.prototype.Clone = function ()
{
	var result = new JSM.TriangleBody (this.name);

	var i, triangle;

	for (i = 0; i < this.vertices.length; i++) {
		result.vertices.push (this.vertices[i].Clone ());
	}

	for (i = 0; i < this.normals.length; i++) {
		result.normals.push (this.normals[i].Clone ());
	}

	for (i = 0; i < this.uvs.length; i++) {
		result.uvs.push (this.uvs[i].Clone ());
	}

	for (i = 0; i < this.triangles.length; i++) {
		triangle = this.triangles[i];
		result.triangles.push ({
			v0 : triangle.v0,
			v1 : triangle.v1,
			v2 : triangle.v2,
			n0 : triangle.n0,
			n1 : triangle.n1,
			n2 : triangle.n2,
			u0 : triangle.u0,
			u1 : triangle.u1,
			u2 : triangle.u2,
			mat : triangle.mat,
			curve : triangle.curve
		});
	}

	return result;
};

JSM.TriangleModel = function ()
{
	this.materials = [];
	this.bodies = [];
	this.defaultMaterial = -1;
};

JSM.TriangleModel.prototype.AddMaterial = function (material)
{
	if (material === undefined || material === null) {
		material = {};
	}

	var newMaterial = {};
	JSM.CopyObjectProperties (material, newMaterial, true);

	this.materials.push (newMaterial);
	return this.materials.length - 1;
};

JSM.TriangleModel.prototype.GetMaterial = function (index)
{
	return this.materials[index];
};

JSM.TriangleModel.prototype.AddDefaultMaterial = function ()
{
	if (this.defaultMaterial == -1) {
		this.defaultMaterial = this.AddMaterial ();
	}
	return this.defaultMaterial;
};

JSM.TriangleModel.prototype.GetDefaultMaterialIndex = function ()
{
	return this.AddDefaultMaterial ();
};

JSM.TriangleModel.prototype.MaterialCount = function ()
{
	return this.materials.length;
};

JSM.TriangleModel.prototype.AddBody = function (body)
{
	this.bodies.push (body);
	return this.bodies.length - 1;
};

JSM.TriangleModel.prototype.AddBodyToIndex = function (body, index)
{
	this.bodies.splice (index, 0, body);
	return index;
};

JSM.TriangleModel.prototype.GetBody = function (index)
{
	return this.bodies[index];
};

JSM.TriangleModel.prototype.BodyCount = function ()
{
	return this.bodies.length;
};

JSM.TriangleModel.prototype.GetBody = function (index)
{
	return this.bodies[index];
};

JSM.TriangleModel.prototype.FinalizeMaterials = function ()
{
	function FinalizeMaterial (material, defaultMaterialData)
	{
		var property;
		for (property in defaultMaterialData) {
			if (defaultMaterialData.hasOwnProperty (property)) {
				if (material[property] === undefined || material[property] === null) {
					material[property] = defaultMaterialData[property];
				}
			}
		}
	}

	var defaultMaterialData = {
		name : 'Default',
		ambient : [0.5, 0.5, 0.5],
		diffuse : [0.5, 0.5, 0.5],
		specular : [0.1, 0.1, 0.1],
		shininess : 0.0,
		opacity : 1.0,
		texture : null,
		offset : null,
		scale : null,
		rotation : null
	};

	if (this.materials.length === 0) {
		this.AddDefaultMaterial ();
	}

	var i, material;
	for (i = 0; i < this.materials.length; i++) {
		material = this.materials[i];
		JSM.CopyObjectProperties (defaultMaterialData, material, false);
	}
};

JSM.TriangleModel.prototype.FinalizeBodies = function ()
{
	var i, body;
	for (i = 0; i < this.bodies.length; i++) {
		body = this.bodies[i];
		body.Finalize (this);
	}
};

JSM.TriangleModel.prototype.Finalize = function ()
{
	this.FinalizeMaterials ();
	this.FinalizeBodies ();
};
<commit_msg>Remove unused function.<commit_after>JSM.TriangleBody = function (name)
{
	this.name = name;
	this.vertices = [];
	this.normals = [];
	this.uvs = [];
	this.triangles = [];
	this.defaultUVIndex = -1;
};

JSM.TriangleBody.prototype.SetName = function (name)
{
	this.name = name;
};

JSM.TriangleBody.prototype.GetName = function ()
{
	return this.name;
};

JSM.TriangleBody.prototype.AddVertex = function (x, y, z)
{
	this.vertices.push (new JSM.Coord (x, y, z));
	return this.vertices.length - 1;
};

JSM.TriangleBody.prototype.GetVertex = function (index)
{
	return this.vertices[index];
};

JSM.TriangleBody.prototype.SetVertex = function (index, x, y, z)
{
	this.vertices[index] = new JSM.Coord (x, y, z);
};

JSM.TriangleBody.prototype.VertexCount = function ()
{
	return this.vertices.length;
};

JSM.TriangleBody.prototype.AddNormal = function (x, y, z)
{
	this.normals.push (new JSM.Coord (x, y, z));
	return this.normals.length - 1;
};

JSM.TriangleBody.prototype.GetNormal = function (index)
{
	return this.normals[index];
};

JSM.TriangleBody.prototype.NormalCount = function ()
{
	return this.normals.length;
};

JSM.TriangleBody.prototype.AddUV = function (x, y)
{
	this.uvs.push (new JSM.Coord2D (x, y));
	return this.uvs.length - 1;
};

JSM.TriangleBody.prototype.AddDefaultUV = function ()
{
	if (this.defaultUVIndex != -1) {
		return this.defaultUVIndex;
	}

	this.defaultUVIndex = this.AddUV (0.0, 0.0);
	return this.defaultUVIndex;
};

JSM.TriangleBody.prototype.GetUV = function (index)
{
	return this.uvs[index];
};

JSM.TriangleBody.prototype.UVCount = function ()
{
	return this.uvs.length;
};

JSM.TriangleBody.prototype.AddTriangle = function (v0, v1, v2, n0, n1, n2, u0, u1, u2, mat, curve)
{
	this.triangles.push ({
		v0 : v0,
		v1 : v1,
		v2 : v2,
		n0 : n0,
		n1 : n1,
		n2 : n2,
		u0 : u0,
		u1 : u1,
		u2 : u2,
		mat : mat,
		curve : curve
	});
	return this.triangles.length - 1;
};

JSM.TriangleBody.prototype.GetTriangle = function (index)
{
	return this.triangles[index];
};

JSM.TriangleBody.prototype.TriangleCount = function ()
{
	return this.triangles.length;
};

JSM.TriangleBody.prototype.Finalize = function (model)
{
	function FinalizeTriangle (body, triangleIndex, triangleNormals, vertexToTriangles)
	{
		function AddAverageNormal (body, vertexIndex, triangleIndex, triangleNormals, vertexToTriangles)
		{
			var averageNormal = new JSM.Vector (0.0, 0.0, 0.0);
			var averageCount = 0;

			var triangle = body.GetTriangle (triangleIndex);
			var neighbourTriangles = vertexToTriangles[vertexIndex];
			var i, neighbourTriangleIndex, neighbourTriangle;
			for (i = 0; i < neighbourTriangles.length; i++) {
				neighbourTriangleIndex = neighbourTriangles[i];
				neighbourTriangle = body.GetTriangle (neighbourTriangleIndex);
				if (triangle.curve == neighbourTriangle.curve) {
					averageNormal = JSM.CoordAdd (averageNormal, triangleNormals[neighbourTriangleIndex]);
					averageCount = averageCount + 1;
				}
			}

			averageNormal = JSM.VectorMultiply (averageNormal, 1.0 / averageCount);
			averageNormal = JSM.VectorNormalize (averageNormal);
			return body.AddNormal (averageNormal.x, averageNormal.y, averageNormal.z);
		}

		var triangle = body.triangles[i];
		if (triangle.mat === undefined) {
			triangle.mat = model.GetDefaultMaterialIndex ();
		}

		var normal, normalIndex;
		if (triangle.n0 === undefined || triangle.n1 === undefined || triangle.n2 === undefined) {
			if (triangle.curve === undefined || triangle.curve === 0) {
				normal = triangleNormals[i];
				normalIndex = body.AddNormal (normal.x, normal.y, normal.z);
				triangle.n0 = normalIndex;
				triangle.n1 = normalIndex;
				triangle.n2 = normalIndex;
			} else {
				triangle.n0 = AddAverageNormal (body, triangle.v0, triangleIndex, triangleNormals, vertexToTriangles);
				triangle.n1 = AddAverageNormal (body, triangle.v1, triangleIndex, triangleNormals, vertexToTriangles);
				triangle.n2 = AddAverageNormal (body, triangle.v2, triangleIndex, triangleNormals, vertexToTriangles);
			}
		}

		if (triangle.u0 === undefined || triangle.u1 === undefined || triangle.u2 === undefined) {
			triangle.u0 = body.AddDefaultUV ();
			triangle.u1 = body.AddDefaultUV ();
			triangle.u2 = body.AddDefaultUV ();
		}
	}

	var triangleNormals = [];
	var vertexToTriangles = {};

	var i;
	for (i = 0; i < this.vertices.length; i++) {
		vertexToTriangles[i] = [];
	}

	var triangle, normal;
	for (i = 0; i < this.triangles.length; i++) {
		triangle = this.triangles[i];
		normal = JSM.CalculateTriangleNormal (this.vertices[triangle.v0], this.vertices[triangle.v1], this.vertices[triangle.v2]);
		triangleNormals.push (normal);
		vertexToTriangles[triangle.v0].push (i);
		vertexToTriangles[triangle.v1].push (i);
		vertexToTriangles[triangle.v2].push (i);
	}

	for (i = 0; i < this.triangles.length; i++) {
		FinalizeTriangle (this, i, triangleNormals, vertexToTriangles);
	}
};

JSM.TriangleBody.prototype.Clone = function ()
{
	var result = new JSM.TriangleBody (this.name);

	var i, triangle;

	for (i = 0; i < this.vertices.length; i++) {
		result.vertices.push (this.vertices[i].Clone ());
	}

	for (i = 0; i < this.normals.length; i++) {
		result.normals.push (this.normals[i].Clone ());
	}

	for (i = 0; i < this.uvs.length; i++) {
		result.uvs.push (this.uvs[i].Clone ());
	}

	for (i = 0; i < this.triangles.length; i++) {
		triangle = this.triangles[i];
		result.triangles.push ({
			v0 : triangle.v0,
			v1 : triangle.v1,
			v2 : triangle.v2,
			n0 : triangle.n0,
			n1 : triangle.n1,
			n2 : triangle.n2,
			u0 : triangle.u0,
			u1 : triangle.u1,
			u2 : triangle.u2,
			mat : triangle.mat,
			curve : triangle.curve
		});
	}

	return result;
};

JSM.TriangleModel = function ()
{
	this.materials = [];
	this.bodies = [];
	this.defaultMaterial = -1;
};

JSM.TriangleModel.prototype.AddMaterial = function (material)
{
	if (material === undefined || material === null) {
		material = {};
	}

	var newMaterial = {};
	JSM.CopyObjectProperties (material, newMaterial, true);

	this.materials.push (newMaterial);
	return this.materials.length - 1;
};

JSM.TriangleModel.prototype.GetMaterial = function (index)
{
	return this.materials[index];
};

JSM.TriangleModel.prototype.AddDefaultMaterial = function ()
{
	if (this.defaultMaterial == -1) {
		this.defaultMaterial = this.AddMaterial ();
	}
	return this.defaultMaterial;
};

JSM.TriangleModel.prototype.GetDefaultMaterialIndex = function ()
{
	return this.AddDefaultMaterial ();
};

JSM.TriangleModel.prototype.MaterialCount = function ()
{
	return this.materials.length;
};

JSM.TriangleModel.prototype.AddBody = function (body)
{
	this.bodies.push (body);
	return this.bodies.length - 1;
};

JSM.TriangleModel.prototype.AddBodyToIndex = function (body, index)
{
	this.bodies.splice (index, 0, body);
	return index;
};

JSM.TriangleModel.prototype.GetBody = function (index)
{
	return this.bodies[index];
};

JSM.TriangleModel.prototype.BodyCount = function ()
{
	return this.bodies.length;
};

JSM.TriangleModel.prototype.GetBody = function (index)
{
	return this.bodies[index];
};

JSM.TriangleModel.prototype.FinalizeMaterials = function ()
{
	var defaultMaterialData = {
		name : 'Default',
		ambient : [0.5, 0.5, 0.5],
		diffuse : [0.5, 0.5, 0.5],
		specular : [0.1, 0.1, 0.1],
		shininess : 0.0,
		opacity : 1.0,
		texture : null,
		offset : null,
		scale : null,
		rotation : null
	};

	if (this.materials.length === 0) {
		this.AddDefaultMaterial ();
	}

	var i, material;
	for (i = 0; i < this.materials.length; i++) {
		material = this.materials[i];
		JSM.CopyObjectProperties (defaultMaterialData, material, false);
	}
};

JSM.TriangleModel.prototype.FinalizeBodies = function ()
{
	var i, body;
	for (i = 0; i < this.bodies.length; i++) {
		body = this.bodies[i];
		body.Finalize (this);
	}
};

JSM.TriangleModel.prototype.Finalize = function ()
{
	this.FinalizeMaterials ();
	this.FinalizeBodies ();
};
<|endoftext|>


<commit_before>/*
  Fake localStorage and sessionStorage.

  Separates each renderer's localStorage.

  Credit: https://github.com/pivotal/jasmine/issues/299
*/

var localStorageData = JSON.stringify(localStorage),
    sessionStorageData = JSON.stringify(sessionStorage);

var storeFactory = function(jsonData) {
  var store;

  if(jsonData){
    store = JSON.parse(jsonData);
  }else{
    store = {};
  }

  store.getItem = function(key) {
    return this[key];
  };
  store.setItem = function(key, value) {
    this[key] = value.toString();
  };
  store.clear = function() {
    var key;
    for(key in this){
      if(this.hasOwnProperty(key) && key !== 'setItem' && key !== 'getItem' &&
         key !== 'clear' && key !== 'removeItem'){
        this[key] = undefined;
      }
    }
  };
  store.removeItem = function(key){
    this[key] = undefined;
  };

  return store;
};

Object.defineProperty(window, 'localStorage', { value: storeFactory(localStorageData) });
Object.defineProperty(window, 'sessionStorage', { value: storeFactory(sessionStorageData) });

/*
  Deterministic Math.random

  Credit: https://gist.github.com/mathiasbynens/5670917
*/

Math.random = (function() {
  var seed = 0x2F6E2B1;
  return function() {
    // Robert Jenkins’ 32 bit integer hash function
    seed = ((seed + 0x7ED55D16) + (seed << 12))  & 0xFFFFFFFF;
    seed = ((seed ^ 0xC761C23C) ^ (seed >>> 19)) & 0xFFFFFFFF;
    seed = ((seed + 0x165667B1) + (seed << 5))   & 0xFFFFFFFF;
    seed = ((seed + 0xD3A2646C) ^ (seed << 9))   & 0xFFFFFFFF;
    seed = ((seed + 0xFD7046C5) + (seed << 3))   & 0xFFFFFFFF;
    seed = ((seed ^ 0xB55A4F09) ^ (seed >>> 16)) & 0xFFFFFFFF;
    return (seed & 0xFFFFFFF) / 0x10000000;
  };
}());

/*
  Mock requestAnimationFrame so that the callbacks can get fired even when the page
  is rendered inside an iframe in the background page
*/

window.requestAnimationFrame = window.webkitRequestAnimationFrame = function(callback){
  setTimeout(callback, 0);
};<commit_msg>Use better polyfill for requestAnimationFrame<commit_after>/*
  Fake localStorage and sessionStorage.

  Separates each renderer's localStorage.

  Credit: https://github.com/pivotal/jasmine/issues/299
*/

var localStorageData = JSON.stringify(localStorage),
    sessionStorageData = JSON.stringify(sessionStorage);

var storeFactory = function(jsonData) {
  var store;

  if(jsonData){
    store = JSON.parse(jsonData);
  }else{
    store = {};
  }

  store.getItem = function(key) {
    return this[key];
  };
  store.setItem = function(key, value) {
    this[key] = value.toString();
  };
  store.clear = function() {
    var key;
    for(key in this){
      if(this.hasOwnProperty(key) && key !== 'setItem' && key !== 'getItem' &&
         key !== 'clear' && key !== 'removeItem'){
        this[key] = undefined;
      }
    }
  };
  store.removeItem = function(key){
    this[key] = undefined;
  };

  return store;
};

Object.defineProperty(window, 'localStorage', { value: storeFactory(localStorageData) });
Object.defineProperty(window, 'sessionStorage', { value: storeFactory(sessionStorageData) });

/*
  Deterministic Math.random

  Credit: https://gist.github.com/mathiasbynens/5670917
*/

Math.random = (function() {
  var seed = 0x2F6E2B1;
  return function() {
    // Robert Jenkins’ 32 bit integer hash function
    seed = ((seed + 0x7ED55D16) + (seed << 12))  & 0xFFFFFFFF;
    seed = ((seed ^ 0xC761C23C) ^ (seed >>> 19)) & 0xFFFFFFFF;
    seed = ((seed + 0x165667B1) + (seed << 5))   & 0xFFFFFFFF;
    seed = ((seed + 0xD3A2646C) ^ (seed << 9))   & 0xFFFFFFFF;
    seed = ((seed + 0xFD7046C5) + (seed << 3))   & 0xFFFFFFFF;
    seed = ((seed ^ 0xB55A4F09) ^ (seed >>> 16)) & 0xFFFFFFFF;
    return (seed & 0xFFFFFFF) / 0x10000000;
  };
}());

/*
  Mock requestAnimationFrame so that the callbacks can get fired even when the page
  is rendered inside an iframe in the background page.

  From 2048's polyfill.
*/

(function(){

var lastTime = 0;
window.requestAnimationFrame = function (callback) {
  var currTime = new Date().getTime();
  var timeToCall = Math.max(0, 16 - (currTime - lastTime));
  var id = window.setTimeout(function () {
    callback(currTime + timeToCall);
  },
  timeToCall);
  lastTime = currTime + timeToCall;
  return id;
};

window.cancelAnimationFrame = function (id) {
  clearTimeout(id);
};

}());<|endoftext|>


<commit_before>import React from "react"
import { connect } from "react-redux"

//import { fetchLinks } from "../actions/linkActions"

@connect((store) => {
  return {
    user: 'Celso',
    myList: ['fee', 'fi', 'fo', 'fum'],
    message: ''//,
    //links: store.links.links
  };
})
export default class Layout extends React.Component {

//   fetchLinks() {
//   this.props.dispatch(fetchLinks())
// }

handleMsgChange() {
  console.log('clicked')
}

handleClick() {
  console.log('clicked')
}

  render() {
    const { user, message, myList } = this.props;

    const list = myList.map((message) => {
      return (

{message}

      )
    });

    return (

Cosecha SMS

      <input type="text" value={message} onChange={this.handleMsgChange.bind(this)} placeholder="Message" />
      <button onClick={this.handleClick.bind(this)} >Send</button>

{list}

)
  }
}
<commit_msg>Try to connect value of input form to state<commit_after>import React from "react"
import { connect } from "react-redux"

//import { fetchLinks } from "../actions/linkActions"

@connect((store) => {
  return {
    user: 'Celso',
    myList: ['fee', 'fi', 'fo', 'fum'],
    message: ''//,
    //links: store.links.links
  };
})
export default class Layout extends React.Component {

//   fetchLinks() {
//   this.props.dispatch(fetchLinks())
// }

handleMsgChange() {
  console.log('message changed')
  this.props.dispatch(handleMsgChange())
}

handleClick() {
  console.log('clicked')
}

  render() {
    const { user, message, myList } = this.props;

    const list = myList.map((message) => {
      return (

{message}

      )
    });

    return (

Cosecha SMS

      <input type="text" value={message} onChange={this.handleMsgChange.bind(this)} placeholder="Message" value={message} />
      <button onClick={this.handleClick.bind(this)} >Send</button>

{list}

)
  }
}
<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc function
 * @name Pear2Pear.controller:NeedsCtrl
 * @description
 * # Needs Ctrl
 * Show Needs for a given project
 */

angular.module('Pear2Pear')
  .config(['$routeProvider', function($routeProvider) {
    $routeProvider
      .when('/communities/:comId/projects/:id/needs', {
        templateUrl: 'needs/index.html',
        controller: 'NeedsCtrl'
      });
  }])
  .controller('NeedsCtrl', [
              'SwellRTSession', 'pear', '$scope', '$route', 'ProjectsSvc',
              function(SwellRTSession, pear, $scope, $route, ProjectsSvc){

    $scope.urlId = pear.urlId;
    $scope.communityId = $route.current.params.comId;

    SwellRTSession.onLoad(function(){
      ProjectsSvc.find($route.current.params.id).then(
        function(proxy){
          $scope.project = proxy;
          $scope.project.timestampProjectAccess();
        }
      );
    });

    // Should use activeLinks, but https://github.com/mcasimir/mobile-angular-ui/issues/262
    $scope.nav = function(id) {
      return id === 'needs' ? 'active' : '';
    };
  }])
  .directive(
    'needDisplay',
    function(){
      return {
        require: '^needList',
        scope: {
          need: '='
        },
        link: function (scope, element, attrs, needsCtrl) {
          scope.toggleCompleted = function (need) {
            var completed = (need.completed === 'true') ? true : false;
            need.completed = (!completed).toString();
            if (completed) {
              need.completionDate = new Date().toString();
            } else {
              need.completionDate = '';
            }
          };

          scope.updateNeed = function(need) {
            if (need.completed === 'add'){
              need.completed = 'false';
              needsCtrl.addNeed(need);
              scope.need = {completed: 'add', text: ''};
            }
            else if (need.text === ''){
              needsCtrl.removeNeed(need);
            }
          };

          scope.keyEventsHandler = function(event){
            if ((event.charCode === 0) && (event.keyCode === 13)){
              event.target.blur();
            }
            if ((event.charCode === 0) && (event.keyCode === 8) && (scope.need.text === '') ){
              scope.updateNeed(scope.need);
            }
          };

          scope.focusElem = function(event){
            event.target.parentNode.children[1].focus();
          };
        },
        templateUrl: 'needs/need.html',
        transclude: true
      };
    }
  ).directive(
    'needList',
    function () {
      return {
        templateUrl: 'needs/list.html',
        transclude: true,
        scope: {
          needs: '='
        },
        controller: function($scope, pear, $route, SwellRTSession) {
          this.addNeed = function (need) {
            if (need.text !== ''){
              $scope.needs.push(need);
              $scope.project.addContributor();
              console.log(SwellRTSession.users.current());
              $scope.project.addChatNotification(
                'need.new.notification',
                {
                  user: SwellRTSession.users.current().split('@')[0],
                  need: need.text
                }
              );
            }
          };
          this.removeNeed = function (need) {
            var i = $scope.needs.indexOf(need);
            $scope.needs.splice(i,1);
          };
        }
      };
    }
  );
<commit_msg>fix need addition<commit_after>'use strict';

/**
 * @ngdoc function
 * @name Pear2Pear.controller:NeedsCtrl
 * @description
 * # Needs Ctrl
 * Show Needs for a given project
 */

angular.module('Pear2Pear')
  .config(['$routeProvider', function($routeProvider) {
    $routeProvider
      .when('/communities/:comId/projects/:id/needs', {
        templateUrl: 'needs/index.html',
        controller: 'NeedsCtrl'
      });
  }])
  .controller('NeedsCtrl', [
              'SwellRTSession', 'pear', '$scope', '$route', 'ProjectsSvc',
              function(SwellRTSession, pear, $scope, $route, ProjectsSvc){

    $scope.urlId = pear.urlId;
    $scope.communityId = $route.current.params.comId;

    SwellRTSession.onLoad(function(){
      ProjectsSvc.find($route.current.params.id).then(
        function(proxy){
          $scope.project = proxy;
          $scope.project.timestampProjectAccess();
        }
      );
    });

    // Should use activeLinks, but https://github.com/mcasimir/mobile-angular-ui/issues/262
    $scope.nav = function(id) {
      return id === 'needs' ? 'active' : '';
    };
  }])
  .directive(
    'needDisplay',
    function(){
      return {
        require: '^needList',
        scope: {
          need: '='
        },
        link: function (scope, element, attrs, needsCtrl) {
          scope.toggleCompleted = function (need) {
            var completed = (need.completed === 'true') ? true : false;
            need.completed = (!completed).toString();
            if (completed) {
              need.completionDate = new Date().toString();
            } else {
              need.completionDate = '';
            }
          };

          scope.updateNeed = function(need) {
            if (need.completed === 'add'){
              need.completed = 'false';
              needsCtrl.addNeed(need);
              scope.need = {completed: 'add', text: ''};
            }
            else if (need.text === ''){
              needsCtrl.removeNeed(need);
            }
          };

          scope.keyEventsHandler = function(event){
            if ((event.charCode === 0) && (event.keyCode === 13)){
              event.target.blur();
            }
            if ((event.charCode === 0) && (event.keyCode === 8) && (scope.need.text === '') ){
              scope.updateNeed(scope.need);
            }
          };

          scope.focusElem = function(event){
            event.target.parentNode.children[1].focus();
          };
        },
        templateUrl: 'needs/need.html',
        transclude: true
      };
    }
  ).directive(
    'needList',
    function () {
      return {
        templateUrl: 'needs/list.html',
        transclude: true,
        scope: {
          needs: '='
        },
        controller: function($scope, pear, $route, SwellRTSession, ProjectsSvc) {
          this.addNeed = function (need) {
            if (need.text !== ''){
              $scope.needs.push(need);
              ProjectsSvc.find($route.current.params.id).then(function(project){
                project.addContributor();
                project.addChatNotification(
                  'need.new.notification',
                  {
                    user: SwellRTSession.users.current().split('@')[0],
                    need: need.text
                  }
                );
              });
            }
          };
          this.removeNeed = function (need) {
            var i = $scope.needs.indexOf(need);
            $scope.needs.splice(i,1);
          };
        }
      };
    }
  );
<|endoftext|>


<commit_before>/**
 * helpers
 */
(function(){
    //variables
    var dictionary = _chorus.data.dictionary,
        domData = _chorus.data.domData,
        defaultConfig = _chorus.defaultConfig;

    //functions
    /**
     * get a random string
     * @param length
     * @returns {*}
     */
    this.generateRandomString = function(length){
        var output;
        for(output = ''; output.length < length;) {
            output += Math.random().toString(36).substr(2, 1);
        }
        return output;
    };

    /**
     * make a copy of a JS object
     * @param from
     * @param to
     * @returns {*}
     */
    this.cloneObject = function(from, to) {
        if (from ==+ null || typeof from !== 'object'){
            return from;
        }
        if (from.constructor != Object && from.constructor != Array){
            return from;
        }
        if (from.constructor == Date || from.constructor == RegExp || from.constructor == Function || from.constructor == String || from.constructor == Number || from.constructor == Boolean){
            return new from.constructor(from);
        }
        to = to || new from.constructor();
        for (var name in from) {
            to[name] = typeof to[name] == 'undefined' ? this.cloneObject(from[name], null) : to[name];
        }
        return to;
    };

    /**
     * get the config value for the key passed or return the default if none available
     * @param key
     * @param container
     * @returns {*}
     */
    this.getConfigValue = function(key, container){
        var configId = _chorus.config.currentConfig;
        if(container){
            configId = document.getElementById(container).getAttribute(domData.config);
            if (configId) {
                if (typeof _chorus.config[configId][key] !== typeof _chorus.defaultConfig[key]) {
                    _chorus.events.sendMessage(dictionary.errorType + ' ' + key);
                }
                return typeof _chorus.config[configId][key] === typeof defaultConfig[key] ? _chorus.config[configId][key] : defaultConfig[key];
            } else {
                return false;
            }
        } else if (configId && configId.length > 0) {
            if (typeof _chorus.config[configId][key] !== typeof _chorus.defaultConfig[key]){
                _chorus.events.sendMessage(dictionary.errorType+' '+key);
            }
            return typeof _chorus.config[configId][key] === typeof defaultConfig[key]?_chorus.config[configId][key]:defaultConfig[key];
        } else {
            return false;
        }
    };

    /**
     * get the object key given the value
     * @param object
     * @param value
     * @returns {string}
     */
    this.getKeyFromValue = function(object, value){
        for(var prop in object) {
            if(object.hasOwnProperty(prop)) {
                if(object[prop] === value) {
                    return prop;
                }
            }
        }
        return false;
    };

    /**
     * gets the size of a one dimensional object
     * @param object
     * @returns {number}
     */
    this.countObjectLength = function(object){
        var key,
            i = 0;
        for(key in object){
            if (object.hasOwnProperty(key)){
                i++;
            }
        }
        return i;
    };

    /**
     * capitalize all of the words in a string
     * @param string
     * @returns {string}
     */
    this.capitalize = function(string){
        return string.toLowerCase().replace( /\b\w/g, function (m) {
            return m.toUpperCase();
        });
    };

    this.mod = function(number,modulus) {
        return ((number%modulus)+modulus)%modulus;
    };

    this.searchComplete = function(callback){
        var configCallback = this.getConfigValue('searchCallback');
        if (callback && typeof callback !== 'string') {
            callback(_chorus.searchResult);
        } else if (configCallback && typeof configCallback === 'string') {
            window[configCallback](_chorus.searchResult);
        }
    };

    this.convertResultsObjectToArray = function(name, resultsObject){
        return {
            name: name,
            tones: resultsObject.tones,
            letters: resultsObject.letters
        };
    };

    this.getDomRepresentationFromStringName = function(container){
        var containerById = document.getElementById(container),
            containerByClass = document.getElementsByClassName(container),
            result = [];
        if (containerById){
            result.push(containerById);
        } else if (containerByClass){
            for(var i = 0; i < containerByClass.length; i++){
                result.push(containerByClass[i]);
            }
        }
        return result;
    };

    this.searchScalesAndChords = function(tones,container,callback){
        _chorus.events.dispatchEvent(_chorus.data.customEvents.chorusSearchStarted, 'chorusJS has started searching');
        _chorus.logic.scales.searchScales(tones,  container, false,
            _chorus.logic.chords.searchChords(tones, container, false,
                function(){
                    _chorus.logic.helpers.searchComplete(callback);
                    _chorus.events.dispatchEvent(_chorus.data.customEvents.chorusSearchComplete, 'chorusJS has finished searching scales and chords');
                }
            ));
    };

}).apply(_chorus.logic.helpers);

/**
 * notes
 */
(function(){
    //variables
    var dictionary = _chorus.data.dictionary,
        domData = _chorus.data.domData,
        notes = _chorus.data.notes,
        events = _chorus.events,
        helpers = _chorus.logic.helpers,
        logicNotes = _chorus.logic.notes;

    //functions
    /**
     * get the tone (int) given the note (char)
     * @param note
     * @returns {number}
     */
    this.getToneByNote = function (note){
        var tone = notes.letter[note.substring(0,1)],
            start = 0;
        while (note.indexOf('#',start)!==-1){
            start = note.indexOf('#',start)+1;
            tone++;
        }
        start = 0;
        while (note.indexOf('b',start)!==-1){
            start = note.indexOf('b',start)+1;
            tone--;
        }
        return helpers.mod(tone,12);
    };

    this.sharpenTone = function(tone){
        return helpers.mod(tone + 1,12);
    };

    this.flattenTone = function(tone){
        return helpers.mod(tone - 1,12);
    };

    /**
     * get the flat note from the int
     * @param tone
     * @returns {string}
     */
    this.getFlatNoteByTone = function(tone){
        return notes.tone[this.sharpenTone(tone)] + 'b';
    };

    /**
     * get the sharp note from the int
     * @param tone
     * @returns {string}
     */
    this.getSharpNoteByTone = function(tone){
        return notes.tone[this.flattenTone(tone)] + '#';
    };

    /**
     * return a note representation of the tone with both sharp and flat values (for the UI grid)
     * @param tone
     * @returns {*}
     */
    this.getNoteByToneDisplay = function(tone){
        var letter;
        tone = helpers.mod(tone,12);
        if (notes.tone.hasOwnProperty(tone)) {
            letter = notes.tone[tone];
        }
        else {
            letter = this.getFlatNoteByTone(tone)+' / '+this.getSharpNoteByTone(tone);
        }
        return letter;
    };

    /**
     * get the note (char) from the tone (int)
     * @param tone
     * @returns {*}
     */
    this.getNoteByToneDefault = function(tone){
        var letter;
        if (notes.tone.hasOwnProperty(tone)) {
            letter = notes.tone[tone];
        }
        else {
            letter = this.getSharpNoteByTone(tone);
        }
        return letter;
    };

    /**
     * get the note (char) from the tone (int) and either make it sharp or flat by specifying the note
     * @param tone
     * @param letter
     * @returns {*}
     */
    this.getNoteByToneForce = function(tone,letter) {
        var difference = tone - this.getToneByNote(letter);
        if (difference > notes.count.tones/2) {
            difference -= notes.count.tones;
        }
        if (difference < notes.count.tones/2*-1) {
            difference += notes.count.tones;
        }
        if (difference !== 0) {
            if (Math.abs(difference) > 1 && notes.tone.hasOwnProperty(tone)){
                return false;
            } else if (difference > 0) {
                for (var i = 0; i < difference; i++) {
                    letter += '#';
                }
            }
            else if (difference < 0) {
                for (var j = 0; j > difference; j--) {
                    letter += 'b';
                }
            }
        }
        return letter;
    };

    /**
     * get the order of the possible letters, starting at the letter passed in
     * and looping around from 'G' to 'A' until reaching the initial letter
     * @param letter
     * @returns {Array.<*>}
     */
    this.getNoteProgression = function(letter){
        var pieces = 'ABCDEFG'.split(letter.replace(/b/g,'').replace(/#/g,'').toUpperCase());
        return [letter].concat(pieces[1].split(''),pieces[0].split(''));
    };

    this.getPianoFromContainer = function(element){
        var result;
        if (element) {
            for (var i = 0; i < element.childNodes.length; i++) {
                if (element.childNodes[i].classList.contains(dictionary.classPianoKeyboard)){
                    result = element.childNodes[i];
                }
            }
        }
        return result;
    };

    this.getFretboardFromContainer = function(element){
        var result;
        if (element) {
            for (var i = 0; i < element.childNodes.length; i++) {
                if (element.childNodes[i].classList.contains(dictionary.classStringContainer)){
                    result = element.childNodes[i];
                }
            }
        }
        return result;
    };

    /**
     * get any tones that are selected in the dom
     * @param container
     */
    this.getSelectedNotes = function(container){
        _chorus.searchResult.containers = [];
        var noteData = [],
            notes = {
                rootTone: '',
                selectedTones:[]
            },
            pianoKeyboard,
            stringFretboard,
            domContainers;
        //search for selected notes by container id or class
        if(container && container.length > 0){
            domContainers = helpers.getDomRepresentationFromStringName(container);
            if (domContainers && domContainers.length > 0){
                domContainers.forEach(function(entry){
                    if (entry.classList.contains('piano')){
                        pianoKeyboard = logicNotes.getPianoFromContainer(entry);
                        if (pianoKeyboard){
                            noteData.push(logicNotes.getTonesFromDOM(pianoKeyboard));
                        }
                    } else {
                        stringFretboard = logicNotes.getFretboardFromContainer(entry);
                        if (stringFretboard){
                            noteData.push(logicNotes.getTonesFromDOM(stringFretboard));
                        }
                    }
                });
            }
            else {
                events.sendMessage(dictionary.errorNotFound+'no container found with matching id or class');
            }
        }
        //get selected notes if no container parameter was passed
        else {
            domContainers = helpers.getDomRepresentationFromStringName(dictionary.classInstrument);
            if (domContainers && domContainers.length > 0) {
                for (var j = 0; j < domContainers.length; j++) {
                    if (j === 0) {
                        //get a default config from the first element in the dom
                        _chorus.config.currentConfig = domContainers[j].getAttribute(domData.config);
                    }
                    if (domContainers[j].classList.contains('piano')) {
                        pianoKeyboard = this.getPianoFromContainer(domContainers[j]);
                        if (pianoKeyboard) {
                            noteData.push(this.getTonesFromDOM(pianoKeyboard));
                        }
                    } else {
                        noteData.push(this.getTonesFromDOM(domContainers[j]));
                    }
                }
            }
        }
        //remove duplicates
        for (var k = 0; k < noteData.length; k++){
            if (noteData[k].rootTone.length > 0 || noteData[k].selectedTones.length > 0){
                _chorus.searchResult.containers.push(noteData[k].container);
            }
            if (noteData[k].rootTone.length > 0){
                if (notes.rootTone.length < 1){
                    notes.rootTone = noteData[k].rootTone;
                }
                else {
                    events.sendMessage(dictionary.warningMultipleRootNotes);
                }
            }
            for (var l = 0; l < noteData[k].selectedTones.length; l++){
                if (notes.selectedTones.indexOf(noteData[k].selectedTones[l]) == -1){
                    notes.selectedTones.push(noteData[k].selectedTones[l]);
                }
            }
        }
        return notes;
    };

    /**
     * find any selected frets or root note frets within a given DOM element
     * @type {Function}
     */
    this.getTonesFromDOM = function(element){
        var parentClassList,
            childClassList,
            selectedTones = [],
            rootTone = '';
        if (element) {
            for (var i = 0; i < element.childNodes.length; i++) {
                if (element.childNodes[i]) {
                    parentClassList = element.childNodes[i].classList;
                    if (parentClassList.contains(dictionary.classString)) {
                        for (var j = 0; j < element.childNodes[i].childNodes.length; j++) {
                            childClassList = element.childNodes[i].childNodes[j].classList;
                            if (childClassList.contains(dictionary.classSelected)) {
                                selectedTones.push(element.childNodes[i].childNodes[j].getAttribute(domData.tone));
                            }
                            else if (childClassList.contains(dictionary.classRoot)) {
                                rootTone = element.childNodes[i].childNodes[j].getAttribute(domData.tone);
                            }
                        }
                    } else if (parentClassList.contains(dictionary.classPianoKey)) {
                        if (parentClassList.contains(dictionary.classSelected)) {
                            selectedTones.push(element.childNodes[i].getAttribute(domData.tone));
                        }
                        else if (parentClassList.contains(dictionary.classRoot)) {
                            rootTone = element.childNodes[i].getAttribute(domData.tone);
                        }
                    }
                }
            }
        } else {
            events.sendMessage(dictionary.errorNotFound+'no element found to search');
        }
        return {
            container: element,
            selectedTones: selectedTones,
            rootTone: rootTone
        };
    };

    /**
     * return if the all of the selected tones exist in the scale or chord
     * @param dataNotes
     * @param selectedNotes
     * @returns {boolean}
     */
    this.tonesInScaleOrChordHelper = function(dataNotes, selectedNotes){
        for(var i = 0; i < selectedNotes.length; i++){
            if (dataNotes.indexOf(parseInt(selectedNotes[i])) === -1){
                return false;
            }
        }
        return true;
    };

    /**
     * return if the scale contains the selected tones or not
     * @param formula
     * @param notes
     * @returns {boolean}
     */
    this.tonesInScaleOrChord = function(formula, notes){
        if (notes.rootTone.length > 0){
            if (formula.tones[0] == notes.rootTone){
                return this.tonesInScaleOrChordHelper(formula.tones,notes.selectedTones);
            }
            else {
                return false;
            }
        }
        else {
            return this.tonesInScaleOrChordHelper(formula.tones,notes.selectedTones);
        }
    };

}).apply(_chorus.logic.notes);<commit_msg>documentation - logic<commit_after>/**
 * helpers
 */
(function(){
    //variables
    var dictionary = _chorus.data.dictionary,
        domData = _chorus.data.domData,
        defaultConfig = _chorus.defaultConfig;

    //functions
    /**
     * get a random string
     * @param {int} length
     * @returns {string}
     */
    this.generateRandomString = function(length){
        var output;
        for(output = ''; output.length < length;) {
            output += Math.random().toString(36).substr(2, 1);
        }
        return output;
    };

    /**
     * make a copy of a JS object
     * @param {Object} from
     * @param {Object} to
     * @returns {Object}
     */
    this.cloneObject = function(from, to) {
        if (from ==+ null || typeof from !== 'object'){
            return from;
        }
        if (from.constructor != Object && from.constructor != Array){
            return from;
        }
        if (from.constructor == Date || from.constructor == RegExp || from.constructor == Function || from.constructor == String || from.constructor == Number || from.constructor == Boolean){
            return new from.constructor(from);
        }
        to = to || new from.constructor();
        for (var name in from) {
            to[name] = typeof to[name] == 'undefined' ? this.cloneObject(from[name], null) : to[name];
        }
        return to;
    };

    /**
     * get the config value for the key passed or return the default if none available
     * @param {string} key
     * @param {string} [container]
     * @returns {string|boolean}
     */
    this.getConfigValue = function(key, container){
        var configId = _chorus.config.currentConfig;
        if(container){
            configId = document.getElementById(container).getAttribute(domData.config);
            if (configId) {
                if (typeof _chorus.config[configId][key] !== typeof _chorus.defaultConfig[key]) {
                    _chorus.events.sendMessage(dictionary.errorType + ' ' + key);
                }
                return typeof _chorus.config[configId][key] === typeof defaultConfig[key] ? _chorus.config[configId][key] : defaultConfig[key];
            } else {
                return false;
            }
        } else if (configId && configId.length > 0) {
            if (typeof _chorus.config[configId][key] !== typeof _chorus.defaultConfig[key]){
                _chorus.events.sendMessage(dictionary.errorType+' '+key);
            }
            return typeof _chorus.config[configId][key] === typeof defaultConfig[key]?_chorus.config[configId][key]:defaultConfig[key];
        } else {
            return false;
        }
    };

    /**
     * get the object key given the value
     * @param {Object} object
     * @param {string} value
     * @returns {string|boolean}
     */
    this.getKeyFromValue = function(object, value){
        for(var prop in object) {
            if(object.hasOwnProperty(prop)) {
                if(object[prop] === value) {
                    return prop;
                }
            }
        }
        return false;
    };

    /**
     * gets the size of a one dimensional object
     * @param {Object} object
     * @returns {number}
     */
    this.countObjectLength = function(object){
        var key,
            i = 0;
        for(key in object){
            if (object.hasOwnProperty(key)){
                i++;
            }
        }
        return i;
    };

    /**
     * capitalize all of the words in a string
     * @param {string} string
     * @returns {string}
     */
    this.capitalize = function(string){
        return string.toLowerCase().replace( /\b\w/g, function (m) {
            return m.toUpperCase();
        });
    };

    /**
     * a filler method for a "real" modulo behavior for javascript
     * @param {int} number
     * @param {int} modulus
     * @returns {number}
     */
    this.mod = function(number,modulus) {
        return ((number%modulus)+modulus)%modulus;
    };

    /**
     * final method for search all modules function
     * @param {function} [callback]
     */
    this.searchComplete = function(callback){
        var configCallback = this.getConfigValue('searchCallback');
        if (callback && typeof callback !== 'string') {
            callback(_chorus.searchResult);
        } else if (configCallback && typeof configCallback === 'string') {
            window[configCallback](_chorus.searchResult);
        }
    };

    /**
     * helper for flattening results output
     * @param {string} name
     * @param {Object} resultsObject
     * @returns {Object}
     */
    this.convertResultsObjectToArray = function(name, resultsObject){
        return {
            name: name,
            tones: resultsObject.tones,
            letters: resultsObject.letters
        };
    };

    /**
     * get all dom elements by the container name, whether by id or class
     * @param {string} container
     * @returns {Array}
     */
    this.getDomRepresentationFromStringName = function(container){
        var containerById = document.getElementById(container),
            containerByClass = document.getElementsByClassName(container),
            result = [];
        if (containerById){
            result.push(containerById);
        } else if (containerByClass){
            for(var i = 0; i < containerByClass.length; i++){
                result.push(containerByClass[i]);
            }
        }
        return result;
    };

    /**
     * search all modules helper
     * @param {Array} [tones]
     * @param {string} [container]
     * @param {function} [callback]
     */
    this.searchScalesAndChords = function(tones,container,callback){
        _chorus.events.dispatchEvent(_chorus.data.customEvents.chorusSearchStarted, 'chorusJS has started searching');
        _chorus.logic.scales.searchScales(tones,  container, false,
            _chorus.logic.chords.searchChords(tones, container, false,
                function(){
                    _chorus.logic.helpers.searchComplete(callback);
                    _chorus.events.dispatchEvent(_chorus.data.customEvents.chorusSearchComplete, 'chorusJS has finished searching scales and chords');
                }
            ));
    };

}).apply(_chorus.logic.helpers);

/**
 * notes
 */
(function(){
    //variables
    var dictionary = _chorus.data.dictionary,
        domData = _chorus.data.domData,
        notes = _chorus.data.notes,
        events = _chorus.events,
        helpers = _chorus.logic.helpers,
        logicNotes = _chorus.logic.notes;

    //functions
    /**
     * get the tone (int) given the note (string)
     * @param {string} note
     * @returns {number}
     */
    this.getToneByNote = function (note){
        var tone = notes.letter[note.substring(0,1)],
            start = 0;
        while (note.indexOf('#',start)!==-1){
            start = note.indexOf('#',start)+1;
            tone++;
        }
        start = 0;
        while (note.indexOf('b',start)!==-1){
            start = note.indexOf('b',start)+1;
            tone--;
        }
        return helpers.mod(tone,12);
    };

    this.sharpenTone = function(tone){
        return helpers.mod(tone + 1,12);
    };

    this.flattenTone = function(tone){
        return helpers.mod(tone - 1,12);
    };

    /**
     * get the flat note from the int
     * @param {string} tone
     * @returns {string}
     */
    this.getFlatNoteByTone = function(tone){
        return notes.tone[this.sharpenTone(tone)] + 'b';
    };

    /**
     * get the sharp note from the int
     * @param {string} tone
     * @returns {string}
     */
    this.getSharpNoteByTone = function(tone){
        return notes.tone[this.flattenTone(tone)] + '#';
    };

    /**
     * return a note representation of the tone with both sharp and flat values (for the UI grid)
     * @param {int} tone
     * @returns {string}
     */
    this.getNoteByToneDisplay = function(tone){
        var letter;
        tone = helpers.mod(tone,12);
        if (notes.tone.hasOwnProperty(String(tone))) {
            letter = notes.tone[tone];
        }
        else {
            letter = this.getFlatNoteByTone(String(tone))+' / '+this.getSharpNoteByTone(String(tone));
        }
        return letter;
    };

    /**
     * get the note (char) from the tone (int)
     * @param {string} tone
     * @returns {string}
     */
    this.getNoteByToneDefault = function(tone){
        var letter;
        if (notes.tone.hasOwnProperty(tone)) {
            letter = notes.tone[tone];
        }
        else {
            letter = this.getSharpNoteByTone(tone);
        }
        return letter;
    };

    /**
     * get the note (char) from the tone (int) and either make it sharp or flat by specifying the note
     * @param {string} tone
     * @param {string} letter
     * @returns {string|boolean}
     */
    this.getNoteByToneForce = function(tone,letter) {
        var difference = tone - this.getToneByNote(letter);
        if (difference > notes.count.tones/2) {
            difference -= notes.count.tones;
        }
        if (difference < notes.count.tones/2*-1) {
            difference += notes.count.tones;
        }
        if (difference !== 0) {
            if (Math.abs(difference) > 1 && notes.tone.hasOwnProperty(tone)){
                return false;
            } else if (difference > 0) {
                for (var i = 0; i < difference; i++) {
                    letter += '#';
                }
            }
            else if (difference < 0) {
                for (var j = 0; j > difference; j--) {
                    letter += 'b';
                }
            }
        }
        return letter;
    };

    /**
     * get the order of the possible letters, starting at the letter passed in
     * and looping around from 'G' to 'A' until reaching the initial letter
     * @param {string} letter
     * @returns {Array}
     */
    this.getNoteProgression = function(letter){
        var pieces = 'ABCDEFG'.split(letter.replace(/b/g,'').replace(/#/g,'').toUpperCase());
        return [letter].concat(pieces[1].split(''),pieces[0].split(''));
    };

    /**
     * get the piano instrument DOM element from the container
     * @param {HTMLElement} element
     * @returns {HTMLElement}
     */
    this.getPianoFromContainer = function(element){
        var result;
        if (element) {
            for (var i = 0; i < element.childNodes.length; i++) {
                if (element.childNodes[i].classList.contains(dictionary.classPianoKeyboard)){
                    result = element.childNodes[i];
                }
            }
        }
        return result;
    };

    /**
     * get the fretted instrument DOM element from the container
     * @param {HTMLElement} element
     * @returns {HTMLElement}
     */
    this.getFretboardFromContainer = function(element){
        var result;
        if (element) {
            for (var i = 0; i < element.childNodes.length; i++) {
                if (element.childNodes[i].classList.contains(dictionary.classStringContainer)){
                    result = element.childNodes[i];
                }
            }
        }
        return result;
    };

    /**
     * get any tones that are selected in the dom
     * @param {string} container
     */
    this.getSelectedNotes = function(container){
        _chorus.searchResult.containers = [];
        var noteData = [],
            notes = {
                rootTone: '',
                selectedTones:[]
            },
            pianoKeyboard,
            stringFretboard,
            domContainers;
        //search for selected notes by container id or class
        if(container && container.length > 0){
            domContainers = helpers.getDomRepresentationFromStringName(container);
            if (domContainers && domContainers.length > 0){
                domContainers.forEach(function(entry){
                    if (entry.classList.contains('piano')){
                        pianoKeyboard = logicNotes.getPianoFromContainer(entry);
                        if (pianoKeyboard){
                            noteData.push(logicNotes.getTonesFromDOM(pianoKeyboard));
                        }
                    } else {
                        stringFretboard = logicNotes.getFretboardFromContainer(entry);
                        if (stringFretboard){
                            noteData.push(logicNotes.getTonesFromDOM(stringFretboard));
                        }
                    }
                });
            }
            else {
                events.sendMessage(dictionary.errorNotFound+'no container found with matching id or class');
            }
        }
        //get selected notes if no container parameter was passed
        else {
            domContainers = helpers.getDomRepresentationFromStringName(dictionary.classInstrument);
            if (domContainers && domContainers.length > 0) {
                for (var j = 0; j < domContainers.length; j++) {
                    if (j === 0) {
                        //get a default config from the first element in the dom
                        _chorus.config.currentConfig = domContainers[j].getAttribute(domData.config);
                    }
                    if (domContainers[j].classList.contains('piano')) {
                        pianoKeyboard = this.getPianoFromContainer(domContainers[j]);
                        if (pianoKeyboard) {
                            noteData.push(this.getTonesFromDOM(pianoKeyboard));
                        }
                    } else {
                        noteData.push(this.getTonesFromDOM(domContainers[j]));
                    }
                }
            }
        }
        //remove duplicates
        for (var k = 0; k < noteData.length; k++){
            if (noteData[k].rootTone.length > 0 || noteData[k].selectedTones.length > 0){
                _chorus.searchResult.containers.push(noteData[k].container);
            }
            if (noteData[k].rootTone.length > 0){
                if (notes.rootTone.length < 1){
                    notes.rootTone = noteData[k].rootTone;
                }
                else {
                    events.sendMessage(dictionary.warningMultipleRootNotes);
                }
            }
            for (var l = 0; l < noteData[k].selectedTones.length; l++){
                if (notes.selectedTones.indexOf(noteData[k].selectedTones[l]) == -1){
                    notes.selectedTones.push(noteData[k].selectedTones[l]);
                }
            }
        }
        return notes;
    };

    /**
     * find any selected frets or root note frets within a given DOM element
     * @param {HTMLElement} element
     */
    this.getTonesFromDOM = function(element){
        var parentClassList,
            childClassList,
            selectedTones = [],
            rootTone = '';
        if (element) {
            for (var i = 0; i < element.childNodes.length; i++) {
                if (element.childNodes[i]) {
                    parentClassList = element.childNodes[i].classList;
                    if (parentClassList.contains(dictionary.classString)) {
                        for (var j = 0; j < element.childNodes[i].childNodes.length; j++) {
                            childClassList = element.childNodes[i].childNodes[j].classList;
                            if (childClassList.contains(dictionary.classSelected)) {
                                selectedTones.push(element.childNodes[i].childNodes[j].getAttribute(domData.tone));
                            }
                            else if (childClassList.contains(dictionary.classRoot)) {
                                rootTone = element.childNodes[i].childNodes[j].getAttribute(domData.tone);
                            }
                        }
                    } else if (parentClassList.contains(dictionary.classPianoKey)) {
                        if (parentClassList.contains(dictionary.classSelected)) {
                            selectedTones.push(element.childNodes[i].getAttribute(domData.tone));
                        }
                        else if (parentClassList.contains(dictionary.classRoot)) {
                            rootTone = element.childNodes[i].getAttribute(domData.tone);
                        }
                    }
                }
            }
        } else {
            events.sendMessage(dictionary.errorNotFound+'no element found to search');
        }
        return {
            container: element,
            selectedTones: selectedTones,
            rootTone: rootTone
        };
    };

    /**
     * return if the all of the selected tones exist in the scale or chord
     * @param {Array} dataNotes
     * @param {Array} selectedNotes
     * @returns {boolean}
     */
    this.tonesInScaleOrChordHelper = function(dataNotes, selectedNotes){
        for(var i = 0; i < selectedNotes.length; i++){
            if (dataNotes.indexOf(parseInt(selectedNotes[i])) === -1){
                return false;
            }
        }
        return true;
    };

    /**
     * return if the scale contains the selected tones or not
     * @param {Object} formula
     * @param {Object} notes
     * @returns {boolean}
     */
    this.tonesInScaleOrChord = function(formula, notes){
        if (notes.rootTone.length > 0){
            if (formula.tones[0] == notes.rootTone){
                return this.tonesInScaleOrChordHelper(formula.tones,notes.selectedTones);
            }
            else {
                return false;
            }
        }
        else {
            return this.tonesInScaleOrChordHelper(formula.tones,notes.selectedTones);
        }
    };

}).apply(_chorus.logic.notes);<|endoftext|>


<commit_before>import './common'

const urlParameter = require('./get-url-parameter')
const accordion = require('./accordion')
const htmlEncode = require('htmlencode')
const marked = require('marked')
marked.setOptions({ sanitize: true })
const apiRoutes = require('./api')
const getApiData = require('./get-api-data')
const analytics = require('./analytics')
const templating = require('./template-render')
const browser = require('./browser')

const theOrganisation = urlParameter.parameter('organisation')
const organisationUrl = `${apiRoutes.organisation}${theOrganisation}`
const accommodationUrl = `${apiRoutes.accommodation}?providerId=${theOrganisation}`

browser.loading()

const isOpen247 = function (openingTimes) {
  return openingTimes.length === 7 && openingTimes.filter((ot) => ot.startTime === '00:00' && ot.endTime === '23:59').length === 7
}

const formatData = function (data) {
  const formatMarkdownFields = () => {
    const markdownFields = ['description', 'itemsDonationDescription', 'donationDescription']

    markdownFields
      .forEach((f) => {
        data[f] = marked(htmlEncode.htmlDecode(data[f]))
      })
  }

  const formatTags = () => {
    data.formattedTags = []
    data.tags.forEach((tag) => {
      data.formattedTags.push({ id: tag, name: tag.replace(/-/g, ' ') })
    })
  }

  const formatServices = () => {
    data.providedServices = data.providedServices
      .sort((a, b) => {
        if (a.name < b.name) return -1
        if (a.name > b.name) return 1
        return 0
      })

    data.providedServices
      .forEach(function (service) {
        if (service.locationDescription !== null) {
          service.locationDescription = marked(htmlEncode.htmlDecode(service.locationDescription))
        }
        if (service.tags !== null) {
          service.tags = service.tags.join(', ')
        }
        if (service.info !== null) {
          service.info = marked(htmlEncode.htmlDecode(service.info))
        }
        service.isOpen247 = isOpen247(service.openingTimes)
      })
  }

  const setOrgOtherServicesAsServicesNotAssignedToAddress = (a) => {
    data.providedServices = data.providedServices
      .filter((s) => {
        return s.address.postcode.replace(/\s/gi, '') !== a.postcode.replace(/\s/gi, '')
      })

    data.hasOtherServices = data.providedServices.length > 0
  }

  const formatAddresses = () => {
    data.hasAddresses = data.addresses.length > 0
    data.addresses.forEach((a) => {
      let groupedOpeningTimes = []
      a.openingTimes.forEach((ot) => {
        let match = groupedOpeningTimes.filter((got) => got.day === ot.day)
        if (match.length === 1) {
          match[0].openingTimes.push({
            endTime: ot.endTime,
            startTime: ot.startTime
          })
        } else {
          let newDay = {
            day: ot.day,
            openingTimes: [{
              endTime: ot.endTime,
              startTime: ot.startTime
            }]
          }
          groupedOpeningTimes.push(newDay)
        }
      })
      a.openingDays = groupedOpeningTimes
      a.services = data.providedServices
        .filter((s) => s.address.postcode.replace(/\s/gi, '') === a.postcode.replace(/\s/gi, ''))
      a.hasServices = a.services.length > 0
      a.hasOpeningTimes = a.openingDays.length > 0

      setOrgOtherServicesAsServicesNotAssignedToAddress(a)
    })
  }

  formatMarkdownFields()
  formatTags()
  formatServices()
  formatAddresses()

  return data
}

getApiData.data(organisationUrl)
  .then(function (result) {
    var data = result.data

    var theTitle = htmlEncode.htmlDecode(data.name + ' - Street Support')
    document.title = theTitle

    // Append object name for Hogan
    var theData = { organisation: formatData(result.data) }

    var callback = function () {
      browser.loaded()
      accordion.init()
      analytics.init(theTitle)
    }

    templating.renderTemplate('js-breadcrumb-tpl', theData, 'js-breadcrumb-output')
    templating.renderTemplate('js-header-tpl', theData, 'js-header-output')
    templating.renderTemplate('js-organisation-tpl', theData, 'js-organisation-output')
    templating.renderTemplate('js-contact-tpl', theData, 'js-contact-output', callback)
  })

getApiData.data(accommodationUrl)
  .then((result) => {
    if (result.data.total > 0) {
      const theData = {
        items: result.data.items
      }
      console.log(theData)
      templating.renderTemplate('js-accommodation-tpl', theData, 'js-accommodation-output')
    }
  })
<commit_msg>Decoded accomodation name (#440)<commit_after>import './common'

const urlParameter = require('./get-url-parameter')
const accordion = require('./accordion')
const htmlEncode = require('htmlencode')
const marked = require('marked')
marked.setOptions({ sanitize: true })
const apiRoutes = require('./api')
const getApiData = require('./get-api-data')
const analytics = require('./analytics')
const templating = require('./template-render')
const browser = require('./browser')

const theOrganisation = urlParameter.parameter('organisation')
const organisationUrl = `${apiRoutes.organisation}${theOrganisation}`
const accommodationUrl = `${apiRoutes.accommodation}?providerId=${theOrganisation}`

browser.loading()

const isOpen247 = function (openingTimes) {
  return openingTimes.length === 7 && openingTimes.filter((ot) => ot.startTime === '00:00' && ot.endTime === '23:59').length === 7
}

const formatData = function (data) {
  const formatMarkdownFields = () => {
    const markdownFields = ['description', 'itemsDonationDescription', 'donationDescription']

    markdownFields
      .forEach((f) => {
        data[f] = marked(htmlEncode.htmlDecode(data[f]))
      })
  }

  const formatTags = () => {
    data.formattedTags = []
    data.tags.forEach((tag) => {
      data.formattedTags.push({ id: tag, name: tag.replace(/-/g, ' ') })
    })
  }

  const formatServices = () => {
    data.providedServices = data.providedServices
      .sort((a, b) => {
        if (a.name < b.name) return -1
        if (a.name > b.name) return 1
        return 0
      })

    data.providedServices
      .forEach(function (service) {
        if (service.locationDescription !== null) {
          service.locationDescription = marked(htmlEncode.htmlDecode(service.locationDescription))
        }
        if (service.tags !== null) {
          service.tags = service.tags.join(', ')
        }
        if (service.info !== null) {
          service.info = marked(htmlEncode.htmlDecode(service.info))
        }
        service.isOpen247 = isOpen247(service.openingTimes)
      })
  }

  const setOrgOtherServicesAsServicesNotAssignedToAddress = (a) => {
    data.providedServices = data.providedServices
      .filter((s) => {
        return s.address.postcode.replace(/\s/gi, '') !== a.postcode.replace(/\s/gi, '')
      })

    data.hasOtherServices = data.providedServices.length > 0
  }

  const formatAddresses = () => {
    data.hasAddresses = data.addresses.length > 0
    data.addresses.forEach((a) => {
      let groupedOpeningTimes = []
      a.openingTimes.forEach((ot) => {
        let match = groupedOpeningTimes.filter((got) => got.day === ot.day)
        if (match.length === 1) {
          match[0].openingTimes.push({
            endTime: ot.endTime,
            startTime: ot.startTime
          })
        } else {
          let newDay = {
            day: ot.day,
            openingTimes: [{
              endTime: ot.endTime,
              startTime: ot.startTime
            }]
          }
          groupedOpeningTimes.push(newDay)
        }
      })
      a.openingDays = groupedOpeningTimes
      a.services = data.providedServices
        .filter((s) => s.address.postcode.replace(/\s/gi, '') === a.postcode.replace(/\s/gi, ''))
      a.hasServices = a.services.length > 0
      a.hasOpeningTimes = a.openingDays.length > 0

      setOrgOtherServicesAsServicesNotAssignedToAddress(a)
    })
  }

  formatMarkdownFields()
  formatTags()
  formatServices()
  formatAddresses()

  return data
}

getApiData.data(organisationUrl)
  .then(function (result) {
    var data = result.data

    var theTitle = htmlEncode.htmlDecode(data.name + ' - Street Support')
    document.title = theTitle

    // Append object name for Hogan
    var theData = { organisation: formatData(result.data) }

    var callback = function () {
      browser.loaded()
      accordion.init()
      analytics.init(theTitle)
    }

    templating.renderTemplate('js-breadcrumb-tpl', theData, 'js-breadcrumb-output')
    templating.renderTemplate('js-header-tpl', theData, 'js-header-output')
    templating.renderTemplate('js-organisation-tpl', theData, 'js-organisation-output')
    templating.renderTemplate('js-contact-tpl', theData, 'js-contact-output', callback)
  })

getApiData.data(accommodationUrl)
  .then((result) => {
    if (result.data.total > 0) {
      var accEntries = result.data.items
      for (var i = 0; i <= accEntries.length - 1; i++){
        accEntries[i].name = htmlEncode.htmlDecode(accEntries[i].name)
      }
      const theData = {
        items: accEntries
      }
      templating.renderTemplate('js-accommodation-tpl', theData, 'js-accommodation-output')
    }
  })
<|endoftext|>


<commit_before>var util2 = require('util2');
var ajax = require('ajax');
var myutil = require('myutil');
var appinfo = require('appinfo');

var Settings = module.exports;

var state;

Settings.settingsUrl = 'http://meiguro.com/simplyjs/settings.html';

Settings.init = function() {
  Settings.reset();

  Settings.loadOptions();
  Settings.loadData();

  // Register listeners for the Settings
  Pebble.addEventListener('showConfiguration', Settings.onOpenConfig);
  Pebble.addEventListener('webviewclosed', Settings.onCloseConfig);
};

Settings.reset = function() {
  state = Settings.state = {
    options: {},
    data: {},
    listeners: [],
  };
};

var toHttpUrl = function(url) {
  if (typeof url === 'string' && url.length && !url.match(/^(\w+:)?\/\//)) {
    url = 'http://' + url;
  }
  return url;
};

Settings.mainScriptUrl = function(scriptUrl) {
  scriptUrl = toHttpUrl(scriptUrl);
  if (scriptUrl) {
    localStorage.setItem('mainJsUrl', scriptUrl);
  } else {
    scriptUrl = localStorage.getItem('mainJsUrl');
  }
  return scriptUrl;
};

Settings.getBaseOptions = function() {
  return {
    scriptUrl: Settings.mainScriptUrl(),
  };
};

var getDataKey = function(path, field) {
  path = path || appinfo.uuid;
  return field + ':' + path;
};

Settings.saveData = function(path, field) {
  field = field || 'data';
  var data = data || state[field];
  localStorage.setItem(getDataKey(path, field), JSON.stringify(data));
};

Settings.loadData = function(path, field) {
  field = field || 'data';
  state[field] = {};
  var data = localStorage.getItem(getDataKey(path, field));
  try {
    data = JSON.parse(data);
  } catch (e) {}
  if (typeof data === 'object' && data !== null) {
    state[field] = data;
  }
};

Settings.saveOptions = function(path) {
  Settings.saveData(path, 'options');
};

Settings.loadOptions = function(path) {
  Settings.loadData(path, 'options');
};

var makeDataAccessor = function(type, path) {
  return function(field, value) {
    var data = state[type];
    if (arguments.length === 0) {
      return data;
    }
    if (arguments.length === 1 && typeof field !== 'object') {
      return data[field];
    }
    if (typeof field !== 'object' && value === undefined || value === null) {
      delete data[field];
      return;
    }
    var def = myutil.toObject(field, value);
    util2.copy(def, data);
    Settings.saveData(path, type);
    return value;
  };
};

Settings.option = makeDataAccessor('options');

Settings.data = makeDataAccessor('data');

Settings.config = function(opt, open, close) {
  if (typeof opt === 'string') {
    opt = { url: opt };
  }
  opt.url = toHttpUrl(opt.url);
  if (close === undefined) {
    close = open;
    open = util2.noop;
  }
  var listener = {
    params: opt,
    open: open,
    close: close,
  };
  state.listeners.push(listener);
};

Settings.onOpenConfig = function(e) {
  var options;
  var url;
  var listener = util2.last(state.listeners);
  if (listener) {
    e = {
      originalEvent: e,
      options: state.options,
      url: listener.params.url,
    };
    var result;
    if (listener.open) {
      result = listener.open(e);
      if (result === false) {
        return;
      }
    }
    url = typeof result === 'string' ? result : listener.params.url;
    options = state.options;
  } else {
    url = Settings.settingsUrl;
    options = Settings.getBaseOptions();
    return;
  }
  var hash = encodeURIComponent(JSON.stringify(options));
  Pebble.openURL(url + '#' + hash);
};

Settings.onCloseConfig = function(e) {
  var listener = util2.last(state.listeners);
  var options = {};
  var format;
  if (e.response && e.response !== 'CANCELLED') {
    try {
      options = JSON.parse(decodeURIComponent(e.response));
      format = 'json';
    } catch (err) {}
    if (!format && e.response.match(/(&|=)/)) {
      options = ajax.deformify(e.response);
      if (util2.count(options) > 0) {
        format = 'form';
      }
    }
  }
  if (listener) {
    e = {
      originalEvent: e,
      response: e.response,
      originalOptions: state.options,
      options: options,
      url: listener.params.url,
      failed: !format,
      format: format,
    };
    if (format && listener.params.autoSave !== false) {
      e.originalOptions = util2.copy(state.options);
      util2.copy(options, state.options);
      Settings.saveOptions();
    }
    return listener.close(e);
  }
};
<commit_msg>Change Settings.config close to be optional<commit_after>var util2 = require('util2');
var ajax = require('ajax');
var myutil = require('myutil');
var appinfo = require('appinfo');

var Settings = module.exports;

var state;

Settings.settingsUrl = 'http://meiguro.com/simplyjs/settings.html';

Settings.init = function() {
  Settings.reset();

  Settings.loadOptions();
  Settings.loadData();

  // Register listeners for the Settings
  Pebble.addEventListener('showConfiguration', Settings.onOpenConfig);
  Pebble.addEventListener('webviewclosed', Settings.onCloseConfig);
};

Settings.reset = function() {
  state = Settings.state = {
    options: {},
    data: {},
    listeners: [],
  };
};

var toHttpUrl = function(url) {
  if (typeof url === 'string' && url.length && !url.match(/^(\w+:)?\/\//)) {
    url = 'http://' + url;
  }
  return url;
};

Settings.mainScriptUrl = function(scriptUrl) {
  scriptUrl = toHttpUrl(scriptUrl);
  if (scriptUrl) {
    localStorage.setItem('mainJsUrl', scriptUrl);
  } else {
    scriptUrl = localStorage.getItem('mainJsUrl');
  }
  return scriptUrl;
};

Settings.getBaseOptions = function() {
  return {
    scriptUrl: Settings.mainScriptUrl(),
  };
};

var getDataKey = function(path, field) {
  path = path || appinfo.uuid;
  return field + ':' + path;
};

Settings.saveData = function(path, field) {
  field = field || 'data';
  var data = data || state[field];
  localStorage.setItem(getDataKey(path, field), JSON.stringify(data));
};

Settings.loadData = function(path, field) {
  field = field || 'data';
  state[field] = {};
  var data = localStorage.getItem(getDataKey(path, field));
  try {
    data = JSON.parse(data);
  } catch (e) {}
  if (typeof data === 'object' && data !== null) {
    state[field] = data;
  }
};

Settings.saveOptions = function(path) {
  Settings.saveData(path, 'options');
};

Settings.loadOptions = function(path) {
  Settings.loadData(path, 'options');
};

var makeDataAccessor = function(type, path) {
  return function(field, value) {
    var data = state[type];
    if (arguments.length === 0) {
      return data;
    }
    if (arguments.length === 1 && typeof field !== 'object') {
      return data[field];
    }
    if (typeof field !== 'object' && value === undefined || value === null) {
      delete data[field];
      return;
    }
    var def = myutil.toObject(field, value);
    util2.copy(def, data);
    Settings.saveData(path, type);
    return value;
  };
};

Settings.option = makeDataAccessor('options');

Settings.data = makeDataAccessor('data');

Settings.config = function(opt, open, close) {
  if (typeof opt === 'string') {
    opt = { url: opt };
  }
  opt.url = toHttpUrl(opt.url);
  if (close === undefined) {
    close = open;
    open = util2.noop;
  }
  var listener = {
    params: opt,
    open: open,
    close: close,
  };
  state.listeners.push(listener);
};

Settings.onOpenConfig = function(e) {
  var options;
  var url;
  var listener = util2.last(state.listeners);
  if (listener) {
    e = {
      originalEvent: e,
      options: state.options,
      url: listener.params.url,
    };
    var result;
    if (listener.open) {
      result = listener.open(e);
      if (result === false) {
        return;
      }
    }
    url = typeof result === 'string' ? result : listener.params.url;
    options = state.options;
  } else {
    url = Settings.settingsUrl;
    options = Settings.getBaseOptions();
    return;
  }
  var hash = encodeURIComponent(JSON.stringify(options));
  Pebble.openURL(url + '#' + hash);
};

Settings.onCloseConfig = function(e) {
  var listener = util2.last(state.listeners);
  var options = {};
  var format;
  if (e.response && e.response !== 'CANCELLED') {
    try {
      options = JSON.parse(decodeURIComponent(e.response));
      format = 'json';
    } catch (err) {}
    if (!format && e.response.match(/(&|=)/)) {
      options = ajax.deformify(e.response);
      if (util2.count(options) > 0) {
        format = 'form';
      }
    }
  }
  if (listener) {
    e = {
      originalEvent: e,
      response: e.response,
      originalOptions: state.options,
      options: options,
      url: listener.params.url,
      failed: !format,
      format: format,
    };
    if (format && listener.params.autoSave !== false) {
      e.originalOptions = util2.copy(state.options);
      util2.copy(options, state.options);
      Settings.saveOptions();
    }
    if (listener.close) {
      return listener.close(e);
    }
  }
};
<|endoftext|>