<commit_before>(function(window, document) {
'use strict';

// Public API
window.containerQueries = {
	reprocess: reprocess,
	reparse: reparse,
	reevaluate: reevaluate,
};

// Reprocess now
setTimeout(reprocess);

window.addEventListener('DOMContentLoaded', reprocess);
window.addEventListener('load', reprocess);
window.addEventListener('resize', reevaluate);

var SELECTOR_REGEXP = /:container\(\s*(?:min|max)-(?:width|height)\s*:\s*[^)]+\s*\)/gi;
var SELECTOR_ESCAPED_REGEXP = /\.\\:container\\\(\s*((?:min|max)-(?:width|height))\s*\\:\s*([^)]+?)\s*\\\)/gi;
var ESCAPE_REGEXP = /[:()]/g;
var SPACE_REGEXP = / /g;
var LENGTH_REGEXP = /^-?(?:\d*\.)?\d+(?:em|ex|ch|rem|vh|vw|vmin|vmax|px|mm|cm|in|pt|pc)$/i;
var URL_VALUE_REGEXP = /url\(\s*(?:(["'])(.*?)\1|([^)\s]*))\s*\)/gi;
var ATTR_REGEXP = /\[.+?\]/g;
var PSEUDO_NOT_REGEXP = /:not\(/g;
var ID_REGEXP = /#[^\[\]\\!"#$%&'()*+,./:;<=>?@^`{|}~-]+/g;
var CLASS_REGEXP = /\.[^\[\]\\!"#$%&'()*+,./:;<=>?@^`{|}~-]+/g;
var PSEUDO_ELEMENT_REGEXP = /::[^\[\]\\!"#$%&'()*+,./:;<=>?@^`{|}~-]+/g;
var PSEUDO_CLASS_REGEXP = /:[^\[\]\\!"#$%&'()*+,./:;<=>?@^`{|}~-]+/g;
var ELEMENT_REGEXP = /[a-z-]+/gi;

var queries;
var containerCache;
var processed = false;
var parsed = false;

function reprocess() {
	preprocess(function() {
		processed = true;
		reparse();
	});
}
function reparse() {
	if (!processed) {
		return reprocess();
	}
	parseRules();
	parsed = true;
	reevaluate();
}
function reevaluate() {
	if (!parsed) {
		return reparse();
	}
	updateClasses();
}

function preprocess(callback) {
	var sheets = document.styleSheets;
	if (!sheets.length) {
		callback();
		return;
	}
	var done = 0;
	for (var i = 0, length = sheets.length; i < length; i++) {
		preprocessSheet(sheets[i], function() {
			done++;
			if (done === length) {
				callback();
			}
		});
	}
}

function preprocessSheet(sheet, callback) {
	if (sheet.disabled) {
		callback();
		return;
	}
	var tag = sheet.ownerNode && sheet.ownerNode.tagName;
	if (tag === 'LINK') {
		loadExternal(sheet.ownerNode.href, function(cssText) {
			// Check again because loadExternal is async
			if (sheet.disabled) {
				callback();
				return;
			}
			cssText = fixRelativeUrls(cssText, sheet.ownerNode.href);
			preprocessStyle(sheet.ownerNode, cssText);
			callback();
		});
	}
	else if (tag === 'STYLE') {
		preprocessStyle(sheet.ownerNode, sheet.ownerNode.innerHTML);
		callback();
	}
	else {
		callback();
	}
}

function loadExternal(href, callback) {
	var xhr = new window.XMLHttpRequest();
	xhr.open('GET', href);
	xhr.onreadystatechange = function() {
		if (xhr.readyState !== 4) {
			return;
		}
		callback(xhr.status === 200 ? xhr.responseText : '');
	};
	xhr.send();
}

function fixRelativeUrls(cssText, href) {
	var base = new URL(href, document.baseURI);
	return cssText.replace(URL_VALUE_REGEXP, function(match, quote, url1, url2) {
		var url = url1 || url2;
		if (!url) {
			return match;
		}
		return 'url(' + (quote || '"') + new URL(url, base).href + (quote || '"') + ')';
	});
}

function preprocessStyle(node, cssText) {
	var found = false;
	cssText = cssText.replace(SELECTOR_REGEXP, function(selector) {
		found = true;
		return '.' + selector.replace(SPACE_REGEXP, '').replace(ESCAPE_REGEXP, '\\$&');
	});
	if (!found) {
		return;
	}
	var style = document.createElement('style');
	style.textContent = cssText;
	style.media = node.media;
	node.parentNode.insertBefore(style, node);
	node.disabled = true;
}

function parseRules() {
	queries = {};
	var sheets = document.styleSheets;
	var rules;
	for (var i = 0; i < sheets.length; i++) {
		if (sheets[i].disabled) {
			continue;
		}
		try {
			rules = sheets[i].cssRules;
		}
		catch(e) {
			continue;
		}
		for (var j = 0; j < rules.length; j++) {
			parseRule(rules[j]);
		}
	}
}

function parseRule(rule) {
	if (rule.cssRules) {
		for (var i = 0; i < rule.cssRules.length; i++) {
			parseRule(rule.cssRules[i]);
		}
		return;
	}
	if (rule.type !== 1) {
		return;
	}
	splitSelectors(rule.selectorText).forEach(function(selector) {
		if (selector.search(SELECTOR_ESCAPED_REGEXP) !== -1) {
			selector.replace(SELECTOR_ESCAPED_REGEXP, function(match, type, value, offset) {
				var precedingSelector = selector.substr(0, offset);
				if (!precedingSelector.substr(-1).trim()) {
					precedingSelector += '*';
				}
				queries[precedingSelector + match.toLowerCase()] = {
					selector: precedingSelector,
					prop: type.split('-')[1].toLowerCase(),
					type: type.split('-')[0].toLowerCase(),
					value: value,
					className: match.toLowerCase().substr(1).replace(/\\(.)/g, '$1'),
				};
			});
		}
	});
}

function splitSelectors(selectors) {
	// TODO: Fix complex selectors like fo\,o[attr="val,u\"e"]
	return selectors.split(/\s*,\s*/);
}

function updateClasses() {
	containerCache = new Map();
	eachQuery(function(query) {
		var elements = document.querySelectorAll(query.selector);
		for (var i = 0; i < elements.length; i++) {
			updateClass(elements[i], query);
		}
	});
}

function updateClass(element, query) {
	var container = getContainer(element.parentNode, query.prop);
	var size = getSize(container, query.prop);
	var value = parseFloat(query.value);
	if (
		(query.type === 'min' && size >= value)
		|| (query.type === 'max' && size <= value)
	) {
		element.classList.add(query.className);
	}
	else {
		element.classList.remove(query.className);
	}
}

function getContainer(element, prop) {

	var cache;
	if (containerCache.has(element)) {
		cache = containerCache.get(element);
		if (cache.container[prop]) {
			return cache.container[prop];
		}
	}
	else {
		cache = {
			container: {},
		};
		containerCache.set(element, cache);
	}

	if (element === document.documentElement) {
		cache.container[prop] = element;
	}

	// Skip inline elements
	else if (window.getComputedStyle(element).display === 'inline') {
		cache.container[prop] = getContainer(element.parentNode, prop);
	}

	else if (isFixedSize(element, prop)) {
		cache.container[prop] = element;
	}

	else {
		var parentContainer = getContainer(element.parentNode, prop);
		var chain = [];
		for (var node = element; node !== parentContainer; node = node.parentNode) {
			// Skip inline elements
			if (window.getComputedStyle(node).display !== 'inline') {
				chain.unshift(node);
			}
		}
		for (var i = 0; i < chain.length; i++) {
			if (isIntrinsicSize(chain[i], prop)) {
				break;
			}
		}
		if (i) {
			cache.container[prop] = chain[i - 1];
		}
		else {
			cache.container[prop] = parentContainer;
		}
	}

	return cache.container[prop];

}

function isFixedSize(element, prop) {
	var originalStyle = getOriginalStyle(element, [prop]);
	if (originalStyle[prop] && originalStyle[prop].search(LENGTH_REGEXP) !== -1) {
		return true;
	}
}

function isIntrinsicSize(element, prop) {

	var computedStyle = window.getComputedStyle(element);

	if (computedStyle.display === 'none') {
		return false;
	}

	if (computedStyle.display === 'inline') {
		return true;
	}

	// Non-floating non-absolute block elements (only width)
	if (
		prop === 'width'
		&& ['block', 'list-item', 'flex', 'grid'].indexOf(computedStyle.display) !== -1
		&& computedStyle.float === 'none'
		&& computedStyle.position !== 'absolute'
		&& computedStyle.position !== 'fixed'
	) {
		return false;
	}

	var originalStyle = getOriginalStyle(element, [prop]);

	// Fixed size
	if (originalStyle[prop] && originalStyle[prop].search(LENGTH_REGEXP) !== -1) {
		return false;
	}

	// Percentage size
	if (originalStyle[prop] && originalStyle[prop].substr(-1) === '%') {
		return false;
	}

	// Elements without a defined size
	return true;

}

function getSize(element, prop) {
	var style = window.getComputedStyle(element);
	if (prop === 'width') {
		return element.offsetWidth
			- parseFloat(style.borderLeftWidth)
			- parseFloat(style.paddingLeft)
			- parseFloat(style.borderRightWidth)
			- parseFloat(style.paddingRight);
	}
	else if (prop === 'height') {
		return element.offsetHeight
			- parseFloat(style.borderTopWidth)
			- parseFloat(style.paddingTop)
			- parseFloat(style.borderBottomWidth)
			- parseFloat(style.paddingBottom);
	}
	return 0;
}

function getOriginalStyle(element, props) {

	var matchedRules = [];
	var sheets = document.styleSheets;
	var rules;
	var result = {};
	var i, j;

	for (i = 0; i < sheets.length; i++) {
		if (sheets[i].disabled) {
			continue;
		}
		try {
			rules = sheets[i].cssRules;
		}
		catch(e) {
			continue;
		}
		matchedRules = matchedRules.concat(filterRulesByElementAndProps(rules, element, props));
	}

	matchedRules = sortRulesBySpecificity(matchedRules);

	// Add style attribute
	matchedRules.unshift({
		rule: {
			style: element.style,
		},
	});

	for (i = 0; i < props.length; i++) {
		for (j = 0; j < matchedRules.length; j++) {
			if (
				matchedRules[j].rule.style.getPropertyValue(props[i])
				&& matchedRules[j].rule.style.getPropertyPriority(props[i]) === 'important'
			) {
				result[props[i]] = matchedRules[j].rule.style.getPropertyValue(props[i]);
				break;
			}
		}
	}

	for (i = 0; i < props.length; i++) {
		// Skip if an !important rule already matched
		if (result[props[i]]) {
			continue;
		}
		for (j = 0; j < matchedRules.length; j++) {
			if (
				matchedRules[j].rule.style.getPropertyValue(props[i])
				&& matchedRules[j].rule.style.getPropertyPriority(props[i]) !== 'important'
			) {
				result[props[i]] = matchedRules[j].rule.style.getPropertyValue(props[i]);
				break;
			}
		}
	}

	return result;

}

function filterRulesByElementAndProps(rules, element, props) {
	var matchedRules = [];
	for (var i = 0; i < rules.length; i++) {
		if (rules[i].cssRules) {
			matchedRules = matchedRules.concat(filterRulesByElementAndProps(rules[i].cssRules, element, props));
		}
		else if (rules[i].type === 1) { // Style rule
			if (
				styleHasProperty(rules[i].style, props)
				&& (
					!rules[i].parentRule
					|| rules[i].parentRule.type !== 4 // @media rule
					|| window.matchMedia(rules[i].parentRule.media).matches
				)
				&& element.matches(rules[i].selectorText)
			) {
				splitSelectors(rules[i].selectorText).forEach(function(selector) {
					if (element.matches(selector)) {
						matchedRules.push({
							selector: selector,
							rule: rules[i],
						});
					}
				});
			}
		}
	}
	return matchedRules;
}

function styleHasProperty(style, props) {
	for (var i = 0; i < style.length; i++) {
		if (props.indexOf(style.item(i)) !== -1) {
			return true;
		}
	}
	return false;
}

function sortRulesBySpecificity(rules) {
	return rules.map(function(rule, i) {
		return [rule, i];
	}).sort(function(a, b) {
		return (getSpecificity(b[0].selector) - getSpecificity(a[0].selector)) || b[1] - a[1];
	}).map(function(rule) {
		return rule[0];
	});
}

function getSpecificity(selector) {
	var idScore = 0;
	var classScore = 0;
	var typeScore = 0;
	selector.replace(SELECTOR_ESCAPED_REGEXP, function() {
		classScore++;
		return '';
	});
	selector.replace(ATTR_REGEXP, function() {
		classScore++;
		return '';
	});
	selector.replace(PSEUDO_NOT_REGEXP, '');
	selector.replace(ID_REGEXP, function() {
		idScore++;
		return '';
	});
	selector.replace(CLASS_REGEXP, function() {
		classScore++;
		return '';
	});
	selector.replace(PSEUDO_ELEMENT_REGEXP, function() {
		typeScore++;
		return '';
	});
	selector.replace(PSEUDO_CLASS_REGEXP, function() {
		classScore++;
		return '';
	});
	selector.replace(ELEMENT_REGEXP, function() {
		typeScore++;
		return '';
	});
	return (
		(idScore * 256 * 256)
		+ (classScore * 256)
		+ typeScore
	);
}

function eachQuery(callback) {
	Object.keys(queries).forEach(function(key) {
		callback(queries[key], key);
	});
}

})(window, document);
<commit_msg>Combine getComputedStyle<commit_after>(function(window, document) {
'use strict';

// Public API
window.containerQueries = {
	reprocess: reprocess,
	reparse: reparse,
	reevaluate: reevaluate,
};

// Reprocess now
setTimeout(reprocess);

window.addEventListener('DOMContentLoaded', reprocess);
window.addEventListener('load', reprocess);
window.addEventListener('resize', reevaluate);

var SELECTOR_REGEXP = /:container\(\s*(?:min|max)-(?:width|height)\s*:\s*[^)]+\s*\)/gi;
var SELECTOR_ESCAPED_REGEXP = /\.\\:container\\\(\s*((?:min|max)-(?:width|height))\s*\\:\s*([^)]+?)\s*\\\)/gi;
var ESCAPE_REGEXP = /[:()]/g;
var SPACE_REGEXP = / /g;
var LENGTH_REGEXP = /^-?(?:\d*\.)?\d+(?:em|ex|ch|rem|vh|vw|vmin|vmax|px|mm|cm|in|pt|pc)$/i;
var URL_VALUE_REGEXP = /url\(\s*(?:(["'])(.*?)\1|([^)\s]*))\s*\)/gi;
var ATTR_REGEXP = /\[.+?\]/g;
var PSEUDO_NOT_REGEXP = /:not\(/g;
var ID_REGEXP = /#[^\[\]\\!"#$%&'()*+,./:;<=>?@^`{|}~-]+/g;
var CLASS_REGEXP = /\.[^\[\]\\!"#$%&'()*+,./:;<=>?@^`{|}~-]+/g;
var PSEUDO_ELEMENT_REGEXP = /::[^\[\]\\!"#$%&'()*+,./:;<=>?@^`{|}~-]+/g;
var PSEUDO_CLASS_REGEXP = /:[^\[\]\\!"#$%&'()*+,./:;<=>?@^`{|}~-]+/g;
var ELEMENT_REGEXP = /[a-z-]+/gi;

var queries;
var containerCache;
var processed = false;
var parsed = false;

function reprocess() {
	preprocess(function() {
		processed = true;
		reparse();
	});
}
function reparse() {
	if (!processed) {
		return reprocess();
	}
	parseRules();
	parsed = true;
	reevaluate();
}
function reevaluate() {
	if (!parsed) {
		return reparse();
	}
	updateClasses();
}

function preprocess(callback) {
	var sheets = document.styleSheets;
	if (!sheets.length) {
		callback();
		return;
	}
	var done = 0;
	for (var i = 0, length = sheets.length; i < length; i++) {
		preprocessSheet(sheets[i], function() {
			done++;
			if (done === length) {
				callback();
			}
		});
	}
}

function preprocessSheet(sheet, callback) {
	if (sheet.disabled) {
		callback();
		return;
	}
	var tag = sheet.ownerNode && sheet.ownerNode.tagName;
	if (tag === 'LINK') {
		loadExternal(sheet.ownerNode.href, function(cssText) {
			// Check again because loadExternal is async
			if (sheet.disabled) {
				callback();
				return;
			}
			cssText = fixRelativeUrls(cssText, sheet.ownerNode.href);
			preprocessStyle(sheet.ownerNode, cssText);
			callback();
		});
	}
	else if (tag === 'STYLE') {
		preprocessStyle(sheet.ownerNode, sheet.ownerNode.innerHTML);
		callback();
	}
	else {
		callback();
	}
}

function loadExternal(href, callback) {
	var xhr = new window.XMLHttpRequest();
	xhr.open('GET', href);
	xhr.onreadystatechange = function() {
		if (xhr.readyState !== 4) {
			return;
		}
		callback(xhr.status === 200 ? xhr.responseText : '');
	};
	xhr.send();
}

function fixRelativeUrls(cssText, href) {
	var base = new URL(href, document.baseURI);
	return cssText.replace(URL_VALUE_REGEXP, function(match, quote, url1, url2) {
		var url = url1 || url2;
		if (!url) {
			return match;
		}
		return 'url(' + (quote || '"') + new URL(url, base).href + (quote || '"') + ')';
	});
}

function preprocessStyle(node, cssText) {
	var found = false;
	cssText = cssText.replace(SELECTOR_REGEXP, function(selector) {
		found = true;
		return '.' + selector.replace(SPACE_REGEXP, '').replace(ESCAPE_REGEXP, '\\$&');
	});
	if (!found) {
		return;
	}
	var style = document.createElement('style');
	style.textContent = cssText;
	style.media = node.media;
	node.parentNode.insertBefore(style, node);
	node.disabled = true;
}

function parseRules() {
	queries = {};
	var sheets = document.styleSheets;
	var rules;
	for (var i = 0; i < sheets.length; i++) {
		if (sheets[i].disabled) {
			continue;
		}
		try {
			rules = sheets[i].cssRules;
		}
		catch(e) {
			continue;
		}
		for (var j = 0; j < rules.length; j++) {
			parseRule(rules[j]);
		}
	}
}

function parseRule(rule) {
	if (rule.cssRules) {
		for (var i = 0; i < rule.cssRules.length; i++) {
			parseRule(rule.cssRules[i]);
		}
		return;
	}
	if (rule.type !== 1) {
		return;
	}
	splitSelectors(rule.selectorText).forEach(function(selector) {
		if (selector.search(SELECTOR_ESCAPED_REGEXP) !== -1) {
			selector.replace(SELECTOR_ESCAPED_REGEXP, function(match, type, value, offset) {
				var precedingSelector = selector.substr(0, offset);
				if (!precedingSelector.substr(-1).trim()) {
					precedingSelector += '*';
				}
				queries[precedingSelector + match.toLowerCase()] = {
					selector: precedingSelector,
					prop: type.split('-')[1].toLowerCase(),
					type: type.split('-')[0].toLowerCase(),
					value: value,
					className: match.toLowerCase().substr(1).replace(/\\(.)/g, '$1'),
				};
			});
		}
	});
}

function splitSelectors(selectors) {
	// TODO: Fix complex selectors like fo\,o[attr="val,u\"e"]
	return selectors.split(/\s*,\s*/);
}

function updateClasses() {
	containerCache = new Map();
	eachQuery(function(query) {
		var elements = document.querySelectorAll(query.selector);
		for (var i = 0; i < elements.length; i++) {
			updateClass(elements[i], query);
		}
	});
}

function updateClass(element, query) {
	var container = getContainer(element.parentNode, query.prop);
	var size = getSize(container, query.prop);
	var value = parseFloat(query.value);
	if (
		(query.type === 'min' && size >= value)
		|| (query.type === 'max' && size <= value)
	) {
		element.classList.add(query.className);
	}
	else {
		element.classList.remove(query.className);
	}
}

function getContainer(element, prop) {

	var cache;
	if (containerCache.has(element)) {
		cache = containerCache.get(element);
		if (cache.container[prop]) {
			return cache.container[prop];
		}
	}
	else {
		cache = {
			container: {},
		};
		containerCache.set(element, cache);
	}

	if (element === document.documentElement) {
		cache.container[prop] = element;
	}

	// Skip inline elements
	else if (getComputedStyle(element).display === 'inline') {
		cache.container[prop] = getContainer(element.parentNode, prop);
	}

	else if (isFixedSize(element, prop)) {
		cache.container[prop] = element;
	}

	else {
		var parentContainer = getContainer(element.parentNode, prop);
		var chain = [];
		for (var node = element; node !== parentContainer; node = node.parentNode) {
			// Skip inline elements
			if (getComputedStyle(node).display !== 'inline') {
				chain.unshift(node);
			}
		}
		for (var i = 0; i < chain.length; i++) {
			if (isIntrinsicSize(chain[i], prop)) {
				break;
			}
		}
		if (i) {
			cache.container[prop] = chain[i - 1];
		}
		else {
			cache.container[prop] = parentContainer;
		}
	}

	return cache.container[prop];

}

function isFixedSize(element, prop) {
	var originalStyle = getOriginalStyle(element, [prop]);
	if (originalStyle[prop] && originalStyle[prop].search(LENGTH_REGEXP) !== -1) {
		return true;
	}
}

function isIntrinsicSize(element, prop) {

	var computedStyle = getComputedStyle(element);

	if (computedStyle.display === 'none') {
		return false;
	}

	if (computedStyle.display === 'inline') {
		return true;
	}

	// Non-floating non-absolute block elements (only width)
	if (
		prop === 'width'
		&& ['block', 'list-item', 'flex', 'grid'].indexOf(computedStyle.display) !== -1
		&& computedStyle.float === 'none'
		&& computedStyle.position !== 'absolute'
		&& computedStyle.position !== 'fixed'
	) {
		return false;
	}

	var originalStyle = getOriginalStyle(element, [prop]);

	// Fixed size
	if (originalStyle[prop] && originalStyle[prop].search(LENGTH_REGEXP) !== -1) {
		return false;
	}

	// Percentage size
	if (originalStyle[prop] && originalStyle[prop].substr(-1) === '%') {
		return false;
	}

	// Elements without a defined size
	return true;

}

function getSize(element, prop) {
	var style = getComputedStyle(element);
	if (prop === 'width') {
		return element.offsetWidth
			- parseFloat(style.borderLeftWidth)
			- parseFloat(style.paddingLeft)
			- parseFloat(style.borderRightWidth)
			- parseFloat(style.paddingRight);
	}
	else if (prop === 'height') {
		return element.offsetHeight
			- parseFloat(style.borderTopWidth)
			- parseFloat(style.paddingTop)
			- parseFloat(style.borderBottomWidth)
			- parseFloat(style.paddingBottom);
	}
	return 0;
}

function getComputedStyle(element) {
	return window.getComputedStyle(element);
}

function getOriginalStyle(element, props) {

	var matchedRules = [];
	var sheets = document.styleSheets;
	var rules;
	var result = {};
	var i, j;

	for (i = 0; i < sheets.length; i++) {
		if (sheets[i].disabled) {
			continue;
		}
		try {
			rules = sheets[i].cssRules;
		}
		catch(e) {
			continue;
		}
		matchedRules = matchedRules.concat(filterRulesByElementAndProps(rules, element, props));
	}

	matchedRules = sortRulesBySpecificity(matchedRules);

	// Add style attribute
	matchedRules.unshift({
		rule: {
			style: element.style,
		},
	});

	for (i = 0; i < props.length; i++) {
		for (j = 0; j < matchedRules.length; j++) {
			if (
				matchedRules[j].rule.style.getPropertyValue(props[i])
				&& matchedRules[j].rule.style.getPropertyPriority(props[i]) === 'important'
			) {
				result[props[i]] = matchedRules[j].rule.style.getPropertyValue(props[i]);
				break;
			}
		}
	}

	for (i = 0; i < props.length; i++) {
		// Skip if an !important rule already matched
		if (result[props[i]]) {
			continue;
		}
		for (j = 0; j < matchedRules.length; j++) {
			if (
				matchedRules[j].rule.style.getPropertyValue(props[i])
				&& matchedRules[j].rule.style.getPropertyPriority(props[i]) !== 'important'
			) {
				result[props[i]] = matchedRules[j].rule.style.getPropertyValue(props[i]);
				break;
			}
		}
	}

	return result;

}

function filterRulesByElementAndProps(rules, element, props) {
	var matchedRules = [];
	for (var i = 0; i < rules.length; i++) {
		if (rules[i].cssRules) {
			matchedRules = matchedRules.concat(filterRulesByElementAndProps(rules[i].cssRules, element, props));
		}
		else if (rules[i].type === 1) { // Style rule
			if (
				styleHasProperty(rules[i].style, props)
				&& (
					!rules[i].parentRule
					|| rules[i].parentRule.type !== 4 // @media rule
					|| window.matchMedia(rules[i].parentRule.media).matches
				)
				&& element.matches(rules[i].selectorText)
			) {
				splitSelectors(rules[i].selectorText).forEach(function(selector) {
					if (element.matches(selector)) {
						matchedRules.push({
							selector: selector,
							rule: rules[i],
						});
					}
				});
			}
		}
	}
	return matchedRules;
}

function styleHasProperty(style, props) {
	for (var i = 0; i < style.length; i++) {
		if (props.indexOf(style.item(i)) !== -1) {
			return true;
		}
	}
	return false;
}

function sortRulesBySpecificity(rules) {
	return rules.map(function(rule, i) {
		return [rule, i];
	}).sort(function(a, b) {
		return (getSpecificity(b[0].selector) - getSpecificity(a[0].selector)) || b[1] - a[1];
	}).map(function(rule) {
		return rule[0];
	});
}

function getSpecificity(selector) {
	var idScore = 0;
	var classScore = 0;
	var typeScore = 0;
	selector.replace(SELECTOR_ESCAPED_REGEXP, function() {
		classScore++;
		return '';
	});
	selector.replace(ATTR_REGEXP, function() {
		classScore++;
		return '';
	});
	selector.replace(PSEUDO_NOT_REGEXP, '');
	selector.replace(ID_REGEXP, function() {
		idScore++;
		return '';
	});
	selector.replace(CLASS_REGEXP, function() {
		classScore++;
		return '';
	});
	selector.replace(PSEUDO_ELEMENT_REGEXP, function() {
		typeScore++;
		return '';
	});
	selector.replace(PSEUDO_CLASS_REGEXP, function() {
		classScore++;
		return '';
	});
	selector.replace(ELEMENT_REGEXP, function() {
		typeScore++;
		return '';
	});
	return (
		(idScore * 256 * 256)
		+ (classScore * 256)
		+ typeScore
	);
}

function eachQuery(callback) {
	Object.keys(queries).forEach(function(key) {
		callback(queries[key], key);
	});
}

})(window, document);
<|endoftext|>


<commit_before>var react = require('react')
  , utils = require('./utils')
  , observables = require('./observables')
  , coordinator = require('./coordinator')
  , instrumentation = require('./instrumentation')
  , pelletReactMixin = require('./pellet-react-mixin');

/**
 * @class pellet
 *
 */
function pellet(config) {
  this.readyFnQue = [];
  this.initFnQue = [];
  this.coordinators = {};
  this.coordinatorSpecs = {};
  this.components = {};
  this.locales = {};

  this.middlewareStack = [];

  if(config) {
    // now update the config
    config = Object.create(config);

    if (config.instrumentation) {
      this.instrumentation = config.instrumentation;
      config.instrumentation = void(0);
    } else {
      this.instrumentation = new instrumentation();
    }

    if (config.logger) {
      this.logger = config.logger;
      config.logger = void(0);
    } else {
      this.logger = null; // TODO: make a mock logger
    }

    this.config = config;
  } else {
    this.config = {};
  }
}

/**
 *
 * @type {observables}
 */
pellet.prototype.observables = observables;

/**
 *
 * @type {exports}
 */
pellet.prototype.createClass = function(spec) {
  if(!spec.mixins) {
    spec.mixins = [];
  }

  if(!(pelletReactMixin in spec.mixins)) {
    spec.mixins.push(pelletReactMixin);
  }

  if(spec.componentConstruction) {
    var _componentConstruction = spec.componentConstruction;
    delete spec.componentConstruction;
  }

  if(spec.layoutTemplate) {
    var _layout = spec.layoutTemplate;
    delete spec.layoutTemplate;
  }

  if(typeof spec.routes !== 'undefined') {
    var i, allRoutes;

    if(typeof spec.routes === 'string') {
      allRoutes = [spec.routes];
    } else if(spec.routes instanceof Array) {
      allRoutes = spec.routes;
    }

    delete spec.routes;
  }

  var reactClass = react.createClass(spec);

  // make sure we have static version of __$construction
  // and __$layout
  if(_componentConstruction) {
    reactClass.__$construction = _componentConstruction;
  }

  if(_layout) {
    reactClass.__$layout = _layout;
  }

  if(allRoutes) {
    for(i in allRoutes) {
      this.addComponentRoute(allRoutes[i], reactClass, {});
    }
  }

  return reactClass;
};

pellet.prototype.setLocaleLookupFn = function(lookupFn) {
  this.suggestLocales = lookupFn;
};

pellet.prototype.loadTranslation = function(locale, fn) {
  this.locales[locale] = fn;
};

pellet.prototype.loadManifestComponents = function(manifest) {
  var last, id, key, keys;

  if(!manifest || typeof(manifest) !== 'object') {
    return;
  }

  keys = Object.keys(manifest);

  keys.sort().reverse();
  for(var i in keys) {
    key = keys[i];
    id = key.substring(0, key.indexOf('@'));
    if(id) {
      if(last !== id) {
        if(this.components[id]) {
          console.warn('duplicate manifest component loaded:', id)
        }

        this.components[id] = manifest[key];
        last = id;
      }

      this.components[key] = manifest[key];
    }
  }
};

/**
 *
 * NOTE: be careful with the options because once initialized
 * we never create the coordinator so for each unique name the options
 * need to match!
 *
 * @param key
 * @param isGlobal
 * @param options
 * @returns {*}
 */
pellet.prototype.getCoordinator = function(name, type) {
  if(!name) {
    throw new Error('name is required');
  }

  if(instance = this.coordinators[name]) {
    return instance;
  }

  if(typeof type !== 'string') {
    type = name;
    if(typeof type === 'object') {
      options = type;
    }
  }

  // now create a global coordinator
  var instance = this.createCoordinator(type);
  this.coordinators[name] = instance;

  return instance;
};

/**
 *
 * @param key
 * @param isGlobal
 * @param options
 * @returns {*}
 */
pellet.prototype.createCoordinator = function(type) {
  if(!type) {
    throw new Error('type is required');
  }

  if(!this.coordinatorSpecs[type]) {
    throw new Error('Cannot find ' + type + ' coordinator spec');
  }

  var instance = new coordinator();
  utils.mixInto(instance, this.coordinatorSpecs[type], false, ['initialize', 'load', 'release']);
  instance.initialize();

  return instance;
};

/**
 * register the coordinator spec that creates the new coordinator
 * of type name.
 *
 * @param name
 * @param fn
 */
pellet.prototype.registerCoordinatorSpec = function(name, spec) {
  if(!spec || !name) {
    throw new Error('Spec and name are required for all coordinators.');
  }

  if(this.coordinatorSpecs[name]) {
    console.error('Error duplicate store specs:', name);
    throw new Error('Cannot have duplicate store specs');
  }

  this.coordinatorSpecs[name] = spec;
};

/**
 * register a function to be called once pellet is ready
 * @param fn
 */
pellet.prototype.onReady = function(fn) {
  // if all ready running fire immediately with the last know err (or null if no errors)
  if(typeof(this.readyError) != 'undefined') {
    setTimeout(function() {
      fn(module.exports.readyError);
    }, 1);

    return;
  }

  this.readyFnQue.push(fn);
};

/**
 * register a function needed to complete before pellet is ready
 * @param fn
 */
pellet.prototype.registerInitFn = function(fn) {
  this.initFnQue.push(fn);
};

/**
 * Called after everyone has register their load functions
 */
pellet.prototype.startInit = function() {
  if(typeof(this.readyError) != 'undefined') {
    throw new Error('Cannot reinit because pellet is all ready running.');
  }

  var cbCount = this.initFnQue.length;
  function done(err) {
    if(err) {
      // console log the error and safe the most recent error
      console.error('Error init pellet because:', err.message);
      module.exports.readyError = err;
    }

    if(--cbCount <= 0) {
      // if all callback had no error set to null
      if(!module.exports.readyError) {
        module.exports.readyError = null;
      }

      var fn;
      while(fn = module.exports.readyFnQue.pop()) {
        fn(module.exports.readyError);
      }
    }
  }

  if(cbCount === 0) {
    done(null);
    return;
  }

  // now call all init fn and wait until all done
  for(i in this.initFnQue) {
    this.initFnQue[i](done);
  }
};

/**
 *
 * @param renderOptions
 * @param component
 * @param options
 * @returns {locals|*|js.locals|module.locals|app.locals|string}
 */
pellet.prototype.suggestLocales = function(renderOptions, component, options) {
  // todo: if server read (Accept-Language) and push it onto array after en
  // todo: if broswer we can use navigator.language etc.
  // final this can be overwrite by a cookie or by url/host

  return module.exports.config.locales || 'en';
}

if(process.env.SERVER_ENV) {
  module.exports = global.__pellet__ref = new pellet(global.__pellet__config);
}
else if(process.env.BROWSER_ENV) {
  module.exports = window.__pellet__ref = new pellet(JSON.parse(window.__pellet__config));

  module.exports.addWindowOnloadEvent = function(fn) {
    var _onload = window.onload;
    if (typeof window.onload != 'function') {
      window.onload = fn;
    } else {
      window.onload = function() {
        if (_onload) {_onload();}
        fn();
      }
    }
  }

  module.exports.addWindowOnloadEvent(function() {
    window.__pellet__ref.startInit();
  });

} else {
  module.exports = new pellet(global.__pellet__ref);
}
<commit_msg>fix: when pellet inits with out config we need default that will not crash pellet<commit_after>var react = require('react')
  , utils = require('./utils')
  , observables = require('./observables')
  , coordinator = require('./coordinator')
  , instrumentation = require('./instrumentation')
  , pelletReactMixin = require('./pellet-react-mixin');

/**
 * @class pellet
 *
 */
function pellet(config) {
  this.readyFnQue = [];
  this.initFnQue = [];
  this.coordinators = {};
  this.coordinatorSpecs = {};
  this.components = {};
  this.locales = {};

  this.middlewareStack = [];

  if(config) {
    // now update the config
    config = Object.create(config);

    if (config.instrumentation) {
      this.instrumentation = config.instrumentation;
      config.instrumentation = void(0);
    } else {
      this.instrumentation = new instrumentation();
    }

    if (config.logger) {
      this.logger = config.logger;
      config.logger = void(0);
    } else {
      this.logger = null; // TODO: make a mock logger
    }

    this.config = config;
  } else {
    this.config = {
      instrumentation: new instrumentation(),
      logger: null
    };
  }
}

/**
 *
 * @type {observables}
 */
pellet.prototype.observables = observables;

/**
 *
 * @type {exports}
 */
pellet.prototype.createClass = function(spec) {
  if(!spec.mixins) {
    spec.mixins = [];
  }

  if(!(pelletReactMixin in spec.mixins)) {
    spec.mixins.push(pelletReactMixin);
  }

  if(spec.componentConstruction) {
    var _componentConstruction = spec.componentConstruction;
    delete spec.componentConstruction;
  }

  if(spec.layoutTemplate) {
    var _layout = spec.layoutTemplate;
    delete spec.layoutTemplate;
  }

  if(typeof spec.routes !== 'undefined') {
    var i, allRoutes;

    if(typeof spec.routes === 'string') {
      allRoutes = [spec.routes];
    } else if(spec.routes instanceof Array) {
      allRoutes = spec.routes;
    }

    delete spec.routes;
  }

  var reactClass = react.createClass(spec);

  // make sure we have static version of __$construction
  // and __$layout
  if(_componentConstruction) {
    reactClass.__$construction = _componentConstruction;
  }

  if(_layout) {
    reactClass.__$layout = _layout;
  }

  if(allRoutes) {
    for(i in allRoutes) {
      this.addComponentRoute(allRoutes[i], reactClass, {});
    }
  }

  return reactClass;
};

pellet.prototype.setLocaleLookupFn = function(lookupFn) {
  this.suggestLocales = lookupFn;
};

pellet.prototype.loadTranslation = function(locale, fn) {
  this.locales[locale] = fn;
};

pellet.prototype.loadManifestComponents = function(manifest) {
  var last, id, key, keys;

  if(!manifest || typeof(manifest) !== 'object') {
    return;
  }

  keys = Object.keys(manifest);

  keys.sort().reverse();
  for(var i in keys) {
    key = keys[i];
    id = key.substring(0, key.indexOf('@'));
    if(id) {
      if(last !== id) {
        if(this.components[id]) {
          console.warn('duplicate manifest component loaded:', id)
        }

        this.components[id] = manifest[key];
        last = id;
      }

      this.components[key] = manifest[key];
    }
  }
};

/**
 *
 * NOTE: be careful with the options because once initialized
 * we never create the coordinator so for each unique name the options
 * need to match!
 *
 * @param key
 * @param isGlobal
 * @param options
 * @returns {*}
 */
pellet.prototype.getCoordinator = function(name, type) {
  if(!name) {
    throw new Error('name is required');
  }

  if(instance = this.coordinators[name]) {
    return instance;
  }

  if(typeof type !== 'string') {
    type = name;
    if(typeof type === 'object') {
      options = type;
    }
  }

  // now create a global coordinator
  var instance = this.createCoordinator(type);
  this.coordinators[name] = instance;

  return instance;
};

/**
 *
 * @param key
 * @param isGlobal
 * @param options
 * @returns {*}
 */
pellet.prototype.createCoordinator = function(type) {
  if(!type) {
    throw new Error('type is required');
  }

  if(!this.coordinatorSpecs[type]) {
    throw new Error('Cannot find ' + type + ' coordinator spec');
  }

  var instance = new coordinator();
  utils.mixInto(instance, this.coordinatorSpecs[type], false, ['initialize', 'load', 'release']);
  instance.initialize();

  return instance;
};

/**
 * register the coordinator spec that creates the new coordinator
 * of type name.
 *
 * @param name
 * @param fn
 */
pellet.prototype.registerCoordinatorSpec = function(name, spec) {
  if(!spec || !name) {
    throw new Error('Spec and name are required for all coordinators.');
  }

  if(this.coordinatorSpecs[name]) {
    console.error('Error duplicate store specs:', name);
    throw new Error('Cannot have duplicate store specs');
  }

  this.coordinatorSpecs[name] = spec;
};

/**
 * register a function to be called once pellet is ready
 * @param fn
 */
pellet.prototype.onReady = function(fn) {
  // if all ready running fire immediately with the last know err (or null if no errors)
  if(typeof(this.readyError) != 'undefined') {
    setTimeout(function() {
      fn(module.exports.readyError);
    }, 1);

    return;
  }

  this.readyFnQue.push(fn);
};

/**
 * register a function needed to complete before pellet is ready
 * @param fn
 */
pellet.prototype.registerInitFn = function(fn) {
  this.initFnQue.push(fn);
};

/**
 * Called after everyone has register their load functions
 */
pellet.prototype.startInit = function() {
  if(typeof(this.readyError) != 'undefined') {
    throw new Error('Cannot reinit because pellet is all ready running.');
  }

  var cbCount = this.initFnQue.length;
  function done(err) {
    if(err) {
      // console log the error and safe the most recent error
      console.error('Error init pellet because:', err.message);
      module.exports.readyError = err;
    }

    if(--cbCount <= 0) {
      // if all callback had no error set to null
      if(!module.exports.readyError) {
        module.exports.readyError = null;
      }

      var fn;
      while(fn = module.exports.readyFnQue.pop()) {
        fn(module.exports.readyError);
      }
    }
  }

  if(cbCount === 0) {
    done(null);
    return;
  }

  // now call all init fn and wait until all done
  for(i in this.initFnQue) {
    this.initFnQue[i](done);
  }
};

/**
 *
 * @param renderOptions
 * @param component
 * @param options
 * @returns {locals|*|js.locals|module.locals|app.locals|string}
 */
pellet.prototype.suggestLocales = function(renderOptions, component, options) {
  // todo: if server read (Accept-Language) and push it onto array after en
  // todo: if broswer we can use navigator.language etc.
  // final this can be overwrite by a cookie or by url/host

  return module.exports.config.locales || 'en';
}

if(process.env.SERVER_ENV) {
  module.exports = global.__pellet__ref = new pellet(global.__pellet__config);
}
else if(process.env.BROWSER_ENV) {
  module.exports = window.__pellet__ref = new pellet(JSON.parse(window.__pellet__config));

  module.exports.addWindowOnloadEvent = function(fn) {
    var _onload = window.onload;
    if (typeof window.onload != 'function') {
      window.onload = fn;
    } else {
      window.onload = function() {
        if (_onload) {_onload();}
        fn();
      }
    }
  }

  module.exports.addWindowOnloadEvent(function() {
    window.__pellet__ref.startInit();
  });

} else {
  module.exports = new pellet(global.__pellet__ref);
}
<|endoftext|>


<commit_before>cdb.geo.ui.TimeSlider = cdb.geo.ui.InfoBox.extend({

  DEFAULT_OFFSET_TOP: 30,
  className: 'cartodb-timeslider',

  defaultTemplate:
    "
 " +
    "
pause
" +
    "

10/20

" +
    "

" +
    "
 "
  ,

  events: {
    'click .button': 'toggleTime'
  },

  initialize: function() {
    _.bindAll(this, '_slide');
    var self = this;
    this.options.template = this.options.template || this.defaultTemplate;
    this.options.position = 'bottom|left';
    this.options.width = null;
    this.torqueLayer = this.options.layer;

    // each time time changes, move the slider
    function updateTime(changes) {
      var tb = self.torqueLayer.getTimeBounds();
      if (tb && tb.start !== undefined) {
        var f = self.formaterForRange(tb.start, tb.end);
        self.$('.value').text(f(changes.time));
      }
    }

    function updateSlider(changes) {
      self.$(".slider" ).slider({ value: changes.step });
    }

    this.torqueLayer.on('change:time', updateSlider);
    this.torqueLayer.on('change:time', updateTime);

    this.on('clean', function() {
      self.torqueLayer.off('change:time', updateSlider);
      self.torqueLayer.off('change:time', updateTime);
    });
    cdb.geo.ui.InfoBox.prototype.initialize.call(this);

  },

  formaterForRange: function(start, end) {
    start = start.getTime ? start.getTime(): start;
    end = end.getTime ? end.getTime(): end;
    var span = (end - start)/1000;
    var ONE_DAY = 3600*24;
    function pad(n) { return n < 10 ? '0' + n : n; };
    // lest than a day
    if (span < ONE_DAY) return function(t) { return pad(t.getUTCHours()) + ":" + pad(t.getUTCMinutes()); };
    return function(t) { return pad(t.getUTCMonth() + 1) + "/" + pad(t.getUTCFullYear()); };
  },

  _slide: function(e, ui) {
    this.killEvent(e);
    var step = ui.value;
    this.torqueLayer.setStep(step);
  },

  _initSlider: function() {
    var torqueLayer = this.torqueLayer;
    var slider = this.$(".slider");
    slider.slider({
      range: 'min',
      min: 0,
      max: this.torqueLayer.options.steps,
      value: 0,
      step: 1,
      slide: this._slide
    });
  },

  toggleTime: function(e) {
    this.killEvent(e);
    this.torqueLayer.toggle();
    this.$('.button')
      [(this.torqueLayer.isRunning() ? 'addClass': 'removeClass')]('stop')
      .attr('href','#/' + (this.torqueLayer.isRunning() ? 'pause': 'play'))
      .html(this.torqueLayer.isRunning() ? 'pause': 'play');
  },

  enable: function() {},

  render: function() {
    cdb.geo.ui.InfoBox.prototype.render.apply(this, arguments);
    this._initSlider();
    return this;
  }

});

<commit_msg>time slider updated<commit_after>cdb.geo.ui.TimeSlider = cdb.geo.ui.InfoBox.extend({

  DEFAULT_OFFSET_TOP: 30,
  className: 'cartodb-timeslider',

  defaultTemplate:
    "
 " +
    "
pause
" +
    "

10/20

" +
    "

" +
    "
 "
  ,

  events: {
    "click .button":  "toggleTime",
    "dragstart":      "killEvent",
    "mousedown":      "killEvent",
    "touchstart":     "killEvent",
    "MSPointerDown":  "killEvent",
    "dblclick":       "killEvent",
    "mousewheel":     "killEvent",
    "DOMMouseScroll": "killEvent",
    "click":          "killEvent"
  },

  initialize: function() {
    _.bindAll(this, '_slide');
    var self = this;
    this.options.template = this.options.template || this.defaultTemplate;
    this.options.position = 'bottom|left';
    this.options.width = null;
    this.torqueLayer = this.options.layer;

    // each time time changes, move the slider
    function updateTime(changes) {
      var tb = self.torqueLayer.getTimeBounds();
      if (tb && tb.start !== undefined) {
        var f = self.formaterForRange(tb.start, tb.end);
        self.$('.value').text(f(changes.time));
      }
    }

    function updateSlider(changes) {
      self.$(".slider" ).slider({ value: changes.step });
    }

    this.torqueLayer.on('change:time', updateSlider);
    this.torqueLayer.on('change:time', updateTime);

    this.on('clean', function() {
      self.torqueLayer.off('change:time', updateSlider);
      self.torqueLayer.off('change:time', updateTime);
    });
    cdb.geo.ui.InfoBox.prototype.initialize.call(this);

  },

  formaterForRange: function(start, end) {
    start = start.getTime ? start.getTime(): start;
    end = end.getTime ? end.getTime(): end;
    var span = (end - start)/1000;
    var ONE_DAY = 3600*24;
    function pad(n) { return n < 10 ? '0' + n : n; };
    // lest than a day
    if (span < ONE_DAY) return function(t) { return pad(t.getUTCHours()) + ":" + pad(t.getUTCMinutes()); };
    return function(t) { return pad(t.getUTCMonth() + 1) + "/" + pad(t.getUTCFullYear()); };
  },

  _slide: function(e, ui) {
    this.killEvent(e);
    var step = ui.value;
    this.torqueLayer.setStep(step);
  },

  _initSlider: function() {
    var torqueLayer = this.torqueLayer;
    var slider = this.$(".slider");
    slider.slider({
      range: 'min',
      min: 0,
      max: this.torqueLayer.options.steps,
      value: 0,
      step: 1,
      slide: this._slide
    });
  },

  toggleTime: function(e) {
    this.killEvent(e);
    this.torqueLayer.toggle();
    this.$('.button')
      [(this.torqueLayer.isRunning() ? 'addClass': 'removeClass')]('stop')
      .attr('href','#/' + (this.torqueLayer.isRunning() ? 'pause': 'play'))
      .html(this.torqueLayer.isRunning() ? 'pause': 'play');
  },

  enable: function() {},

  render: function() {
    cdb.geo.ui.InfoBox.prototype.render.apply(this, arguments);
    this._initSlider();
    return this;
  }

});

<|endoftext|>


<commit_before>var json = '';
var currentRecord = 0;

$(document).ready(function () {
  $.ajax({
    url:    "http://108.24.150.90/LehighHacks/registrant_aggregator.php",
    type:   "POST",
    data:   {
        data:  "data"
    },
    success: function(data) {
      $('#loading').hide();

      if(data.indexOf("Error") > -1){
        $('#record-wrapper').append('

'+data.replace('Error', '')+'
');
      }
      else{
        console.log("success");
        json = $.parseJSON(data);
        for(var i=0; i<json.length; i++){
          console.log(json[i]);
          $("#record-table").append('
'+''+json[i].firstName+'	'+json[i].lastName+'	'+json[i].email+'	'+json[i].phone+'
');
        }
      }
    }
  });
});

$(document).on('click', '.record', function () {
  currentRecord = parseInt($(this).attr('id').replace('movie', ''));

  $("#firstname-label").val(json[currentRecord].firstName);
  $("#lastname-label").val(json[currentRecord].lastName);
  $("#email-label").val(json[currentRecord].email);
  $("#phone-label").val(json[currentRecord].phone);
  $("#suggestions-label").val(json[currentRecord].suggestions);
  $("#diet-label").val(json[currentRecord].diet);
});<commit_msg>admin display<commit_after>var json = '';
var currentRecord = 0;

$(document).ready(function () {
  $.ajax({
    url:    "http://108.24.150.90/LehighHacks/registrant_aggregator.php",
    type:   "POST",
    data:   {
        data:  "data"
    },
    success: function(data) {
      $('#loading').hide();

      if(data.indexOf("Error") > -1){
        $('#record-wrapper').append('

'+data.replace('Error', '')+'
');
      }
      else{
        console.log("success");
        json = $.parseJSON(data);
        for(var i=0; i<json.length; i++){
          console.log(json[i]);
          $("#record-table").append('
'+''+json[i].firstName+'	'+json[i].lastName+'	'+json[i].email+'	'+json[i].phone+'
');
        }
      }
    }
  });
});

$(document).on('click', '.record', function () {
  currentRecord = parseInt($(this).attr('id').replace('record', ''));

  $("#firstname-label").val(json[currentRecord].firstName);
  $("#lastname-label").val(json[currentRecord].lastName);
  $("#email-label").val(json[currentRecord].email);
  $("#phone-label").val(json[currentRecord].phone);
  $("#suggestions-label").val(json[currentRecord].suggestions);
  $("#diet-label").val(json[currentRecord].diet);
});<|endoftext|>


<commit_before>'use strict'

const assert = require('assert')
const sinon = require('sinon')

const clientHandler = require('./client-handler')
const utils = require('./utils')

function getRecordData(expression, recordName) {
  return clientHandler.getClients(expression).map(client => client.record.records[recordName])
}

function getListData(expression, listName) {
  return clientHandler.getClients(expression).map(client => client.record.lists[listName])
}

module.exports = function () {

  this.When(/(.+) gets? the record "([^"]*)"$/, (clientExpression, recordName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      const recordData = {
        record: client.client.record.getRecord(recordName),
        discardCallback: sinon.spy(),
        deleteCallback: sinon.spy(),
        callbackError: sinon.spy(),
        subscribeCallback: sinon.spy(),
        setCallback: undefined,
        subscribePathCallbacks: {}
      }
      recordData.record.on('discard', recordData.discardCallback)
      recordData.record.on('delete', recordData.deleteCallback)
      client.record.records[recordName] = recordData
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.When(/(.+) sets the merge strategy to (remote|local)$/, (clientExpression, recordName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      const recordData = {
        record: client.client.record.getRecord(recordName),
        discardCallback: sinon.spy(),
        deleteCallback: sinon.spy(),
        callbackError: sinon.spy(),
        subscribeCallback: sinon.spy(),
        subscribePathCallbacks: {}
      }
      recordData.record.on('discard', recordData.discardCallback)
      recordData.record.on('delete', recordData.deleteCallback)
      client.record.records[recordName] = recordData
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Then(/^(.+) gets? notified of record "([^"]*)" getting (discarded|deleted)$/, (clientExpression, recordName, action) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (action === 'discarded') {
        sinon.assert.calledOnce(recordData.discardCallback)
        recordData.discardCallback.reset()
      } else {
        sinon.assert.calledOnce(recordData.deleteCallback)
        recordData.deleteCallback.reset()
      }
    })
  })

  this.Then(/^(.+) receives? an update for record "([^"]*)" with data '([^']+)'$/, (clientExpression, recordName, data) => {
    data = utils.parseData(data)
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      sinon.assert.calledOnce(recordData.subscribeCallback)
      sinon.assert.calledWith(recordData.subscribeCallback, data)
      recordData.subscribeCallback.reset()
    })
  })

  this.Then(/^(.+) receives? an update for record "([^"]*)" and path "([^"]*)" with data '([^']+)'$/, (clientExpression, recordName, path, data) => {
    data = utils.parseData(data)
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      sinon.assert.calledOnce(recordData.subscribePathCallbacks[path])
      sinon.assert.calledWith(recordData.subscribePathCallbacks[path], data)
      recordData.subscribePathCallbacks[path].reset()
    })
  })

  this.Then(/^(.+) (?:don't|doesn't|does not) receive an update for record "([^"]*)"$/, (clientExpression, recordName) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      sinon.assert.notCalled(recordData.subscribeCallback)
    })
  })

  this.Then(/^(.+) don't receive an update for record "([^"]*)" and path "([^"]*)"$/, (clientExpression, recordName, path) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      sinon.assert.notCalled(recordData.subscribePathCallbacks[path])
    })
  })

  this.Given(/^(.+) (un)?subscribes? to record "([^"]*)"( with immediate flag)?$/, (clientExpression, not, recordName, immedate) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (not) {
        recordData.record.unsubscribe(recordData.subscribeCallback)
      } else {
        recordData.record.subscribe(recordData.subscribeCallback, !!immedate)
      }
    })
  })

  this.Given(/^(.+) (un)?subscribes? to record "([^"]*)" with path "([^"]*)"( with immediate flag)?$/, (clientExpression, not, recordName, path, immedate) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (not) {
        recordData.record.unsubscribe(path, recordData.subscribePathCallbacks[path])
      } else {
        recordData.subscribePathCallbacks[path] = sinon.spy()
        recordData.record.subscribe(path, recordData.subscribePathCallbacks[path], !!immedate)
      }
    })
  })

  this.Then(/^(.+) (?:have|has) record "([^"]*)" with data '([^']+)'$/, (clientExpression, recordName, data) => {
    data = utils.parseData(data)
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      assert.deepEqual(data, recordData.record.get())
    })
  })

  this.Then(/^(.+) (?:have|has) record "([^"]*)" with path "([^"]*)" and data '([^']+)'$/, (clientExpression, recordName, path, data) => {
    data = utils.parseData(data)
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      assert.deepEqual(data, recordData.record.get(path))
    })
  })

  this.Given(/^(.+) (discards?|deletes?) record "([^"]*)"$/, (clientExpression, action, recordName, done) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (action.indexOf('di') > -1) {
        recordData.record.discard()
      } else {
        recordData.record.delete()
      }
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.When(/^(.+) requires? write acknowledgements for record "([^"]*)"$/, (clientExpression, recordName) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      client.record.records[recordName].setCallback = sinon.spy()
    })
  })

  this.When(/^(.+) sets? the record "([^"]*)" with data '([^']+)'$/, (clientExpression, recordName, data, done) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (recordData.setCallback) { recordData.record.set(utils.parseData(data), recordData.setCallback) } else { recordData.record.set(utils.parseData(data)) }
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.When(/^(.+) sets? the record "([^"]*)" and path "([^"]*)" with data '([^']+)'$/, (clientExpression, recordName, path, data, done) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (recordData.setCallback) { recordData.record.set(path, utils.parseData(data), recordData.setCallback) } else { recordData.record.set(path, utils.parseData(data)) }
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Then(/^(.+) is told that the record "([^"]*)" was set without error$/, (clientExpression, recordName) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      sinon.assert.calledOnce(recordData.setCallback)
      sinon.assert.calledWith(recordData.setCallback, null)
      recordData.setCallback.reset()
    })
  })

  this.Then(/^(.+) is told that the record "([^"]*)" experienced error "([^"]*)" while setting$/, (clientExpression, recordName, errorMessage) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      sinon.assert.calledOnce(recordData.setCallback)
      sinon.assert.calledWith(recordData.setCallback, errorMessage)
      recordData.setCallback.reset()
    })
  })

  this.Given(/^(.+) requests? a snapshot of record "([^"]*)"$/, (clientExpression, recordName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      client.client.record.snapshot(recordName, client.record.snapshotCallback)
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Then(/^(.+) gets? a snapshot response for "([^"]*)" with (data|error) '([^']+)'$/, (clientExpression, recordName, type, data) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      sinon.assert.calledOnce(client.record.snapshotCallback)
      if (type === 'data') {
        sinon.assert.calledWith(client.record.snapshotCallback, null, utils.parseData(data))
      } else {
        sinon.assert.calledWith(client.record.snapshotCallback, data.replace(/"/g, ''))
      }
      client.record.snapshotCallback.reset()
    })
  })

  this.Given(/^(.+) asks? if record "([^"]*)" exists$/, (clientExpression, recordName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      client.client.record.has(recordName, client.record.hasCallback)
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Then(/^(.+) gets? told record "([^"]*)" (.*)exists?$/, (clientExpression, recordName, adjective) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      sinon.assert.calledOnce(client.record.hasCallback)
      sinon.assert.calledWith(client.record.hasCallback, null, adjective.indexOf('not') === -1)
      client.record.hasCallback.reset()
    })
  })

  /** ******************************************************************************************************************************
   *********************************************************** Lists ************************************************************
   ********************************************************************************************************************************/

  this.When(/(.+) gets? the list "([^"]*)"$/, (clientExpression, listName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      const listData = {
        list: client.client.record.getList(listName),
        discardCallback: sinon.spy(),
        deleteCallback: sinon.spy(),
        callbackError: sinon.spy(),
        subscribeCallback: sinon.spy(),
        addedCallback: sinon.spy(),
        removedCallback: sinon.spy(),
        movedCallback: sinon.spy()
      }
      listData.list.on('discard', listData.discardCallback)
      listData.list.on('delete', listData.deleteCallback)
      listData.list.on('entry-added', listData.addedCallback)
      listData.list.on('entry-removed', listData.removedCallback)
      listData.list.on('entry-moved', listData.movedCallback)
      listData.list.subscribe(listData.subscribeCallback)
      client.record.lists[listName] = listData
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Given(/^(.+) sets the entries on the list "([^"]*)" to '([^']*)'$/, (clientExpression, listName, data, done) => {
    data = utils.parseData(data)
    getListData(clientExpression, listName).forEach((listData) => {
      listData.list.setEntries(data)
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Given(/^(.+) (adds|removes) an entry "([^"]*)" (?:to|from) "([^""]*)"$/, (clientExpression, action, entryName, listName, done) => {
    getListData(clientExpression, listName).forEach((listData) => {
      if (action === 'adds') {
        listData.list.addEntry(entryName)
      } else {
        listData.list.removeEntry(entryName)
      }
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Then(/^(.+) have a list "([^"]*)" with entries '([^']*)'$/, (clientExpression, listName, data) => {
    data = utils.parseData(data)
    getListData(clientExpression, listName).forEach((listData) => {
      assert.deepEqual(listData.list.getEntries(), data)
    })
  })

  this.Then(/^(.+) gets? notified of "([^"]*)" being (added|removed|moved) (?:to|in|from) "([^""]*)"$/, (clientExpression, entryName, action, listName) => {
    getListData(clientExpression, listName).forEach((listData) => {
      if (action === 'added') {
        sinon.assert.calledWith(listData.addedCallback, entryName)
      } else if (action === 'removed') {
        sinon.assert.calledWith(listData.removedCallback, entryName)
      } else {
        sinon.assert.calledWith(listData.movedCallback, entryName)
      }
    })
  })

  this.Then(/^(.+) gets? notified of list "([^"]*)" entries changing to '([^']*)'$/, (clientExpression, listName, data) => {
    data = utils.parseData(data)
    getListData(clientExpression, listName).forEach((listData) => {
      // sinon.assert.calledOnce( listData.subscribeCallback );
      sinon.assert.calledWith(listData.subscribeCallback, data)
    })
  })

  /** ******************************************************************************************************************************
   *********************************************************** ANONYMOUS RECORDS ************************************************************
   ********************************************************************************************************************************/

  this.When(/(.+) gets? a anonymous record$/, (clientExpression) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      client.record.anonymousRecord = client.client.record.getAnonymousRecord()
    })
  })

  this.When(/(.+) sets? the underlying record to "([^"]*)" on the anonymous record$/, (clientExpression, recordName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      console.log(recordName)
      client.record.anonymousRecord.setName(recordName)
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.When(/(.+) anonymous record data is '([^']*)'$/, (clientExpression, data) => {
    data = utils.parseData(data)
    clientHandler.getClients(clientExpression).forEach((client) => {
      assert.deepEqual(client.record.anonymousRecord.get(), data)
    })
  })

}
<commit_msg>fix(record-test): add timeout to error due to new requestIdleCallback<commit_after>'use strict'

