<commit_before>import path from 'path';
import glob from 'glob';
import fastmatter from 'fastmatter';
import _ from 'lodash';

import {
	getExtension,
	removeExtension,
	readFile,
	writeFile,
	readYamlFile,
	formatFieldsForSortByOrder
} from './util';

/**
 * Convert file path to URL.
 *
 * @param {String} filepath
 * @return {String}
 */
export function filepathToUrl(filepath) {
	let url = '/' + removeExtension(filepath);
	url = url.replace(/\/index$/, '');
	if (url === '') {
		return '/';
	}
	return url;
}

/**
 * Renders source using appropriate renderer based on file extension.
 *
 * @param {String} source Source file contents.
 * @param {String} filepath Source file path.
 * @param {Object} renderers {ext: renderFunction}
 * @return {String}
 */
export function renderByType(source, filepath, renderers = {}) {
	let extension = getExtension(filepath);
	let render = renderers[extension];
	if (_.isFunction(render)) {
		return render(source);
	}
	return source;
}

/**
 * Return attributes object with parsed custom fields.
 *
 * @param {Object} attributes
 * @param {Object} fieldParsers  Custom field parsers: {name: parseFunction}
 * @return {Object}
 */
export function parseCustomFields(attributes, fieldParsers) {
	let parsedAttributes = {};
	for (let name in fieldParsers) {
		parsedAttributes[name] = fieldParsers[name](attributes[name], attributes);
	}
	return {...attributes, ...parsedAttributes};
}

/**
 * Parse front matter and render contents.
 *
 * @param {String} source Source file contents.
 * @param {String} folder Source folder.
 * @param {String} filepath Source file path relative to `folder`.
 * @param {Object} options.renderers Content renderers: {ext: renderFunction}.
 * @param {Object} options.fieldParsers Custom field parsers: {name: parseFunction}.
 * @param {Object} options.cutTag Cut separator.
 * @return {Object} { sourcePath, content, excerpt, more, url }
 */
export function parsePage(source, folder, filepath, { renderers = {}, fieldParsers = {}, cutTag } = {}) {
	let { attributes, body } = fastmatter(source);

	let url = filepathToUrl(filepath);

	let content = renderByType(body, filepath, renderers);

	let excerpt, more;
	if (cutTag) {
		[excerpt, more] = content.split(cutTag);
	}

	attributes = {
		...attributes,
		sourcePath: filepath,
		content,
		excerpt,
		more,
		url
	};

	attributes = parseCustomFields(attributes, fieldParsers);

	return attributes;
}

/**
 * Return list of source files.
 *
 * @param {String} folder Source folder.
 * @param {Array} types List of file extensions.
 * @return {Array}
 */
export function getSourceFilesList(folder, types) {
	let typesMask = types.join(',');
	let mask = `**/*.{${typesMask}}`;
	return glob.sync(mask, {cwd: folder});
}

/**
 * Load source files from a disk.
 *
 * @param {String} folder Source folder.
 * @param {Array} types List of file extensions.
 * @param {Object} options { renderers, fieldParsers, cutTag }
 * @return {Array} [{ sourcePath, content, url }, ...]
 */
export function loadSourceFiles(folder, types, options) {
	let files = getSourceFilesList(folder, types);
	return files.map((filepath) => {
		let source = readFile(path.join(folder, filepath));
		return parsePage(source, folder, filepath, options);
	});
}

/**
 * Return list of config files.
 *
 * @param {String} folder Configs folder.
 * @return {Array}
 */
export function getConfigFilesList(folder) {
	return glob.sync(path.join(folder, '*.yml'));
}

/**
 * Read config files from a disk.
 *
 * @param {Array} files Config files list.
 * @return {Object} {base: {...}, langs: {...}}
 */
export function readConfigFiles(files) {
	return files.reduce((configs, filepath) => {
		let name = removeExtension(path.basename(filepath));
		if (name === 'base') {
			configs.base = readYamlFile(filepath);
		}
		else {
			configs.langs[name] = readYamlFile(filepath);
		}
		return configs;
	}, {base: {}, langs: {}});
}

/**
 * Merge base config with language specific configs.
 *
 * @param {Object} configs
 * @return {Object} {base: {...}} or {langs: {...}}
 */
export function mergeConfigs(configs) {
	let { base, langs } = configs;
	let baseConfig = {
		base
	};

	if (_.isEmpty(langs)) {
		return baseConfig;
	}

	return Object.keys(langs).reduce((merged, lang) => {
		merged[lang] = {...configs.base, ...langs[lang]};
		return merged;
	}, baseConfig);
}

/**
 * Load config files from a disk.
 *
 * @param {String} folder Source folder.
 * @return {Object} {base: {...}} or {langs: {...}}
 */
export function loadConfig(folder) {
	let files = getConfigFilesList(folder);
	let configs = readConfigFiles(files);
	return mergeConfigs(configs);
}

/**
 * Filter documents.
 *
 * @param {Array} documents Documents.
 * @param {Object} fields Filters by field: {lang: 'en', url: /^posts\//}
 * @return {Array}
 */
export function filterDocuments(documents, fields) {
	return documents.filter((document) => {
		for (let field in fields) {
			let value = fields[field];
			let documentValue = document[field];
			if (_.isRegExp(value)) {
				if (!value.test(documentValue)) {
					return false;
				}
			}
			else if (documentValue !== value) {
				return false;
			}
		}
		return true;
	});
}

/**
 * Order documents.
 *
 * @param {Array} documents Documents.
 * @param {Array} fields ['foo', '-bar']
 * @return {Array}
 */
export function orderDocuments(documents, fields) {
	fields = formatFieldsForSortByOrder(fields);
	return _.sortByOrder(documents, ...fields);
}

/**
 * Group documents by values of a given field.
 *
 * @param {Array} documents Documents.
 * @param {String|Function} field Field name or function.
 * @return {Object} {fieldValue1: [...], fieldValue2: [...], ...}
 */
export function groupDocuments(documents, field) {
	return documents.reduce((grouped, document) => {
		let value = document[field];
		if (Array.isArray(value)) {
			value.forEach((subValue) => {
				if (!grouped[subValue]) {
					grouped[subValue] = [];
				}
				grouped[subValue].push(document);
			});
		}
		else {
			if (_.isFunction(field)) {
				value = field(document);
			}
			if (!value) {
				return grouped;
			}
			if (!grouped[value]) {
				grouped[value] = [];
			}
			grouped[value].push(document);
		}
		return grouped;
	}, {});
}

/**
 * Return URL for given page number.
 *
 * @param {String} urlPrefix
 * @param {Number} pageNumber
 * @param {Boolean} options.index First page will be `index` if true.
 * @return {String}
 */
export function getPageNumberUrl(urlPrefix, pageNumber, { index } = {}) {
	if (pageNumber === 1) {
		if (index) {
			return `${urlPrefix}/index`;
		}
		else {
			return urlPrefix;
		}
	}
	else {
		return `${urlPrefix}/page/${pageNumber}`;
	}
}

/**
 * Generate documents to paginate given documents.
 *
 * @param {Array} documents Documents to paginate
 * @param {String} options.sourcePathPrefix Source path prefix.
 * @param {String} options.urlPrefix URL prefix.
 * @param {Number} options.documentsPerPage Documents per page.
 * @param {String} options.layout Page layout.
 * @param {Boolean} options.index Add `index` to the first page’s source path.
 * @param {Object} options.extra Extra document options.
 * @return {Array}
 */
export function paginate(documents, { sourcePathPrefix, urlPrefix, documentsPerPage, layout, index, extra = {} } = {}) {
	if (!sourcePathPrefix) {
		throw new Error('"sourcePathPrefix" not specified for paginate().');
	}
	if (!urlPrefix) {
		throw new Error('"urlPrefix" not specified for paginate().');
	}
	if (!documentsPerPage) {
		throw new Error('"documentsPerPage" not specified for paginate().');
	}
	if (!layout) {
		throw new Error('"layout" not specified for paginate().');
	}

	let totalPages = Math.ceil(documents.length / documentsPerPage);

	return _.range(totalPages).map((pageNumber) => {
		pageNumber++;
		let sourcePath = getPageNumberUrl(sourcePathPrefix, pageNumber, { index });
		let url = getPageNumberUrl(urlPrefix, pageNumber);
		let begin = (pageNumber - 1) * documentsPerPage;
		return {
			...extra,
			previousUrl: pageNumber > 1 ? getPageNumberUrl(urlPrefix, pageNumber - 1) : null,
			nextUrl: pageNumber < totalPages ? getPageNumberUrl(urlPrefix, pageNumber + 1) : null,
			documents: documents.slice(begin, begin + documentsPerPage),
			sourcePath,
			layout,
			url
		};
	});
}

/**
 * Create context for page rendering: merges document, config and helpers into one object.
 *
 * @param {Object} document
 * @param {Object} config
 * @param {Object} helpers
 * @return {Object}
 */
export function makeContext(document, config, helpers) {
	return {
		...helpers,
		config,
		...document
	};
}

/**
 * Generate page.
 *
 * @param {Object} document
 * @param {Object} config
 * @param {Object} helpers
 * @param {Object} renderers {extension: renderFunction}
 * @return {Object} { pagePath, content }
 */
export function generatePage(document, config, helpers, renderers) {
	if (!document.sourcePath) {
		throw new Error(`Source path not specified. Add "sourcePath" front matter field.`);
	}
	if (!document.layout) {
		throw new Error(`Layout not specified for ${document.sourcePath}. Add "layout" front matter field.`);
	}

	let [templateExtension, render] = _.pairs(renderers).shift();
	let templateFile = `${document.layout}.${templateExtension}`;

	let pageContext = makeContext(document, config, helpers);
	let content = render(templateFile, pageContext);

	let pageExtension = getExtension(document.layout);
	if (!pageExtension) {
		pageExtension = 'html';
	}
	let pagePath = removeExtension(document.sourcePath) + `.${pageExtension}`;

	return {
		pagePath,
		content
	};
}

/**
 * Generate pages.
 *
 * @param {Array} documents
 * @param {Object} config
 * @param {Object} helpers
 * @param {Object} renderers {extension: renderFunction}
 * @return {Array} [{ pagePath, content }, ...]
 */
export function generatePages(documents, config, helpers, renderers) {
	return documents.map(document => generatePage(document, config, helpers, renderers));
}

/**
 * Saves page to a disk.
 *
 * @param {Object} page
 * @param {String} folder Folder to save files.
 */
export function savePage(page, folder) {
	writeFile(path.join(folder, page.pagePath), page.content);
}

/**
 * Saves pages to a disk.
 *
 * @param {Array} pages
 * @param {String} folder Folder to save files.
 */
export function savePages(pages, folder) {
	pages.forEach(page => savePage(page, folder));
}
<commit_msg>Empty string is a valid value for sourcePathPrefix and urlPrefix.<commit_after>import path from 'path';
import glob from 'glob';
import fastmatter from 'fastmatter';
import _ from 'lodash';

import {
	getExtension,
	removeExtension,
	readFile,
	writeFile,
	readYamlFile,
	formatFieldsForSortByOrder
} from './util';

/**
 * Convert file path to URL.
 *
 * @param {String} filepath
 * @return {String}
 */
export function filepathToUrl(filepath) {
	let url = '/' + removeExtension(filepath);
	url = url.replace(/\/index$/, '');
	if (url === '') {
		return '/';
	}
	return url;
}

