<commit_before>/*global module, require */

'use strict';

const fs = require('fs');
const path = require('path');
const glob = require('glob');
const _ = require('lodash');
const Verbalize = require('verbalize');
const checkstyleFormatter = require('checkstyle-formatter');
const chalk = require('chalk');
const logSymbols = require('log-symbols');
const pathIsAbsolute = require('path-is-absolute');

const log = new Verbalize();

/**
 * Uses lodash isEqual to perform non-strict object comparison.
 *
 * @see http://stackoverflow.com/a/4587130/167987
 * @param {Object} obj - The object to search for.
 * @param {Array} list - The array of objects to search.
 */
const containsObject = (obj, list) => {
	for (let i = 0; i < list.length; i += 1) {
		if (_.isEqual(list[i], obj)) {
			return true;
		}
	}

	return false;
};

/**
 * @param {string} line - The file line to check for an XML file prolog.
 */
const checkIsXMLFile = (line) => {
	const XMLSearch = line.match(/(<\?xml|type="text\/xml)/);
	let isXMLFile = false;
	if (XMLSearch !== null) {
		isXMLFile = true;
	}
	return isXMLFile;
};

/**
 * Compares two arrays of cfml taglib prefixes to see if there are any mismatches.
 *
 * @param {Array} prefixArray1 - The first array of taglib prefixes.
 * @param {Array} prefixArray2 - The second array of taglib prefixes.
 * @param {string} message - The message to display in case of a violation.
 * @param {string} severity - The violation severity.
 */
const comparePrefixArrays = (prefixArray1, prefixArray2, message, severity) => {
	const prefixedViolations = {};
	const prefixManifest = {};
	const violations = [];

	prefixArray1.forEach((value) => {
		if (!prefixedViolations.hasOwnProperty(value.prefix)) {
			prefixedViolations[value.prefix] = [];
		}

		const formattedMessage = message.replace('{2}', value.prefix);

		prefixArray2.forEach((value2) => {
			// Key not found

			if (value.prefix !== value2.prefix) {
				// Don't override a true value with false - true is sticky
				if (!prefixManifest.hasOwnProperty(value.prefix) ||
					!prefixManifest[value.prefix]
				) {
					prefixManifest[value.prefix] = false;
				}
			} else {
				prefixManifest[value.prefix] = true;
			}

			const messageObj = {
				line: value.line,
				column: value.column || 1,
				message: formattedMessage,
				severity: severity
			};

			// console.log(prefixedViolations[value.prefix]);

			if (!containsObject(messageObj, prefixedViolations[value.prefix])) {
				prefixedViolations[value.prefix].push(messageObj);
			}
		});

		if (prefixArray2.length === 0) {
			prefixManifest[value.prefix] = false;
			const messageObj = {
				line: value.line,
				column: value.column || 1,
				message: formattedMessage,
				severity: severity
			};
			if (!containsObject(messageObj, prefixedViolations[value.prefix])) {
				prefixedViolations[value.prefix].push(messageObj);
			}
		}
	});

	// Delete the array of messages for prefix keys that *were* found
	for (const prefix in prefixManifest) {
		if (prefixManifest.hasOwnProperty(prefix)) {
			if (prefixManifest[prefix]) {
				delete prefixedViolations[prefix];
			} else {
				prefixedViolations[prefix].forEach((value) => {
					violations.push(value);
				});
			}
		}
	}

	return violations;
}

/**
 * @param {string} str - The string to match.
 * @param {RegExp} regex - The RegExp to use.
 */
const matchAll = (str, regex) => {
	const res = [];
	let m;
	if (regex.global) {
		while ((m = regex.exec(str))) {
			res.push(m);
		}
	} else {
		if ((m = regex.exec(str))) {
			res.push(m);
		}
	}
	return res;
};

/**
 * @param {string} filePath - The path of the file to check.
 * Checks a file for missing paths.
 */
const checkFile = (filePath) => {
	const templatePathViolations = [];
	const taglibPathViolations = [];
	const prefixes = [];
	const prefixUsages = [];
	let isXMLFile = false;
	let lineNumber = 1;

	const lines = fs
		.readFileSync(filePath, 'utf8')
		.replace(/\r\n/, '\n')
		.split('\n');

	// Cache the dirname of the file being analysed
	const fileDirname = path.dirname(filePath);

	lines.forEach((line) => {
		// console.log('Line from file:', line);

		isXMLFile = checkIsXMLFile(line);

		// Exclude @usage doc lines including code snippets
		const isUsageLine = line.match(/^@usage/) !== null;

		const importSearch = line.match(/prefix=["']([A-Za-z0-9]+)["']/);

		if (importSearch !== null) {
			// console.log(importSearch);
			prefixes.push({
				prefix: importSearch[1],
				line: lineNumber,
				column: importSearch.index + 1
			});
		}

		const namespaceSearch = matchAll(line, /<([A-Za-z0-9]+):/g);
		// console.log(namespaceSearch);

		// We're outputting an XML file - don't attempt to collate namespace prefix usages
		if (!isXMLFile && !isUsageLine) {
			namespaceSearch.forEach((value) => {
				prefixUsages.push({
					prefix: value[1],
					line: lineNumber,
					column: value.index + 1
				});
			});
		}

		const taglibMatches = matchAll(line, /taglib=["']([^"']+)["']/g);

		taglibMatches.forEach((taglibMatch) => {
			let taglibPath = taglibMatch[1];
			if (!pathIsAbsolute(taglibPath)) {
				taglibPath = path.resolve(fileDirname, taglibPath);
			}
			if (!fs.existsSync(taglibPath)) {
				taglibPathViolations.push({
					line: lineNumber,
					column: taglibMatch.index + 1,
					message: `cfimport taglib path ${taglibPath} not found`,
					severity: 'error'
				});
			}
		});

		// <cfinclude template="$path" />
		const cfIncludeMatches = matchAll(line, /template=["']([^"']+)["']/g);

		// include '$path'; (inside <cfscript>)
		const includeMatches = matchAll(line, /\binclude\s['"](.*\.cfm)['"]/g);

		cfIncludeMatches.concat(includeMatches).forEach((includeMatch) => {
			// console.log(includeMatch);

			// Dynamic path (contains # or &): all we can check is the non-dynamic part,
			// wound back to the last slash
			let templatePath = includeMatch[1];
			const hashPos = templatePath.indexOf('#');
			const ampersandPos = templatePath.indexOf('&');
			if (hashPos !== -1 || ampersandPos !== -1) {
				const searchPos = hashPos !== -1 ? hashPos : ampersandPos;
				const lastSlashPos = templatePath.lastIndexOf('/', searchPos);
				templatePath = path.dirname(templatePath.substr(0, lastSlashPos));
			}

			// Can't work with webroot-virtual paths, e.g. /missing.cfm
			if (templatePath.substr(0, 1) !== '/') {
				if (!pathIsAbsolute(templatePath)) {
					// Resolve the templatePath relative to the dirname of the including file
					templatePath = path.resolve(fileDirname, templatePath);
				}

				if (!fs.existsSync(templatePath)) {
					templatePathViolations.push({
						line: lineNumber,
						column: includeMatch.index + 1,
						message: `cfinclude/include template path ${templatePath} not found`,
						severity: 'error'
					});
				}
			}
		});

		lineNumber += 1;
	});

	const unusedPrefixViolations = comparePrefixArrays(
		prefixes,
		prefixUsages,
		'cfimported namespace prefix "{2}" not used',
		'warning'
	);

	const unimportedPrefixViolations = comparePrefixArrays(
		prefixUsages,
		prefixes,
		'used namespace prefix "{2}" not cfimported',
		'error'
	);

	const violations = unimportedPrefixViolations.concat(
		unusedPrefixViolations,
		templatePathViolations,
		taglibPathViolations
	);

	return violations;
};

module.exports = {
	/**
	 * @param {string} filePath - The full path of the file to check.
	 */
	check: (filePath) => {
		let fileNames = [];
		const violations = [];

		// Resolve the path, if a relative path was passed in
		if (!pathIsAbsolute(filePath)) {
			filePath = path.resolve(filePath);
		}

		// The path exists...
		if (fs.existsSync(filePath)) {
			try {
				// ...try a readdirSync and...
				fs.readdirSync(filePath);

				// (Add a trailing slash if not present)
				if (filePath.substr(-1) !== '/') {
					filePath += '/';
				}
				fileNames = glob.sync(`${filePath}**/*.cfm`, {
					ignore: ['**/WEB-INF/**', '**/node_modules/**']
				});
			} catch (e) {
				// ...if that fails, it's a file, not a directory
				fileNames = [filePath];
			}
		}

		// console.log(fileNames);

		// Loop over our file list, checking each file
		fileNames.forEach((fileName) => {
			const fileViolations = checkFile(fileName);
			// console.log(fileViolations);
			if (fileViolations.length > 0) {
				violations.push({
					filename: fileName,
					messages: fileViolations
				});
			}
		});

		// console.log(violations);

		return violations;
	},

	/**
	 * @param {Array} violations - The violations array.
	 * @param {string} format - The output format to use.
	 */
	formatter: (violations, format) => {
		let output;
		if (format === 'checkstyle') {
			output = checkstyleFormatter(violations);
		} else {
			output = violations;
		}
		return output;
	},

	/**
	 * @param {string} output - The file contents to write.
	 * @param {string} outFile - The file to write to.
	 */
	writeFile: (output, outFile) => {
		// Resolve the path if it's not absolute
		if (!pathIsAbsolute(outFile)) {
			outFile = path.resolve(outFile);
		}

		// Warn that the target directory doesn't exist
		if (!fs.existsSync(path.dirname(outFile))) {
			// fs.mkdirSync(path.dirname(outFile));
			log.warn(
				`Cannot write ${outFile}. Destination directory doesn't exist`
			);
		} else {
			fs.writeFileSync(outFile, output, 'utf8');
		}
	},

	/**
	 * @param {string|Array} output - The output to write.
	 */
	writeOutput: (output) => {
		if (output instanceof Array) {
			output.forEach((violation) => {
				log.writeln(`File: ${chalk.green(violation.filename)}`);
				violation.messages.forEach((message) => {
					let messageText = `L${message.line}:${message.column} - ${message.message}`;
					if (message.severity === 'error') {
						messageText = chalk.red(messageText);
					} else if (message.severity === 'warning') {
						messageText = chalk.yellow(messageText);
					}

					log.writeln('  ', logSymbols[message.severity], messageText);
				});
			});
		} else {
			log.writeln(output);
		}
	}
};
<commit_msg>[CHORE] Move file reading into a function<commit_after>/*global module, require */

'use strict';

const fs = require('fs');
const path = require('path');
const glob = require('glob');
const _ = require('lodash');
const Verbalize = require('verbalize');
const checkstyleFormatter = require('checkstyle-formatter');
const chalk = require('chalk');
const logSymbols = require('log-symbols');
const pathIsAbsolute = require('path-is-absolute');

const log = new Verbalize();

/**
 * Uses lodash isEqual to perform non-strict object comparison.
 *
 * @see http://stackoverflow.com/a/4587130/167987
 * @param {Object} obj - The object to search for.
 * @param {Array} list - The array of objects to search.
 */
const containsObject = (obj, list) => {
	for (let i = 0; i < list.length; i += 1) {
		if (_.isEqual(list[i], obj)) {
			return true;
		}
	}

	return false;
};

/**
 * @param {string} line - The file line to check for an XML file prolog.
 */
const checkIsXMLFile = (line) => {
	const XMLSearch = line.match(/(<\?xml|type="text\/xml)/);
	let isXMLFile = false;
	if (XMLSearch !== null) {
		isXMLFile = true;
	}
	return isXMLFile;
};

/**
 * Compares two arrays of cfml taglib prefixes to see if there are any mismatches.
 *
 * @param {Array} prefixArray1 - The first array of taglib prefixes.
 * @param {Array} prefixArray2 - The second array of taglib prefixes.
 * @param {string} message - The message to display in case of a violation.
 * @param {string} severity - The violation severity.
 */
const comparePrefixArrays = (prefixArray1, prefixArray2, message, severity) => {
	const prefixedViolations = {};
	const prefixManifest = {};
	const violations = [];

	prefixArray1.forEach((value) => {
		if (!prefixedViolations.hasOwnProperty(value.prefix)) {
			prefixedViolations[value.prefix] = [];
		}

		const formattedMessage = message.replace('{2}', value.prefix);

		prefixArray2.forEach((value2) => {
			// Key not found

			if (value.prefix !== value2.prefix) {
				// Don't override a true value with false - true is sticky
				if (!prefixManifest.hasOwnProperty(value.prefix) ||
					!prefixManifest[value.prefix]
				) {
					prefixManifest[value.prefix] = false;
				}
			} else {
				prefixManifest[value.prefix] = true;
			}

			const messageObj = {
				line: value.line,
				column: value.column || 1,
				message: formattedMessage,
				severity: severity
			};

			// console.log(prefixedViolations[value.prefix]);

			if (!containsObject(messageObj, prefixedViolations[value.prefix])) {
				prefixedViolations[value.prefix].push(messageObj);
			}
		});

		if (prefixArray2.length === 0) {
			prefixManifest[value.prefix] = false;
			const messageObj = {
				line: value.line,
				column: value.column || 1,
				message: formattedMessage,
				severity: severity
			};
			if (!containsObject(messageObj, prefixedViolations[value.prefix])) {
				prefixedViolations[value.prefix].push(messageObj);
			}
		}
	});

	// Delete the array of messages for prefix keys that *were* found
	for (const prefix in prefixManifest) {
		if (prefixManifest.hasOwnProperty(prefix)) {
			if (prefixManifest[prefix]) {
				delete prefixedViolations[prefix];
			} else {
				prefixedViolations[prefix].forEach((value) => {
					violations.push(value);
				});
			}
		}
	}

	return violations;
}

/**
 * @param {string} str - The string to match.
 * @param {RegExp} regex - The RegExp to use.
 */
const matchAll = (str, regex) => {
	const res = [];
	let m;
	if (regex.global) {
		while ((m = regex.exec(str))) {
			res.push(m);
		}
	} else {
		if ((m = regex.exec(str))) {
			res.push(m);
		}
	}
	return res;
};

const readFile = (filePath) => {
	return fs
		.readFileSync(filePath, 'utf8')
		.replace(/\r\n/, '\n');
}

/**
 * @param {string} filePath - The path of the file to check.
 * Checks a file for missing paths.
 */
const checkFile = (filePath) => {
	const templatePathViolations = [];
	const taglibPathViolations = [];
	const prefixes = [];
	const prefixUsages = [];
	let isXMLFile = false;
	let lineNumber = 1;

	const lines = readFile(filePath).split('\n');

	// Cache the dirname of the file being analysed
	const fileDirname = path.dirname(filePath);

	lines.forEach((line) => {
		// console.log('Line from file:', line);

		isXMLFile = checkIsXMLFile(line);

		// Exclude @usage doc lines including code snippets
		const isUsageLine = line.match(/^@usage/) !== null;

		const importSearch = line.match(/prefix=["']([A-Za-z0-9]+)["']/);

		if (importSearch !== null) {
			// console.log(importSearch);
			prefixes.push({
				prefix: importSearch[1],
				line: lineNumber,
				column: importSearch.index + 1
			});
		}

		const namespaceSearch = matchAll(line, /<([A-Za-z0-9]+):/g);
		// console.log(namespaceSearch);

		// We're outputting an XML file - don't attempt to collate namespace prefix usages
		if (!isXMLFile && !isUsageLine) {
			namespaceSearch.forEach((value) => {
				prefixUsages.push({
					prefix: value[1],
					line: lineNumber,
					column: value.index + 1
				});
			});
		}

		const taglibMatches = matchAll(line, /taglib=["']([^"']+)["']/g);

		taglibMatches.forEach((taglibMatch) => {
			let taglibPath = taglibMatch[1];
			if (!pathIsAbsolute(taglibPath)) {
				taglibPath = path.resolve(fileDirname, taglibPath);
			}
			if (!fs.existsSync(taglibPath)) {
				taglibPathViolations.push({
					line: lineNumber,
					column: taglibMatch.index + 1,
					message: `cfimport taglib path ${taglibPath} not found`,
					severity: 'error'
				});
			}
		});

		// <cfinclude template="$path" />
		const cfIncludeMatches = matchAll(line, /template=["']([^"']+)["']/g);

		// include '$path'; (inside <cfscript>)
		const includeMatches = matchAll(line, /\binclude\s['"](.*\.cfm)['"]/g);

		cfIncludeMatches.concat(includeMatches).forEach((includeMatch) => {
			// console.log(includeMatch);

			// Dynamic path (contains # or &): all we can check is the non-dynamic part,
			// wound back to the last slash
			let templatePath = includeMatch[1];
			const hashPos = templatePath.indexOf('#');
			const ampersandPos = templatePath.indexOf('&');
			if (hashPos !== -1 || ampersandPos !== -1) {
				const searchPos = hashPos !== -1 ? hashPos : ampersandPos;
				const lastSlashPos = templatePath.lastIndexOf('/', searchPos);
				templatePath = path.dirname(templatePath.substr(0, lastSlashPos));
			}

			// Can't work with webroot-virtual paths, e.g. /missing.cfm
			if (templatePath.substr(0, 1) !== '/') {
				if (!pathIsAbsolute(templatePath)) {
					// Resolve the templatePath relative to the dirname of the including file
					templatePath = path.resolve(fileDirname, templatePath);
				}

				if (!fs.existsSync(templatePath)) {
					templatePathViolations.push({
						line: lineNumber,
						column: includeMatch.index + 1,
						message: `cfinclude/include template path ${templatePath} not found`,
						severity: 'error'
					});
				}
			}
		});

		lineNumber += 1;
	});

	const unusedPrefixViolations = comparePrefixArrays(
		prefixes,
		prefixUsages,
		'cfimported namespace prefix "{2}" not used',
		'warning'
	);

	const unimportedPrefixViolations = comparePrefixArrays(
		prefixUsages,
		prefixes,
		'used namespace prefix "{2}" not cfimported',
		'error'
	);

	const violations = unimportedPrefixViolations.concat(
		unusedPrefixViolations,
		templatePathViolations,
		taglibPathViolations
	);

	return violations;
};

module.exports = {
	/**
	 * @param {string} filePath - The full path of the file to check.
	 */
	check: (filePath) => {
		let fileNames = [];
		const violations = [];

		// Resolve the path, if a relative path was passed in
		if (!pathIsAbsolute(filePath)) {
			filePath = path.resolve(filePath);
		}

		// The path exists...
		if (fs.existsSync(filePath)) {
			try {
				// ...try a readdirSync and...
				fs.readdirSync(filePath);

				// (Add a trailing slash if not present)
				if (filePath.substr(-1) !== '/') {
					filePath += '/';
				}
				fileNames = glob.sync(`${filePath}**/*.cfm`, {
					ignore: ['**/WEB-INF/**', '**/node_modules/**']
				});
			} catch (e) {
				// ...if that fails, it's a file, not a directory
				fileNames = [filePath];
			}
		}

		// console.log(fileNames);

		// Loop over our file list, checking each file
		fileNames.forEach((fileName) => {
			const fileViolations = checkFile(fileName);
			// console.log(fileViolations);
			if (fileViolations.length > 0) {
				violations.push({
					filename: fileName,
					messages: fileViolations
				});
			}
		});

		// console.log(violations);

		return violations;
	},

	/**
	 * @param {Array} violations - The violations array.
	 * @param {string} format - The output format to use.
	 */
	formatter: (violations, format) => {
		let output;
		if (format === 'checkstyle') {
			output = checkstyleFormatter(violations);
		} else {
			output = violations;
		}
		return output;
	},

	/**
	 * @param {string} output - The file contents to write.
	 * @param {string} outFile - The file to write to.
	 */
	writeFile: (output, outFile) => {
		// Resolve the path if it's not absolute
		if (!pathIsAbsolute(outFile)) {
			outFile = path.resolve(outFile);
		}

		// Warn that the target directory doesn't exist
		if (!fs.existsSync(path.dirname(outFile))) {
			// fs.mkdirSync(path.dirname(outFile));
			log.warn(
				`Cannot write ${outFile}. Destination directory doesn't exist`
			);
		} else {
			fs.writeFileSync(outFile, output, 'utf8');
		}
	},

	/**
	 * @param {string|Array} output - The output to write.
	 */
	writeOutput: (output) => {
		if (output instanceof Array) {
			output.forEach((violation) => {
				log.writeln(`File: ${chalk.green(violation.filename)}`);
				violation.messages.forEach((message) => {
					let messageText = `L${message.line}:${message.column} - ${message.message}`;
					if (message.severity === 'error') {
						messageText = chalk.red(messageText);
					} else if (message.severity === 'warning') {
						messageText = chalk.yellow(messageText);
					}

					log.writeln('  ', logSymbols[message.severity], messageText);
				});
			});
		} else {
			log.writeln(output);
		}
	}
};
<|endoftext|>


<commit_before>/* global $ _ requests sidebar */
'use strict';
// ==UserScript==
// @name         MusicBrainz: Shortcuts
// @namespace    mbz-joseffriedrich
// @author       Josef Friedrich
// @version      5
// @downloadURL  https://raw.githubusercontent.com/Josef-Friedrich/greasemonkey-user-scripts/master/mbz-shortcuts.user.js
// @updateURL    https://raw.githubusercontent.com/Josef-Friedrich/greasemonkey-user-scripts/master/mbz-shortcuts.user.js
// @supportURL   https://github.com/Josef-Friedrich/greasemonkey-user-scripts
// @icon         https://raw.githubusercontent.com/Josef-Friedrich/greasemonkey-user-scripts/master/icon.png
// @description  musicbrainz.org: Add some shortcuts
// @compatible   firefox+greasemonkey
// @licence      MIT (https://opensource.org/licenses/MIT)
// @include      http*://musicbrainz.org/release/*/edit-relationships
// @require      https://craig.global.ssl.fastly.net/js/mousetrap/mousetrap.min.js
// @grant        none
// @run-at       document-end
// ==/UserScript==

function AddShortCuts(id, key) {
    $("#" + id)
      .attr("accesskey", key)
      .attr("title", "Shortcut: " + key);
}

$(window).on("load", function() {
    AddShortCuts("batch-recording", "r");
});
<commit_msg>Fix jquery issue<commit_after>/* global $ _ requests sidebar */
'use strict';
// ==UserScript==
// @name         MusicBrainz: Shortcuts
// @namespace    mbz-joseffriedrich
// @author       Josef Friedrich
// @version      6
// @downloadURL  https://raw.githubusercontent.com/Josef-Friedrich/greasemonkey-user-scripts/master/mbz-shortcuts.user.js
// @updateURL    https://raw.githubusercontent.com/Josef-Friedrich/greasemonkey-user-scripts/master/mbz-shortcuts.user.js
// @supportURL   https://github.com/Josef-Friedrich/greasemonkey-user-scripts
// @icon         https://raw.githubusercontent.com/Josef-Friedrich/greasemonkey-user-scripts/master/icon.png
// @description  musicbrainz.org: Add some shortcuts
// @compatible   firefox+greasemonkey
// @licence      MIT (https://opensource.org/licenses/MIT)
// @include      http*://musicbrainz.org/release/*/edit-relationships
// @require      https://craig.global.ssl.fastly.net/js/mousetrap/mousetrap.min.js
// @grant        none
// @run-at       document-end
// ==/UserScript==

function AddShortCuts(id, key) {
    $("#" + id).attr("accesskey", key).attr("title", "Shortcut: " + key);
}

$(window).on("load", function() {
    AddShortCuts("batch-recording", "r");
});
<|endoftext|>


<commit_before>(function (name, global, definition) {
  if (typeof module !== 'undefined') {
    module.exports = definition();
  } else if (typeof require !== 'undefined' && typeof require.amd === 'object') {
    define(definition);
  } else {
    global[name] = definition();
  }
})('namespace', this, function () {
  function namespace(namespaceString) {
    var ns = window;
    var parts = namespaceString.split('.');

    parts.forEach(function (part) {
      if (typeof ns[part] === 'undefined') {
        ns[part] = {};
      }

      ns = ns[part];
    });

    return ns;
  }

  namespace.import = function (namespaceString) {
    var object = window;
    var parts = namespaceString.split('.');

    parts.forEach(function (part) {
      if (typeof object[part] === 'undefined') {
        throw new Error('namespace ' + part + ' doesn\'t exist!');
      }

      object = object[part];
    });

    return object;
  };

  return namespace;
});
<commit_msg>Add changes to namespacing.js file.<commit_after>(function (name, global, definition) {
  if (typeof module !== 'undefined') {
    module.exports = definition();
  } else if (typeof global.require !== 'undefined' && typeof global.require.amd === 'object') {
    global.define(definition);
  } else {
    global[name] = definition();
  }
}('namespace', this, function () {
  function namespace(namespaceString) {
    var ns = global;
    var parts = namespaceString.split('.');

    parts.forEach(function (part) {
      if (typeof ns[part] === 'undefined') {
        ns[part] = {};
      }

      ns = ns[part];
    });

    return ns;
  }

  namespace.import = function (namespaceString) {
    var object = global;
    var parts = namespaceString.split('.');

    parts.forEach(function (part) {
      if (typeof object[part] === 'undefined') {
        throw new Error('namespace ' + part + ' doesn\'t exist!');
      }

      object = object[part];
    });

    return object;
  };

  return namespace;
}));
<|endoftext|>


<commit_before>'use strict'

const NakoCompiler = require('../src/nako3')
const PluginSystem = require('../src/plugin_system')

const nako = new NakoCompiler()
const js = nako.compile('「こんにちは」と表示。')
const vars = nako.getVarsCode()
const head = nako.getHeader()
const code = head + vars + js

console.log('--- generated ---')
console.log(code)
console.log('--- eval ---')
eval(code)
<commit_msg>パスを修正<commit_after>'use strict'

const NakoCompiler = require('../../src/nako3')
const PluginSystem = require('../../src/plugin_system')

const nako = new NakoCompiler()
const js = nako.compile('「こんにちは」と表示。')
const vars = nako.getVarsCode()
const head = nako.getHeader()
const code = head + vars + js

console.log('--- generated ---')
console.log(code)
console.log('--- eval ---')
eval(code)
<|endoftext|>


<commit_before>'use strict'

const _ = require('lodash')

const Logger = require('../util/logger')

class Warnings {
  constructor (config, jirascope) {
    this.config = config
    this.jirascope = jirascope
  }

  async run () {
    await this.jirascope.populate()
    await this.jirascope.store()

    const count = Math.round(this.jirascope.issues.length / 10)
    const highest = _.chain(this.jirascope.issues).orderBy(['analysis.scoreSize'], ['desc']).take(count).value()

    Logger.global.info(`${highest.length} highest scoring issues`)
    highest.forEach((issue) => {
      Logger.global.info(`${issue.analysis.scoreSize}, ${issue.key}, ${issue.status}, ${issue.summary}`)
    })
  }
}

exports = module.exports = Warnings
<commit_msg>highest is of those scored<commit_after>'use strict'

const _ = require('lodash')

const Logger = require('../util/logger')

class Warnings {
  constructor (config, jirascope) {
    this.config = config
    this.jirascope = jirascope
  }

  async run () {
    await this.jirascope.populate()
    await this.jirascope.store()

    const count = Math.round(this.jirascope.issues.length / 10)
    const highest = _.chain(this.jirascope.issues).filter('analysis.scoreSize').orderBy(['analysis.scoreSize'], ['desc']).take(count).value()

    Logger.global.info(`${highest.length} highest scoring issues`)
    highest.forEach((issue) => {
      Logger.global.info(`${issue.analysis.scoreSize}, ${issue.key}, ${issue.status}, ${issue.summary}`)
    })
  }
}

exports = module.exports = Warnings
<|endoftext|>


<commit_before>'use strict';
exports.info = {
  desc: 'Get information about the message author.',
  usage: '',
  aliases: [],
};

const moment = require('moment');

exports.run = (client, msg) => new Promise(async(resolve, reject) => {
  // Gat capitalized user presence or null
  let status = msg.author.presence.status ? client.utils.capitalize(msg.author.presence.status) : null;
  // If presence is DND caps all
  if (status === 'Dnd') {
    status = 'DND';
  }
  let roles;
  // Get the message members roles if message was in text channel
  if (msg.channel.type === 'text') {
    roles = msg.member.roles
      .filter(x => x.id !== msg.guild.id)
      .map(x => x.name);
  }
  // Build string to post to Discord
  let str = '--Info--\n';
  str += `ID: ${msg.author.id}\n`;
  // DM channel members don't have nicknames
  if (msg.channel.type === 'text') {
    str += `Nickname: ${msg.member.nickname}\n`;
  }
  str += `Bot: ${msg.author.bot}\n`;
  str += `Status: ${status}\n`;
  str += `Game: ${msg.author.presence.game}\n`;
  str += `Avatar: '${msg.author.avatar}'\n`;
  // DM channels members don't have roles
  if (msg.channel.type === 'text') {
    str += `Roles: ${roles.sort().join(', ')}\n`;
  }
  str += `\n--Joined--\n`;
  let d = moment.duration(moment() - msg.author.createdAt).asMonths().toFixed(0);
  str += `Discord: '${moment(msg.author.createdAt).utc().format()}' ` +
    `(${d}+ month${d === 1 ? '' : 's'})\n`;
  if (msg.channel.type === 'text') {
    d = moment.duration(moment() - msg.member.joinedAt).asMonths().toFixed(0);
    str += `${msg.guild.name.replace(/\s/g, '')}: '${moment(msg.member.joinedAt).utc().format()}' ` +
      `(${d}+ month${d === 1 ? '' : 's'})\n`;
  }
  str = `\`\`\`qml\n${str}\`\`\``;
  msg.channel.sendEmbed(new client.Discord.RichEmbed()
    .setTitle(`${msg.author.username} #${msg.author.discriminator}`)
    .setDescription(str)
    .setThumbnail(msg.author.avatarURL)
  ).then(resolve).catch(reject);
});
<commit_msg>Update myinfo command<commit_after>'use strict';
exports.info = {
  desc: 'Get information about the message author.',
  usage: '',
  aliases: [],
};

const moment = require('moment');

exports.run = (client, msg) => new Promise(async(resolve, reject) => {
  // Gat capitalized user presence or null
  let status = msg.author.presence.status ? client.utils.capitalize(msg.author.presence.status) : null;
  // If presence is DND caps all
  if (status === 'Dnd') {
    status = 'DND';
  }
  let roles;
  // Get the message members roles if message was in text channel
  if (msg.channel.type === 'text') {
    roles = msg.member.roles
      .filter(x => x.id !== msg.guild.id)
      .map(x => x.name);
  }
  // Build string to post to Discord
  let str = '--Info--\n';
  str += `ID: ${msg.author.id}\n`;
  // DM channel members don't have nicknames
  if (msg.channel.type === 'text') {
    str += `Nickname: ${msg.member.nickname}\n`;
  }
  str += `Bot: ${msg.author.bot}\n`;
  str += `Status: ${status}\n`;
  str += `Game: ${msg.author.presence.game ? msg.author.presence.game.name : null}\n`;
  str += `Avatar: '${msg.author.avatar}'\n`;
  // DM channels members don't have roles
  if (msg.channel.type === 'text') {
    str += `Roles: ${roles.sort().join(', ')}\n`;
  }
  str += `\n--Joined--\n`;
  let d = moment.duration(moment() - msg.author.createdAt).asMonths().toFixed(0);
  str += `Discord: '${moment(msg.author.createdAt).utc().format()}' ` +
    `(${d}+ month${d === 1 ? '' : 's'})\n`;
  if (msg.channel.type === 'text') {
    d = moment.duration(moment() - msg.member.joinedAt).asMonths().toFixed(0);
    str += `${msg.guild.name.replace(/\s/g, '')}: '${moment(msg.member.joinedAt).utc().format()}' ` +
      `(${d}+ month${d === 1 ? '' : 's'})\n`;
  }
  str = `\`\`\`qml\n${str}\`\`\``;
  msg.channel.sendEmbed(new client.Discord.RichEmbed()
    .setTitle(`${msg.author.username} #${msg.author.discriminator}`)
    .setDescription(str)
    .setThumbnail(msg.author.avatarURL)
  ).then(resolve).catch(reject);
});
<|endoftext|>


<commit_before>Playlists = new Mongo.Collection("playlists");

if(Meteor.isServer){
  Meteor.publish("playlists", function() {
    if (!this.userId) {
      return this.ready();
    }
    playlists = Playlists.find({
      userId: this.userId
    });
    playlistIds = playlists.map(function(playlist){return playlist._id});
    fetchPlaylistMetaData(playlistIds);
    return playlists;
  });
}

if(Meteor.isClient){
  Meteor.subscribe("playlists");
  ClientPlaylists = new Mongo.Collection("clientPlaylists"); // client-only playlists when the user isn't logged-in
}

Meteor.users.deny({
  update: function() {
    return true;
  }
});
<commit_msg>remove client-side collection idea<commit_after>Playlists = new Mongo.Collection("playlists");

if(Meteor.isServer){
  Meteor.publish("playlists", function() {
    if (!this.userId) {
      return this.ready();
    }
    playlists = Playlists.find({
      userId: this.userId
    });
    playlistIds = playlists.map(function(playlist){return playlist._id});
    fetchPlaylistMetaData(playlistIds);
    return playlists;
  });
}

if(Meteor.isClient){
  Meteor.subscribe("playlists");
}

Meteor.users.deny({
  update: function() {
    return true;
  }
});
<|endoftext|>


<commit_before>var http = require('http');
var path = require('path');
var express = require('express');

var serveStatic = require('serve-static');
var finalhandler = require('finalhandler');
var router = require('../router');

var httpd;

module.exports = function up(options, done) {
  if( !options ) return done(new Error('missing options'));
  if( typeof options.port !== 'number' ) return done(new Error('port number must be a number'));
  if( options.port < 0 || isNaN(options.port) || options.port > 65535 ) return done(new Error('illegal port number:' + options.port));

  var cwd = options.cwd || process.cwd();
  var docbase = path.resolve(cwd, options.docbase || '.');
  var host = options.host || '0.0.0.0';
  var port = options.port;

  /*
  var app = express()
  .use('/', express.static(webroot))
  .use('/web_modules', router({
    selfref: options.selfref
  }));*/

  var serve_docbase = serveStatic(docbase);
  var serve_webmodules = router({
    cwd: cwd,
    selfref: options.selfref
  });

  httpd = http.createServer(function(req, res){
    var next = finalhandler(req, res);

    if( !req.url.indexOf('/web_modules/') ) {
      req.url = req.url.substring('/web_modules'.length);
      serve_webmodules(req, res, next);
    } else {
      serve_docbase(req, res, next);
    }
  })
  .on('error', function(err) {
    return done(err);
  }).listen({
    host: host,
    port: port
  }, function() {
    done(null, {
      httpd: httpd,
      address: httpd.address(),
      docbase: docbase
    });
  });
};<commit_msg>Remove express dependency<commit_after>var http = require('http');
var path = require('path');
var serveStatic = require('serve-static');
var finalhandler = require('finalhandler');
var router = require('../router');

var httpd;

module.exports = function up(options, done) {
  if( !options ) return done(new Error('missing options'));
  if( typeof options.port !== 'number' ) return done(new Error('port number must be a number'));
  if( options.port < 0 || isNaN(options.port) || options.port > 65535 ) return done(new Error('illegal port number:' + options.port));

  var cwd = options.cwd || process.cwd();
  var docbase = path.resolve(cwd, options.docbase || '.');
  var host = options.host || '0.0.0.0';
  var port = options.port;

  var serve_docbase = serveStatic(docbase);
  var serve_webmodules = router({
    cwd: cwd,
    selfref: options.selfref
  });

  httpd = http.createServer(function(req, res){
    var next = finalhandler(req, res);

    if( !req.url.indexOf('/web_modules/') ) {
      req.url = req.url.substring('/web_modules'.length);
      serve_webmodules(req, res, next);
    } else {
      serve_docbase(req, res, next);
    }
  })
  .on('error', function(err) {
    done(err);
  }).listen({
    host: host,
    port: port
  }, function() {
    done(null, {
      httpd: httpd,
      address: httpd.address(),
      docbase: docbase
    });
  });
};<|endoftext|>


<commit_before>/* configUtils.js
 * Defines an object that provides functions to manipulate the configuration object
 */

var configUtils = {}

/* configUtils.isTruthy(thing, ...)
 * `thing` - An array of thing else that is evaluated
 * `...` - Arguments passed to functions inside `thing`
 */
configUtils.isTruthy = function isTruthy (thing/*, ...*/) {
  return _.every([].concat( this.execFuncs.apply(this, arguments) ))
}

/* configUtils.execFuncs(thing)
 * `thing` - A template's filename, function or a simple string of HTML
 * `...` - Arguments passed to the `thing` if it's a function
 * returns the rendered thing.
 */
configUtils.execFuncs = function execFuncs (thing/* ... */) {
  if(Array.isArray(thing)) {
    return thing.map(this.execFuncs.bind(this))
  } else if(typeof thing === 'function') {
    return thing.apply(null, _.rest(arguments))
  }
  return thing
}

/* configUtils.deepMerge(obj[, obj][, ...])
 * `obj` - An object
 */
configUtils.deepMerge = function deepMerge (/* arguments */) {
  return _.reduce(arguments, function (merged, config) {
    _.each(config, function (value, prop) {
      if(merged[prop] && Array.isArray(merged[prop])) {
        merged[prop] = merged[prop].concat(value)
      } else {
        merged[prop] = value
      }
    }, {})
    return merged
  })
}

_altboilerScope = _altboilerScope || {}
_altboilerScope.configUtils = configUtils
<commit_msg>Fix a bug in deep-merge<commit_after>/* configUtils.js
 * Defines an object that provides functions to manipulate the configuration object
 */

var configUtils = {}

/* configUtils.isTruthy(thing, ...)
 * `thing` - An array of thing else that is evaluated
 * `...` - Arguments passed to functions inside `thing`
 */
configUtils.isTruthy = function isTruthy (thing/*, ...*/) {
  return _.every([].concat( this.execFuncs.apply(this, arguments) ))
}

/* configUtils.execFuncs(thing)
 * `thing` - A template's filename, function or a simple string of HTML
 * `...` - Arguments passed to the `thing` if it's a function
 * returns the rendered thing.
 */
configUtils.execFuncs = function execFuncs (thing/* ... */) {
  if(Array.isArray(thing)) {
    return thing.map(this.execFuncs.bind(this))
  } else if(typeof thing === 'function') {
    return thing.apply(null, _.rest(arguments))
  }
  return thing
}

/* configUtils.deepMerge(obj[, obj][, ...])
 * `obj` - An object
 */
configUtils.deepMerge = function deepMerge (/* arguments */) {
  var returnVal = _.reduce(arguments, function (merged, config) {
    merged = _.clone(merged)
    _.each(config, function (value, prop) {
      console.log(prop)
      if(merged[prop] && Array.isArray(merged[prop])) {
        merged[prop] = merged[prop].concat(value)
      } else {
        merged[prop] = value
      }
    }, {})
    return merged
  })
  console.log(arguments[0].css, arguments[1].css)
  return returnVal
}

_altboilerScope = _altboilerScope || {}
_altboilerScope.configUtils = configUtils
<|endoftext|>


<commit_before>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

/* global chrome */

var _ = require('lodash');
var async = require('async');
var getIn = require('./getIn');

var serialDevice = require('../serialDevice');
var hidDevice = require('../hidDevice');
var driverManager = require('../driverManager');
var builder = require('../objectBuilder')();

var dexcomDriver = require('../drivers/dexcomDriver');
var oneTouchMiniDriver = require('../drivers/oneTouchMiniDriver');
var abbottPrecisionXtra = require('../drivers/abbottPrecisionXtra');
var tandemTslimDriver = require('../drivers/tandemTslimDriver');
var insuletOmniPod = require('../drivers/insuletDriver');
var oneTouchUltra2 = require('../drivers/oneTouchUltra2');
var abbottFreeStyleLite = require('../drivers/abbottFreeStyleLite');
var bayerContourNext = require('../drivers/bayerContourNext');

var device = {
  log: require('../bows')('Device')
};

device._deviceDrivers = {
  'DexcomG4': dexcomDriver,
  'OneTouchMini': oneTouchMiniDriver,
  'AbbottPrecisionXtra': abbottPrecisionXtra,
  'InsuletOmniPod': insuletOmniPod,
  'TandemTslim': tandemTslimDriver,
  'OneTouchUltra2': oneTouchUltra2,
  'AbbottFreeStyleLite': abbottFreeStyleLite,
  'AbbottFreeStyleFreedomLite': abbottFreeStyleLite,
  'BayerContourNext': bayerContourNext,
  'BayerContourNextUsb': bayerContourNext,
  'BayerContourUsb': bayerContourNext,
  'BayerContourNextLink': bayerContourNext
};

device._deviceComms = {
  'DexcomG4': serialDevice,
  'OneTouchMini': serialDevice,
  'AbbottPrecisionXtra': serialDevice,
  'OneTouchUltra2': serialDevice,
  'AbbottFreeStyleLite': serialDevice,
  'AbbottFreeStyleFreedomLite': serialDevice,
  'TandemTslim': serialDevice,
  'BayerContourNext': hidDevice,
  'BayerContourNextUsb': hidDevice,
  'BayerContourUsb': hidDevice,
  'BayerContourNextLink': hidDevice
};

device._silentComms = {};
_.forEach(_.keys(device._deviceComms), function(driverId) {

  var comm = device._deviceComms[driverId];
  device._silentComms[driverId] = comm({silent: true});
  device._deviceComms[driverId] = comm();
});

// this is a cache for device information
// we need it so that what we learn in detect()
// can be used by process().
device._deviceInfoCache = {};

device.init = function(options, cb) {
  var self=this;
  self._defaultTimezone = options.defaultTimezone;
  self._driverManifests = self._getAllDriverManifests();
  self._api = options.api;
  self._version = options.version;
  self._groupId = options.targetId;

  chrome.runtime.getPlatformInfo(function (platformInfo) {
    self._os = platformInfo.os;
    if (self._os == 'win') {
      self._portpattern = 'COM[0-9]+';
    } else {
      self._portpattern = '/dev/cu\\.usb.+';
    }
    cb();
  });

};

device._getAllDriverManifests = function() {
  var manifest = chrome.runtime.getManifest();

  var usbDevicesPermission = _.find(manifest.permissions, function(permission) {
    return permission.usbDevices;
  });
  return _.reduce(usbDevicesPermission.usbDevices, function(acc, usbDevice) {
    acc[usbDevice.driverId] = usbDevice;
    return acc;
  }, {});
};

device.getDriverManifests = function() {
  return _.cloneDeep(this._driverManifests);
};

device.getDriverIds = function() {
  return _.keys(this._driverManifests);
};

device.getDriverManifest = function(driverId) {
  var driverManifest = this._driverManifests[driverId];
  if (!driverManifest) {
    throw new Error('Could not find driver manifest for "' + driverId + '"');
  }
  return driverManifest;
};

device.detectHelper = function(driverId, options, cb) {
  // Detect can run on a loop, so don't pollute the console with logging
  options.silent = true;
  var dm = this._createDriverManager(driverId, options);
  dm.detect(driverId, cb);
};

device._createDriverManager = function(driverId, options) {
  var drivers = {};
  drivers[driverId] = this._deviceDrivers[driverId];
  var configs = {};
  configs[driverId] = this._createDriverConfig(driverId, options);

  return driverManager(drivers, configs);
};

device._createDriverConfig = function(driverId, options) {
  options = options || {};
  var timezone = options.timezone || this._defaultTimezone;
  var comms = options.silent ? this._silentComms : this._deviceComms;
  var theVersion = options.version || this._version;
  var uploadGroup = options.targetId || this._groupId;

  // handle config for block-mode devices, which includes the file name and data
  if (options.filename != null) {
    return {
      filename: options.filename,
      filedata: options.filedata,
      deviceInfo: this._deviceInfoCache[driverId],
      timezone: timezone,
      groupId: uploadGroup,
      api: this._api,
      version: options.version,
      builder: builder,
      progress: options.progress,
      silent: Boolean(options.silent)
    };
  }

  return {
    deviceInfo: this._deviceInfoCache[driverId],
    deviceComms: comms[driverId],
    timezone: timezone,
    groupId: uploadGroup,
    api: this._api,
    version: options.version,
    builder: builder,
    progress: options.progress,
    silent: Boolean(options.silent)
  };
};

device.detectHid = function(driverId, cb) {
  var self = this;
  var driverManifest = this.getDriverManifest(driverId);
  var identification = {
    vendorId: driverManifest.vendorId,
    productId: driverManifest.productId
  };
  chrome.hid.getDevices(identification, function(results) {
    var devices = _.map(results, function(result) {
      var retval = {
        driverId: driverId,
        deviceId: result.deviceId,
        vendorId: result.vendorId,
        productId: result.productId
      };

      if (self._os == 'win') {
        if (driverManifest.winPortPattern) {
          retval.portPattern = driverManifest.winPortPattern;
        }
      } else {
        if (driverManifest.macPortPattern) {
          retval.portPattern = driverManifest.macPortPattern;
        }
      }

      return retval;
    });

    var devdata = _.first(devices);

    if (devices.length > 1) {
      self.log('WARNING: More than one device found for "' + driverId + '"');
      device.othersConnected = devices.length - 1;
    }

    return cb(null, devdata);
  });
};

device.detectUsb = function(driverId, cb) {
  var self = this;
  var driverManifest = this.getDriverManifest(driverId);
  var identification = {
    vendorId: driverManifest.vendorId,
    productId: driverManifest.productId
  };
  chrome.serial.getDevices(function(results) {
    self.log('Connected device(s): ');
    for(var i in results) {
        self.log(results[i].path);
    }
    var devices = _.map(results, function(result) {
      var retval = {
        driverId: driverId,
        vendorId: driverManifest.vendorId,
        productId: driverManifest.productId,
        portPattern: self._portpattern,
        usbDevice: result.device
      };
      if (self._os == 'win') {
        if (driverManifest.winPortPattern) {
          retval.portPattern = driverManifest.winPortPattern;
        }
      } else {
        if (driverManifest.macPortPattern) {
          retval.portPattern = driverManifest.macPortPattern;
        }
      }
      if (!!driverManifest.bitrate) {
        retval.bitrate = driverManifest.bitrate;
      }
      return retval;
    });

    var devdata = _.first(devices);

    if (devices.length > 1) {
      self.log('WARNING: More than one device found for "' + driverId + '"');
      device.othersConnected = devices.length - 1;
    }
    return cb(null, devdata);
  });
};

device.detect = function(driverId, options, cb) {
  var self = this;
  if (_.isFunction(options)) {
    cb = options;
    options = { version: self._version };
  }
  var driverManifest = this.getDriverManifest(driverId);

  if(driverManifest.mode === 'HID'){
      this.detectHid(driverId, function(err, devdata) {

        if (err) {
          return cb(err);
        }

        if (!devdata) {
          return cb();
        }

        self._deviceInfoCache[driverId] = _.cloneDeep(devdata);
        self.detectHelper(driverId, options, function(err, ftdiDevice) {

          if (err) {
            return cb(err);
          }
          device = _.assign(devdata, ftdiDevice);
          return cb(null, devdata);
        });
      });

  }else{

    this.detectUsb(driverId, function(err, devdata) {

      if (err) {
        return cb(err);
      }

      if (!devdata) {
        return cb();
      }

      self._deviceInfoCache[driverId] = _.cloneDeep(devdata);
      self.detectHelper(driverId, options, function(err, ftdiDevice) {
        if (err) {
          return cb(err);
        }
        device = _.assign(devdata, ftdiDevice);
        return cb(null, devdata);
      });
    });
  }
};

device.detectAll = function(cb) {
  async.map(this.getDriverIds(), this.detect.bind(this), function(err, results) {
    if (err) {
      return cb(err);
    }
    // Filter out any nulls
    results = _.filter(results);
    cb(null, results);
  });
};

device.upload = function(driverId, options, cb) {
  var dm = this._createDriverManager(driverId, options);
  dm.process(driverId, function(err, result) {
    if (err) {
      return cb(err);
    }
    return cb(null, result.post_records);
  });
};

module.exports = device;
<commit_msg>passing through timeout values to deviceInfo<commit_after>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

/* global chrome */

var _ = require('lodash');
var async = require('async');
var getIn = require('./getIn');

var serialDevice = require('../serialDevice');
var hidDevice = require('../hidDevice');
var driverManager = require('../driverManager');
var builder = require('../objectBuilder')();

var dexcomDriver = require('../drivers/dexcomDriver');
var oneTouchMiniDriver = require('../drivers/oneTouchMiniDriver');
var abbottPrecisionXtra = require('../drivers/abbottPrecisionXtra');
var tandemTslimDriver = require('../drivers/tandemTslimDriver');
var insuletOmniPod = require('../drivers/insuletDriver');
var oneTouchUltra2 = require('../drivers/oneTouchUltra2');
var abbottFreeStyleLite = require('../drivers/abbottFreeStyleLite');
var bayerContourNext = require('../drivers/bayerContourNext');

var device = {
  log: require('../bows')('Device')
};

device._deviceDrivers = {
  'DexcomG4': dexcomDriver,
  'OneTouchMini': oneTouchMiniDriver,
  'AbbottPrecisionXtra': abbottPrecisionXtra,
  'InsuletOmniPod': insuletOmniPod,
  'TandemTslim': tandemTslimDriver,
  'OneTouchUltra2': oneTouchUltra2,
  'AbbottFreeStyleLite': abbottFreeStyleLite,
  'AbbottFreeStyleFreedomLite': abbottFreeStyleLite,
  'BayerContourNext': bayerContourNext,
  'BayerContourNextUsb': bayerContourNext,
  'BayerContourUsb': bayerContourNext,
  'BayerContourNextLink': bayerContourNext
};

device._deviceComms = {
  'DexcomG4': serialDevice,
  'OneTouchMini': serialDevice,
  'AbbottPrecisionXtra': serialDevice,
  'OneTouchUltra2': serialDevice,
  'AbbottFreeStyleLite': serialDevice,
  'AbbottFreeStyleFreedomLite': serialDevice,
  'TandemTslim': serialDevice,
  'BayerContourNext': hidDevice,
  'BayerContourNextUsb': hidDevice,
  'BayerContourUsb': hidDevice,
  'BayerContourNextLink': hidDevice
};

device._silentComms = {};
_.forEach(_.keys(device._deviceComms), function(driverId) {

  var comm = device._deviceComms[driverId];
  device._silentComms[driverId] = comm({silent: true});
  device._deviceComms[driverId] = comm();
});

// this is a cache for device information
// we need it so that what we learn in detect()
// can be used by process().
device._deviceInfoCache = {};

device.init = function(options, cb) {
  var self=this;
  self._defaultTimezone = options.defaultTimezone;
  self._driverManifests = self._getAllDriverManifests();
  self._api = options.api;
  self._version = options.version;
  self._groupId = options.targetId;

  chrome.runtime.getPlatformInfo(function (platformInfo) {
    self._os = platformInfo.os;
    if (self._os == 'win') {
      self._portpattern = 'COM[0-9]+';
    } else {
      self._portpattern = '/dev/cu\\.usb.+';
    }
    cb();
  });

};

device._getAllDriverManifests = function() {
  var manifest = chrome.runtime.getManifest();

  var usbDevicesPermission = _.find(manifest.permissions, function(permission) {
    return permission.usbDevices;
  });
  return _.reduce(usbDevicesPermission.usbDevices, function(acc, usbDevice) {
    acc[usbDevice.driverId] = usbDevice;
    return acc;
  }, {});
};

device.getDriverManifests = function() {
  return _.cloneDeep(this._driverManifests);
};

device.getDriverIds = function() {
  return _.keys(this._driverManifests);
};

device.getDriverManifest = function(driverId) {
  var driverManifest = this._driverManifests[driverId];
  if (!driverManifest) {
    throw new Error('Could not find driver manifest for "' + driverId + '"');
  }
  return driverManifest;
};

device.detectHelper = function(driverId, options, cb) {
  // Detect can run on a loop, so don't pollute the console with logging
  options.silent = true;
  var dm = this._createDriverManager(driverId, options);
  dm.detect(driverId, cb);
};

device._createDriverManager = function(driverId, options) {
  var drivers = {};
  drivers[driverId] = this._deviceDrivers[driverId];
  var configs = {};
  configs[driverId] = this._createDriverConfig(driverId, options);

  return driverManager(drivers, configs);
};

device._createDriverConfig = function(driverId, options) {
  options = options || {};
  var timezone = options.timezone || this._defaultTimezone;
  var comms = options.silent ? this._silentComms : this._deviceComms;
  var theVersion = options.version || this._version;
  var uploadGroup = options.targetId || this._groupId;

  // handle config for block-mode devices, which includes the file name and data
  if (options.filename != null) {
    return {
      filename: options.filename,
      filedata: options.filedata,
      deviceInfo: this._deviceInfoCache[driverId],
      timezone: timezone,
      groupId: uploadGroup,
      api: this._api,
      version: options.version,
      builder: builder,
      progress: options.progress,
      silent: Boolean(options.silent)
    };
  }

  return {
    deviceInfo: this._deviceInfoCache[driverId],
    deviceComms: comms[driverId],
    timezone: timezone,
    groupId: uploadGroup,
    api: this._api,
    version: options.version,
    builder: builder,
    progress: options.progress,
    silent: Boolean(options.silent)
  };
};

device.detectHid = function(driverId, cb) {
  var self = this;
  var driverManifest = this.getDriverManifest(driverId);
  var identification = {
    vendorId: driverManifest.vendorId,
    productId: driverManifest.productId
  };
  chrome.hid.getDevices(identification, function(results) {
    var devices = _.map(results, function(result) {
      var retval = {
        driverId: driverId,
        deviceId: result.deviceId,
        vendorId: result.vendorId,
        productId: result.productId
      };

      if (self._os == 'win') {
        if (driverManifest.winPortPattern) {
          retval.portPattern = driverManifest.winPortPattern;
        }
      } else {
        if (driverManifest.macPortPattern) {
          retval.portPattern = driverManifest.macPortPattern;
        }
      }

      return retval;
    });

    var devdata = _.first(devices);

    if (devices.length > 1) {
      self.log('WARNING: More than one device found for "' + driverId + '"');
      device.othersConnected = devices.length - 1;
    }

    return cb(null, devdata);
  });
};

device.detectUsb = function(driverId, cb) {
  var self = this;
  var driverManifest = this.getDriverManifest(driverId);
  var identification = {
    vendorId: driverManifest.vendorId,
    productId: driverManifest.productId
  };
  chrome.serial.getDevices(function(results) {
    self.log('Connected device(s): ');
    for(var i in results) {
        self.log(results[i].path);
    }
    var devices = _.map(results, function(result) {
      var retval = {
        driverId: driverId,
        vendorId: driverManifest.vendorId,
        productId: driverManifest.productId,
        portPattern: self._portpattern,
        usbDevice: result.device
      };
      if (self._os == 'win') {
        if (driverManifest.winPortPattern) {
          retval.portPattern = driverManifest.winPortPattern;
        }
      } else {
        if (driverManifest.macPortPattern) {
          retval.portPattern = driverManifest.macPortPattern;
        }
      }
      if (!!driverManifest.bitrate) {
        retval.bitrate = driverManifest.bitrate;
      }
      if (!!driverManifest.sendTimeout) {
        retval.sendTimeout = driverManifest.sendTimeout;
      }
      if(!!driverManifest.receiveTimeout) {
        retval.receiveTimeout = driverManifest.receiveTimeout;
      }
      return retval;
    });

    var devdata = _.first(devices);

    if (devices.length > 1) {
      self.log('WARNING: More than one device found for "' + driverId + '"');
      device.othersConnected = devices.length - 1;
    }
    return cb(null, devdata);
  });
};

device.detect = function(driverId, options, cb) {
  var self = this;
  if (_.isFunction(options)) {
    cb = options;
    options = { version: self._version };
  }
  var driverManifest = this.getDriverManifest(driverId);

  if(driverManifest.mode === 'HID'){
      this.detectHid(driverId, function(err, devdata) {

        if (err) {
          return cb(err);
        }

        if (!devdata) {
          return cb();
        }

        self._deviceInfoCache[driverId] = _.cloneDeep(devdata);
        self.detectHelper(driverId, options, function(err, ftdiDevice) {

          if (err) {
            return cb(err);
          }
          device = _.assign(devdata, ftdiDevice);
          return cb(null, devdata);
        });
      });

  }else{

    this.detectUsb(driverId, function(err, devdata) {

      if (err) {
        return cb(err);
      }

      if (!devdata) {
        return cb();
      }

      self._deviceInfoCache[driverId] = _.cloneDeep(devdata);
      self.detectHelper(driverId, options, function(err, ftdiDevice) {
        if (err) {
          return cb(err);
        }
        device = _.assign(devdata, ftdiDevice);
        return cb(null, devdata);
      });
    });
  }
};

device.detectAll = function(cb) {
  async.map(this.getDriverIds(), this.detect.bind(this), function(err, results) {
    if (err) {
      return cb(err);
    }
    // Filter out any nulls
    results = _.filter(results);
    cb(null, results);
  });
};

device.upload = function(driverId, options, cb) {
  var dm = this._createDriverManager(driverId, options);
  dm.process(driverId, function(err, result) {
    if (err) {
      return cb(err);
    }
    return cb(null, result.post_records);
  });
};

module.exports = device;
<|endoftext|>


<commit_before>var mesh-slice-polygon = function() {

}

if (typeof module !== "undefined" && typeof module.exports == "object") {
  module.exports = mesh-slice-polygon;
}

if (typeof window !== "undefined") {
  window.mesh-slice-polygon = window.mesh-slice-polygon || mesh-slice-polygon;
}
<commit_msg>functional<commit_after>(function() {
  function Vertex(x, y, z) {
    if (x instanceof Float32Array) {
      this.position = x;
    } else if (Array.isArray(x)) {
      this.position = vec3.fromValues(x[0], x[1], x[2]);
    } else {
      this.position = vec3.fromValues(x, y, z);
    }

    this.id = Vertex.id++;
  }

  Vertex.id = 0;

  Vertex.toString = function(x, y, z) {
    if (x instanceof Float32Array) {
      return '(' + [x[0], x[1], x[2]].join(',') + ')'
    } else {
      if (!Array.isArray(x)) {
        x = [x, y, z];
      }
      return '(' + x.join(',') + ')'
    }
  };

  Vertex.prototype = {
    near : function(vert, threshold) {
      return vec3.dist(this.position, vert.position) < (threshold || 0.1)
    },

    toString : function() {
      return Vertex.toString(this.position);
    }
  };

  function Triangle(a, b, c, normal) {
    this.verts = [a, b, c];
    this.normal = normal;

    this.sortByZ();
    this.id = Triangle.id++;
  }

  Triangle.id = 0;

  Triangle.prototype.sortByZAscending = function(a, b) {
    return a.position[2] > b.position[2] ? -1 : 1;
  };

  Triangle.prototype.sortByZ = function() {
    // TODO SORT: reverse sort if milling/printing
    this.verts.sort(this.sortByZAscending);
  };

  Triangle.prototype.toString = function() {
    return '[' + this.id + ':' + [this.verts[0].id, this.verts[1].id, this.verts[2].id].join(',') + ']';
  };

  function ZPlane(sliceZ) {
    this.position = vec3.fromValues(0,0,sliceZ);
    this.normal = vec3.fromValues(0, 0, 1);
  }

  ZPlane.prototype.intersect = function(start, end) {
    var tmp = vec3.fromValues(0, 0, 0)
    var num = vec3.dot(
      this.normal,
      vec3.subtract(
        vec3.fromValues(0, 0, 0),
        this.position,
        start.position
      )
    );

    var line = vec3.subtract(
      vec3.fromValues(0, 0, 0),
      end.position,
      start.position
    );

    var den = vec3.dot(this.normal,line);

    var res = num/den;
    if (!isNaN(res) && 0 <= res && res <= 1.0) {
      var isect = vec3.add(
        vec3.fromValues(0, 0, 0),
        start.position,
        vec3.multiply(
          vec3.fromValues(0, 0, 0),
          line,
          vec3.fromValues(res, res, res)
        )
      );

      return isect;
    }
  };

  function MeshSlicePolygon() {
    this.plane = new ZPlane(sliceZ)
    this.seenVerts = {};
    this.sharedTriangles = {};
    this.triangles = [];
    this.bounds = {
      max : [-Infinity, -Infinity, -Infinity],
      min : [Infinity, Infinity, Infinity]
    };

    this.groups = [];
    this.group = [];
  }

  MeshSlicePolygon.prototype.trackBounds = function(coords) {
    var bounds = this.bounds;

    for (var i = 0; i<3; i++) {
      if (coords[i] > bounds.max[i]) {
        bounds.max[i] = coords[i];
      }

      if (coords[i] < bounds.min[i]) {
        bounds.min[i] = coords[i];
      }
    }
  };

  MeshSlicePolygon.prototype.upsertVert = function(x, y, z) {
    var key = Vertex.toString(x, y, z);

    if (!this.seenVerts[key]) {
      this.seenVerts[key] = new Vertex(x, y, z);
      this.trackBounds(this.seenVerts[key].position);
    }

    return this.seenVerts[key];
  }

  MeshSlicePolygon.prototype.sharedTriangle = function(a, b, ignore) {
    var aa = this.sharedTriangles[a.id];
    var ab = this.sharedTriangles[b.id];

    for (var i = 0; i<aa.length; i++) {
      var ai = aa[i];
      for (var j = 0; j<ab.length; j++) {
        if (ai.id === ab[j].id && ignore.indexOf(ai.id) === -1) {
          return ai;
        }
      }
    }

    return false;
  };

  MeshSlicePolygon.prototype.addTriangle = function(a, b, c) {
    this.dirty = true;
    var a = this.upsertVert(a[0], a[1], a[2]);
    var b = this.upsertVert(b[0], b[1], b[2]);
    var c = this.upsertVert(c[0], c[1], c[2]);

    var triangle = new Triangle(a, b, c);

    // TODO: we don't really need a loop here...

    [a, b, c].forEach(function(vertex) {
      if (!this.sharedTriangles[vertex.id]) {
        this.sharedTriangles[vertex.id] = [];
      }

      this.sharedTriangles[vertex.id].push(triangle);
    }.bind(this));

    this.triangles.push(triangle);
  };

  var sortShared = function(a, b) {
    return (a.id > b.id) ? -1 : 1;
  };

  MeshSlicePolygon.prototype.sort = function() {
    Object.keys(this.sharedTriangles).forEach(function(key) {
      this.sharedTriangles[key].sort(sortShared);
    }.bind(this));

    this.triangles.sort(function(a, b) {
      return (a.verts[0].position[2] < b.verts[0].position[2]) ? -1 : 1;
    });
  };

  var isectTests = [[0,1], [0, 2], [1, 2]];

  MeshSlicePolygon.prototype.followIntersectionChain = function(tri, startTri) {
    this.group = [];
    var last = startTri;
    while (tri) {

      if (this.seenTriangles[tri.id]) {
        break;
      }

      this.seenTriangles[tri.id] = true;

      var isects = [];
      for (var i=0; i<isectTests.length; i++) {
        var test = isectTests[i];
        var isect = this.plane.intersect(tri.verts[test[0]], tri.verts[test[1]])
        if (isect) {
          var vert = this.upsertVert(isect);
          vert.shared = test;
          isects.push(vert);
        }
      }

      if (isects.length === 3) {
        console.log('PARALLEL',
          this.sharedTriangles[tri.verts[0].id].length,
          this.sharedTriangles[tri.verts[1].id].length,
          this.sharedTriangles[tri.verts[2].id].length
        );
        break;
      } else if (isects.length === 2) {
        this.group.push(isects[0]);

        var shared = this.sharedTriangle(
          tri.verts[isects[0].shared[0]],
          tri.verts[isects[0].shared[1]],
          [tri.id, last, startTri]
        );

        if (!shared) {
          shared = this.sharedTriangle(
            tri.verts[isects[1].shared[0]],
            tri.verts[isects[1].shared[1]],
            [tri.id, last, startTri]
          );
        }

        if (shared && shared.id !== tri.id && shared.id !== startTri) {
          last = tri.id;
          tri = shared;
        } else {
          if (this.group.length > 0) {
            this.groups.push(this.group);
            this.group = [];
          }
          break;
        }
      } else {
        break;
      }
    }
  };

  MeshSlicePolygon.prototype.slice = function(z) {
    this.plane.position[2] = z;

    if (this.dirty) {
      this.dirty = false;
      this.sort();
    }

    var l = this.triangles.length;
    this.groups = [];
    this.group = [];

    this.seenTriangles = {};
    while (l--) {
      var startTri = this.triangles[l].id;

      if (!this.seenTriangles[startTri]) {
        var triVerts = this.triangles[l].verts;

        if (triVerts[0].position[2] >= z) {
          this.followIntersectionChain(this.triangles[l], startTri);
        } else {
          break;
        }
      }
    }

    return this.groups;
  };

  if (typeof module !== "undefined" && typeof module.exports == "object") {
    module.exports = MeshSlicePolygon;
  }

  if (typeof window !== "undefined") {
    window.MeshSlicePolygon = window.MeshSlicePolygon || MeshSlicePolygon;
  }
})()<|endoftext|>


<commit_before>//POPULATE the Dropdown of Collections

var tm_containerSlideUp = 0;
var selectCollectionItem = function(index){
	clearTimeout(tm_containerSlideUp);
	$('.collectionItem').removeClass('collectionItemClicked');
	$('.collectionItem').eq(index).addClass('collectionItemClicked');
	tm_containerSlideUp = setTimeout(function(){
		toggleCollections(100);
	},100);
};

var collectionsButtonClicked = false;

var toggleCollections = function(slidespeed = 50){
	var button = $('#btnCollections');
	var container = $('#collectionsContainer');

	if(collectionsButtonClicked==false){
		button.toggleClass('pressed');
		button.children('span').html('🔺');
		//button.css({backgroundColor:'gray'});
		container.slideDown(slidespeed);

		$('.spacer#top').animate({height:'130px'},slidespeed);
		collectionsButtonClicked = true;
	}
	else{
		button.toggleClass('pressed');
		button.children('span').html('🔻');
		//button.css({backgroundColor:'black'});
		container.slideUp(slidespeed);
		$('.spacer#top').animate({height:'90px'},slidespeed);
		collectionsButtonClicked = false;
	}
}

var teaseSlideBackTimeout = 0;
var popDropdown = function(){

		/*$("#dropdown").html("");
		for(var c in collections){
				$("#dropdown").append("<option>"+collections[c]+"</option>");

		}
		$("#dropdown").append("<option>new collection...</option>");

		document.getElementById("dropdown").selectedIndex=dbIndex;*/

		// New Code:

		var container = $('#collectionsContainer');

		container.html("");
		for(var c in collections){
			$(container).append(''+collections[c]+'');
		}
		// bind click event to collectionItems:
		$('.collectionItem').on('click',function(){
			selectCollectionItem($(this).index());
			changeCollection($(this).index());
		});

		// append "new collection" button to the end:
		$(container).append('+');

		$(selectCollectionItem(dbIndex)); // select the collectionItem corresponding to the current dbIndex

		//bind new collection button click event
		$('#btnNewCollection').on('click',function(){
			newCollection();
		});

};

// CHANGE the current collection
var changeCollection=function(new_index){
	dbIndex = new_index;

	imageDB = DATABASE[dbIndex];
	$("#collectionTitleSpan").html(collections[dbIndex]);
	document.title = collections[dbIndex];
	localStorage.setItem("last_visited_index",dbIndex); // saves the state AKA the last collection you had open
	if(imageDB==null || typeof imageDB=='undefined'){
		imageDB = [];
	}
	applyChanges();
	List(true); // with animations
	$('#txtInput').focus();
};

//CREATE a NEW collection

var newCollection = function(){
	var new_collection;
	new_collection = prompt("Enter a name for your new collection","","New image collection");

	// if its bad input, just do nothing:
	if(new_collection==""||new_collection==null){ // force the user to give the collection a name
			//$('#dropdown').prop("selectedIndex",(localStorage.getItem("last_visited_index"))); // a little trick to jump back out of the "new collection..." menu item
			$('#btnCollections').click();
			return;
	}
	collections.push(new_collection); // add new collection
	localStorage.setItem("collection_names",JSON.stringify(collections)); // update the list of collection names ;
	popDropdown();
	changeCollection(collections.length-1); // Switch over to the new collection

};

// DELETE a collection
var deleteCollection=function(){
	var really = confirm("Are you sure you want to delete '"+collections[dbIndex]+"'?");
		if (collections.length>1){
			if(really){
				var new_deleted = {
					restoreType:"deleted_collection",
					index:dbIndex,
					collectionName:collections[dbIndex],
					collectionContent:imageDB
				};
				_history.push(new_deleted); // push the new _history state for undo
				DATABASE.splice(dbIndex,1); //delete the collection from DATABASE
				collections.splice(dbIndex,1); // remove its name from collection_names
				localStorage.setItem("collection_names",JSON.stringify(collections));
				localStorage.setItem("imageDB",JSON.stringify(DATABASE));
				changeCollection(dbIndex-1); // Now that this doesn't exist, go back 1 collection
				popDropdown(); // refresh the dropdown of collections

				setTimeout(notify('"' + new_deleted.collectionName + '" deleted',"warning"),100);
				return;

			}
			else{
				return;
			}
		}
		else{
			alert("Must have one collection"); // this is to preserve the indexing of collections
		}
};

var renameCollection = function(newname){

	var new_name = $('#txtRenameCollection').val();
		var old_name = collections[dbIndex];
		// change collection name only if new name is a an actual name and not the old name
		if(new_name !== "" && new_name !== null && new_name !== old_name){
			collections[dbIndex] = new_name;
			localStorage.setItem("collection_names",JSON.stringify(collections));
			popDropdown();
			changeCollection(dbIndex);

			//notification
			notify('Renamed "' + old_name + '" to "' + new_name + '"',"good");
			// store old collection name in _history
			_history.push({restoreType:"collection_name",collection_index:dbIndex,name:old_name});
		}
}

$(function(){
	$(document).mouseup(function (e)
{
    var container = $("#collectionsContainer");
	var button = $('#btnCollections');

    if (!container.is(e.target) && container.has(e.target).length === 0 && !button.is(e.target) && button.has(e.target).length === 0){
		if(container.css('display')!=='none'){
			toggleCollections();
		}
    }
});
});<commit_msg>changed alert to nofity('warning')<commit_after>//POPULATE the Dropdown of Collections

var tm_containerSlideUp = 0;
var selectCollectionItem = function(index){
	clearTimeout(tm_containerSlideUp);
	$('.collectionItem').removeClass('collectionItemClicked');
	$('.collectionItem').eq(index).addClass('collectionItemClicked');
	tm_containerSlideUp = setTimeout(function(){
		toggleCollections(100);
	},100);
};

var collectionsButtonClicked = false;

var toggleCollections = function(slidespeed = 50){
	var button = $('#btnCollections');
	var container = $('#collectionsContainer');

	if(collectionsButtonClicked==false){
		button.toggleClass('pressed');
		button.children('span').html('🔺');
		//button.css({backgroundColor:'gray'});
		container.slideDown(slidespeed);

		$('.spacer#top').animate({height:'130px'},slidespeed);
		collectionsButtonClicked = true;
	}
	else{
		button.toggleClass('pressed');
		button.children('span').html('🔻');
		//button.css({backgroundColor:'black'});
		container.slideUp(slidespeed);
		$('.spacer#top').animate({height:'90px'},slidespeed);
		collectionsButtonClicked = false;
	}
}

var teaseSlideBackTimeout = 0;
var popDropdown = function(){

		/*$("#dropdown").html("");
		for(var c in collections){
				$("#dropdown").append("<option>"+collections[c]+"</option>");

		}
		$("#dropdown").append("<option>new collection...</option>");

		document.getElementById("dropdown").selectedIndex=dbIndex;*/

		// New Code:

		var container = $('#collectionsContainer');

		container.html("");
		for(var c in collections){
			$(container).append(''+collections[c]+'');
		}
		// bind click event to collectionItems:
		$('.collectionItem').on('click',function(){
			selectCollectionItem($(this).index());
			changeCollection($(this).index());
		});

		// append "new collection" button to the end:
		$(container).append('+');

		$(selectCollectionItem(dbIndex)); // select the collectionItem corresponding to the current dbIndex

		//bind new collection button click event
		$('#btnNewCollection').on('click',function(){
			newCollection();
		});

};

// CHANGE the current collection
var changeCollection=function(new_index){
	dbIndex = new_index;

	imageDB = DATABASE[dbIndex];
	$("#collectionTitleSpan").html(collections[dbIndex]);
	document.title = collections[dbIndex];
	localStorage.setItem("last_visited_index",dbIndex); // saves the state AKA the last collection you had open
	if(imageDB==null || typeof imageDB=='undefined'){
		imageDB = [];
	}
	applyChanges();
	List(true); // with animations
	$('#txtInput').focus();
};

//CREATE a NEW collection

var newCollection = function(){
	var new_collection;
	new_collection = prompt("Enter a name for your new collection","","New image collection");

	// if its bad input, just do nothing:
	if(new_collection==""||new_collection==null){ // force the user to give the collection a name
			//$('#dropdown').prop("selectedIndex",(localStorage.getItem("last_visited_index"))); // a little trick to jump back out of the "new collection..." menu item
			$('#btnCollections').click();
			return;
	}
	collections.push(new_collection); // add new collection
	localStorage.setItem("collection_names",JSON.stringify(collections)); // update the list of collection names ;
	popDropdown();
	changeCollection(collections.length-1); // Switch over to the new collection

};

// DELETE a collection
var deleteCollection=function(){
	var really = confirm("Are you sure you want to delete '"+collections[dbIndex]+"'?");
		if (collections.length>1){
			if(really){
				var new_deleted = {
					restoreType:"deleted_collection",
					index:dbIndex,
					collectionName:collections[dbIndex],
					collectionContent:imageDB
				};
				_history.push(new_deleted); // push the new _history state for undo
				DATABASE.splice(dbIndex,1); //delete the collection from DATABASE
				collections.splice(dbIndex,1); // remove its name from collection_names
				localStorage.setItem("collection_names",JSON.stringify(collections));
				localStorage.setItem("imageDB",JSON.stringify(DATABASE));
				changeCollection(dbIndex-1); // Now that this doesn't exist, go back 1 collection
				popDropdown(); // refresh the dropdown of collections

				setTimeout(notify('"' + new_deleted.collectionName + '" deleted',"warning"),100);
				return;

			}
			else{
				notify('Must have at least 1 collection!','warning');
				return;
			}
		}
		else{
			notify("Must have one collection"); // this is to preserve the indexing of collections
		}
};

var renameCollection = function(newname){

	var new_name = $('#txtRenameCollection').val();
		var old_name = collections[dbIndex];
		// change collection name only if new name is a an actual name and not the old name
		if(new_name !== "" && new_name !== null && new_name !== old_name){
			collections[dbIndex] = new_name;
			localStorage.setItem("collection_names",JSON.stringify(collections));
			popDropdown();
			changeCollection(dbIndex);

			//notification
			notify('Renamed "' + old_name + '" to "' + new_name + '"',"good");
			// store old collection name in _history
			_history.push({restoreType:"collection_name",collection_index:dbIndex,name:old_name});
		}
}

$(function(){
	$(document).mouseup(function (e)
{
    var container = $("#collectionsContainer");
	var button = $('#btnCollections');

    if (!container.is(e.target) && container.has(e.target).length === 0 && !button.is(e.target) && button.has(e.target).length === 0){
		if(container.css('display')!=='none'){
			toggleCollections();
		}
    }
});
});<|endoftext|>