const assert = require('assert')
const sinon = require('sinon')

const clientHandler = require('./client-handler')
const utils = require('./utils')

function getRecordData(expression, recordName) {
  return clientHandler.getClients(expression).map(client => client.record.records[recordName])
}

function getListData(expression, listName) {
  return clientHandler.getClients(expression).map(client => client.record.lists[listName])
}

module.exports = function () {

  this.When(/(.+) gets? the record "([^"]*)"$/, (clientExpression, recordName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      const recordData = {
        record: client.client.record.getRecord(recordName),
        discardCallback: sinon.spy(),
        deleteCallback: sinon.spy(),
        callbackError: sinon.spy(),
        subscribeCallback: sinon.spy(),
        setCallback: undefined,
        subscribePathCallbacks: {}
      }
      recordData.record.on('discard', recordData.discardCallback)
      recordData.record.on('delete', recordData.deleteCallback)
      client.record.records[recordName] = recordData
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.When(/(.+) sets the merge strategy to (remote|local)$/, (clientExpression, recordName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      const recordData = {
        record: client.client.record.getRecord(recordName),
        discardCallback: sinon.spy(),
        deleteCallback: sinon.spy(),
        callbackError: sinon.spy(),
        subscribeCallback: sinon.spy(),
        subscribePathCallbacks: {}
      }
      recordData.record.on('discard', recordData.discardCallback)
      recordData.record.on('delete', recordData.deleteCallback)
      client.record.records[recordName] = recordData
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Then(/^(.+) gets? notified of record "([^"]*)" getting (discarded|deleted)$/, (clientExpression, recordName, action) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (action === 'discarded') {
        sinon.assert.calledOnce(recordData.discardCallback)
        recordData.discardCallback.reset()
      } else {
        sinon.assert.calledOnce(recordData.deleteCallback)
        recordData.deleteCallback.reset()
      }
    })
  })

  this.Then(/^(.+) receives? an update for record "([^"]*)" with data '([^']+)'$/, (clientExpression, recordName, data) => {
    data = utils.parseData(data)
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      sinon.assert.calledOnce(recordData.subscribeCallback)
      sinon.assert.calledWith(recordData.subscribeCallback, data)
      recordData.subscribeCallback.reset()
    })
  })

  this.Then(/^(.+) receives? an update for record "([^"]*)" and path "([^"]*)" with data '([^']+)'$/, (clientExpression, recordName, path, data) => {
    data = utils.parseData(data)
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      sinon.assert.calledOnce(recordData.subscribePathCallbacks[path])
      sinon.assert.calledWith(recordData.subscribePathCallbacks[path], data)
      recordData.subscribePathCallbacks[path].reset()
    })
  })

  this.Then(/^(.+) (?:don't|doesn't|does not) receive an update for record "([^"]*)"$/, (clientExpression, recordName) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      sinon.assert.notCalled(recordData.subscribeCallback)
    })
  })

  this.Then(/^(.+) don't receive an update for record "([^"]*)" and path "([^"]*)"$/, (clientExpression, recordName, path) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      sinon.assert.notCalled(recordData.subscribePathCallbacks[path])
    })
  })

  this.Given(/^(.+) (un)?subscribes? to record "([^"]*)"( with immediate flag)?$/, (clientExpression, not, recordName, immedate) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (not) {
        recordData.record.unsubscribe(recordData.subscribeCallback)
      } else {
        recordData.record.subscribe(recordData.subscribeCallback, !!immedate)
      }
    })
  })

  this.Given(/^(.+) (un)?subscribes? to record "([^"]*)" with path "([^"]*)"( with immediate flag)?$/, (clientExpression, not, recordName, path, immedate) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (not) {
        recordData.record.unsubscribe(path, recordData.subscribePathCallbacks[path])
      } else {
        recordData.subscribePathCallbacks[path] = sinon.spy()
        recordData.record.subscribe(path, recordData.subscribePathCallbacks[path], !!immedate)
      }
    })
  })

  this.Then(/^(.+) (?:have|has) record "([^"]*)" with data '([^']+)'$/, (clientExpression, recordName, data) => {
    data = utils.parseData(data)
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      assert.deepEqual(data, recordData.record.get())
    })
  })

  this.Then(/^(.+) (?:have|has) record "([^"]*)" with path "([^"]*)" and data '([^']+)'$/, (clientExpression, recordName, path, data) => {
    data = utils.parseData(data)
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      assert.deepEqual(data, recordData.record.get(path))
    })
  })

  this.Given(/^(.+) (discards?|deletes?) record "([^"]*)"$/, (clientExpression, action, recordName, done) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (action.indexOf('di') > -1) {
        recordData.record.discard()
      } else {
        recordData.record.delete()
      }
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.When(/^(.+) requires? write acknowledgements for record "([^"]*)"$/, (clientExpression, recordName) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      client.record.records[recordName].setCallback = sinon.spy()
    })
  })

  this.When(/^(.+) sets? the record "([^"]*)" with data '([^']+)'$/, (clientExpression, recordName, data, done) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (recordData.setCallback) { recordData.record.set(utils.parseData(data), recordData.setCallback) } else { recordData.record.set(utils.parseData(data)) }
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.When(/^(.+) sets? the record "([^"]*)" and path "([^"]*)" with data '([^']+)'$/, (clientExpression, recordName, path, data, done) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      if (recordData.setCallback) { recordData.record.set(path, utils.parseData(data), recordData.setCallback) } else { recordData.record.set(path, utils.parseData(data)) }
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Then(/^(.+) is told that the record "([^"]*)" was set without error$/, (clientExpression, recordName) => {
    getRecordData(clientExpression, recordName).forEach((recordData) => {
      sinon.assert.calledOnce(recordData.setCallback)
      sinon.assert.calledWith(recordData.setCallback, null)
      recordData.setCallback.reset()
    })
  })

  this.Then(/^(.+) is told that the record "([^"]*)" experienced error "([^"]*)" while setting$/, (clientExpression, recordName, errorMessage, done) => {
    setTimeout(() => {
      getRecordData(clientExpression, recordName).forEach((recordData) => {
        sinon.assert.calledOnce(recordData.setCallback)
        sinon.assert.calledWith(recordData.setCallback, errorMessage)
        recordData.setCallback.reset()
      })
      done()
    }, 100)
  })

  this.Given(/^(.+) requests? a snapshot of record "([^"]*)"$/, (clientExpression, recordName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      client.client.record.snapshot(recordName, client.record.snapshotCallback)
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Then(/^(.+) gets? a snapshot response for "([^"]*)" with (data|error) '([^']+)'$/, (clientExpression, recordName, type, data) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      sinon.assert.calledOnce(client.record.snapshotCallback)
      if (type === 'data') {
        sinon.assert.calledWith(client.record.snapshotCallback, null, utils.parseData(data))
      } else {
        sinon.assert.calledWith(client.record.snapshotCallback, data.replace(/"/g, ''))
      }
      client.record.snapshotCallback.reset()
    })
  })

  this.Given(/^(.+) asks? if record "([^"]*)" exists$/, (clientExpression, recordName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      client.client.record.has(recordName, client.record.hasCallback)
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Then(/^(.+) gets? told record "([^"]*)" (.*)exists?$/, (clientExpression, recordName, adjective) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      sinon.assert.calledOnce(client.record.hasCallback)
      sinon.assert.calledWith(client.record.hasCallback, null, adjective.indexOf('not') === -1)
      client.record.hasCallback.reset()
    })
  })

  /** ******************************************************************************************************************************
   *********************************************************** Lists ************************************************************
   ********************************************************************************************************************************/

  this.When(/(.+) gets? the list "([^"]*)"$/, (clientExpression, listName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      const listData = {
        list: client.client.record.getList(listName),
        discardCallback: sinon.spy(),
        deleteCallback: sinon.spy(),
        callbackError: sinon.spy(),
        subscribeCallback: sinon.spy(),
        addedCallback: sinon.spy(),
        removedCallback: sinon.spy(),
        movedCallback: sinon.spy()
      }
      listData.list.on('discard', listData.discardCallback)
      listData.list.on('delete', listData.deleteCallback)
      listData.list.on('entry-added', listData.addedCallback)
      listData.list.on('entry-removed', listData.removedCallback)
      listData.list.on('entry-moved', listData.movedCallback)
      listData.list.subscribe(listData.subscribeCallback)
      client.record.lists[listName] = listData
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Given(/^(.+) sets the entries on the list "([^"]*)" to '([^']*)'$/, (clientExpression, listName, data, done) => {
    data = utils.parseData(data)
    getListData(clientExpression, listName).forEach((listData) => {
      listData.list.setEntries(data)
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Given(/^(.+) (adds|removes) an entry "([^"]*)" (?:to|from) "([^""]*)"$/, (clientExpression, action, entryName, listName, done) => {
    getListData(clientExpression, listName).forEach((listData) => {
      if (action === 'adds') {
        listData.list.addEntry(entryName)
      } else {
        listData.list.removeEntry(entryName)
      }
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.Then(/^(.+) have a list "([^"]*)" with entries '([^']*)'$/, (clientExpression, listName, data) => {
    data = utils.parseData(data)
    getListData(clientExpression, listName).forEach((listData) => {
      assert.deepEqual(listData.list.getEntries(), data)
    })
  })

  this.Then(/^(.+) gets? notified of "([^"]*)" being (added|removed|moved) (?:to|in|from) "([^""]*)"$/, (clientExpression, entryName, action, listName) => {
    getListData(clientExpression, listName).forEach((listData) => {
      if (action === 'added') {
        sinon.assert.calledWith(listData.addedCallback, entryName)
      } else if (action === 'removed') {
        sinon.assert.calledWith(listData.removedCallback, entryName)
      } else {
        sinon.assert.calledWith(listData.movedCallback, entryName)
      }
    })
  })

  this.Then(/^(.+) gets? notified of list "([^"]*)" entries changing to '([^']*)'$/, (clientExpression, listName, data) => {
    data = utils.parseData(data)
    getListData(clientExpression, listName).forEach((listData) => {
      // sinon.assert.calledOnce( listData.subscribeCallback );
      sinon.assert.calledWith(listData.subscribeCallback, data)
    })
  })

  /** ******************************************************************************************************************************
   *********************************************************** ANONYMOUS RECORDS ************************************************************
   ********************************************************************************************************************************/

  this.When(/(.+) gets? a anonymous record$/, (clientExpression) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      client.record.anonymousRecord = client.client.record.getAnonymousRecord()
    })
  })

  this.When(/(.+) sets? the underlying record to "([^"]*)" on the anonymous record$/, (clientExpression, recordName, done) => {
    clientHandler.getClients(clientExpression).forEach((client) => {
      console.log(recordName)
      client.record.anonymousRecord.setName(recordName)
    })
    setTimeout(done, utils.defaultDelay)
  })

  this.When(/(.+) anonymous record data is '([^']*)'$/, (clientExpression, data) => {
    data = utils.parseData(data)
    clientHandler.getClients(clientExpression).forEach((client) => {
      assert.deepEqual(client.record.anonymousRecord.get(), data)
    })
  })

}
<|endoftext|>