/**
 * Renders source using appropriate renderer based on file extension.
 *
 * @param {String} source Source file contents.
 * @param {String} filepath Source file path.
 * @param {Object} renderers {ext: renderFunction}
 * @return {String}
 */
export function renderByType(source, filepath, renderers = {}) {
	let extension = getExtension(filepath);
	let render = renderers[extension];
	if (_.isFunction(render)) {
		return render(source);
	}
	return source;
}

/**
 * Return attributes object with parsed custom fields.
 *
 * @param {Object} attributes
 * @param {Object} fieldParsers  Custom field parsers: {name: parseFunction}
 * @return {Object}
 */
export function parseCustomFields(attributes, fieldParsers) {
	let parsedAttributes = {};
	for (let name in fieldParsers) {
		parsedAttributes[name] = fieldParsers[name](attributes[name], attributes);
	}
	return {...attributes, ...parsedAttributes};
}

/**
 * Parse front matter and render contents.
 *
 * @param {String} source Source file contents.
 * @param {String} folder Source folder.
 * @param {String} filepath Source file path relative to `folder`.
 * @param {Object} options.renderers Content renderers: {ext: renderFunction}.
 * @param {Object} options.fieldParsers Custom field parsers: {name: parseFunction}.
 * @param {Object} options.cutTag Cut separator.
 * @return {Object} { sourcePath, content, excerpt, more, url }
 */
export function parsePage(source, folder, filepath, { renderers = {}, fieldParsers = {}, cutTag } = {}) {
	let { attributes, body } = fastmatter(source);

	let url = filepathToUrl(filepath);

	let content = renderByType(body, filepath, renderers);

	let excerpt, more;
	if (cutTag) {
		[excerpt, more] = content.split(cutTag);
	}

	attributes = {
		...attributes,
		sourcePath: filepath,
		content,
		excerpt,
		more,
		url
	};

	attributes = parseCustomFields(attributes, fieldParsers);

	return attributes;
}

/**
 * Return list of source files.
 *
 * @param {String} folder Source folder.
 * @param {Array} types List of file extensions.
 * @return {Array}
 */
export function getSourceFilesList(folder, types) {
	let typesMask = types.join(',');
	let mask = `**/*.{${typesMask}}`;
	return glob.sync(mask, {cwd: folder});
}

/**
 * Load source files from a disk.
 *
 * @param {String} folder Source folder.
 * @param {Array} types List of file extensions.
 * @param {Object} options { renderers, fieldParsers, cutTag }
 * @return {Array} [{ sourcePath, content, url }, ...]
 */
export function loadSourceFiles(folder, types, options) {
	let files = getSourceFilesList(folder, types);
	return files.map((filepath) => {
		let source = readFile(path.join(folder, filepath));
		return parsePage(source, folder, filepath, options);
	});
}

/**
 * Return list of config files.
 *
 * @param {String} folder Configs folder.
 * @return {Array}
 */
export function getConfigFilesList(folder) {
	return glob.sync(path.join(folder, '*.yml'));
}

/**
 * Read config files from a disk.
 *
 * @param {Array} files Config files list.
 * @return {Object} {base: {...}, langs: {...}}
 */
export function readConfigFiles(files) {
	return files.reduce((configs, filepath) => {
		let name = removeExtension(path.basename(filepath));
		if (name === 'base') {
			configs.base = readYamlFile(filepath);
		}
		else {
			configs.langs[name] = readYamlFile(filepath);
		}
		return configs;
	}, {base: {}, langs: {}});
}

/**
 * Merge base config with language specific configs.
 *
 * @param {Object} configs
 * @return {Object} {base: {...}} or {langs: {...}}
 */
export function mergeConfigs(configs) {
	let { base, langs } = configs;
	let baseConfig = {
		base
	};

	if (_.isEmpty(langs)) {
		return baseConfig;
	}

	return Object.keys(langs).reduce((merged, lang) => {
		merged[lang] = {...configs.base, ...langs[lang]};
		return merged;
	}, baseConfig);
}

/**
 * Load config files from a disk.
 *
 * @param {String} folder Source folder.
 * @return {Object} {base: {...}} or {langs: {...}}
 */
export function loadConfig(folder) {
	let files = getConfigFilesList(folder);
	let configs = readConfigFiles(files);
	return mergeConfigs(configs);
}

/**
 * Filter documents.
 *
 * @param {Array} documents Documents.
 * @param {Object} fields Filters by field: {lang: 'en', url: /^posts\//}
 * @return {Array}
 */
export function filterDocuments(documents, fields) {
	return documents.filter((document) => {
		for (let field in fields) {
			let value = fields[field];
			let documentValue = document[field];
			if (_.isRegExp(value)) {
				if (!value.test(documentValue)) {
					return false;
				}
			}
			else if (documentValue !== value) {
				return false;
			}
		}
		return true;
	});
}

/**
 * Order documents.
 *
 * @param {Array} documents Documents.
 * @param {Array} fields ['foo', '-bar']
 * @return {Array}
 */
export function orderDocuments(documents, fields) {
	fields = formatFieldsForSortByOrder(fields);
	return _.sortByOrder(documents, ...fields);
}

/**
 * Group documents by values of a given field.
 *
 * @param {Array} documents Documents.
 * @param {String|Function} field Field name or function.
 * @return {Object} {fieldValue1: [...], fieldValue2: [...], ...}
 */
export function groupDocuments(documents, field) {
	return documents.reduce((grouped, document) => {
		let value = document[field];
		if (Array.isArray(value)) {
			value.forEach((subValue) => {
				if (!grouped[subValue]) {
					grouped[subValue] = [];
				}
				grouped[subValue].push(document);
			});
		}
		else {
			if (_.isFunction(field)) {
				value = field(document);
			}
			if (!value) {
				return grouped;
			}
			if (!grouped[value]) {
				grouped[value] = [];
			}
			grouped[value].push(document);
		}
		return grouped;
	}, {});
}

/**
 * Return URL for given page number.
 *
 * @param {String} urlPrefix
 * @param {Number} pageNumber
 * @param {Boolean} options.index First page will be `index` if true.
 * @return {String}
 */
export function getPageNumberUrl(urlPrefix, pageNumber, { index } = {}) {
	if (pageNumber === 1) {
		if (index) {
			return `${urlPrefix}/index`;
		}
		else {
			return urlPrefix;
		}
	}
	else {
		return `${urlPrefix}/page/${pageNumber}`;
	}
}

/**
 * Generate documents to paginate given documents.
 *
 * @param {Array} documents Documents to paginate
 * @param {String} options.sourcePathPrefix Source path prefix.
 * @param {String} options.urlPrefix URL prefix.
 * @param {Number} options.documentsPerPage Documents per page.
 * @param {String} options.layout Page layout.
 * @param {Boolean} options.index Add `index` to the first page’s source path.
 * @param {Object} options.extra Extra document options.
 * @return {Array}
 */
export function paginate(documents, { sourcePathPrefix, urlPrefix, documentsPerPage, layout, index, extra = {} } = {}) {
	if (sourcePathPrefix === undefined) {
		throw new Error('"sourcePathPrefix" not specified for paginate().');
	}
	if (urlPrefix === undefined) {
		throw new Error('"urlPrefix" not specified for paginate().');
	}
	if (!documentsPerPage) {
		throw new Error('"documentsPerPage" not specified for paginate().');
	}
	if (!layout) {
		throw new Error('"layout" not specified for paginate().');
	}

	let totalPages = Math.ceil(documents.length / documentsPerPage);

	return _.range(totalPages).map((pageNumber) => {
		pageNumber++;
		let sourcePath = getPageNumberUrl(sourcePathPrefix, pageNumber, { index });
		let url = getPageNumberUrl(urlPrefix, pageNumber);
		let begin = (pageNumber - 1) * documentsPerPage;
		return {
			...extra,
			previousUrl: pageNumber > 1 ? getPageNumberUrl(urlPrefix, pageNumber - 1) : null,
			nextUrl: pageNumber < totalPages ? getPageNumberUrl(urlPrefix, pageNumber + 1) : null,
			documents: documents.slice(begin, begin + documentsPerPage),
			sourcePath,
			layout,
			url
		};
	});
}

/**
 * Create context for page rendering: merges document, config and helpers into one object.
 *
 * @param {Object} document
 * @param {Object} config
 * @param {Object} helpers
 * @return {Object}
 */
export function makeContext(document, config, helpers) {
	return {
		...helpers,
		config,
		...document
	};
}

/**
 * Generate page.
 *
 * @param {Object} document
 * @param {Object} config
 * @param {Object} helpers
 * @param {Object} renderers {extension: renderFunction}
 * @return {Object} { pagePath, content }
 */
export function generatePage(document, config, helpers, renderers) {
	if (!document.sourcePath) {
		throw new Error(`Source path not specified. Add "sourcePath" front matter field.`);
	}
	if (!document.layout) {
		throw new Error(`Layout not specified for ${document.sourcePath}. Add "layout" front matter field.`);
	}

	let [templateExtension, render] = _.pairs(renderers).shift();
	let templateFile = `${document.layout}.${templateExtension}`;

	let pageContext = makeContext(document, config, helpers);
	let content = render(templateFile, pageContext);

	let pageExtension = getExtension(document.layout);
	if (!pageExtension) {
		pageExtension = 'html';
	}
	let pagePath = removeExtension(document.sourcePath) + `.${pageExtension}`;

	return {
		pagePath,
		content
	};
}

/**
 * Generate pages.
 *
 * @param {Array} documents
 * @param {Object} config
 * @param {Object} helpers
 * @param {Object} renderers {extension: renderFunction}
 * @return {Array} [{ pagePath, content }, ...]
 */
export function generatePages(documents, config, helpers, renderers) {
	return documents.map(document => generatePage(document, config, helpers, renderers));
}

/**
 * Saves page to a disk.
 *
 * @param {Object} page
 * @param {String} folder Folder to save files.
 */
export function savePage(page, folder) {
	writeFile(path.join(folder, page.pagePath), page.content);
}

/**
 * Saves pages to a disk.
 *
 * @param {Array} pages
 * @param {String} folder Folder to save files.
 */
export function savePages(pages, folder) {
	pages.forEach(page => savePage(page, folder));
}
<|endoftext|>


<commit_before>(function( window, $ ) {
  var $window, $doc;

  $window = $(window);
  $doc = $( document.documentElement );

  window.componentNamespace = window.componentNamespace || window;

  Function.prototype.bind = function( context ) {
    var self = this;

    return function() {
      self.apply( context, arguments );
    };
  };

  var Tau = window.componentNamespace.Tau = function( element ) {
    var startIndex;

    this.element = element;
    this.$element = $( element );

    this.createImages();

    // TODO all of this should probably wait until the images load
    startIndex = parseInt( this.$images.first().attr("data-start") || "0", 10 );
    this.goto( startIndex );
    this.autoRotate();
    this.bind();
  };

  Tau.autoRotateDelay = 64;
  Tau.verticalScrollRatio = 4;

  Tau.prototype.change = function( delta ) {
    this.goto( this.index + delta );
  };

  Tau.prototype.goto = function( index ) {
    if( this.$current ) {
      this.$current.removeClass( "focused" );
    }

    // deal with negative indices properly
    if( index < 0 ) {
      index = this.$images.length + index;
    }

    // make sure we stay within the bounds of our image set, record the new value
    this.index = index % this.$images.length;

    // record the current focused image and make it visible
    this.$current = this.$images.eq( this.index );
    this.$current.addClass( "focused" );
  };

  // TODO transplant the attributes from the initial image
  Tau.prototype.createImages = function() {
    var $initial, src, frames;

    $initial = this.$element.find( "img" );
    src = $initial.attr( "data-src-template" );
    frames = parseInt( $initial.attr( "data-frames" ), 10 );

    for( var i = 2; i <= frames; i++) {
      this.$element.append( "" );
    }

    this.$images = this.$element.find( "img" );
  };

  Tau.prototype.bind = function() {
    $doc.bind( "mouseup touchend", this.release.bind(this) );
    this.$element.bind( "mousedown touchstart", this.track.bind(this) );
  };

  Tau.prototype.autoRotate = function() {
    this.autoInterval = setInterval(function() {
      this.change( 1 );
    }.bind(this), Tau.autoRotateDelay);
  };

  Tau.prototype.stopAutoRotate = function() {
    clearInterval( this.autoInterval );
  };

  Tau.prototype.track = function( event ) {
    // prevent dragging behavior for mousedown
    if( event.type === "mousedown"  ){
      event.preventDefault();
    }

    if( this.tracking ) {
      return;
    }

    this.tracking = true;

    this.cursorGrab();

    // calculate/store how many pixels makes for an image switch
    this.rotateThreshold = $doc[0].clientWidth / this.$images.length;

    // record the x for threshold calculations
    this.downX = this.getX( event );
    this.downY = this.getY( event );
    this.downIndex = this.index;

    $doc.bind( "mousemove", this.rotate.bind(this) );
    $doc.bind( "touchmove", this.rotate.bind(this) );
  };

  Tau.prototype.release = function( event ) {
    this.cursorRelease();
    $doc.unbind( "mousemove", this.rotate.bind(this) );
    $doc.unbind( "touchmove", this.rotate.bind(this) );
    this.tracking = false;
  };

  Tau.prototype.cursorGrab = function() {
    $doc.addClass( "grabbing" );
    this.$element.addClass( "grabbing" );
  };

  Tau.prototype.cursorRelease = function() {
    $doc.removeClass( "grabbing" );
    this.$element.removeClass( "grabbing" );
  };

  Tau.prototype.getX = function( event ) {
    var touches = event.touches || (event.originalEvent && event.originalEvent.touches);

    if( touches ){
      return touches[0].pageX;
    }

    return event.pageX;
  };

  Tau.prototype.getY = function( event ) {
    var touches = event.touches || (event.originalEvent && event.originalEvent.touches);

    if( touches ){
      return touches[0].pageY;
    }

    return event.pageY;
  };

  Tau.prototype.rotate = function( event ) {
    var deltaX, deltaY;

    deltaX = this.getX( event ) - this.downX;
    deltaY = this.getY( event ) - this.downY;

    if( Math.abs(deltaY) / Math.abs(deltaX) >= Tau.verticalScrollRatio ) {
      return;
    }

    this.stopAutoRotate();

    // NOTE to reverse the spin direction add the delta/thresh to the downIndex
    if( Math.abs(deltaX) >= this.rotateThreshold ) {
      event.preventDefault();
      this.goto( this.downIndex - Math.round(deltaX / this.rotateThreshold) );
    }
  };
})(this, jQuery);
<commit_msg>refactor for getx and gety to getpoint<commit_after>(function( window, $ ) {
  var $window, $doc;

  $window = $(window);
  $doc = $( document.documentElement );

  window.componentNamespace = window.componentNamespace || window;

  Function.prototype.bind = function( context ) {
    var self = this;

    return function() {
      self.apply( context, arguments );
    };
  };

  var Tau = window.componentNamespace.Tau = function( element ) {
    var startIndex;

    this.element = element;
    this.$element = $( element );

    this.createImages();

    // TODO all of this should probably wait until the images load
    startIndex = parseInt( this.$images.first().attr("data-start") || "0", 10 );
    this.goto( startIndex );
    this.autoRotate();
    this.bind();
  };

  Tau.autoRotateDelay = 64;
  Tau.verticalScrollRatio = 4;

  Tau.prototype.change = function( delta ) {
    this.goto( this.index + delta );
  };

  Tau.prototype.goto = function( index ) {
    if( this.$current ) {
      this.$current.removeClass( "focused" );
    }

    // deal with negative indices properly
    if( index < 0 ) {
      index = this.$images.length + index;
    }

    // make sure we stay within the bounds of our image set, record the new value
    this.index = index % this.$images.length;

    // record the current focused image and make it visible
    this.$current = this.$images.eq( this.index );
    this.$current.addClass( "focused" );
  };

  // TODO transplant the attributes from the initial image
  Tau.prototype.createImages = function() {
    var $initial, src, frames;

    $initial = this.$element.find( "img" );
    src = $initial.attr( "data-src-template" );
    frames = parseInt( $initial.attr( "data-frames" ), 10 );

    for( var i = 2; i <= frames; i++) {
      this.$element.append( "" );
    }

    this.$images = this.$element.find( "img" );
  };

  Tau.prototype.bind = function() {
    $doc.bind( "mouseup touchend", this.release.bind(this) );
    this.$element.bind( "mousedown touchstart", this.track.bind(this) );
  };

  Tau.prototype.autoRotate = function() {
    this.autoInterval = setInterval(function() {
      this.change( 1 );
    }.bind(this), Tau.autoRotateDelay);
  };

  Tau.prototype.stopAutoRotate = function() {
    clearInterval( this.autoInterval );
  };

  Tau.prototype.track = function( event ) {
    var point;

    // prevent dragging behavior for mousedown
    if( event.type === "mousedown"  ){
      event.preventDefault();
    }

    if( this.tracking ) {
      return;
    }

    this.tracking = true;

    this.cursorGrab();

    // calculate/store how many pixels makes for an image switch
    this.rotateThreshold = $doc[0].clientWidth / this.$images.length;

    // record the x for threshold calculations
    point = this.getPoint( event );
    this.downX = point.x;
    this.downY = point.y;
    this.downIndex = this.index;

    $doc.bind( "mousemove", this.rotate.bind(this) );
    $doc.bind( "touchmove", this.rotate.bind(this) );
  };

  Tau.prototype.release = function( event ) {
    this.cursorRelease();
    $doc.unbind( "mousemove", this.rotate.bind(this) );
    $doc.unbind( "touchmove", this.rotate.bind(this) );
    this.tracking = false;
  };

  Tau.prototype.cursorGrab = function() {
    $doc.addClass( "grabbing" );
    this.$element.addClass( "grabbing" );
  };

  Tau.prototype.cursorRelease = function() {
    $doc.removeClass( "grabbing" );
    this.$element.removeClass( "grabbing" );
  };

  Tau.prototype.getPoint = function( event ) {
    var touch = event.touches || (event.originalEvent && event.originalEvent.touches);

    if( touch ){
      return {
        x: touch[0].pageX,
        y: touch[0].pageY
      };
    }

    return {
      x: event.pageX,
      y: event.pageY
    };
  };

  Tau.prototype.rotate = function( event ) {
    var deltaX, deltaY, point;

    point = this.getPoint( event );
    deltaX = point.x - this.downX;
    deltaY = point.y - this.downY;

    if( Math.abs(deltaY) / Math.abs(deltaX) >= Tau.verticalScrollRatio ) {
      return;
    }

    this.stopAutoRotate();

    // NOTE to reverse the spin direction add the delta/thresh to the downIndex
    if( Math.abs(deltaX) >= this.rotateThreshold ) {
      event.preventDefault();
      this.goto( this.downIndex - Math.round(deltaX / this.rotateThreshold) );
    }
  };
})(this, jQuery);
<|endoftext|>


<commit_before>var bindings = {};
var KEY_NAMES = {
  'backspace': 8,
  'enter': 13,
  'esc': 27
};

exports.KEY_NAMES = KEY_NAMES;
exports.hasKeybinding = hasKeybinding;
exports.attachKeybindings = exports.attachKeybinding = attachKeybindings;
exports.removeKeybindings = exports.removeKeybinding = removeKeybindings;

//- Function to call when adding keybindings
//- @arg {String} bindings - the character key to be bound
//-   || {Object} bindings - the character to listen for as the key, method as the value {[character]: method}
//- @arg {Function} method - the callback handler to call when string is passed to bindings
function attachKeybindings (binding, method) {
  if (!binding) return console.warn('attachKeybinding requires character or object for binding');
  if (typeof binding === 'string' && !method) console.warn('attachKeybindings requries method as second arg');
  if (hasKeybinding(binding, method)) return console.warn(`attachKeybinding: already attached ${binding} to method`, method);

  if (typeof binding === 'string') addMethod(binding, method);
  else Object.keys(binding).forEach((key) => addMethod(key, binding[key]))
}

//- Function to call to remove keybindings
//- @arg {String} bindings - the character key to be removed
//    || {Object} bindings - the character to remove, with method as the value {[character]: method}
//- @arg {Function} method - the callback handler to call when string is passed to bindingsr
function removeKeybindings (bindings, method) {
  if (!bindings) return;
  if (typeof bindings === 'string' && !method) console.warn('removeKeybindings requries method as second arg');
  if (typeof bindings === 'string') return removeMethod(bindings, method);
  Object.keys(bindings).forEach((key) => removeMethod(key, bindings[key]));
}

//- Adds the event to window and the methods to bindings
//- @arg {String} char     - the character key to be bound
//- @arg {Function} method - the callback handler to call
function addMethod (char, method) {
  var keyIsBound = hasKeybinding(char);
  var listener = keyupHandler.bind(null, char, method);

  bindings[char] = bindings[char] || {methods: [], listeners: []};

  if (keyIsBound) window.removeEventListener('keyup', bindings[char].listeners[0]);

  bindings[char].methods.unshift(method);
  bindings[char].listeners.unshift(listener);
  window.addEventListener('keyup', listener);
}

//- Removes the event from window and the methods from bindings
//- @arg {String} char     - the character key to be removed
//- @arg {Function} method - the callback handler to remove
function removeMethod (char, method) {
  if (!hasKeybinding(char, method)) return;
  var fnIndex = bindings[char].methods.indexOf(method);
  window.removeEventListener('keyup', bindings[char].listeners[fnIndex]);
  bindings[char].methods.splice(fnIndex, 1);
  bindings[char].listeners.splice(fnIndex, 1);

  if (!bindings[char].methods.length) {
    delete bindings[char];
  } else if (fnIndex === 0) {
    window.addEventListener('keyup', bindings[char].listeners[0]);
  }
}

//- Returns Boolean if key is bound to a method, or if any bindings exist for that character
//- @arg {String} key - character in question
//- @arg {Function} method - used when you want to know if a key has been bound to a method.
function hasKeybinding (key, method) {
  if (!bindings[key]) return false;
  return method ? !!~bindings[key].methods.indexOf(method) : true;
}

// The method we call to parse the event for the key pressed
//- @arg {String}   matchChar - the character to match
//- @arg {Function} method    - function to call when the key specified is pressed
//- @arg {Object}   evt       - default browser keyup event
function keyupHandler (matchChar, method, evt) {
  // except for esc, we don't want to fire events when somebody is typing in an input
  if ((evt.target.tagName !== 'INPUT' && evt.target.tagName !== 'TEXTAREA' && !evt.target.hasAttribute('contenteditable')) || evt.keyCode === KEY_NAMES.esc) {
    if (evt.keyCode === KEY_NAMES[matchChar] || String.fromCharCode(evt.keyCode) === matchChar.toUpperCase()) method(evt);
  }
}
<commit_msg>deprecate keyCode in favor of key<commit_after>var bindings = {};
var KEYS = {
  'backspace': 'Backspace',
  'enter': 'Enter',
  'esc': 'Escape'
}
var KEY_NAMES = {
  'backspace': 8,
  'enter': 13,
  'esc': 27
};