<commit_before>const {desktopCapturer, screen} = window.require('electron');

/**
 * get current display size
 * @returns {{width: number, height: number}}
 */
function getScreenSize() {
  // const displays = screen.getAllDisplays();
  const displays = [screen.getPrimaryDisplay()];
  const size = {
    width: 0,
    height: 0
  };
  for (const display of displays) {
    const {width, height} = display.size;
    size.width += width;
    size.height += height;
  }
  return size;
}

/**
 * a promise wrapper to desktopCapturer.getSources of electron
 * @returns {Promise}
 */
function getSources() {
  return new Promise((resolve, reject) => {
    desktopCapturer.getSources({types: ['window', 'screen']}, (error, sources) => {
      if (error) {
        reject(error);
      } else {
        resolve(sources);
      }
    });
  });
}

export async function takeScreenShot() {
  const sources = await getSources();
  const source = sources.find((src) => src.name === 'Entire screen'); // Entire screen

  if (!source) {
    throw Error('Couldn\'t find "Entire screen"');
  }

  const {width, height} = getScreenSize();
  const stream = await navigator.mediaDevices.getUserMedia({
    audio: false,
    video: {
      mandatory: {
        chromeMediaSource: 'desktop',
        chromeMediaSourceId: source.id,
        minWidth: width,
        maxWidth: width,
        minHeight: height,
        maxHeight: height
      }
    }
  });

  const video = document.createElement('video');
  const canvas = document.createElement('canvas');

  return new Promise((resolve) => {
    video.src = URL.createObjectURL(stream);
    video.addEventListener('loadedmetadata', () => {
      const ratio = video.videoWidth / video.videoHeight;
      const w = video.videoWidth;
      const h = parseInt(w / ratio, 10);

      canvas.width = w;
      canvas.height = h;

      const ctx = canvas.getContext('2d');
      ctx.drawImage(video, 0, 0, w, h);

      resolve(ctx.getImageData(0, 0, w, h));
    }, false);
  });
}
<commit_msg>fix(helpers): stop video track once screen captured<commit_after>const {desktopCapturer, screen} = window.require('electron');

/**
 * get current display size
 * @returns {{width: number, height: number}}
 */
function getScreenSize() {
  // const displays = screen.getAllDisplays();
  const displays = [screen.getPrimaryDisplay()];
  const size = {
    width: 0,
    height: 0
  };
  for (const display of displays) {
    const {width, height} = display.size;
    size.width += width;
    size.height += height;
  }
  return size;
}

/**
 * a promise wrapper to desktopCapturer.getSources of electron
 * @returns {Promise}
 */
function getSources() {
  return new Promise((resolve, reject) => {
    desktopCapturer.getSources({types: ['window', 'screen']}, (error, sources) => {
      if (error) {
        reject(error);
      } else {
        resolve(sources);
      }
    });
  });
}

export async function takeScreenShot() {
  const sources = await getSources();
  const source = sources.find((src) => src.name === 'Entire screen'); // Entire screen

  if (!source) {
    throw Error('Couldn\'t find "Entire screen"');
  }

  const {width, height} = getScreenSize();
  const stream = await navigator.mediaDevices.getUserMedia({
    audio: false,
    video: {
      mandatory: {
        chromeMediaSource: 'desktop',
        chromeMediaSourceId: source.id,
        minWidth: width,
        maxWidth: width,
        minHeight: height,
        maxHeight: height
      }
    }
  });

  const video = document.createElement('video');
  const canvas = document.createElement('canvas');

  return new Promise((resolve) => {
    video.src = URL.createObjectURL(stream);
    video.addEventListener('loadedmetadata', () => {
      const ratio = video.videoWidth / video.videoHeight;
      const w = video.videoWidth;
      const h = parseInt(w / ratio, 10);

      canvas.width = w;
      canvas.height = h;

      const ctx = canvas.getContext('2d');
      ctx.drawImage(video, 0, 0, w, h);

      resolve(ctx.getImageData(0, 0, w, h));
      stream.getVideoTracks()[0].stop();
    }, false);
  });
}
<|endoftext|>