exports.KEY_NAMES = KEY_NAMES;
exports.hasKeybinding = hasKeybinding;
exports.attachKeybindings = exports.attachKeybinding = attachKeybindings;
exports.removeKeybindings = exports.removeKeybinding = removeKeybindings;

//- Function to call when adding keybindings
//- @arg {String} bindings - the character key to be bound
//-   || {Object} bindings - the character to listen for as the key, method as the value {[character]: method}
//- @arg {Function} method - the callback handler to call when string is passed to bindings
function attachKeybindings (binding, method) {
  if (!binding) return console.warn('attachKeybinding requires character or object for binding');
  if (typeof binding === 'string' && !method) console.warn('attachKeybindings requries method as second arg');
  if (hasKeybinding(binding, method)) return console.warn(`attachKeybinding: already attached ${binding} to method`, method);

  if (typeof binding === 'string') addMethod(binding, method);
  else Object.keys(binding).forEach((key) => addMethod(key, binding[key]))
}

//- Function to call to remove keybindings
//- @arg {String} bindings - the character key to be removed
//    || {Object} bindings - the character to remove, with method as the value {[character]: method}
//- @arg {Function} method - the callback handler to call when string is passed to bindingsr
function removeKeybindings (bindings, method) {
  if (!bindings) return;
  if (typeof bindings === 'string' && !method) console.warn('removeKeybindings requries method as second arg');
  if (typeof bindings === 'string') return removeMethod(bindings, method);
  Object.keys(bindings).forEach((key) => removeMethod(key, bindings[key]));
}

//- Adds the event to window and the methods to bindings
//- @arg {String} char     - the character key to be bound
//- @arg {Function} method - the callback handler to call
function addMethod (char, method) {
  var keyIsBound = hasKeybinding(char);
  var listener = keyupHandler.bind(null, char, method);

  bindings[char] = bindings[char] || {methods: [], listeners: []};

  if (keyIsBound) window.removeEventListener('keyup', bindings[char].listeners[0]);

  bindings[char].methods.unshift(method);
  bindings[char].listeners.unshift(listener);
  window.addEventListener('keyup', listener);
}

//- Removes the event from window and the methods from bindings
//- @arg {String} char     - the character key to be removed
//- @arg {Function} method - the callback handler to remove
function removeMethod (char, method) {
  if (!hasKeybinding(char, method)) return;
  var fnIndex = bindings[char].methods.indexOf(method);
  window.removeEventListener('keyup', bindings[char].listeners[fnIndex]);
  bindings[char].methods.splice(fnIndex, 1);
  bindings[char].listeners.splice(fnIndex, 1);

  if (!bindings[char].methods.length) {
    delete bindings[char];
  } else if (fnIndex === 0) {
    window.addEventListener('keyup', bindings[char].listeners[0]);
  }
}

//- Returns Boolean if key is bound to a method, or if any bindings exist for that character
//- @arg {String} key - character in question
//- @arg {Function} method - used when you want to know if a key has been bound to a method.
function hasKeybinding (key, method) {
  if (!bindings[key]) return false;
  return method ? !!~bindings[key].methods.indexOf(method) : true;
}

// The method we call to parse the event for the key pressed
//- @arg {String}   matchChar - the character to match
//- @arg {Function} method    - function to call when the key specified is pressed
//- @arg {Object}   evt       - default browser keyup event
function keyupHandler (matchChar, method, evt) {
  // except for esc, we don't want to fire events when somebody is typing in an input
  if ((evt.target.tagName !== 'INPUT' && evt.target.tagName !== 'TEXTAREA' && !evt.target.hasAttribute('contenteditable')) || keysMatch(evt, 'esc')) {
    if (keysMatch(evt, matchChar)) method(evt);
  }
}

function keysMatch (evt, matchChar) {
  if (evt.code) {
    return evt.key === KEYS[matchChar] || evt.key === matchChar;
  } else if (evt.keyCode) {
    // KeyCode is being deprecated https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
    return evt.keyCode === KEY_NAMES[matchChar] || String.fromCharCode(evt.keyCode) === matchChar.toUpperCase();
  }
}<|endoftext|>


<commit_before>describe("MealCtrl", function() {

    var scope, controller;
    beforeEach(module('App'));

    beforeEach(inject(function (
        $rootScope,
        $controller,
        $ionicModal,
        $ionicLoading,
        $ionicPopup,
        Meals,
        $filter,
        $window,
        $ionicSideMenuDelegate) {

            scope = $rootScope.$new();

            controller = $controller('MealCtrl', {
                $scope: scope,
                $rootScope: $rootScope,
                $ionicModal: $ionicModal,
                $ionicLoading: $ionicLoading,
                $ionicPopup: $ionicPopup,
                Meals: Meals,
                $filter: $filter,
                $window: $window,
                $ionicSideMenuDelegate: $ionicSideMenuDelegate

            });
    }));

    it("should have a scope variable defined", function() {
        expect(scope).toBeDefined();
    });

    it("should have at least one registration", function(){
        expect(scope.Registrations.length).not.toEqual(0);
    });

    it("should be able to find a registered meal from id", function(){
        expect(scope.getRegistrationByID(1).userSSN).toEqual(1234567890);
    });

    it("should be able to register a meal registration", function(){
        scope.data = {};
        scope.data.userSSN = 1234567890;

        scope.createRegistration();
        expect(scope.getRegistrationByID(scope.Regisrations.All.count-1).userSSN).toEqual(1234567890);
    });
});

<commit_msg>Chenged the test to use RegistrationController instead of meal controller<commit_after>describe("RegistrationCtrl", function() {

    var scope, controller;
    beforeEach(module('App'));

    beforeEach(inject(function (
        $rootScope,
        $controller,
        $ionicModal,
        $ionicLoading,
        $ionicPopup,
        Meals,
        $filter,
        $window,
        $ionicSideMenuDelegate) {

            scope = $rootScope.$new();

            controller = $controller('RegistrationCtrl', {
                $scope: scope,
                $rootScope: $rootScope,
                $ionicModal: $ionicModal,
                $ionicLoading: $ionicLoading,
                $ionicPopup: $ionicPopup,
                Meals: Meals,
                $filter: $filter,
                $window: $window,
                $ionicSideMenuDelegate: $ionicSideMenuDelegate

            });
    }));

    it("should have a scope variable defined", function() {
        expect(scope).toBeDefined();
    });

    it("should have at least one registration", function(){
        expect(scope.registrations.length).not.toEqual(0);
    });

    it("should be able to find a registered meal from id", function(){
        expect(scope.getRegistrationByID(1).userSSN).toEqual(1234567890);
    });

    it("should be able to register a meal registration", function(){
        scope.data = {};
        scope.data.userSSN = 1234567890;

        scope.createRegistration();
        expect(scope.getRegistrationByID(scope.Regisrations.All.count-1).userSSN).toEqual(1234567890);
    });

//    it("should be able to change amount");
});

<|endoftext|>


<commit_before>// Commands
//   bocbot [give me|spread some] joy|love - Get a random meme from thecodinglove.com

var cheerio = require('cheerio');

module.exports = function(robot){

	robot.codinglove = {

		url: 'http://thecodinglove.com/random',
		textSelector: 'body .post h3',
		imageSelector: 'body .post img',

		loadRequestData: function(data){
			this.$ = cheerio.load(data);
		},

		send: function(response, location){
			var self = this,
				url = !!location ? location : this.url;

			response.http(url).get()(function(err, res, body){
				if (!!err)
					return response.send('Unable to process request');

				// If site responds with a redirect, get new location and try again
				if (res.statusCode == 301 || res.statusCode == 302){
					var loc = res.headers['location'];
					return self.send(response, loc);
				}

				// Initialize cheerio
				this.loadRequestData(body);

				// Scrape inportant data from page
				var caption = self.getText();
				var imgUrl = self.getImage();

				// If image url is from 'i.minus.com', do the request again because that site no longer works
				if (imgUrl.indexOf('i.minus.com') >= 0)
					return self.send(response);

				response.send(robot.util.capitalize(caption) + '\n' + imgUrl);
			});
		},

		getImage: function(){
			return $(this.imageSelector).first().attr('src');
		},

		getText: function(){
			return $(this.textSelector).first().text();
		}
	};

	robot.respond(/((give me|spread) some )?(joy|love)/i, function(res){
		robot.codinglove.send(res);
	});
}<commit_msg>Fix logical errors in codinglove.js<commit_after>// Commands
//   bocbot [give me|spread some] joy|love - Get a random meme from thecodinglove.com

var cheerio = require('cheerio');

module.exports = function(robot){

	robot.codinglove = {

		url: 'http://thecodinglove.com/random',
		textSelector: 'body .post h3',
		imageSelector: 'body .post img',

		loadRequestData: function(data){
			this.$ = cheerio.load(data);
		},

		send: function(response, location){
			var self = this,
				url = !!location ? location : this.url;

			response.http(url).get()(function(err, res, body){
				if (!!err)
					return response.send('Unable to process request');

				// If site responds with a redirect, get new location and try again
				if (res.statusCode == 301 || res.statusCode == 302){
					var loc = res.headers['location'];
					return self.send(response, loc);
				}

				// Initialize cheerio
				self.loadRequestData(body);

				// Scrape inportant data from page
				var caption = self.getText();
				var imgUrl = self.getImage();

				// If image url is from 'i.minus.com', do the request again because that site no longer works
				if (imgUrl.indexOf('i.minus.com') >= 0)
					return self.send(response);

				response.send(robot.util.capitalize(caption) + '\n' + imgUrl);
			});
		},

		getImage: function(){
			return this.$(this.imageSelector).first().attr('src');
		},

		getText: function(){
			return this.$(this.textSelector).first().text();
		}
	};

	robot.respond(/((give me|spread) some )?(joy|love)/i, function(res){
		robot.codinglove.send(res);
	});
}<|endoftext|>


<commit_before>var boot_params = require('./boot_params');
var fw = require('./fw');
var platforms = require('./platforms');
var servers = require('./servers');
var tasks = require('./tasks');
var ur = require('./ur');
var vms = require('./vms');
var zfs = require('./zfs');
var verror = require('verror');
var restify = require('restify');
var ModelServer = require('../models/server');
var assert = require('assert-plus');

var CONNECTION_CHECKS = {
    moray: ensureConnectedToMoray,
    amqp: ensureConnectedToAMQP,
    redis: ensureConnectedToRedis,
    workflow: ensureConnectedToWorkflow
};

var PREPOPULATE_FNS = {
    server: prepopulateServer,
    vm: prepopulateVm
};

function ensureConnectedToMoray(opts, req, res, next) {
    if (!opts.app.getModel().moray.connected) {
        next(new restify.InternalError(
            'Precondition failed: no connection moray'));
        return;
    }
    next();
}

function ensureConnectedToAMQP(opts, req, res, next) {
    if (!opts.app.amqpConnection.connected) {
        next(new restify.InternalError(
            'Precondition failed: no connection to AMQP'));
        return;
    }
    next();
}

function ensureConnectedToRedis(opts, req, res, next) {
    if (!opts.app.getModel().redis.isConnected()) {
        next(new restify.InternalError(
            'Precondition failed: no connection to Redis'));
        return;
    }
    next();
}