<commit_before>/**
 *
 * Created by Arjun on 10/7/2014.
 */

var TIME_HIGHLIGHT = 1000;
var TIME_TRANSLATE = 1000;
var TIME_UNHIGHLIGHT = 100;
var TIME_BUCKET = 1000;
var TIME_TEXT_PER_WORD = 300;
var TIME_SET_VISIBILITY = 0;
var TIME_SWAP = 1000;
var TIME_PHASE = 1000;

function BoxedList(parent, parentElem, start, nodeList) {
	this.nodeList = nodeList;
	this.nodeMap = {};
	this.parent = parent;
	this.buckets = new Set();
	this.isStart = start;

	var container = $("

");
	parentElem.append(container).append("
");
	this.elem = $("

");
	container.append(this.elem);
}

BoxedList.prototype.addNode = function (node) {
	this.nodeList.append(node);
};

BoxedList.prototype.generateChildren = function () {
	for (var i = 0; i < this.nodeList.length; i++) {
		this.generateChildElement(this.nodeList[i]);
	}
};

BoxedList.prototype.generateChildElement = function (thisNode) {
	var childElem = $("	");
	this.nodeMap[thisNode.id] = childElem.find("span");
	this.nodeMap[thisNode.id].text(thisNode.value);
	this.elem.append(childElem);
};

BoxedList.prototype.animate = function (animationList, skipDelays) {
	var i = 0;
	var maxDelay = -1;
	var childStartLists = [], childEndLists = [];
	for (var j = 0; j < this.parent.children.length; j++) {
		var maps = [];
		for (var k = 0; k < this.parent.children[j].endStack.length; k++) {
			maps.push(this.parent.children[j].endStack[k].nodeMap);
		}
		if (maps.length > 0) childEndLists.push($.extend.apply($, maps));
		maps = [];
		for (var k = 0; k < this.parent.children[j].startStack.length; k++) {
			maps.push(this.parent.children[j].startStack[k].nodeMap);
		}
		if (maps.length > 0) childStartLists.push($.extend.apply($, maps));
	}
	var doAnim = function (boxedList) {
		if (i >= animationList.length) {
			boxedList.animating = null;
			return;
		}
		var delay = 0;
		switch (animationList[i].animationType) {
			case "highlight":
				var nodeSpecs = animationList[i].nodeSpecs;
				var color = animationList[i].color;
				for (var j = 0; j < nodeSpecs.length; j++) {
					var elem = boxedList.getElem(nodeSpecs[j]);
					if (elem != null) {
						elem.css("border-color", color);
					}
				}
				maxDelay = Math.max(maxDelay, TIME_HIGHLIGHT);
				delay = skipDelays ? 0 : TIME_HIGHLIGHT;
				break;
			case "unhighlight":
				var nodeSpecs = animationList[i].nodeSpecs;
				for (var j = 0; j < nodeSpecs.length; j++) {
					var elem = boxedList.getElem(nodeSpecs[j]);
					if (elem != null) {
						elem.css("border-color", "black");
					}
				}
				maxDelay = Math.max(maxDelay, TIME_UNHIGHLIGHT);
				delay = skipDelays ? 0 : TIME_UNHIGHLIGHT;
				break;
			case "translate":
				var sourceElem = boxedList.getElem(animationList[i].sourceSpec);
				var destElem = boxedList.getElem(animationList[i].destSpec);

				if(sourceElem == null || destElem == null) break;
				var sourcePosition = offsetFrom(sourceElem, mainDiv);
				var ghost = $(sourceElem[0].outerHTML);
				ghost.addClass("ghost");
				ghost.css({
					position: "absolute",
					width: sourceElem.width(),
					height: sourceElem.height()
				}).css(sourcePosition);
				mainDiv.append(ghost);
				var moveSource = animationList[i].moveSource;
				var parentCell = destElem.parent();
				ghost.animate(offsetFrom(destElem, mainDiv), TIME_TRANSLATE, function () {
					ghost.remove();
					if (moveSource) {
						parentCell.append(sourceElem);
					}
				});

				maxDelay = Math.max(maxDelay, TIME_TRANSLATE);
				delay = skipDelays ? 0 : TIME_TRANSLATE;
				break;
			case "bucket":
				var thisList = boxedList.getAdjacentBoxedList(animationList[i].visualizationSpec);
				animationList[i].addBuckets.forEach(function (e) {
					thisList.buckets.add(e + "");
				});
				animationList[i].removeBuckets.forEach(function (e) {
					thisList.buckets.delete(e + "");
				});
				thisList.elem.find("td").removeClass("bucket start end");
				thisList.buckets.forEach(function (e){
					var bucket = e.split(",");
					bucket[0] *= 1;
					bucket[1] *= 1;
					thisList.elem.find("td").slice(bucket[0], bucket[1] + 1).addClass("bucket");
					thisList.elem.find("td:nth-child(" + (1 + bucket[0]) + ")").addClass("start");
					thisList.elem.find("td:nth-child(" + (1 + bucket[1]) + ")").addClass("end");
				});
				maxDelay = Math.max(maxDelay, TIME_BUCKET);
				delay = skipDelays ? 0 : TIME_BUCKET;
				break;
			case "text":
				addConsoleCard(animationList[i].text, animationList[i].cardColor);
				delay = TIME_TEXT_PER_WORD * animationList[i].text.split(" ").length;
				maxDelay = Math.max(maxDelay, delay);
				delay = skipDelays ? 0 : delay;
				break;
			case "visibility":
				var thisList = boxedList.getAdjacentBoxedList(animationList[i].visualizationSpec);
				animationList[i].showRanges.forEach(function (e) {
					thisList.elem.find("span").slice(e[0], e[1] + 1)
						.css("visibility", "initial");
				});
				animationList[i].hideRanges.forEach(function (e) {
					thisList.elem.find("span").slice(e[0], e[1] + 1)
						.css("visibility", "hidden");
				});
				maxDelay = Math.max(maxDelay, TIME_SET_VISIBILITY);
				delay = skipDelays ? 0 : TIME_SET_VISIBILITY;
				break;
			case "swap":
				var elem1 = boxedList.getElem(animationList[i].node1);
				var elem2 = boxedList.getElem(animationList[i].node2);
				if(elem1 == elem2) break;
				var pos1 = offsetFrom(elem1, mainDiv);
				var pos2 = offsetFrom(elem2, mainDiv);
				var elemLeft = null, elemRight = null;
				var posLeft = null, posRight = null;
				if (pos1.left < pos2.left) {
					elemLeft = elem1;
					posLeft = pos1;
					elemRight = elem2;
					posRight = pos2;
				} else {
					elemLeft = elem2;
					posLeft = pos2;
					elemRight = elem1;
					posRight = pos1;
				}
				var ghostLeft = $(elemLeft[0].outerHTML);
				var ghostRight = $(elemRight[0].outerHTML);
				ghostLeft.addClass("ghost");
				ghostRight.addClass("ghost");
				ghostLeft.css({
					position: "absolute",
					width: elemLeft.width(),
					height: elemLeft.height()
				}).css(posLeft);
				ghostRight.css({
					position: "absolute",
					width: elemRight.width(),
					height: elemRight.height()
				}).css(posRight);
				mainDiv.append(ghostLeft);
				mainDiv.append(ghostRight);
				elemLeft.css("visibility", "hidden");
				elemRight.css("visibility", "hidden");
				var parentLeft = elemLeft.parent();
				var parentRight = elemRight.parent();
				parentLeft.append(elemRight);
				parentRight.append(elemLeft);
				ghostLeft.animate(posRight,{
					duration: TIME_SWAP,
					complete: function () {
						elemLeft.css("visibility", "initial");
						ghostLeft.remove();
					},
					step: function (now, fx) {
						ghostLeft.css("top", Math.sin(Math.PI * (now - fx.end) / (fx.start - fx.end)) * parentLeft.height() + posLeft.top);
					}
				});
				ghostRight.animate(posLeft,{
					duration: TIME_SWAP,
					complete: function () {
						elemRight.css("visibility", "initial");
						ghostRight.remove();
					},
					step: function (now, fx) {
						ghostRight.css("top", -Math.sin(Math.PI * (now - fx.end) / (fx.start - fx.end)) * parentRight.height() + posRight.top);
					}
				});
				maxDelay = Math.max(maxDelay, TIME_SWAP);
				delay = skipDelays ? 0 : TIME_SWAP;
				break;
			case "phase":
				var thisBoxedList = boxedList.getAdjacentBoxedList(animationList[i].vSpec);
				var thisList = thisBoxedList.elem.parents("table:first");
				var ghost = $(thisList[0].outerHTML);
				ghost.addClass("ghost");
				ghost.css({
					position: "absolute",
					width: thisList.width(),
					height: thisList.height()
				}).css(offsetFrom(thisList, mainDiv));
				mainDiv.append(ghost);
				thisList.css("opacity", "0");
				var tds = thisList.find("td").removeClass("bucket start end");
				for (var j in animationList[i].newState){
					var nodeElem = thisBoxedList.nodeMap[animationList[i].newState[j].id];
					nodeElem.css("border-color", "black");
					$(tds[j]).append(nodeElem);
				}
				ghost.animate({
					opacity: 0
				}, TIME_PHASE, function () {
					ghost.remove();
				});
				thisList.animate({
					opacity: 1
				}, TIME_PHASE);
				break;
			case "bundle":
				//console.log(animationList[i]);
				delay = boxedList.animate(animationList[i].animations, true);
				//console.log(delay);
				maxDelay = Math.max(maxDelay, delay);
				delay = skipDelays ? 0 : delay;
				break;
			default:
				break;
		}
		i++;
		if (delay > 0) {
			boxedList.animating = setTimeout(doAnim, delay, boxedList);
		} else {
			doAnim(boxedList);
		}
	};
	doAnim(this);
	return maxDelay;
};

BoxedList.prototype.getElem = function(nodeSpec) {
	var circle = this.parent;
	for(var i = 0; i < nodeSpec.parentLevel; i++) {
		circle = circle.parent;
	}

	for( var i=0; i<nodeSpec.childIndexes.length; i++) {
		circle = circle.children[nodeSpec.childIndexes[i]];
	}

	// TODO: make circles store flattened nodemaps for the two stacks
	var stack = nodeSpec.list == "start" ? circle.startStack : circle.endStack;
	var nodeMap = $.extend.apply($, stack.map(function(blist) {
		return blist.nodeMap;
	}));
	return nodeMap[nodeSpec.node.id];
};

BoxedList.prototype.getAdjacentBoxedList = function(listSpec) {
	var circle = this.parent;
	for(var i = 0; i < listSpec.parentLevel; i++) {
		circle = circle.parent;
	}

	for( var i=0; i<listSpec.childIndexes.length; i++) {
		circle = circle.children[listSpec.childIndexes[i]];
	}

	var stack = listSpec.list == "start" ? circle.startStack : circle.endStack;
	return stack[listSpec.stackIndex];
}
<commit_msg>Fixed bug in bucket animation<commit_after>/**
 *
 * Created by Arjun on 10/7/2014.
 */

var TIME_HIGHLIGHT = 1000;
var TIME_TRANSLATE = 1000;
var TIME_UNHIGHLIGHT = 100;
var TIME_BUCKET = 1000;
var TIME_TEXT_PER_WORD = 300;
var TIME_SET_VISIBILITY = 0;
var TIME_SWAP = 1000;
var TIME_PHASE = 1000;

function BoxedList(parent, parentElem, start, nodeList) {
	this.nodeList = nodeList;
	this.nodeMap = {};
	this.parent = parent;
	this.buckets = new Set();
	this.isStart = start;

	var container = $("

");
	parentElem.append(container).append("
");
	this.elem = $("

");
	container.append(this.elem);
}

BoxedList.prototype.addNode = function (node) {
	this.nodeList.append(node);
};

BoxedList.prototype.generateChildren = function () {
	for (var i = 0; i < this.nodeList.length; i++) {
		this.generateChildElement(this.nodeList[i]);
	}
};

BoxedList.prototype.generateChildElement = function (thisNode) {
	var childElem = $("	");
	this.nodeMap[thisNode.id] = childElem.find("span");
	this.nodeMap[thisNode.id].text(thisNode.value);
	this.elem.append(childElem);
};

BoxedList.prototype.animate = function (animationList, skipDelays) {
	var i = 0;
	var maxDelay = -1;
	var childStartLists = [], childEndLists = [];
	for (var j = 0; j < this.parent.children.length; j++) {
		var maps = [];
		for (var k = 0; k < this.parent.children[j].endStack.length; k++) {
			maps.push(this.parent.children[j].endStack[k].nodeMap);
		}
		if (maps.length > 0) childEndLists.push($.extend.apply($, maps));
		maps = [];
		for (var k = 0; k < this.parent.children[j].startStack.length; k++) {
			maps.push(this.parent.children[j].startStack[k].nodeMap);
		}
		if (maps.length > 0) childStartLists.push($.extend.apply($, maps));
	}
	var doAnim = function (boxedList) {
		if (i >= animationList.length) {
			boxedList.animating = null;
			return;
		}
		var delay = 0;
		switch (animationList[i].animationType) {
			case "highlight":
				var nodeSpecs = animationList[i].nodeSpecs;
				var color = animationList[i].color;
				for (var j = 0; j < nodeSpecs.length; j++) {
					var elem = boxedList.getElem(nodeSpecs[j]);
					if (elem != null) {
						elem.css("border-color", color);
					}
				}
				maxDelay = Math.max(maxDelay, TIME_HIGHLIGHT);
				delay = skipDelays ? 0 : TIME_HIGHLIGHT;
				break;
			case "unhighlight":
				var nodeSpecs = animationList[i].nodeSpecs;
				for (var j = 0; j < nodeSpecs.length; j++) {
					var elem = boxedList.getElem(nodeSpecs[j]);
					if (elem != null) {
						elem.css("border-color", "black");
					}
				}
				maxDelay = Math.max(maxDelay, TIME_UNHIGHLIGHT);
				delay = skipDelays ? 0 : TIME_UNHIGHLIGHT;
				break;
			case "translate":
				var sourceElem = boxedList.getElem(animationList[i].sourceSpec);
				var destElem = boxedList.getElem(animationList[i].destSpec);

				if(sourceElem == null || destElem == null) break;
				var sourcePosition = offsetFrom(sourceElem, mainDiv);
				var ghost = $(sourceElem[0].outerHTML);
				ghost.addClass("ghost");
				ghost.css({
					position: "absolute",
					width: sourceElem.width(),
					height: sourceElem.height()
				}).css(sourcePosition);
				mainDiv.append(ghost);
				var moveSource = animationList[i].moveSource;
				var parentCell = destElem.parent();
				ghost.animate(offsetFrom(destElem, mainDiv), TIME_TRANSLATE, function () {
					ghost.remove();
					if (moveSource) {
						parentCell.append(sourceElem);
					}
				});

				maxDelay = Math.max(maxDelay, TIME_TRANSLATE);
				delay = skipDelays ? 0 : TIME_TRANSLATE;
				break;
			case "bucket":
				var thisList = boxedList.getAdjacentBoxedList(animationList[i].visualizationSpec);
				animationList[i].addBuckets.forEach(function (e) {
					thisList.buckets.add(e + "");
				});
				animationList[i].removeBuckets.forEach(function (e) {
					thisList.buckets.delete(e + "");
				});
				thisList.elem.find("td").removeClass("bucket start end");
				thisList.buckets.forEach(function (e){
					var bucket = e.split(",");
					bucket[0] *= 1;
					bucket[1] *= 1;
					thisList.elem.find("td").slice(bucket[0], bucket[1] + 1).addClass("bucket");
					thisList.elem.find("td:nth-child(" + (1 + bucket[0]) + ")").addClass("start");
					if(bucket[0] != 0) thisList.elem.find("td:nth-child(" + (1 + bucket[0] - 1) + ")").addClass("end");
					thisList.elem.find("td:nth-child(" + (1 + bucket[1]) + ")").addClass("end");
				});
				maxDelay = Math.max(maxDelay, TIME_BUCKET);
				delay = skipDelays ? 0 : TIME_BUCKET;
				break;
			case "text":
				addConsoleCard(animationList[i].text, animationList[i].cardColor);
				delay = TIME_TEXT_PER_WORD * animationList[i].text.split(" ").length;
				maxDelay = Math.max(maxDelay, delay);
				delay = skipDelays ? 0 : delay;
				break;
			case "visibility":
				var thisList = boxedList.getAdjacentBoxedList(animationList[i].visualizationSpec);
				animationList[i].showRanges.forEach(function (e) {
					thisList.elem.find("span").slice(e[0], e[1] + 1)
						.css("visibility", "initial");
				});
				animationList[i].hideRanges.forEach(function (e) {
					thisList.elem.find("span").slice(e[0], e[1] + 1)
						.css("visibility", "hidden");
				});
				maxDelay = Math.max(maxDelay, TIME_SET_VISIBILITY);
				delay = skipDelays ? 0 : TIME_SET_VISIBILITY;
				break;
			case "swap":
				var elem1 = boxedList.getElem(animationList[i].node1);
				var elem2 = boxedList.getElem(animationList[i].node2);
				if(elem1 == elem2) break;
				var pos1 = offsetFrom(elem1, mainDiv);
				var pos2 = offsetFrom(elem2, mainDiv);
				var elemLeft = null, elemRight = null;
				var posLeft = null, posRight = null;
				if (pos1.left < pos2.left) {
					elemLeft = elem1;
					posLeft = pos1;
					elemRight = elem2;
					posRight = pos2;
				} else {
					elemLeft = elem2;
					posLeft = pos2;
					elemRight = elem1;
					posRight = pos1;
				}
				var ghostLeft = $(elemLeft[0].outerHTML);
				var ghostRight = $(elemRight[0].outerHTML);
				ghostLeft.addClass("ghost");
				ghostRight.addClass("ghost");
				ghostLeft.css({
					position: "absolute",
					width: elemLeft.width(),
					height: elemLeft.height()
				}).css(posLeft);
				ghostRight.css({
					position: "absolute",
					width: elemRight.width(),
					height: elemRight.height()
				}).css(posRight);
				mainDiv.append(ghostLeft);
				mainDiv.append(ghostRight);
				elemLeft.css("visibility", "hidden");
				elemRight.css("visibility", "hidden");
				var parentLeft = elemLeft.parent();
				var parentRight = elemRight.parent();
				parentLeft.append(elemRight);
				parentRight.append(elemLeft);
				ghostLeft.animate(posRight,{
					duration: TIME_SWAP,
					complete: function () {
						elemLeft.css("visibility", "initial");
						ghostLeft.remove();
					},
					step: function (now, fx) {
						ghostLeft.css("top", Math.sin(Math.PI * (now - fx.end) / (fx.start - fx.end)) * parentLeft.height() + posLeft.top);
					}
				});
				ghostRight.animate(posLeft,{
					duration: TIME_SWAP,
					complete: function () {
						elemRight.css("visibility", "initial");
						ghostRight.remove();
					},
					step: function (now, fx) {
						ghostRight.css("top", -Math.sin(Math.PI * (now - fx.end) / (fx.start - fx.end)) * parentRight.height() + posRight.top);
					}
				});
				maxDelay = Math.max(maxDelay, TIME_SWAP);
				delay = skipDelays ? 0 : TIME_SWAP;
				break;
			case "phase":
				var thisBoxedList = boxedList.getAdjacentBoxedList(animationList[i].vSpec);
				var thisList = thisBoxedList.elem.parents("table:first");
				var ghost = $(thisList[0].outerHTML);
				ghost.addClass("ghost");
				ghost.css({
					position: "absolute",
					width: thisList.width(),
					height: thisList.height()
				}).css(offsetFrom(thisList, mainDiv));
				mainDiv.append(ghost);
				thisList.css("opacity", "0");
				var tds = thisList.find("td").removeClass("bucket start end");
				for (var j in animationList[i].newState){
					var nodeElem = thisBoxedList.nodeMap[animationList[i].newState[j].id];
					nodeElem.css("border-color", "black");
					$(tds[j]).append(nodeElem);
				}
				ghost.animate({
					opacity: 0
				}, TIME_PHASE, function () {
					ghost.remove();
				});
				thisList.animate({
					opacity: 1
				}, TIME_PHASE);
				break;
			case "bundle":
				//console.log(animationList[i]);
				delay = boxedList.animate(animationList[i].animations, true);
				//console.log(delay);
				maxDelay = Math.max(maxDelay, delay);
				delay = skipDelays ? 0 : delay;
				break;
			default:
				break;
		}
		i++;
		if (delay > 0) {
			boxedList.animating = setTimeout(doAnim, delay, boxedList);
		} else {
			doAnim(boxedList);
		}
	};
	doAnim(this);
	return maxDelay;
};

BoxedList.prototype.getElem = function(nodeSpec) {
	var circle = this.parent;
	for(var i = 0; i < nodeSpec.parentLevel; i++) {
		circle = circle.parent;
	}

	for( var i=0; i<nodeSpec.childIndexes.length; i++) {
		circle = circle.children[nodeSpec.childIndexes[i]];
	}

	// TODO: make circles store flattened nodemaps for the two stacks
	var stack = nodeSpec.list == "start" ? circle.startStack : circle.endStack;
	var nodeMap = $.extend.apply($, stack.map(function(blist) {
		return blist.nodeMap;
	}));
	return nodeMap[nodeSpec.node.id];
};

BoxedList.prototype.getAdjacentBoxedList = function(listSpec) {
	var circle = this.parent;
	for(var i = 0; i < listSpec.parentLevel; i++) {
		circle = circle.parent;
	}

	for( var i=0; i<listSpec.childIndexes.length; i++) {
		circle = circle.children[listSpec.childIndexes[i]];
	}

	var stack = listSpec.list == "start" ? circle.startStack : circle.endStack;
	return stack[listSpec.stackIndex];
}
<|endoftext|>


<commit_before>const fs = require('fs');
const path = require('path');
const env = require('env2');
env('./config.env');

const YotiClient = require('yoti-node-sdk');
const CLIENT_SDK_ID = process.env.SDK;
const PEM = fs.readFileSync(path.join(__dirname, '../../keys_pem/help-access-security.pem'));
const yotiClient = new YotiClient(CLIENT_SDK_ID, PEM);

const userTable = require('../database/tables/users');
const userHelper = require('../helpers/userHelper');
const errorHelper = require('../helpers/errorHelper.js')

module.exports = function (token, callback) {
  yotiClient
  .getActivityDetails(token)
  .then((activityDetails) => {
    let user = userHelper.getUser(activityDetails);
    userTable.queryUserId(user, function (err, userData) {
      if (err) {
        callback(errorHelper.databaseError);
      }
      if (userData) {
        user.exists = true;
        user.admin = userData.admin;
      }
      callback(null, user);
    });
  }).catch((err) => {
    callback(errorHelper.loginError);
  });
};
<commit_msg>Comment on pem file use<commit_after>const fs = require('fs');
const path = require('path');
const env = require('env2');
env('./config.env');

const YotiClient = require('yoti-node-sdk');
const CLIENT_SDK_ID = process.env.SDK;
// local only
const PEM = fs.readFileSync(path.join(__dirname, '../../keys_pem/help-access-security.pem'));
const yotiClient = new YotiClient(CLIENT_SDK_ID, PEM);

const userTable = require('../database/tables/users');
const userHelper = require('../helpers/userHelper');
const errorHelper = require('../helpers/errorHelper.js')

module.exports = function (token, callback) {
  yotiClient
  .getActivityDetails(token)
  .then((activityDetails) => {
    let user = userHelper.getUser(activityDetails);
    userTable.queryUserId(user, function (err, userData) {
      if (err) {
        callback(errorHelper.databaseError);
      }
      if (userData) {
        user.exists = true;
        user.admin = userData.admin;
      }
      callback(null, user);
    });
  }).catch((err) => {
    callback(errorHelper.loginError);
  });
};
<|endoftext|>