function ensureConnectedToWorkflow(opts, req, res, next) {
    if (!opts.app.getModel().workflow.connected) {
        next(new restify.InternalError(
            'Precondition failed: no connection to Workflow API'));
        return;
    }
    next();
}

function ensureConnectionTimeout(opts, req, res, next) {
    req.connection.setTimeout(opts.connectionTimeoutSeconds * 1000);
    next();
}

function prepopulateServer(opts, req, res, next) {
    assert.string(req.params.server_uuid, 'server_uuid');

    req.stash.server = new ModelServer(req.params.server_uuid);
    req.stash.server.getRaw(function (error, server) {
        // Check if any servers were returned
        if (!server) {
            var errorMsg = 'Server ' + req.params.server_uuid + ' not found';
            next(new restify.ResourceNotFoundError(errorMsg));
            return;
        }
        next();
    });
}

function prepopulateVm(opts, req, res, next) {
    assert.string(req.params.uuid, 'uuid');

    var uuid = req.params.uuid;
    req.stash.server.cacheCheckVmExists(
        req.params.uuid,
        function (cacheError, exists) {
            var errorMsg;
            if (!exists) {
                errorMsg = 'VM ' + uuid + ' not found';
                next(
                    new restify.ResourceNotFoundError(
                        errorMsg));
                    return;
            }

            req.stash.vm = req.stash.server.getVM(uuid);
            next();
        });
}

function ensure(opts) {
    var fns = [];

    opts.log = opts.app.getLog();
    opts.connectionTimeoutSeconds = opts.connectionTimeoutSeconds || 60 * 60;

    // Override timeout
    fns.push(function (req, res, next) {
        if (!req.stash) {

            if (!opts.app.getModel()) {
                res.send(500, 'CNAPI model not yet initialized');
            } else {
                req.stash = {};
                req.stash.app = opts.app;
                req.stash.model = opts.app.getModel();
            }
        }
        next();
    });

    fns.push(function (req, res, next) {
        ensureConnectionTimeout(opts, req, res, next);
    });

    var connected = opts.connected || {};
    var prepopulate = opts.prepopulate || [];

    connected.forEach(function (service) {
        if (!CONNECTION_CHECKS.hasOwnProperty(service)) {
            throw (
                new verror.VError(
                    'unknown service for precondition check, %s', service));
        }

        fns.push(function (req, res, next) {
            CONNECTION_CHECKS[service](opts, req, res, next);
        });
    });

    prepopulate.forEach(function (resource) {
        if (!PREPOPULATE_FNS.hasOwnProperty(resource)) {
            throw (
                new verror.VError(
                    'unknown resource for prepopulation, %s', resource));
        }

        fns.push(function (req, res, next) {
            PREPOPULATE_FNS[resource](opts, req, res, next);
        });
    });

    return fns;
}

/**
 * Return CNAPI's service status details.
 *
 * @name Ping
 * @endpoint GET /ping
 * @section Ping
 *
 * @example GET /ping
 *
 * @response 200 Object Status details.
 */

function ping(app, req, res, next) {
    var services = {
        redis:
            (app.getModel().redis.isConnected()) ? 'online' : 'offline',
        workflow:
            (app.getModel().workflow.client &&
             app.getModel().workflow.connected) ? 'online' : 'offline',
        moray:
            (app.getModel().moray._morayClient &&
             app.getModel().moray.connected) ? 'online' : 'offline',
        amqp:
            (app.amqpConnection &&
             app.amqpConnection.connected) ? 'online' : 'offline'
    };
    res.send(200, {
        ready:
            services.redis === 'online' &&
            services.workflow === 'online' &&
            services.moray === 'online' &&
            services.amqp === 'online',
        services: services
    });
    next();
}

function attachTo(http, app) {
    http.post(
        '/loglevel',
        function (req, res, next) {
            var level = req.params.level;
            app.getLog().debug('Setting loglevel to %s', level);
            app.getLog().level(level);
            res.send();
            return next();
        });

    http.get(
        '/loglevel',
        function (req, res, next) {
            res.send({ level: app.getLog().level() });
            return next();
        });

    http.get('/ping', function (req, res, next) {
        ping(app, req, res, next);
    });

    fw.attachTo(http, app);
    platforms.attachTo(http, app);
    servers.attachTo(http, app);
    vms.attachTo(http, app);
    tasks.attachTo(http, app);
    boot_params.attachTo(http, app);
    ur.attachTo(http, app);
    zfs.attachTo(http, app);
}

exports.attachTo = attachTo;
exports.ensure = ensure;
<commit_msg>CNAPI-215: Do not return 404 if there was an error fetching server<commit_after>var boot_params = require('./boot_params');
var fw = require('./fw');
var platforms = require('./platforms');
var servers = require('./servers');
var tasks = require('./tasks');
var ur = require('./ur');
var vms = require('./vms');
var zfs = require('./zfs');
var verror = require('verror');
var restify = require('restify');
var ModelServer = require('../models/server');
var assert = require('assert-plus');

var CONNECTION_CHECKS = {
    moray: ensureConnectedToMoray,
    amqp: ensureConnectedToAMQP,
    redis: ensureConnectedToRedis,
    workflow: ensureConnectedToWorkflow
};

var PREPOPULATE_FNS = {
    server: prepopulateServer,
    vm: prepopulateVm
};

function ensureConnectedToMoray(opts, req, res, next) {
    if (!opts.app.getModel().moray.connected) {
        next(new restify.InternalError(
            'Precondition failed: no connection moray'));
        return;
    }
    next();
}

function ensureConnectedToAMQP(opts, req, res, next) {
    if (!opts.app.amqpConnection.connected) {
        next(new restify.InternalError(
            'Precondition failed: no connection to AMQP'));
        return;
    }
    next();
}

function ensureConnectedToRedis(opts, req, res, next) {
    if (!opts.app.getModel().redis.isConnected()) {
        next(new restify.InternalError(
            'Precondition failed: no connection to Redis'));
        return;
    }
    next();
}

function ensureConnectedToWorkflow(opts, req, res, next) {
    if (!opts.app.getModel().workflow.connected) {
        next(new restify.InternalError(
            'Precondition failed: no connection to Workflow API'));
        return;
    }
    next();
}

function ensureConnectionTimeout(opts, req, res, next) {
    req.connection.setTimeout(opts.connectionTimeoutSeconds * 1000);
    next();
}

function prepopulateServer(opts, req, res, next) {
    assert.string(req.params.server_uuid, 'server_uuid');

    req.stash.server = new ModelServer(req.params.server_uuid);
    req.stash.server.getRaw(function (error, server) {
        if (error) {
            req.log.error(error);
            next(new restify.InternalError(error.message));
            return;
        }

        // Check if any servers were returned
        if (!server) {
            var errorMsg = 'Server ' + req.params.server_uuid + ' not found';
            next(new restify.ResourceNotFoundError(errorMsg));
            return;
        }
        next();
    });
}

function prepopulateVm(opts, req, res, next) {
    assert.string(req.params.uuid, 'uuid');

    var uuid = req.params.uuid;
    req.stash.server.cacheCheckVmExists(
        req.params.uuid,
        function (cacheError, exists) {
            var errorMsg;
            if (!exists) {
                errorMsg = 'VM ' + uuid + ' not found';
                next(
                    new restify.ResourceNotFoundError(
                        errorMsg));
                    return;
            }

            req.stash.vm = req.stash.server.getVM(uuid);
            next();
        });
}

function ensure(opts) {
    var fns = [];

    opts.log = opts.app.getLog();
    opts.connectionTimeoutSeconds = opts.connectionTimeoutSeconds || 60 * 60;

    // Override timeout
    fns.push(function (req, res, next) {
        if (!req.stash) {

            if (!opts.app.getModel()) {
                res.send(500, 'CNAPI model not yet initialized');
            } else {
                req.stash = {};
                req.stash.app = opts.app;
                req.stash.model = opts.app.getModel();
            }
        }
        next();
    });

    fns.push(function (req, res, next) {
        ensureConnectionTimeout(opts, req, res, next);
    });

    var connected = opts.connected || {};
    var prepopulate = opts.prepopulate || [];

    connected.forEach(function (service) {
        if (!CONNECTION_CHECKS.hasOwnProperty(service)) {
            throw (
                new verror.VError(
                    'unknown service for precondition check, %s', service));
        }

        fns.push(function (req, res, next) {
            CONNECTION_CHECKS[service](opts, req, res, next);
        });
    });

    prepopulate.forEach(function (resource) {
        if (!PREPOPULATE_FNS.hasOwnProperty(resource)) {
            throw (
                new verror.VError(
                    'unknown resource for prepopulation, %s', resource));
        }

        fns.push(function (req, res, next) {
            PREPOPULATE_FNS[resource](opts, req, res, next);
        });
    });

    return fns;
}

/**
 * Return CNAPI's service status details.
 *
 * @name Ping
 * @endpoint GET /ping
 * @section Ping
 *
 * @example GET /ping
 *
 * @response 200 Object Status details.
 */

function ping(app, req, res, next) {
    var services = {
        redis:
            (app.getModel().redis.isConnected()) ? 'online' : 'offline',
        workflow:
            (app.getModel().workflow.client &&
             app.getModel().workflow.connected) ? 'online' : 'offline',
        moray:
            (app.getModel().moray._morayClient &&
             app.getModel().moray.connected) ? 'online' : 'offline',
        amqp:
            (app.amqpConnection &&
             app.amqpConnection.connected) ? 'online' : 'offline'
    };
    res.send(200, {
        ready:
            services.redis === 'online' &&
            services.workflow === 'online' &&
            services.moray === 'online' &&
            services.amqp === 'online',
        services: services
    });
    next();
}

function attachTo(http, app) {
    http.post(
        '/loglevel',
        function (req, res, next) {
            var level = req.params.level;
            app.getLog().debug('Setting loglevel to %s', level);
            app.getLog().level(level);
            res.send();
            return next();
        });

    http.get(
        '/loglevel',
        function (req, res, next) {
            res.send({ level: app.getLog().level() });
            return next();
        });

    http.get('/ping', function (req, res, next) {
        ping(app, req, res, next);
    });

    fw.attachTo(http, app);
    platforms.attachTo(http, app);
    servers.attachTo(http, app);
    vms.attachTo(http, app);
    tasks.attachTo(http, app);
    boot_params.attachTo(http, app);
    ur.attachTo(http, app);
    zfs.attachTo(http, app);
}

exports.attachTo = attachTo;
exports.ensure = ensure;
<|endoftext|>


<commit_before>
/*
Common decorators
@author Jared Smith
Remember to compile with the -b (bare) flag!
 */

(function() {
  var __slice = [].slice;

  (function(root, main) {
    var MOD_NAME;
    MOD_NAME = 'Decorators';
    switch (false) {
      case !((typeof module !== "undefined" && module !== null) && (module.exports != null)):
        return module.exports = main(root);
      case !(typeof define === 'function' && define.amd):
        return define(main.bind(root, root));
      default:
        return root[MOD_NAME] = main(root);
    }
  })((typeof window !== "undefined" && window !== null ? window : null), function(_global) {
    'use strict';
    var checkJSON, curry, debounce, denodeify, log, onlyIf, runTime, setLocalStorage, throttle, timeoutP, unGather, unNew, workerify, _getFnName, _invalidArgumentError, _isArray, _noGlobalCtx;
    _invalidArgumentError = new TypeError("Invalid argument");
    _getFnName = function(fn) {
      if (typeof fn !== 'function') {
        throw _invalidArgumentError;
      }
      if (fn.name != null) {
        return fn.name;
      } else {
        return fn.toString().match(/^\s*function\s*(\S*)\s*\(/)[1];
      }
    };
    _isArray = function(a) {
      return (Object.prototype.toString.call(a) === "[object Array]") || (a instanceof Array);
    };
    _noGlobalCtx = function(fn) {
      if (typeof fn !== 'function') {
        throw _invalidArgumentError;
      }
      return curry(fn.length, function() {
        var args, context;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        context = this === _global ? null : this;
        return fn.apply(context, args);
      });
    };
    curry = (function() {
      var _curry;
      _curry = function() {
        var args, fn;
        fn = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
        return function() {
          var fnArgs;
          fnArgs = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
          return fn.apply(this, args.concat(fnArgs));
        };
      };
      curry = function(n, f) {
        var fn, length, _ref, _ref1;
        fn = null;
        length = 0;
        switch (false) {
          case f == null:
            if (typeof f !== 'function' || typeof n !== 'number') {
              throw _invalidArgumentError;
            }
            _ref = [f, n], fn = _ref[0], length = _ref[1];
            break;
          case typeof n !== 'function':
            _ref1 = [n, n.length], fn = _ref1[0], length = _ref1[1];
            break;
          case typeof n !== 'number':
            return function(fn) { return curry.call(this, n, fn); };
            break;
          default:
            throw _invalidArgumentError;
        }
        return function() {
          var concated, context, currLength, fnArgs, val;
          fnArgs = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
          context = this === _global ? null : this;
          if (fnArgs.length < length) {
            concated = [fn].concat(fnArgs);
            currLength = length - fnArgs.length;
            val = currLength > 0 ? curry(currLength, _curry.apply(context, concated)) : _curry.apply(context, concated);
            return val;
          } else {
            return fn.apply(context, fnArgs);
          }
        };
      };
      return curry;
    })();
    unGather = (function(_this) {
      return function() {
        var args, fn, func, initArgs;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        fn = args[0], initArgs = 2 <= args.length ? __slice.call(args, 1) : [];
        if (typeof fn !== 'function') {
          throw _invalidArgumentError;
        }
        func = _noGlobalCtx(function() {
          var fnArgs, params;
          fnArgs = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
          params = fnArgs.length === 1 && _isArray(fnArgs[0]) ? fnArgs[0] : fnArgs;
          return fn.apply(this, params);
        });
        if (initArgs.length) {
          return func.apply(_this, initArgs);
        } else {
          return func;
        }
      };
    })(this);
    onlyIf = function(fn) {
      if (typeof fn !== 'function') {
        throw _invalidArgumentError;
      }
      return _noGlobalCtx(unGather(function() {
        var args, passed;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        passed = fn.length && args.length === 0 ? false : args.every(function(x) {
          return x != null;
        });
        if (passed) {
          return fn.apply(this, args);
        } else {
          return null;
        }
      }));
    };
    debounce = curry(function(delay, fn) {
      var timer;
      timer = null;
      return _noGlobalCtx(function() {
        var args;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        clearTimeout(timer);
        timer = setTimeout(((function(_this) {
          return function() {
            return fn.apply(_this, args);
          };
        })(this)), delay);
        return timer;
      });
    });
    throttle = curry(function(delay, fn) {
      var last, timer;
      last = null;
      timer = null;
      return _noGlobalCtx(function() {
        var args, now;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        now = Date.now();
        if ((last != null) && now < last + delay) {
          clearTimeout(timer);
          return timer = setTimeout(((function(_this) {
            return function() {
              last = now;
              return fn.apply(_this, args);
            };
          })(this)), delay);
        } else {
          last = now;
          return fn.apply(this, args);
        }
      });
    });
    log = function(fn) {
      return curry(fn.length, _noGlobalCtx(function() {
        var args, calledArgs, name, res, str;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        res = fn.apply(this, args);
        str = (function() {
          switch (typeof res) {
            case 'object':
              return JSON.stringify(res);
            case 'string':
              return res;
            default:
              return res.toString();
          }
        })();
        name = _getFnName(fn) || "Anonymous";
        calledArgs = args.length ? args : "none";
        console.log("Function " + name + " called with arguments " + calledArgs + " and yielded " + str);
        return res;
      }));
    };
    setLocalStorage = function(fn, prop, val) {
      if (prop == null) {
        prop = 'label';
      }
      if (val == null) {
        val = 'value';
      }
      return function(e) {
        var key, result, value;
        result = fn(e);
        if (_isArray(result)) {
          key = result[0], value = result[1];
        }
        if (key == null) {
          key = e.target[prop] || e.target.parentNode.innerText.trim();
        }
        if (value == null) {
          value = ((function() {
            switch (typeof e.target[val]) {
              case 'string':
              case 'undefined':
                return e.target[val];
              default:
                return e.target[val].toString();
            }
          })()).trim();
        }
        if (key && (value != null)) {
          localStorage.setItem(key, value);
        }
        return e;
      };
    };
    denodeify = (function(_this) {
      return function(fn) {
        return _noGlobalCtx(function() {
          var args;
          args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
          return new Promise(function(resolve, reject) {
            return fn.apply(this, args.concat([
              (function() {
                var err, res, resArgs;
                err = arguments[0], resArgs = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
                if (err != null) {
                  reject(err);
                }
                res = (function() {
                  switch (resArgs.length) {
                    case 0:
                      return true;
                    case 1:
                      return resArgs[0];
                    default:
                      return resArgs;
                  }
                })();
                return resolve(res);
              })
            ]));
          });
        });
      };
    })(this);
    timeoutP = (function() {
      var err;
      err = new Error("Sorry it is taking an unusually long time to retrieve the data you requested. If you are not\nexperiencing the awesome in the next few seconds, retry your request or reload the page.\nSorry for any inconvenience.");
      return (function(_this) {
        return function(timeout, fn) {
          var func;
          if (timeout == null) {
            throw new Error("Function timeoutP called with no timeout.");
          }
          func = function() {
            var args, context;
            args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
            context = this === _global ? null : this;
            return new Promise(function(resolve, reject) {
              var promise, timer;
              promise = fn.apply(context, args);
              timer = setTimeout((function() {
                return reject(err);
              }), timeout);
              promise.then((function(val) {
                clearTimeout(testTimer);
                clearTimeout(timer);
                return resolve(val);
              }), (function(e) {
                clearTimeout(timer);
                clearTimeout(testTimer);
                return reject(e);
              }));
              return null;
            });
          };
          if (fn != null) {
            return func;
          } else {
            return function(fnArg) {
              return timeoutP(timeout, fnArg);
            };
          }
        };
      })(this);
    })();
    workerify = function(fn) {
      var blob, url, worker;
      blob = new Blob(["onmessage = function(e) { postMessage((" + fn + ")(e)); })"]);
      url = URL.createURLObject(blob);
      worker = new Worker(url);
      URL.revokeURLObject(url);
      return function(arg) {
        worker.postMessage(arg);
        return new Promise(function(resolve, reject) {
          var listener;
          listener = function(e) {
            worker.removeEventListener('message', listener);
            return resolve(e.data);
          };
          return worker.addEventListener('message', listener);
        });
      };
    };
    unNew = function() {
      var args, constructor, func, initArgs;
      initArgs = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
      constructor = initArgs[0], args = 2 <= initArgs.length ? __slice.call(initArgs, 1) : [];
      if ((constructor == null) || typeof constructor !== 'function') {
        throw _invalidArgumentError;
      }
      func = function() {
        var fnArgs;
        fnArgs = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        return new (Function.prototype.bind.apply(constructor, [constructor].concat(fnArgs)));
      };
      if (args.length) {
        return func.apply(this, args);
      } else {
        return func;
      }
    };
    checkJSON = function(f) {
      var fn, _notJSONError;
      if (typeof f !== 'function') {
        throw _invalidArgumentError;
      }
      _notJSONError = new Error("Function " + (getFnName(f)) + " should return a valid JSON string");
      fn = ifOnly(_noGlobalCtx(f));
      return function() {
        var args, json;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        json = fn.apply(this, args);
        if (typeof json !== 'string') {
          throw _notJSONError;
        }
        switch (false) {
          case !(json.length < 3):
          case !!json[0].match(/[\[,\{,0-9,n,t,f]/i):
            return null;
          default:
            return JSON.parse(json);
        }
      };
    };
    runTime = function(f) {
      var fn;
      fn = log(f);
      return function() {
        var args, res;
        args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
        console.time(getFnName(f));
        res = fn.apply(this, args);
        console.timeEnd(getFnName(f));
        return res;
      };
    };
    return {
      setLocalStorage: setLocalStorage,
      onlyIf: onlyIf,
      timeoutP: timeoutP,
      debounce: debounce,
      throttle: throttle,
      denodeify: denodeify,
      log: log,
      workerify: workerify,
      unNew: unNew,
      unGather: unGather,
      checkJSON: checkJSON,
      runTime: runTime
    };
  });

}).call(this);
<commit_msg>Added runTime Function<commit_after>// Generated by CoffeeScript 1.10.0

/*
Common decorators
@author Jared Smith
Remember to compile with the -b (bare) flag!
 */
var slice = [].slice;

(function(root, main) {
  var MOD_NAME;
  MOD_NAME = 'Decorators';
  switch (false) {
    case !((typeof module !== "undefined" && module !== null) && (module.exports != null)):
      return module.exports = main(root);
    case !(typeof define === 'function' && define.amd):
      return define(main.bind(root, root));
    default:
      return root[MOD_NAME] = main(root);
  }
})((typeof window !== "undefined" && window !== null ? window : null), function(_global) {
  'use strict';
  var _getFnName, _invalidArgumentError, _isArray, _noGlobalCtx, checkJSON, curry, debounce, denodeify, log, onlyIf, runTime, setLocalStorage, throttle, timeoutP, unGather, unNew, workerify;
  _invalidArgumentError = new TypeError("Invalid argument");
  _getFnName = function(fn) {
    if (typeof fn !== 'function') {
      throw _invalidArgumentError;
    }
    if (fn.name != null) {
      return fn.name;
    } else {
      return fn.toString().match(/^\s*function\s*(\S*)\s*\(/)[1];
    }
  };
  _isArray = function(a) {
    return (Object.prototype.toString.call(a) === "[object Array]") || (a instanceof Array);
  };
  _noGlobalCtx = function(fn) {
    if (typeof fn !== 'function') {
      throw _invalidArgumentError;
    }
    return curry(fn.length, function() {
      var args, context;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      context = this === _global ? null : this;
      return fn.apply(context, args);
    });
  };
  curry = (function() {
    var _curry;
    _curry = function() {
      var args, fn;
      fn = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
      return function() {
        var fnArgs;
        fnArgs = 1 <= arguments.length ? slice.call(arguments, 0) : [];
        return fn.apply(this, args.concat(fnArgs));
      };
    };
    curry = function(n, f) {
      var fn, length, ref, ref1;
      fn = null;
      length = 0;
      switch (false) {
        case f == null:
          if (typeof f !== 'function' || typeof n !== 'number') {
            throw _invalidArgumentError;
          }
          ref = [f, n], fn = ref[0], length = ref[1];
          break;
        case typeof n !== 'function':
          ref1 = [n, n.length], fn = ref1[0], length = ref1[1];
          break;
        case typeof n !== 'number':
          return function(fn) { return curry.call(this, n, fn); };
          break;
        default:
          throw _invalidArgumentError;
      }
      return function() {
        var concated, context, currLength, fnArgs, val;
        fnArgs = 1 <= arguments.length ? slice.call(arguments, 0) : [];
        context = this === _global ? null : this;
        if (fnArgs.length < length) {
          concated = [fn].concat(fnArgs);
          currLength = length - fnArgs.length;
          val = currLength > 0 ? curry(currLength, _curry.apply(context, concated)) : _curry.apply(context, concated);
          return val;
        } else {
          return fn.apply(context, fnArgs);
        }
      };
    };
    return curry;
  })();
  unGather = (function(_this) {
    return function() {
      var args, fn, func, initArgs;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      fn = args[0], initArgs = 2 <= args.length ? slice.call(args, 1) : [];
      if (typeof fn !== 'function') {
        throw _invalidArgumentError;
      }
      func = _noGlobalCtx(function() {
        var fnArgs, params;
        fnArgs = 1 <= arguments.length ? slice.call(arguments, 0) : [];
        params = fnArgs.length === 1 && _isArray(fnArgs[0]) ? fnArgs[0] : fnArgs;
        return fn.apply(this, params);
      });
      if (initArgs.length) {
        return func.apply(_this, initArgs);
      } else {
        return func;
      }
    };
  })(this);
  onlyIf = function(fn) {
    if (typeof fn !== 'function') {
      throw _invalidArgumentError;
    }
    return _noGlobalCtx(unGather(function() {
      var args, passed;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      passed = fn.length && args.length === 0 ? false : args.every(function(x) {
        return x != null;
      });
      if (passed) {
        return fn.apply(this, args);
      } else {
        return null;
      }
    }));
  };
  debounce = curry(function(delay, fn) {
    var timer;
    timer = null;
    return _noGlobalCtx(function() {
      var args;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      clearTimeout(timer);
      timer = setTimeout(((function(_this) {
        return function() {
          return fn.apply(_this, args);
        };
      })(this)), delay);
      return timer;
    });
  });
  throttle = curry(function(delay, fn) {
    var last, timer;
    last = null;
    timer = null;
    return _noGlobalCtx(function() {
      var args, now;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      now = Date.now();
      if ((last != null) && now < last + delay) {
        clearTimeout(timer);
        return timer = setTimeout(((function(_this) {
          return function() {
            last = now;
            return fn.apply(_this, args);
          };
        })(this)), delay);
      } else {
        last = now;
        return fn.apply(this, args);
      }
    });
  });
  log = function(fn) {
    return curry(fn.length, _noGlobalCtx(function() {
      var args, calledArgs, name, res, str;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      res = fn.apply(this, args);
      str = (function() {
        switch (typeof res) {
          case 'object':
            return JSON.stringify(res);
          case 'string':
            return res;
          default:
            return res.toString();
        }
      })();
      name = _getFnName(fn) || "Anonymous";
      calledArgs = args.length ? args : "none";
      console.log("Function " + name + " called with arguments " + calledArgs + " and yielded " + str);
      return res;
    }));
  };
  setLocalStorage = function(fn, prop, val) {
    if (prop == null) {
      prop = 'label';
    }
    if (val == null) {
      val = 'value';
    }
    return function(e) {
      var key, result, value;
      result = fn(e);
      if (_isArray(result)) {
        key = result[0], value = result[1];
      }
      if (key == null) {
        key = e.target[prop] || e.target.parentNode.innerText.trim();
      }
      if (value == null) {
        value = ((function() {
          switch (typeof e.target[val]) {
            case 'string':
            case 'undefined':
              return e.target[val];
            default:
              return e.target[val].toString();
          }
        })()).trim();
      }
      if (key && (value != null)) {
        localStorage.setItem(key, value);
      }
      return e;
    };
  };
  denodeify = (function(_this) {
    return function(fn) {
      return _noGlobalCtx(function() {
        var args;
        args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
        return new Promise(function(resolve, reject) {
          return fn.apply(this, args.concat([
            (function() {
              var err, res, resArgs;
              err = arguments[0], resArgs = 2 <= arguments.length ? slice.call(arguments, 1) : [];
              if (err != null) {
                reject(err);
              }
              res = (function() {
                switch (resArgs.length) {
                  case 0:
                    return true;
                  case 1:
                    return resArgs[0];
                  default:
                    return resArgs;
                }
              })();
              return resolve(res);
            })
          ]));
        });
      });
    };
  })(this);
  timeoutP = (function() {
    var err;
    err = new Error("Sorry it is taking an unusually long time to retrieve the data you requested. If you are not\nexperiencing the awesome in the next few seconds, retry your request or reload the page.\nSorry for any inconvenience.");
    return (function(_this) {
      return function(timeout, fn) {
        var func;
        if (timeout == null) {
          throw new Error("Function timeoutP called with no timeout.");
        }
        func = function() {
          var args, context;
          args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
          context = this === _global ? null : this;
          return new Promise(function(resolve, reject) {
            var promise, timer;
            promise = fn.apply(context, args);
            timer = setTimeout((function() {
              return reject(err);
            }), timeout);
            promise.then((function(val) {
              clearTimeout(testTimer);
              clearTimeout(timer);
              return resolve(val);
            }), (function(e) {
              clearTimeout(timer);
              clearTimeout(testTimer);
              return reject(e);
            }));
            return null;
          });
        };
        if (fn != null) {
          return func;
        } else {
          return function(fnArg) {
            return timeoutP(timeout, fnArg);
          };
        }
      };
    })(this);
  })();
  workerify = function(fn) {
    var blob, url, worker;
    blob = new Blob(["onmessage = function(e) { postMessage((" + fn + ")(e)); })"]);
    url = URL.createURLObject(blob);
    worker = new Worker(url);
    URL.revokeURLObject(url);
    return function(arg) {
      worker.postMessage(arg);
      return new Promise(function(resolve, reject) {
        var listener;
        listener = function(e) {
          worker.removeEventListener('message', listener);
          return resolve(e.data);
        };
        return worker.addEventListener('message', listener);
      });
    };
  };
  unNew = function() {
    var args, constructor, func, initArgs;
    initArgs = 1 <= arguments.length ? slice.call(arguments, 0) : [];
    constructor = initArgs[0], args = 2 <= initArgs.length ? slice.call(initArgs, 1) : [];
    if ((constructor == null) || typeof constructor !== 'function') {
      throw _invalidArgumentError;
    }
    func = function() {
      var fnArgs;
      fnArgs = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      return new (Function.prototype.bind.apply(constructor, [constructor].concat(fnArgs)));
    };
    if (args.length) {
      return func.apply(this, args);
    } else {
      return func;
    }
  };
  checkJSON = function(f) {
    var _notJSONError, fn;
    if (typeof f !== 'function') {
      throw _invalidArgumentError;
    }
    _notJSONError = new Error("Function " + (getFnName(f)) + " should return a valid JSON string");
    fn = ifOnly(_noGlobalCtx(f));
    return function() {
      var args, json;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      json = fn.apply(this, args);
      if (typeof json !== 'string') {
        throw _notJSONError;
      }
      switch (false) {
        case !(json.length < 3):
        case !!json[0].match(/[\[,\{,0-9,n,t,f]/i):
          return null;
        default:
          return JSON.parse(json);
      }
    };
  };
  runTime = function(f) {
    var fn;
    fn = log(f);
    return function() {
      var args, res;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      console.time(getFnName(f));
      res = fn.apply(this, args);
      console.timeEnd(getFnName(f));
      return res;
    };
  };
  return {
    setLocalStorage: setLocalStorage,
    onlyIf: onlyIf,
    timeoutP: timeoutP,
    debounce: debounce,
    throttle: throttle,
    denodeify: denodeify,
    log: log,
    workerify: workerify,
    unNew: unNew,
    unGather: unGather,
    checkJSON: checkJSON,
    runTime: runTime
  };
});
<|endoftext|>


<commit_before>'use strict';

var
	Promise = require('bluebird');

var
	cli = require('../../cli-logger');

var exports = module.exports = Promise.method(function (opts) {
	if (opts.set) return set(opts);
	else if (opts.get) return get(opts);
	else if (opts.remove) return remove(opts);
	else if (opts.reset) return reset(opts);
	else if (opts.value === undefined) return get(opts);
	else return remove(opts);
});

function get (opts) {
	return opts.env.get(opts.target, opts.global).then(function (value) {
		cli(value);
		return value;
	});
}

function set (opts) {
	return opts.env.set(opts.target, opts.value, opts.global, opts.array);
}

function remove (opts) {
	return opts.env.remove(opts.target, opts.value, opts.global, opts.array);
}

function reset (opts) {
	return opts.env.reset(opts.target, opts.global);
}<commit_msg>it doesn't make sense for the default to be remove in this case<commit_after>'use strict';

var
	Promise = require('bluebird');

var
	cli = require('../../cli-logger');

var exports = module.exports = Promise.method(function (opts) {
	if (opts.set) return set(opts);
	else if (opts.get) return get(opts);
	else if (opts.remove) return remove(opts);
	else if (opts.reset) return reset(opts);
	else if (opts.value === undefined) return get(opts);
	else return set(opts);
});

function get (opts) {
	return opts.env.get(opts.target, opts.global).then(function (value) {
		cli(value);
		return value;
	});
}

function set (opts) {
	return opts.env.set(opts.target, opts.value, opts.global, opts.array);
}

function remove (opts) {
	return opts.env.remove(opts.target, opts.value, opts.global, opts.array);
}

function reset (opts) {
	return opts.env.reset(opts.target, opts.global);
}<|endoftext|>


<commit_before>!function _anonymousWrapper(require, exports) {
	"use strict";

	var pd = require("pd"),
		events = require("EventEmitter2"),
		EventEmitter2 = events.EventEmitter2 || events,
		after = require("after");

	var nCore = pd.make(EventEmitter2.prototype, {
		use: use,
		remove: remove,
		destroy: destroy,
		init: init,
		constructor: constructor,
		_meta: pd.Name()
	});

	exports.nCore = nCore;

    /*
    	Attach a module to the core.

    	Calls the attach method of the module

    	@param String name - name of module
    	@param Object module - module to attach
		@param [optional] Object data - data passed to module
		@param [optional] Function callback - callback invoked
			if this module needs to be initialized
    */
	function use(name, module, data, callback) {
		if (typeof name !== "string") {
			if (name.name) {
				callback = data;
				data = module;
				module = name;
				name = module.name;
			} else {
				callback = data;
				data = module;
				return Object.keys(name).forEach(
					invokeUseOnModules, this);
			}
		}

		if (typeof data === "function" && callback === undefined) {
			callback = data;
			data = null;
		}

		if (data === undefined || data === null) {
			data = this;
		}

		if (!this._modules) {
			this._modules = {};
		}

		this._modules[name] = module;

		module.attach && module.attach.call(this, data, this);

		if (this._initialized) {
			module.init &&
				module.init.call(this, callback || noop, this);
		}

		function invokeUseOnModules(key) {
			var module = name[key];
			this.use(key, module, data, callback);
		}
	}

	/*
		Initializes all modules attached to the core

		Calls the init method of all modules

		@param [optional] Any options - ignored,
			there for backwards support with broadway
		@param Function callback - callback function
			to be invoked when all modules have initialized.

	*/
	function init(options, callback) {
		if (typeof options === "function" && callback === undefined) {
			callback = options;
			options = null;
		}

		this._initialized = true;

		if (!this._modules) return;

		var keys = Object.keys(this._modules);

		var next = after(keys.length, callback);

		keys.forEach(invokeInit, this);

		function invokeInit(name) {
			var module = this._modules[name];
			if (module.init) {
				module.init.call(this, next, this);
			} else {
				next();
			}
			this._meta(module).initialized = true;
		}
	}

	/*
		Removes a module from the core.

		Invokes the modules detach method

		@param String name - name of module to be removed
		@param [optional] Function callback - callback to be
			invoked if the module to be removed
			also needs to be destroyed
	*/
	function remove(name, callback) {
		if (typeof name !== "string") {
			if (name.name) {
				name = name.name;
			} else {
				return Object.keys(name).forEach(
					invokeRemoveOnModules, this);
			}
		}

		var module = this._modules[name];

		if (this._meta(module).initialized) {
			if (module.destroy) {
				module.destroy.call(this, callback || noop, this);
			} else {
				callback && callback();
			}
		}
		module.detach && module.detach.call(this, this);

		delete this._modules[name];

		function invokeRemoveOnModules(key) {
			this.remove(key)
		}
	}

	/*
		destroys and detaches all attached modules

		@param [optional] Function callback - callback to be
			invoked when all modules are destroyed
	*/
	function destroy(callback) {
		var keys = Object.keys(this._modules);

		var next = after(keys.length, afterDestroy.bind(this));

		keys.forEach(invokeDestroyOnModules, this);

		function invokeDestroyOnModules(name) {
			var module = this._modules[name];

			if (module.destroy) {
				module.destroy.call(this, next, this);
			} else {
				next();
			}
		}

		function afterDestroy() {
			keys.forEach(invokeDetachOnModules, this);

			callback();
		}

		function invokeDetachOnModules(name) {
			var module = this._modules[name];

			module.detach && module.detach.call(this, this);
		}
	}

	/*
		Constructor initializes the value of _meta to a new Name.
	*/
	function constructor() {
		this._meta = pd.Name();

		return this;
	}

	function noop() {

	}

}(
	function _require(name) {
		return require ? require(name) : window[name];
	},
	typeof window !== "undefined" ? window : exports
);<commit_msg>Added support for browsers by not crashing.<commit_after>!function _anonymousWrapper(require, exports) {
	"use strict";

	var pd = require("pd"),
		events = require("EventEmitter2"),
		EventEmitter2 = events.EventEmitter2 || events,
		after = require("after");

	var nCore = pd.make(EventEmitter2.prototype, {
		use: use,
		remove: remove,
		destroy: destroy,
		init: init,
		constructor: constructor,
		_meta: pd.Name()
	});

	exports.nCore = nCore;

    /*
    	Attach a module to the core.

    	Calls the attach method of the module

    	@param String name - name of module
    	@param Object module - module to attach
		@param [optional] Object data - data passed to module
		@param [optional] Function callback - callback invoked
			if this module needs to be initialized
    */
	function use(name, module, data, callback) {
		if (typeof name !== "string") {
			if (name.name) {
				callback = data;
				data = module;
				module = name;
				name = module.name;
			} else {
				callback = data;
				data = module;
				return Object.keys(name).forEach(
					invokeUseOnModules, this);
			}
		}

		if (typeof data === "function" && callback === undefined) {
			callback = data;
			data = null;
		}

		if (data === undefined || data === null) {
			data = this;
		}

		if (!this._modules) {
			this._modules = {};
		}

		this._modules[name] = module;

		module.attach && module.attach.call(this, data, this);

		if (this._initialized) {
			module.init &&
				module.init.call(this, callback || noop, this);
		}

		function invokeUseOnModules(key) {
			var module = name[key];
			this.use(key, module, data, callback);
		}
	}

	/*
		Initializes all modules attached to the core

		Calls the init method of all modules

		@param [optional] Any options - ignored,
			there for backwards support with broadway
		@param Function callback - callback function
			to be invoked when all modules have initialized.

	*/
	function init(options, callback) {
		if (typeof options === "function" && callback === undefined) {
			callback = options;
			options = null;
		}

		this._initialized = true;

		if (!this._modules) return;

		var keys = Object.keys(this._modules);

		var next = after(keys.length, callback);

		keys.forEach(invokeInit, this);

		function invokeInit(name) {
			var module = this._modules[name];
			if (module.init) {
				module.init.call(this, next, this);
			} else {
				next();
			}
			this._meta(module).initialized = true;
		}
	}

	/*
		Removes a module from the core.

		Invokes the modules detach method

		@param String name - name of module to be removed
		@param [optional] Function callback - callback to be
			invoked if the module to be removed
			also needs to be destroyed
	*/
	function remove(name, callback) {
		if (typeof name !== "string") {
			if (name.name) {
				name = name.name;
			} else {
				return Object.keys(name).forEach(
					invokeRemoveOnModules, this);
			}
		}

		var module = this._modules[name];

		if (this._meta(module).initialized) {
			if (module.destroy) {
				module.destroy.call(this, callback || noop, this);
			} else {
				callback && callback();
			}
		}
		module.detach && module.detach.call(this, this);

		delete this._modules[name];

		function invokeRemoveOnModules(key) {
			this.remove(key)
		}
	}

	/*
		destroys and detaches all attached modules

		@param [optional] Function callback - callback to be
			invoked when all modules are destroyed
	*/
	function destroy(callback) {
		var keys = Object.keys(this._modules);

		var next = after(keys.length, afterDestroy.bind(this));

		keys.forEach(invokeDestroyOnModules, this);

		function invokeDestroyOnModules(name) {
			var module = this._modules[name];

			if (module.destroy) {
				module.destroy.call(this, next, this);
			} else {
				next();
			}
		}

		function afterDestroy() {
			keys.forEach(invokeDetachOnModules, this);

			callback();
		}

		function invokeDetachOnModules(name) {
			var module = this._modules[name];

			module.detach && module.detach.call(this, this);
		}
	}

	/*
		Constructor initializes the value of _meta to a new Name.
	*/
	function constructor() {
		this._meta = pd.Name();

		return this;
	}

	function noop() {

	}

}(
	function _require(name) {
		return typeof require !== 'undefined' ? require(name) : window[name];
	},
	typeof window !== "undefined" ? window : exports
);<|endoftext|>


<commit_before>import expect from 'expectations';
import TextTrack from '../../../../src/js/core/track/TextTrack.js';

describe('TextTrack', function () {
    it('gets exported as a module', function () {
        expect(TextTrack).toBeDefined();
    });

    it('cannot be contructed', function () {
        const actual = function () {
            return new TextTrack();
        };

        expect(actual).toThrow(TypeError);
    });

    it('cannot be called', function () {
        const actual = function () {
            return new TextTrack();
        };

        expect(actual).toThrow(TypeError);
    });

    describe('.create(kind, label, language)', function () {
        it('is a defined function', function () {
            expect(typeOf(TextTrack.create)).toBe('function');
        });

        it('returns a new `TextTrack` object with the correct state', function () {
            const textTrack = TextTrack.create();

            expect(textTrack instanceof TextTrack).toBe(true);
            expect(textTrack.kind).toEqual('subtitles');
            expect(textTrack.label).toEqual('');
            expect(textTrack.language).toEqual('');
            expect(textTrack.id).toEqual('');
            expect(textTrack.inBandMetadataTrackDispatchType).toEqual('');
            expect(textTrack.mode).toEqual('disabled');
            expect(textTrack.cues.length).toEqual(0);
            expect(textTrack.activeCues.length).toEqual(0);
        });

        context('when the `kind` argument is provided, it returns the `TextTrack`', function () {
            it('with the `kind` property set to the same value as the argument', function () {
                const textTrack = TextTrack.create('chapters');

                expect(textTrack.kind).toEqual('chapters');
            });

            it('or with the `kind` property set to "metadata" if the value is invalid', function () {
                const textTrack = TextTrack.create('foo');

                expect(textTrack.kind).toEqual('metadata');
            });
        });

        context('when the `label` argument is provided, it returns the `TextTrack`', function () {
            it('with the `label` property set to the same value as the argument', function () {
                const textTrack = TextTrack.create('subtitles', 'my label');

                expect(textTrack.label).toEqual('my label');
            });
        });

        context('when the `language` argument is provided, it returns the `TextTrack`', function () {
            it('with the `language` property set to the same value as the argument', function () {
                const textTrack = TextTrack.create('subtitles', '', 'en');

                expect(textTrack.language).toEqual('en');
            });
        });
    });

    describe('#addCue(cue)', function () {
        it('is a defined function', function () {
            const textTrack = TextTrack.create();

            expect(typeOf(textTrack.addCue)).toBe('function');
        });
    });

    describe('#removeCue(cue)', function () {
        it('is a defined function', function () {
            const textTrack = TextTrack.create();

            expect(typeOf(textTrack.removeCue)).toBe('function');
        });
    });
});
<commit_msg>fix: Incorrect unit test<commit_after>import expect from 'expectations';
import TextTrack from '../../../../src/js/core/track/TextTrack.js';

describe('TextTrack', function () {
    it('gets exported as a module', function () {
        expect(TextTrack).toBeDefined();
    });

    it('cannot be contructed', function () {
        const actual = function () {
            return new TextTrack();
        };

        expect(actual).toThrow(TypeError);
    });

    it('cannot be called', function () {
        const actual = function () {
            TextTrack();
        };

        expect(actual).toThrow(TypeError);
    });

    describe('.create(kind, label, language)', function () {
        it('is a defined function', function () {
            expect(typeOf(TextTrack.create)).toBe('function');
        });

        it('returns a new `TextTrack` object with the correct state', function () {
            const textTrack = TextTrack.create();

            expect(textTrack instanceof TextTrack).toBe(true);
            expect(textTrack.kind).toEqual('subtitles');
            expect(textTrack.label).toEqual('');
            expect(textTrack.language).toEqual('');
            expect(textTrack.id).toEqual('');
            expect(textTrack.inBandMetadataTrackDispatchType).toEqual('');
            expect(textTrack.mode).toEqual('disabled');
            expect(textTrack.cues.length).toEqual(0);
            expect(textTrack.activeCues.length).toEqual(0);
        });

        context('when the `kind` argument is provided, it returns the `TextTrack`', function () {
            it('with the `kind` property set to the same value as the argument', function () {
                const textTrack = TextTrack.create('chapters');

                expect(textTrack.kind).toEqual('chapters');
            });

            it('or with the `kind` property set to "metadata" if the value is invalid', function () {
                const textTrack = TextTrack.create('foo');

                expect(textTrack.kind).toEqual('metadata');
            });
        });

        context('when the `label` argument is provided, it returns the `TextTrack`', function () {
            it('with the `label` property set to the same value as the argument', function () {
                const textTrack = TextTrack.create('subtitles', 'my label');

                expect(textTrack.label).toEqual('my label');
            });
        });

        context('when the `language` argument is provided, it returns the `TextTrack`', function () {
            it('with the `language` property set to the same value as the argument', function () {
                const textTrack = TextTrack.create('subtitles', '', 'en');

                expect(textTrack.language).toEqual('en');
            });
        });
    });

    describe('#addCue(cue)', function () {
        it('is a defined function', function () {
            const textTrack = TextTrack.create();

            expect(typeOf(textTrack.addCue)).toBe('function');
        });
    });

    describe('#removeCue(cue)', function () {
        it('is a defined function', function () {
            const textTrack = TextTrack.create();

            expect(typeOf(textTrack.removeCue)).toBe('function');
        });
    });
});
<|endoftext|>