<commit_before>'use strict'

const micro = require('micro')
const { send, createError } = require('micro')
const { router, get, post, put, patch, del } = require('microrouter')

const signale = require('./utils/signale')
const pipe = require('./utils/pipe')
const isDefined = require('./utils/isDefined')
const customTrackerUrl = require('./utils/customTrackerUrl')
const requireAuth = require('./middlewares/requireAuth')
const blockDemo = require('./middlewares/blockDemo')
const ui = require('./routes/ui')
const tokens = require('./routes/tokens')
const domains = require('./routes/domains')
const records = require('./routes/records')
const views = require('./routes/views')
const pages = require('./routes/pages')
const referrers = require('./routes/referrers')
const languages = require('./routes/languages')
const durations = require('./routes/durations')

const catchError = (fn) => async (req, res) => {

	try {

		return await fn(req, res)

	} catch (err) {

		const isUnknownError = err.statusCode == null
		const hasOriginalError = err.originalError != null

		// Only log the full error stack when the error isn't a known API response
		if (isUnknownError === true) {
			signale.fatal(err)
			return send(res, 500, err.message)
		}

		signale.warn(hasOriginalError === true ? err.originalError.message : err.message)
		send(res, err.statusCode, err.message)

	}

}

const ACKEE_ALLOW_ORIGIN = process.env.ACKEE_ALLOW_ORIGIN

const attachCorsHeaders = (fn) => async (req, res) => {

	if (ACKEE_ALLOW_ORIGIN == null) return fn(req, res)

	res.setHeader('Access-Control-Allow-Origin', ACKEE_ALLOW_ORIGIN)
	res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, OPTIONS')
	res.setHeader('Access-Control-Allow-Headers', 'Content-Type')

	return fn(req, res)

}

const notFound = async (req) => {

	const err = new Error(`\`${ req.url }\` not found`)

	throw createError(404, 'Not found', err)

}

const routes = [

	get('/', ui.index),
	get('/index.html', ui.index),
	get('/favicon.ico', ui.favicon),
	get('/index.css', ui.styles),
	get('/index.js', ui.scripts),
	get('/tracker.js', ui.tracker),
	customTrackerUrl != null ? get(customTrackerUrl, ui.tracker) : undefined,

	post('/tokens', tokens.add),
	del('/tokens/:tokenId', tokens.del),

	post('/domains', pipe(requireAuth, blockDemo, domains.add)),
	get('/domains', pipe(requireAuth, domains.all)),
	put('/domains/:domainId', pipe(requireAuth, blockDemo, domains.update)),
	del('/domains/:domainId', pipe(requireAuth, blockDemo, domains.del)),

	post('/domains/:domainId/records', records.add),
	patch('/domains/:domainId/records/:recordId', records.update),

	get('/domains/:domainId/views', pipe(requireAuth, views.get)),

	get('/domains/:domainId/pages', pipe(requireAuth, pages.get)),

	get('/domains/:domainId/referrers', pipe(requireAuth, referrers.get)),

	get('/domains/:domainId/languages', pipe(requireAuth, languages.get)),

	get('/domains/:domainId/durations', pipe(requireAuth, durations.get)),

	get('/*', notFound),
	post('/*', notFound),
	put('/*', notFound),
	patch('/*', notFound),
	del('/*', notFound)

].filter(isDefined)

module.exports = micro(
	attachCorsHeaders(
		catchError(
			router(...routes)
		)
	)
)<commit_msg>Restructure fn<commit_after>'use strict'

const micro = require('micro')
const { send, createError } = require('micro')
const { router, get, post, put, patch, del } = require('microrouter')

const signale = require('./utils/signale')
const pipe = require('./utils/pipe')
const isDefined = require('./utils/isDefined')
const customTrackerUrl = require('./utils/customTrackerUrl')
const requireAuth = require('./middlewares/requireAuth')
const blockDemo = require('./middlewares/blockDemo')
const ui = require('./routes/ui')
const tokens = require('./routes/tokens')
const domains = require('./routes/domains')
const records = require('./routes/records')
const views = require('./routes/views')
const pages = require('./routes/pages')
const referrers = require('./routes/referrers')
const languages = require('./routes/languages')
const durations = require('./routes/durations')

const catchError = (fn) => async (req, res) => {

	try {

		return await fn(req, res)

	} catch (err) {

		const isUnknownError = err.statusCode == null
		const hasOriginalError = err.originalError != null

		// Only log the full error stack when the error isn't a known API response
		if (isUnknownError === true) {
			signale.fatal(err)
			return send(res, 500, err.message)
		}

		signale.warn(hasOriginalError === true ? err.originalError.message : err.message)
		send(res, err.statusCode, err.message)

	}

}

const attachCorsHeaders = (fn) => async (req, res) => {

	const allowOrigin = process.env.ACKEE_ALLOW_ORIGIN

	if (allowOrigin != null) {
		res.setHeader('Access-Control-Allow-Origin', allowOrigin)
		res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, OPTIONS')
		res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
	}

	return fn(req, res)

}

const notFound = async (req) => {

	const err = new Error(`\`${ req.url }\` not found`)

	throw createError(404, 'Not found', err)

}

const routes = [

	get('/', ui.index),
	get('/index.html', ui.index),
	get('/favicon.ico', ui.favicon),
	get('/index.css', ui.styles),
	get('/index.js', ui.scripts),
	get('/tracker.js', ui.tracker),
	customTrackerUrl != null ? get(customTrackerUrl, ui.tracker) : undefined,

	post('/tokens', tokens.add),
	del('/tokens/:tokenId', tokens.del),

	post('/domains', pipe(requireAuth, blockDemo, domains.add)),
	get('/domains', pipe(requireAuth, domains.all)),
	put('/domains/:domainId', pipe(requireAuth, blockDemo, domains.update)),
	del('/domains/:domainId', pipe(requireAuth, blockDemo, domains.del)),

	post('/domains/:domainId/records', records.add),
	patch('/domains/:domainId/records/:recordId', records.update),

	get('/domains/:domainId/views', pipe(requireAuth, views.get)),

	get('/domains/:domainId/pages', pipe(requireAuth, pages.get)),

	get('/domains/:domainId/referrers', pipe(requireAuth, referrers.get)),

	get('/domains/:domainId/languages', pipe(requireAuth, languages.get)),

	get('/domains/:domainId/durations', pipe(requireAuth, durations.get)),

	get('/*', notFound),
	post('/*', notFound),
	put('/*', notFound),
	patch('/*', notFound),
	del('/*', notFound)

].filter(isDefined)

module.exports = micro(
	attachCorsHeaders(
		catchError(
			router(...routes)
		)
	)
)<|endoftext|>


<commit_before>var matrix = require('../src/matrix').matrix;
var assert = require('assert');

describe('matrix.identity', function() {
    it('should return an empty matrix when given zero for its dimensions',
        function() {
            var expected = [];
            var actual = matrix.identity(0);
            assert.deepEqual(expected, actual);
        }
    );

    it('should return an n-by-n identity matrix when given a positive '
        + 'integer n for its dimensions', function() {
        var expected = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
        var actual = matrix.identity(3);
        assert.deepEqual(expected, actual);
    });

    it('should throw MatrixError when given a negative integer for its '
        + 'dimensions', function() {
        assert.throws(function() {
            matrix.identity(-3);
        }, matrix.MatrixError, 'Invalid matrix dimensions given.');
    });

    it('should throw MatrixError when not given an integer for its dimensions',
        function() {
            assert.throws(function() {
                matrix.identity('a');
            }, matrix.MatrixError, 'Invalid matrix dimensions given.');
        }
    );

    it('should be integrated to Array.prototype', function() {
        var expected = true;
        var actual = Array.prototype.hasOwnProperty('identity');
        assert.equal(expected, actual);
    });
});
<commit_msg>converted tests for matrix.identity to es2015<commit_after>import { identity, MatrixError } from '../src/matrix';
import assert from 'assert';

describe('matrix.identity', () => {
    it('should return an empty matrix when given zero for its dimensions',
        () => {
            var expected = [];
            var actual = identity(0);
            assert.deepEqual(expected, actual);
        }
    );

    it('should return an n-by-n identity matrix when given a positive integer'
        + 'n for its dimensions', () => {
        var expected = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
        var actual = identity(3);
        assert.deepEqual(expected, actual);
    });

    it('should throw MatrixError when given a negative integer for its '
        + 'dimensions', () => {
        assert.throws(() => {
            identity(-3);
        }, MatrixError, 'Invalid matrix dimensions given.');
    });

    it('should throw MatrixError when not given an integer for its dimensions',
        () => {
            assert.throws(() => {
                identity('a');
            }, MatrixError, 'Invalid matrix dimensions given.');
        }
    );

    it('should be integrated to Array.prototype', () => {
        var expected = true;
        var actual = Array.prototype.hasOwnProperty('identity');
        assert.equal(expected, actual);
    });
});
<|endoftext|>


<commit_before>const mongoose = require('./config/lib/mongoose');
const express = require('./config/lib/express');
const logger = require('./config/lib/winston');
const config = require('./config/config');

logger.info('Initializing Node server');

mongoose.connect().then(connection => {
  logger.info('Mongoose connected');
  // Initialize express
  const app = express.init(connection);
  // Start the app on the configured port
  app.listen(config.port);
  // Initializing complete
  logger.info('App listening on port', config.port);
}).catch(function () {
  process.exit(1);
});
<commit_msg>Vim test<commit_after>const mongoose = require('./config/lib/mongoose');
const express = require('./config/lib/express');
const logger = require('./config/lib/winston');
const config = require('./config/config');

logger.info('Initializing Node server');

mongoose.connect().then(connection => {
  logger.info('Mongoose connected');
  // Initialize express
  const app = express.init(connection);
  // Start the app on the configured port
  app.listen(config.port);
  // Initializing complete
  logger.info('App listening on port', config.port);
}).catch(function () {
  process.exit(1);
});

<|endoftext|>


<commit_before>import url from 'url';
import webpack from 'webpack';
import WebpackDevServer from 'webpack-dev-server';
import express from 'express';
import staticTransform from 'connect-static-transform';
import { printWebpackConfig } from './util';
import makeWebpackConfig from '../config/webpack.development.config';

/* eslint-disable no-console */

export default function server(options, callback) {
	let webpackConfig = makeWebpackConfig(options);

	if (options.verbose) {
		printWebpackConfig(webpackConfig);
	}

	let app = express();

	// Inject Webpack bundle
	app.use(staticTransform({
		root: 'public',

		// The middleware expects a regex, but we can use a duck object to match /yo/index.html as well as /yo/foo?a=1
		match: {
			test(str) {
				const { pathname } = url.parse(str);
				const basename = pathname.split('/').pop();
				return basename === '' || basename.substr(-5) === '.html';
			},
		},

		// Append index.html to a path if needed
		normalize(requestPath) {
			requestPath = requestPath.split('?')[0];
			if (requestPath.substr(-1) === '/') {
				requestPath += 'index.html';
			}
			return requestPath;
		},

		transform: (path, html, send) => {
			// Remove stylesheet link, CSS will be injected by Webpack bundle
			html = html.replace(
				/<link href="\/build\/styles.css(?:\?\d+)?" rel="stylesheet">/,
				''
			);

			// Load Webpack main bundle from Webpack dev server
			let webpackUrl = `http://${options.host}:${options.webpackPort}`;
			if (/\n`
			);

			send(html, { 'Content-Type': 'text/html; charset=utf-8' });
		},
	}));

	// Serve other static assets
	app.use(express.static('public'));

	app.listen(options.port, options.host, callback);

	// Webpack dev server
	let devServerConfig = {
		inline: true,
		publicPath: webpackConfig.output.publicPath,
	};
	if (options.verbose) {
		devServerConfig.stats = {
			colors: true,
			chunks: false,
			chunkModules: false,
		};
	}
	else {
		devServerConfig.noInfo = true;
	}
	new WebpackDevServer(webpack(webpackConfig), devServerConfig).listen(options.webpackPort);
}
<commit_msg>Escape dots in regexps.<commit_after>import url from 'url';
import webpack from 'webpack';
import WebpackDevServer from 'webpack-dev-server';
import express from 'express';
import staticTransform from 'connect-static-transform';
import { printWebpackConfig } from './util';
import makeWebpackConfig from '../config/webpack.development.config';

/* eslint-disable no-console */

export default function server(options, callback) {
	let webpackConfig = makeWebpackConfig(options);

	if (options.verbose) {
		printWebpackConfig(webpackConfig);
	}

	let app = express();

	// Inject Webpack bundle
	app.use(staticTransform({
		root: 'public',

		// The middleware expects a regex, but we can use a duck object to match /yo/index.html as well as /yo/foo?a=1
		match: {
			test(str) {
				const { pathname } = url.parse(str);
				const basename = pathname.split('/').pop();
				return basename === '' || basename.substr(-5) === '.html';
			},
		},

		// Append index.html to a path if needed
		normalize(requestPath) {
			requestPath = requestPath.split('?')[0];
			if (requestPath.substr(-1) === '/') {
				requestPath += 'index.html';
			}
			return requestPath;
		},

		transform: (path, html, send) => {
			// Remove stylesheet link, CSS will be injected by Webpack bundle
			html = html.replace(
				/<link href="\/build\/styles\.css(?:\?\d+)?" rel="stylesheet">/,
				''
			);

			// Load Webpack main bundle from Webpack dev server
			let webpackUrl = `http://${options.host}:${options.webpackPort}`;
			if (/\n`
			);

			send(html, { 'Content-Type': 'text/html; charset=utf-8' });
		},
	}));

	// Serve other static assets
	app.use(express.static('public'));

	app.listen(options.port, options.host, callback);

	// Webpack dev server
	let devServerConfig = {
		inline: true,
		publicPath: webpackConfig.output.publicPath,
	};
	if (options.verbose) {
		devServerConfig.stats = {
			colors: true,
			chunks: false,
			chunkModules: false,
		};
	}
	else {
		devServerConfig.noInfo = true;
	}
	new WebpackDevServer(webpack(webpackConfig), devServerConfig).listen(options.webpackPort);
}
<|endoftext|>


<commit_before><commit_msg>fix ios scrollable issue<commit_after><|endoftext|>


<commit_before>var fs = require('fs-extra');
var tmp = require('tmp');
var path = require('path');
var jszip = require('jszip');
var esprima = require('esprima');

var loadExtension = require('./ext-loader');
var apiProxyPath = __dirname + '/../static/chrome-apis-proxy.js';

function updateManifest (extensionPath, extensionId, cb) {
    // Add missing fields to json manifest
    var manifestPath = extensionPath + "/manifest.json";

    fs.readFile(manifestPath, function (error, manifest) {
        if (error) {
            return cb(error);
        }

        var m;
        try {
            m = JSON.parse(manifest);
        }
        catch (originalError) {
            // JSON parsing failed
            // trying to remove comments with esprima

            var jsString = 'var o =' + manifest;
            try {
                var tokens = esprima.tokenize(jsString).slice(3);
                var json = tokens.reduce((json, t) => json + t.value, '');
                m = JSON.parse(json);
            }
            catch (e) {
                originalError.message = 'Failed to parse manifest.json:\n' + originalError.message;
                return cb(originalError);
            }
        }

        m.applications = {
            gecko: {
                id: extensionId || "crx2ff@example.org"
            }
        };

        // Add path to our api proxy script
        if (!m.background) m.background = {};
        if (!m.background.scripts) m.background.scripts = [];

        // Must be first script in list since it overrides the chrome object
        m.background.scripts.unshift('chrome-apis-proxy.js');

        fs.writeFile(manifestPath, JSON.stringify(m), cb);
    });
}

function convertExtension (extensionPath, outputPath, extensionId, cb) {
    updateManifest(extensionPath, extensionId, function (error) {
        if (error) {
            return cb(error);
        }

        var zip = new jszip();
        var zipOpts = { compression: 'deflate' };

        // Zip converted extension
        fs.walk(extensionPath)
        .on('data', function (item) {
            if (item.stats.isFile()) {
                var relPath = path.relative(extensionPath, item.path);
                zip.file(relPath, fs.readFileSync(item.path), zipOpts);
            }
        })
        .on('end', function () {
            // Add our api proxy script to bundle
            zip.file('chrome-apis-proxy.js', fs.readFileSync(apiProxyPath), zipOpts);

            var z = zip.generate({type: 'nodebuffer'});

            fs.writeFile(outputPath || 'crx2ff.xpi', z, cb);
        });
    });
}

function converter (pathOrId, outputPath, extensionId, cb) {
    return loadExtension(pathOrId, false, function (error, extensionPath) {
        if (error) {
            return cb(error);
        }

        return convertExtension(extensionPath, outputPath, extensionId, cb);
    });
}

module.exports = converter;
<commit_msg>enable JSON pretty-print<commit_after>var fs = require('fs-extra');
var tmp = require('tmp');
var path = require('path');
var jszip = require('jszip');
var esprima = require('esprima');

var loadExtension = require('./ext-loader');
var apiProxyPath = __dirname + '/../static/chrome-apis-proxy.js';

function updateManifest (extensionPath, extensionId, cb) {
    // Add missing fields to json manifest
    var manifestPath = extensionPath + "/manifest.json";

    fs.readFile(manifestPath, function (error, manifest) {
        if (error) {
            return cb(error);
        }

        var m;
        try {
            m = JSON.parse(manifest);
        }
        catch (originalError) {
            // JSON parsing failed
            // trying to remove comments with esprima

            var jsString = 'var o =' + manifest;
            try {
                var tokens = esprima.tokenize(jsString).slice(3);
                var json = tokens.reduce((json, t) => json + t.value, '');
                m = JSON.parse(json);
            }
            catch (e) {
                originalError.message = 'Failed to parse manifest.json:\n' + originalError.message;
                return cb(originalError);
            }
        }

        m.applications = {
            gecko: {
                id: extensionId || "crx2ff@example.org"
            }
        };

        // Add path to our api proxy script
        if (!m.background) m.background = {};
        if (!m.background.scripts) m.background.scripts = [];

        // Must be first script in list since it overrides the chrome object
        m.background.scripts.unshift('chrome-apis-proxy.js');

        fs.writeFile(manifestPath, JSON.stringify(m, null, '\t'), cb);
    });
}

function convertExtension (extensionPath, outputPath, extensionId, cb) {
    updateManifest(extensionPath, extensionId, function (error) {
        if (error) {
            return cb(error);
        }

        var zip = new jszip();
        var zipOpts = { compression: 'deflate' };

        // Zip converted extension
        fs.walk(extensionPath)
        .on('data', function (item) {
            if (item.stats.isFile()) {
                var relPath = path.relative(extensionPath, item.path);
                zip.file(relPath, fs.readFileSync(item.path), zipOpts);
            }
        })
        .on('end', function () {
            // Add our api proxy script to bundle
            zip.file('chrome-apis-proxy.js', fs.readFileSync(apiProxyPath), zipOpts);

            var z = zip.generate({type: 'nodebuffer'});

            fs.writeFile(outputPath || 'crx2ff.xpi', z, cb);
        });
    });
}

function converter (pathOrId, outputPath, extensionId, cb) {
    return loadExtension(pathOrId, false, function (error, extensionPath) {
        if (error) {
            return cb(error);
        }

        return convertExtension(extensionPath, outputPath, extensionId, cb);
    });
}

module.exports = converter;
<|endoftext|>


<commit_before><commit_msg>Fix issues with auth login with changes in version<commit_after><|endoftext|>


<commit_before>define(["dojo/_base/declare", "dojo/_base/lang", "dojo/_base/Deferred", "dojo/on", "dojo/aspect", "put-selector/put"],
function(declare, lang, Deferred, listen, aspect, put){
	// This module isolates the base logic required by store-aware list/grid
	// components, e.g. OnDemandList/Grid and the Pagination extension.

	// Noop function, needed for _trackError when callback due to a bug in 1.8
	// (see http://bugs.dojotoolkit.org/ticket/16667)
	function noop(value){ return value; }

	function emitError(err){
		// called by _trackError in context of list/grid, if an error is encountered
		if(typeof err !== "object"){
			// Ensure we actually have an error object, so we can attach a reference.
			err = new Error(err);
		}else if(err.dojoType === "cancel"){
			// Don't fire dgrid-error events for errors due to canceled requests
			// (unfortunately, the Deferred instrumentation will still log them)
			return;
		}
		// TODO: remove this @ 0.4 (prefer grid property directly on event object)
		err.grid = this;

		if(listen.emit(this.domNode, "dgrid-error", {
				grid: this,
				error: err,
				cancelable: true,
				bubbles: true })){
			console.error(err);
		}
	}

	return declare(null, {
		// collection: Object
		//		The object collection (implementing the dstore/api/Store API) from which data is
		//		to be fetched.
		collection: null,

		// _rows: Array
		//		A sparse array of row nodes, used to maintain the grid in response to events from a tracked collection.
		//		Each node's index corresponds to the index of its data object in the collection.
		_rows: null,

		// _observerHandle: Object
		//		The observer handle for the current collection, if trackable.
		_observerHandle: null,

		// getBeforePut: boolean
		//		If true, a get request will be performed to the store before each put
		//		as a baseline when saving; otherwise, existing row data will be used.
		getBeforePut: true,

		// noDataMessage: String
		//		Message to be displayed when no results exist for a collection, whether at
		//		the time of the initial query or upon subsequent observed changes.
		//		Defined by _StoreMixin, but to be implemented by subclasses.
		noDataMessage: "",

		// loadingMessage: String
		//		Message displayed when data is loading.
		//		Defined by _StoreMixin, but to be implemented by subclasses.
		loadingMessage: "",

		constructor: function(){
			// Create empty objects on each instance, not the prototype
			this.dirty = {};
			this._updating = {}; // Tracks rows that are mid-update
			this._columnsWithSet = {};

			// Reset _columnsWithSet whenever column configuration is reset
			aspect.before(this, "configStructure", lang.hitch(this, function(){
				this._columnsWithSet = {};
			}));
		},

		destroy: function(){
			this.inherited(arguments);

			// Set collection to null to clean up after existing collection
			this.set("collection", null);
		},

		_configColumn: function(column){
			// summary:
			//		Implements extension point provided by Grid to store references to
			//		any columns with `set` methods, for use during `save`.
			if (column.set){
				this._columnsWithSet[column.field] = column;
			}
			this.inherited(arguments);
		},

		_setCollection: function(collection){
			// summary:
			//		Assigns a new collection to the list,
			//		and tells it to refresh.

			if(this.collection){
				if(this.collection.tracking){
					this.collection.tracking.remove();
				}

				// Remove observer and existing rows so any sub-row observers will be cleaned up
				if(this._observerHandle){
					this._observerHandle.remove();
					this._observerHandle = this._rows = null;
				}
				this.cleanup();

				this.dirty = {}; // discard dirty map, as it applied to a previous collection
			}

			if(collection){
				if(this.sort && this.sort.length > 0){
					collection = collection.sort(this.sort);
				}

				if(collection.track){
					collection = this.collection = collection.track();
					this._rows = [];

					this._observerHandle = this._observeCollection(collection, this.contentNode, this._rows);
				}else{
					this.collection = collection;
				}

				this.refresh();
			}
		},

		_applySort: function(){
			if(this.collection){
				this.set('collection', this.collection);
			}
		},

		row: function(target){
			// Extend List#row with more appropriate lookup-by-id logic
			var row = this.inherited(arguments);
			if(row && row.data && typeof row.id !== "undefined"){
				row.id = this.collection.getIdentity(row.data);
			}
			return row;
		},

		insertRow: function(object, parent, beforeNode, i, options){
			var store = this.collection,
				dirty = this.dirty,
				id = store && store.getIdentity(object),
				dirtyObj,
				row;

			if(id in dirty && !(id in this._updating)){ dirtyObj = dirty[id]; }
			if(dirtyObj){
				// restore dirty object as delegate on top of original object,
				// to provide protection for subsequent changes as well
				object = lang.delegate(object, dirtyObj);
			}

			row = this.inherited(arguments);

			// Remove no data message when a new row appears.
			// Run after inherited logic to prevent confusion due to noDataNode
			// no longer being present as a sibling.
			if(this.noDataNode){
				put(this.noDataNode, "!");
				this.noDataNode = null;
			}

			return row;
		},

		updateDirty: function(id, field, value){
			// summary:
			//		Updates dirty data of a field for the item with the specified ID.
			var dirty = this.dirty,
				dirtyObj = dirty[id];

			if(!dirtyObj){
				dirtyObj = dirty[id] = {};
			}
			dirtyObj[field] = value;
		},

		save: function() {
			// Keep track of the store and puts
			var self = this,
				store = this.collection,
				dirty = this.dirty,
				dfd = new Deferred(), promise = dfd.promise,
				getFunc = function(id){
					// returns a function to pass as a step in the promise chain,
					// with the id variable closured
					var data;
					return (self.getBeforePut || !(data = self.row(id).data)) ?
						function(){ return store.get(id); } :
						function(){ return data; };
				};

			// function called within loop to generate a function for putting an item
			function putter(id, dirtyObj) {
				// Return a function handler
				return function(object) {
					var colsWithSet = self._columnsWithSet,
						updating = self._updating,
						key, data;

					if (typeof object.set === "function") {
						object.set(dirtyObj);
					} else {
						// Copy dirty props to the original, applying setters if applicable
						for(key in dirtyObj){
							object[key] = dirtyObj[key];
						}
					}

					// Apply any set methods in column definitions.
					// Note that while in the most common cases column.set is intended
					// to return transformed data for the key in question, it is also
					// possible to directly modify the object to be saved.
					for(key in colsWithSet){
						data = colsWithSet[key].set(object);
						if(data !== undefined){ object[key] = data; }
					}

					updating[id] = true;
					// Put it in the store, returning the result/promise
					return Deferred.when(store.put(object), function() {
						// Clear the item now that it's been confirmed updated
						delete dirty[id];
						delete updating[id];
					});
				};
			}

			// For every dirty item, grab the ID
			for(var id in dirty) {
				// Create put function to handle the saving of the the item
				var put = putter(id, dirty[id]);

				// Add this item onto the promise chain,
				// getting the item from the store first if desired.
				promise = promise.then(getFunc(id)).then(put);
			}

			// Kick off and return the promise representing all applicable get/put ops.
			// If the success callback is fired, all operations succeeded; otherwise,
			// save will stop at the first error it encounters.
			dfd.resolve();
			return promise;
		},

		revert: function(){
			// summary:
			//		Reverts any changes since the previous save.
			this.dirty = {};
			this.refresh();
		},

		_trackError: function(func){
			// summary:
			//		Utility function to handle emitting of error events.
			// func: Function|String
			//		A function which performs some store operation, or a String identifying
			//		a function to be invoked (sans arguments) hitched against the instance.
			//		If sync, it can return a value, but may throw an error on failure.
			//		If async, it should return a promise, which would fire the error
			//		callback on failure.
			// tags:
			//		protected

			if(typeof func == "string"){ func = lang.hitch(this, func); }

			var self = this,
				promise;

			try{
				promise = Deferred.when(func());
			}catch(err){
				// report sync error
				var dfd = new Deferred();
				dfd.reject(err);
				promise = dfd.promise;
			}

			promise.otherwise(function(err){
				emitError.call(self, err);
			});
			return promise;
		},

		removeRow: function(rowElement, justCleanup){
			var row = {element: rowElement};
			// Check to see if we are now empty...
			if(!justCleanup && this.noDataMessage &&
					(this.up(row).element === rowElement) &&
					(this.down(row).element === rowElement)){
				// ...we are empty, so show the no data message.
				this.noDataNode = put(this.contentNode, "div.dgrid-no-data");
				this.noDataNode.innerHTML = this.noDataMessage;
			}
			return this.inherited(arguments);
		},

		renderCollection: function(collection, beforeNode, options){
			// summary:
			//		Renders objects from a collection as rows, before the given node.
			//		This will listen for changes in the collection if an observe method
			//		is available (i.e. from an Observable data store).

			options = options || {};
			var self = this,
				start = options.start || 0,
				rows = options.rows || this._rows,
				container;

			return Deferred.when(collection.fetch()).then(function(resolvedResults){
				var resolvedRows,
					i;

				container = beforeNode ? beforeNode.parentNode : self.contentNode;
				if(container && container.parentNode &&
						(container !== self.contentNode || resolvedResults.length)){
					resolvedRows = self.renderArray(resolvedResults, beforeNode, options);
					i = resolvedRows.length;

					if(rows){
						for (var itemIndex = 0; itemIndex < resolvedRows.length; ++itemIndex){
							rows[start + itemIndex] = resolvedRows[itemIndex];
						}
					}

					delete self._lastCollection; // used only for non-store List/Grid
				}else{
					// Don't bother inserting; the container has been removed from the DOM
					// or there were no rows to render
					resolvedRows = [];
				}
				return resolvedRows;
			});
		},

		_observeCollection: function(collection, container, rows, options){
			var self = this, row;

			options = options || {};

			var handles = [
				collection.on("remove, update", function(event){
					var from = event.previousIndex;
					if(from !== undefined && rows[from]){
						// remove from old slot
						row = rows.splice(from, 1)[0];

						// adjust the rowIndex so adjustRowIndices has the right starting point
						rows[from] && rows[from].rowIndex--;

						// check to make the sure the node is still there before we try to remove it, (in case it was moved to a different place in the DOM)
						if(row.parentNode == container){
							self.removeRow(row); // now remove
						}

						// the removal of rows could cause us to need to page in more items
						if(self._processScroll){
							self._processScroll();
						}
					}
				}),

				collection.on("add, update", function(event){
					var to = event.index, nextNode;

					function advanceNext() {
						nextNode = (nextNode.connected || nextNode).nextSibling;
					}

					if(to !== undefined){
						// Add to new slot (either before an existing row, or at the end)
						// First determine the DOM node that this should be placed before.
						if(rows.length){
							nextNode = rows[to];
							if(!nextNode){
								nextNode = rows[to - 1];
								if(nextNode){
									// Make sure to skip connected nodes, so we don't accidentally
									// insert a row in between a parent and its children.
									advanceNext();
								}
							}
						}else{
							// There are no rows.  Allow for subclasses to insert new rows somewhere other than
							// at the end of the parent node.
							nextNode = self._getFirstRowSibling && self._getFirstRowSibling(container);
						}
						// Make sure we don't trip over a stale reference to a
						// node that was removed, or try to place a node before
						// itself (due to overlapped queries)
						if(row && nextNode && row.id === nextNode.id){
							advanceNext();
						}
						if(nextNode && !nextNode.parentNode){
							nextNode = document.getElementById(nextNode.id);
						}
						// TODO: This was taken from the previous observe listener where each range request was observed individually. Is this still necessary?
						//parentNode = (beforeNode && beforeNode.parentNode) ||
						//	(nextNode && nextNode.parentNode) || self.contentNode;
						row = self.insertRow(event.target, container, nextNode, to, options);
						self.highlightRow(row);

						// TODO: When would row be falsy?
						if(row){
							rows.splice(to, 0, row);
						}
					}
				}),

				collection.on("add, remove, update", function(event){
					var from = (typeof event.previousIndex !== "undefined") ? event.previousIndex : Infinity,
						to = (typeof event.index !== "undefined") ? event.index : Infinity,
						adjustAtIndex = Math.min(from, to);
					from !== to && rows[adjustAtIndex] && self.adjustRowIndices(rows[adjustAtIndex]);

					self._onNotification(rows, event);
				})
			];

			return {
				remove: function(){
					while(handles.length > 0){
						handles.pop().remove();
					}
				}
			};
		},

		_onNotification: function(rows, event){
			// summary:
			//		Protected method called whenever a store notification is observed.
			//		Intended to be extended as necessary by mixins/extensions.
			// rows: Array
			//		A sparse array of row nodes corresponding to data objects in the collection.
			// event: Object
			//		The notification event
		}
	});
});
<commit_msg>_StoreMixin: remove event.error.grid property (use event.grid)<commit_after>define(["dojo/_base/declare", "dojo/_base/lang", "dojo/_base/Deferred", "dojo/on", "dojo/aspect", "put-selector/put"],
function(declare, lang, Deferred, listen, aspect, put){
	// This module isolates the base logic required by store-aware list/grid
	// components, e.g. OnDemandList/Grid and the Pagination extension.

	// Noop function, needed for _trackError when callback due to a bug in 1.8
	// (see http://bugs.dojotoolkit.org/ticket/16667)
	function noop(value){ return value; }

	function emitError(err){
		// called by _trackError in context of list/grid, if an error is encountered
		if(typeof err !== "object"){
			// Ensure we actually have an error object, so we can attach a reference.
			err = new Error(err);
		}else if(err.dojoType === "cancel"){
			// Don't fire dgrid-error events for errors due to canceled requests
			// (unfortunately, the Deferred instrumentation will still log them)
			return;
		}

		if(listen.emit(this.domNode, "dgrid-error", {
				grid: this,
				error: err,
				cancelable: true,
				bubbles: true })){
			console.error(err);
		}
	}

	return declare(null, {
		// collection: Object
		//		The object collection (implementing the dstore/api/Store API) from which data is
		//		to be fetched.
		collection: null,

		// _rows: Array
		//		A sparse array of row nodes, used to maintain the grid in response to events from a tracked collection.
		//		Each node's index corresponds to the index of its data object in the collection.
		_rows: null,

		// _observerHandle: Object
		//		The observer handle for the current collection, if trackable.
		_observerHandle: null,

		// getBeforePut: boolean
		//		If true, a get request will be performed to the store before each put
		//		as a baseline when saving; otherwise, existing row data will be used.
		getBeforePut: true,

		// noDataMessage: String
		//		Message to be displayed when no results exist for a collection, whether at
		//		the time of the initial query or upon subsequent observed changes.
		//		Defined by _StoreMixin, but to be implemented by subclasses.
		noDataMessage: "",

		// loadingMessage: String
		//		Message displayed when data is loading.
		//		Defined by _StoreMixin, but to be implemented by subclasses.
		loadingMessage: "",

		constructor: function(){
			// Create empty objects on each instance, not the prototype
			this.dirty = {};
			this._updating = {}; // Tracks rows that are mid-update
			this._columnsWithSet = {};

			// Reset _columnsWithSet whenever column configuration is reset
			aspect.before(this, "configStructure", lang.hitch(this, function(){
				this._columnsWithSet = {};
			}));
		},

		destroy: function(){
			this.inherited(arguments);

			// Set collection to null to clean up after existing collection
			this.set("collection", null);
		},

		_configColumn: function(column){
			// summary:
			//		Implements extension point provided by Grid to store references to
			//		any columns with `set` methods, for use during `save`.
			if (column.set){
				this._columnsWithSet[column.field] = column;
			}
			this.inherited(arguments);
		},

		_setCollection: function(collection){
			// summary:
			//		Assigns a new collection to the list,
			//		and tells it to refresh.

			if(this.collection){
				if(this.collection.tracking){
					this.collection.tracking.remove();
				}

				// Remove observer and existing rows so any sub-row observers will be cleaned up
				if(this._observerHandle){
					this._observerHandle.remove();
					this._observerHandle = this._rows = null;
				}
				this.cleanup();

				this.dirty = {}; // discard dirty map, as it applied to a previous collection
			}

			if(collection){
				if(this.sort && this.sort.length > 0){
					collection = collection.sort(this.sort);
				}

				if(collection.track){
					collection = this.collection = collection.track();
					this._rows = [];

					this._observerHandle = this._observeCollection(collection, this.contentNode, this._rows);
				}else{
					this.collection = collection;
				}

				this.refresh();
			}
		},

		_applySort: function(){
			if(this.collection){
				this.set('collection', this.collection);
			}
		},

		row: function(target){
			// Extend List#row with more appropriate lookup-by-id logic
			var row = this.inherited(arguments);
			if(row && row.data && typeof row.id !== "undefined"){
				row.id = this.collection.getIdentity(row.data);
			}
			return row;
		},

		insertRow: function(object, parent, beforeNode, i, options){
			var store = this.collection,
				dirty = this.dirty,
				id = store && store.getIdentity(object),
				dirtyObj,
				row;

			if(id in dirty && !(id in this._updating)){ dirtyObj = dirty[id]; }
			if(dirtyObj){
				// restore dirty object as delegate on top of original object,
				// to provide protection for subsequent changes as well
				object = lang.delegate(object, dirtyObj);
			}

			row = this.inherited(arguments);

			// Remove no data message when a new row appears.
			// Run after inherited logic to prevent confusion due to noDataNode
			// no longer being present as a sibling.
			if(this.noDataNode){
				put(this.noDataNode, "!");
				this.noDataNode = null;
			}

			return row;
		},

		updateDirty: function(id, field, value){
			// summary:
			//		Updates dirty data of a field for the item with the specified ID.
			var dirty = this.dirty,
				dirtyObj = dirty[id];

			if(!dirtyObj){
				dirtyObj = dirty[id] = {};
			}
			dirtyObj[field] = value;
		},

		save: function() {
			// Keep track of the store and puts
			var self = this,
				store = this.collection,
				dirty = this.dirty,
				dfd = new Deferred(), promise = dfd.promise,
				getFunc = function(id){
					// returns a function to pass as a step in the promise chain,
					// with the id variable closured
					var data;
					return (self.getBeforePut || !(data = self.row(id).data)) ?
						function(){ return store.get(id); } :
						function(){ return data; };
				};

			// function called within loop to generate a function for putting an item
			function putter(id, dirtyObj) {
				// Return a function handler
				return function(object) {
					var colsWithSet = self._columnsWithSet,
						updating = self._updating,
						key, data;

					if (typeof object.set === "function") {
						object.set(dirtyObj);
					} else {
						// Copy dirty props to the original, applying setters if applicable
						for(key in dirtyObj){
							object[key] = dirtyObj[key];
						}
					}

					// Apply any set methods in column definitions.
					// Note that while in the most common cases column.set is intended
					// to return transformed data for the key in question, it is also
					// possible to directly modify the object to be saved.
					for(key in colsWithSet){
						data = colsWithSet[key].set(object);
						if(data !== undefined){ object[key] = data; }
					}

					updating[id] = true;
					// Put it in the store, returning the result/promise
					return Deferred.when(store.put(object), function() {
						// Clear the item now that it's been confirmed updated
						delete dirty[id];
						delete updating[id];
					});
				};
			}

			// For every dirty item, grab the ID
			for(var id in dirty) {
				// Create put function to handle the saving of the the item
				var put = putter(id, dirty[id]);

				// Add this item onto the promise chain,
				// getting the item from the store first if desired.
				promise = promise.then(getFunc(id)).then(put);
			}

			// Kick off and return the promise representing all applicable get/put ops.
			// If the success callback is fired, all operations succeeded; otherwise,
			// save will stop at the first error it encounters.
			dfd.resolve();
			return promise;
		},

		revert: function(){
			// summary:
			//		Reverts any changes since the previous save.
			this.dirty = {};
			this.refresh();
		},

		_trackError: function(func){
			// summary:
			//		Utility function to handle emitting of error events.
			// func: Function|String
			//		A function which performs some store operation, or a String identifying
			//		a function to be invoked (sans arguments) hitched against the instance.
			//		If sync, it can return a value, but may throw an error on failure.
			//		If async, it should return a promise, which would fire the error
			//		callback on failure.
			// tags:
			//		protected

			if(typeof func == "string"){ func = lang.hitch(this, func); }

			var self = this,
				promise;

			try{
				promise = Deferred.when(func());
			}catch(err){
				// report sync error
				var dfd = new Deferred();
				dfd.reject(err);
				promise = dfd.promise;
			}

			promise.otherwise(function(err){
				emitError.call(self, err);
			});
			return promise;
		},

		removeRow: function(rowElement, justCleanup){
			var row = {element: rowElement};
			// Check to see if we are now empty...
			if(!justCleanup && this.noDataMessage &&
					(this.up(row).element === rowElement) &&
					(this.down(row).element === rowElement)){
				// ...we are empty, so show the no data message.
				this.noDataNode = put(this.contentNode, "div.dgrid-no-data");
				this.noDataNode.innerHTML = this.noDataMessage;
			}
			return this.inherited(arguments);
		},

		renderCollection: function(collection, beforeNode, options){
			// summary:
			//		Renders objects from a collection as rows, before the given node.
			//		This will listen for changes in the collection if an observe method
			//		is available (i.e. from an Observable data store).

			options = options || {};
			var self = this,
				start = options.start || 0,
				rows = options.rows || this._rows,
				container;

			return Deferred.when(collection.fetch()).then(function(resolvedResults){
				var resolvedRows,
					i;

				container = beforeNode ? beforeNode.parentNode : self.contentNode;
				if(container && container.parentNode &&
						(container !== self.contentNode || resolvedResults.length)){
					resolvedRows = self.renderArray(resolvedResults, beforeNode, options);
					i = resolvedRows.length;

					if(rows){
						for (var itemIndex = 0; itemIndex < resolvedRows.length; ++itemIndex){
							rows[start + itemIndex] = resolvedRows[itemIndex];
						}
					}

					delete self._lastCollection; // used only for non-store List/Grid
				}else{
					// Don't bother inserting; the container has been removed from the DOM
					// or there were no rows to render
					resolvedRows = [];
				}
				return resolvedRows;
			});
		},

		_observeCollection: function(collection, container, rows, options){
			var self = this, row;

			options = options || {};

			var handles = [
				collection.on("remove, update", function(event){
					var from = event.previousIndex;
					if(from !== undefined && rows[from]){
						// remove from old slot
						row = rows.splice(from, 1)[0];

						// adjust the rowIndex so adjustRowIndices has the right starting point
						rows[from] && rows[from].rowIndex--;

						// check to make the sure the node is still there before we try to remove it, (in case it was moved to a different place in the DOM)
						if(row.parentNode == container){
							self.removeRow(row); // now remove
						}

						// the removal of rows could cause us to need to page in more items
						if(self._processScroll){
							self._processScroll();
						}
					}
				}),

				collection.on("add, update", function(event){
					var to = event.index, nextNode;

					function advanceNext() {
						nextNode = (nextNode.connected || nextNode).nextSibling;
					}

					if(to !== undefined){
						// Add to new slot (either before an existing row, or at the end)
						// First determine the DOM node that this should be placed before.
						if(rows.length){
							nextNode = rows[to];
							if(!nextNode){
								nextNode = rows[to - 1];
								if(nextNode){
									// Make sure to skip connected nodes, so we don't accidentally
									// insert a row in between a parent and its children.
									advanceNext();
								}
							}
						}else{
							// There are no rows.  Allow for subclasses to insert new rows somewhere other than
							// at the end of the parent node.
							nextNode = self._getFirstRowSibling && self._getFirstRowSibling(container);
						}
						// Make sure we don't trip over a stale reference to a
						// node that was removed, or try to place a node before
						// itself (due to overlapped queries)
						if(row && nextNode && row.id === nextNode.id){
							advanceNext();
						}
						if(nextNode && !nextNode.parentNode){
							nextNode = document.getElementById(nextNode.id);
						}
						// TODO: This was taken from the previous observe listener where each range request was observed individually. Is this still necessary?
						//parentNode = (beforeNode && beforeNode.parentNode) ||
						//	(nextNode && nextNode.parentNode) || self.contentNode;
						row = self.insertRow(event.target, container, nextNode, to, options);
						self.highlightRow(row);

						// TODO: When would row be falsy?
						if(row){
							rows.splice(to, 0, row);
						}
					}
				}),

				collection.on("add, remove, update", function(event){
					var from = (typeof event.previousIndex !== "undefined") ? event.previousIndex : Infinity,
						to = (typeof event.index !== "undefined") ? event.index : Infinity,
						adjustAtIndex = Math.min(from, to);
					from !== to && rows[adjustAtIndex] && self.adjustRowIndices(rows[adjustAtIndex]);

					self._onNotification(rows, event);
				})
			];

			return {
				remove: function(){
					while(handles.length > 0){
						handles.pop().remove();
					}
				}
			};
		},

		_onNotification: function(rows, event){
			// summary:
			//		Protected method called whenever a store notification is observed.
			//		Intended to be extended as necessary by mixins/extensions.
			// rows: Array
			//		A sparse array of row nodes corresponding to data objects in the collection.
			// event: Object
			//		The notification event
		}
	});
});
<|endoftext|>


<commit_before>(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict'

function injectStyleTag (document, fileName, cb) {
  var style = document.getElementById(fileName)

  if (style) {
    cb(style)
  } else {
    var head = document.getElementsByTagName('head')[0]

    style = document.createElement('style')
    if (fileName != null) style.id = fileName
    cb(style)
    head.appendChild(style)
  }

  return style
}

module.exports = function (css, customDocument, fileName) {
  var doc = customDocument || document
  /* istanbul ignore if: not supported by Electron */
  if (doc.createStyleSheet) {
    var sheet = doc.createStyleSheet()
    sheet.cssText = css
    return sheet.ownerNode
  } else {
    return injectStyleTag(doc, fileName, function (style) {
      /* istanbul ignore if: not supported by Electron */
      if (style.styleSheet) {
        style.styleSheet.cssText = css
      } else {
        style.innerHTML = css
      }
    })
  }
}

module.exports.byUrl = function (url) {
  /* istanbul ignore if: not supported by Electron */
  if (document.createStyleSheet) {
    return document.createStyleSheet(url).ownerNode
  } else {
    var head = document.getElementsByTagName('head')[0]
    var link = document.createElement('link')

    link.rel = 'stylesheet'
    link.href = url

    head.appendChild(link)
    return link
  }
}

},{}],2:[function(require,module,exports){
require('./ttips.css');

/**
 * @module ttips
 */

var SELECTOR_CLASS = 'ttip';
var HOST_SELECTOR_CLASS = 'ttip-host';
var ACTIVE_CLASS = 'ttip-active';
var DISTANCE_TO_ELEMENT = 10;

/**
 * @param  {Element} ttipEl
 */
function cloneToHost(ttipEl) {
    removeHostChilds();
    getHostEl().appendChild(ttipEl.cloneNode(true));
}

/**
 *
 */
function removeHostChilds() {
    var hostEl = getHostEl();
    while (hostEl.firstChild) {
        hostEl.removeChild(hostEl.firstChild);
    }
}

/**
 * update the tooltip position
 * @param {Element} targetEl
 */
function updatePosition(targetEl) {

    var ttipHostEl = getHostEl();
    var ttipEl = targetEl.nextElementSibling;

    var targetRect = targetEl.getBoundingClientRect();
    var ttipRect = ttipHostEl.getBoundingClientRect();
    var position = ttipEl.getAttribute('data-ttip-position');
    var ttipStyle = ttipHostEl.style;

    var left, marginLeft;

    if (position === 'left') {

        ttipStyle.left = targetRect.left - ttipRect.width - DISTANCE_TO_ELEMENT + 'px';
        ttipStyle.top = targetRect.top + (targetRect.height - ttipRect.height) / 2 + 'px';
        ttipStyle.marginLeft = 0;

    } else if (position === 'right') {

        ttipStyle.left = targetRect.right + DISTANCE_TO_ELEMENT + 'px';
        ttipStyle.top = targetRect.top + (targetRect.height - ttipRect.height) / 2 + 'px';
        ttipStyle.marginLeft = 0;

    } else if (position === 'top') {

        left = targetRect.left + (targetRect.width / 2);
        marginLeft = -1 * (ttipHostEl.offsetWidth / 2);

        ttipStyle.left = left + marginLeft < 0 ? 0 : left + 'px';
        ttipStyle.marginLeft = left + marginLeft < 0 ? 0 : marginLeft + 'px';
        ttipStyle.top = targetRect.top - ttipRect.height - DISTANCE_TO_ELEMENT + 'px';

    } else {

        // default - bottom
        left = targetRect.left + (targetRect.width / 2);
        marginLeft = -1 * (ttipHostEl.offsetWidth / 2);

        ttipStyle.left = left + marginLeft < 0 ? 0 : left + 'px';
        ttipStyle.marginLeft = left + marginLeft < 0 ? 0 : marginLeft + 'px';
        ttipStyle.top = targetRect.top + targetRect.height + DISTANCE_TO_ELEMENT + 'px';
    }
}

/**
 * @param  {Event} ev
 * @return {Element}
 */
function getTtipElFromEvent(ev) {
    var ttipEl;
    if (ev.target.nextElementSibling && ev.target.nextElementSibling.classList.contains('ttip')) {
        ttipEl = ev.target.nextElementSibling;
    } else if (ev.currentTarget.nextElementSibling && ev.currentTarget.nextElementSibling.classList.contains('ttip')) {
        ttipEl = ev.currentTarget.nextElementSibling;
    }
    return ttipEl;
}

/**
 * @param  {Element} ttipEl
 */
function show(ttipEl) {

    var targetEl = ttipEl.previousElementSibling;

    cloneToHost(ttipEl);
    updatePosition(targetEl);
    getHostEl().classList.add(ACTIVE_CLASS);

    window.addEventListener('scroll', onMouseLeave);
    window.addEventListener('touchmove', onMouseLeave);
}

/**
 * Hide any visible tooltip
 */
function hide(){
    var hostEl = getHostEl();
    if(hostEl.classList.contains(ACTIVE_CLASS)){
        hostEl.classList.remove(ACTIVE_CLASS);
        window.removeEventListener('scroll', onMouseLeave);
        window.removeEventListener('touchmove', onMouseLeave);
        while (hostEl.firstChild) {
            hostEl.removeChild(hostEl.firstChild);
        }
    }
}

/**
 * @param {Event} ev
 */
function onMouseEnter(ev) {
    var ttipEl = getTtipElFromEvent(ev);
    if (ttipEl) {
        show(ttipEl);
    }
}

/**
 * @param {Event} [ev]
 */
function onMouseLeave(ev) {
    hide();
}

/**
 * Initialize the tooltip
 * @param {Element} ttipEl - The toggle element.
 */
function init(ttipEl) {
    var targetEl;
    if (!ttipEl._ttip && !ttipEl.parentNode.classList.contains('ttip-host')) {
        ttipEl._ttip = true;
        targetEl = ttipEl.previousElementSibling;

        targetEl.addEventListener('mouseenter', onMouseEnter);
        targetEl.addEventListener('mouseleave', onMouseLeave);
        targetEl.addEventListener('blur', onMouseLeave);
    }
}

/**
 * @param {Element} ttipEl
 */
function destroySingle(ttipEl) {
    var targetEl;
    if (ttipEl._ttip === true) {
        targetEl = ttipEl.previousElementSibling;
        if (ttipEl.classList.contains(ACTIVE_CLASS)) {
            getHostEl.classList.remove(ACTIVE_CLASS);
        }
        targetEl.removeEventListener('mouseenter', onMouseEnter);
        targetEl.removeEventListener('mouseleave', onMouseLeave);
        targetEl.removeEventListener('blur', onMouseLeave);

        ttipEl._ttip = null;
    }
}

/**
 * returns the tooltip elements
 * @return {NodeList}
 */
function getTtipElements() {
    return document.querySelectorAll('.' + SELECTOR_CLASS);
}
/**
 * @return {Element | null}
 */
function getHostEl() {
    return document.querySelector('.' + HOST_SELECTOR_CLASS);
}

/**
 * @param  {Element} hostParentEl
 */
function createHost(hostParentEl) {

    hostParentEl = hostParentEl || document.body;

    if (getHostEl()) {
        return;
    }
    var hostEl = document.createElement('div');
    hostEl.classList.add(HOST_SELECTOR_CLASS);
    hostParentEl.appendChild(hostEl);
}

/**
 *
 */
function update(){
    var elements = getTtipElements();
    for (var i = elements.length - 1; i >= 0; i--) {
        init(elements[i]);
    }
}

/**
 * initialize tooltips
 * @param  {Element} hostParentEl
 */
function initialize(hostParentEl) {
    createHost(hostParentEl);
    update();
}

/**
 * destroy all tooltips
 */
function destroy() {
    var elements = getTtipElements();
    var hostEl = getHostEl();

    // destroy the tooltips
    for (var i = elements.length - 1; i >= 0; i--) {
        destroySingle(elements[i]);
    }
    // remove the host
    hostEl.parentNode.removeChild(hostEl);
    hostEl = null;
}

/**
 * module API
 * @type {Object}
 */
module.exports = {
    initialize: initialize,
    update: update,
    hide: hide,
    destroy: destroy
};

},{"./ttips.css":3}],3:[function(require,module,exports){
var inject = require('./../node_modules/cssify');
var css = "@-webkit-keyframes fadeIn {\n\t0% { opacity: 0 }\n    50% { opacity: 0.99 }\n\t100% { opacity: 1 }\n}\n\n@keyframes fadeIn {\n\t0% { opacity: 0 }\n    50% { opacity: 0.99 }\n\t100% { opacity: 1 }\n}\n\n@-webkit-keyframes fadeOut {\n\t0% { opacity: 1 }\n    50% { opacity: 0.99 }\n\t100% { opacity: 0 }\n}\n\n@keyframes fadeOut {\n\t0% { opacity: 1 }\n    50% { opacity: 0.99 }\n\t100% { opacity: 0 }\n}\n\n.ttip {\n    display: none;\n\tfont-size: 11px;\n    line-height: 14px;\n    padding: 5px;\n\tbackground: rgb(38, 38, 38);\n    color: rgb(255, 255, 255);\n}\n\n.ttip-host {\n\tposition: fixed;\n    display: inline-block;\n\t-webkit-transition: opacity 0.3s ease-in-out;\n\ttransition: opacity 0.3s ease-in-out;\n    -webkit-animation-name: fadeOut;\n            animation-name: fadeOut;\n\topacity: 0;\n\ttop: -9999px;\n    left: -9999px;\n    z-index: 9999;\n}\n.ttip-host .ttip{\n\tdisplay: inline-block;\n}\n\n.ttip-host.ttip-active {\n    -webkit-animation-name: fadeIn;\n            animation-name: fadeIn;\n\topacity: 1;\n    visibility: visible;\n}\n";
inject(css, undefined, '_1azmkon');
module.exports = css;

},{"./../node_modules/cssify":1}]},{},[2]);
<commit_msg>Revert "added bundle.js"<commit_after><|endoftext|>


<commit_before><commit_msg>Started work on timelapse functionality.<commit_after><|endoftext|>


<commit_before>var Filer = require('../../src');
var expect = require('chai').expect;

describe('Filer', function() {
  it('is defined', function() {
    expect(typeof Filer).not.to.equal(undefined);
  });

  it('has FileSystem constructor', function() {
    expect(typeof Filer.FileSystem).to.equal('function');
  });

  it('has Shell constructor', function() {
    expect(typeof Filer.Shell).to.equal('function');
  });
});
<commit_msg>Fixes issue 75<commit_after>var Filer = require('../../src');
var expect = require('chai').expect;

describe('Filer', function() {
  it('is defined', function() {
    expect(typeof Filer).not.to.equal(undefined);
  });

  it('has FileSystem constructor', function() {
    expect(typeof Filer.FileSystem).to.equal('function');
  });

  it('has Shell constructor', function() {
    expect(typeof Filer.Shell).to.equal('function');
  });

  it('must honor the \'FORMAT\' flag', function(done) {
    var fs = new Filer.FileSystem({name: 'local-test'});
    var fs2 = new Filer.FileSystem({name: 'local-test'});

    fs.mkdir('/test', function(err){
      if(err) throw err;

      fs2.readdir('/', function(err, list) {
        if(err) throw err;

        expect(list).to.exist;
        expect(list).to.have.length(1);

        fs2 = new Filer.FileSystem({name: 'local-test', flags:['FORMAT']});
        fs2.readdir('/', function(err, list2) {
          expect(err).to.not.exist;
          expect(list2).to.exist;
          expect(list2).to.have.length(0);
          done();
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>import isEmpty from 'lodash/isEmpty';
import isArray from 'lodash/isArray';
import isObject from 'lodash/isObject';
import map from 'lodash/map';
import each from 'lodash/each';

function processElement(refractElement) {
  if (!refractElement) {
    return;
  }

  const attributes = refractElement.attributes;

  // Then, see if it the element has any samples and process them as well!
  if (attributes && !isEmpty(attributes.samples)) {
    attributes.samples = map(attributes.samples, (sample) => {
      if (isArray(sample) || isObject(sample)) {
        return sample;
      }

      return {
        element: refractElement.element,
        content: sample,
      };
    });
  }

  // Then, see if it has children and process each of the children as well!
  if (refractElement.content) {
    if (refractElement.element === 'member' && refractElement.content.value) {
      // This is a member of an object.
      processElement(refractElement.content.value);
    } else if (refractElement.content.length && refractElement.content[0].element) {
      // This is an array of items.
      each(refractElement.content, (nestedRefractElement) => {
        processElement(nestedRefractElement);
      });
    }
  }
}

export function preprocess(refractElement) {
  return processElement(refractElement);
};
<commit_msg>SamplesPreprocessor: Wrap array sample in a parent (array) element.<commit_after>import isEmpty from 'lodash/isEmpty';
import isArray from 'lodash/isArray';
import isObject from 'lodash/isObject';
import map from 'lodash/map';
import each from 'lodash/each';

function processElement(refractElement) {
  if (!refractElement) {
    return;
  }

  const attributes = refractElement.attributes;

  // Then, see if it the element has any samples and process them as well!
  if (attributes && !isEmpty(attributes.samples)) {
    attributes.samples = map(attributes.samples, (sample) => {
      if (refractElement.element === 'array' && isArray(sample)) {
        return {
          element: refractElement.element,
          content: sample,
        };
      }

      if (isArray(sample) || isObject(sample)) {
        return sample;
      }

      return {
        element: refractElement.element,
        content: sample,
      };
    });
  }

  if (attributes && attributes.default) {
    if (refractElement.element === 'array' && isArray(attributes.default)) {
      attributes.default = {
        element: refractElement.element,
        content: attributes.default,
      };
    } else if (isArray(attributes.default) || isObject(attributes.default)) {

    } else {
      attributes.default = {
        element: refractElement.element,
        content: attributes.default,
      };
    };
  }

  // Then, see if it has children and process each of the children as well!
  if (refractElement.content) {
    if (refractElement.element === 'member' && refractElement.content.value) {
      // This is a member of an object.
      processElement(refractElement.content.value);
    } else if (refractElement.content.length && refractElement.content[0].element) {
      // This is an array of items.
      each(refractElement.content, (nestedRefractElement) => {
        processElement(nestedRefractElement);
      });
    }
  }
}

function preprocessSamples(refractElement) {
  return processElement(refractElement);
};

export {
  preprocessSamples,
};
<|endoftext|>


<commit_before>import { setModifierManager } from '@ember/modifier';
import { closest, documentOrBodyContains, ios } from './utils';

export default setModifierManager(
  () => ({
    createModifier(factory, args) {
      return {
        element: null,
        eventHandler: null,
        action: null
      };
    },

    installModifier(state, element, args) {
      let [action] = args.positional;
      let { exceptSelector } = args.named;

      if (action) {
        state.action = action;
        state.element = element;
        state.eventHandler = createHandler(element, action, exceptSelector);

        document.addEventListener('click', state.eventHandler);
      }

      if (ios()) {
        document.body.style.cursor = 'pointer';
      }
    },

    updateModifier(state, args) {
      let [action] = args.positional;
      let { exceptSelector } = args.named;

      if (state.action) {
        document.removeEventListener('click', state.eventHandler);
      }

      if (action) {
        state.action = action;
        state.eventHandler = createHandler(state.element, action, exceptSelector);

        document.addEventListener('click', state.eventHandler);
      }
    },

    destroyModifier(state, element) {
      if (state.action) {
        document.removeEventListener('click', state.eventHandler);
      }

      if (ios()) {
        document.body.style.cursor = '';
      }
    }
  }),
  class OnClickOutsideModifier {}
);

const createHandler = (element, action, exceptSelector) => (e) => {
  if (exceptSelector && closest(e.target, exceptSelector)) {
    return;
  }

  let path = e.path || (e.composedPath && e.composedPath());

  if (path) {
    path.includes(element) || action(e);
  } else {
    // Check if the click target still is in the DOM.
    // If not, there is no way to know if it was inside the element or not.
    let isRemoved = !e.target || !documentOrBodyContains(e.target);

    // Check the element is found as a parent of the click target.
    let isInside = element === e.target || element.contains(e.target);

    if (!isRemoved && !isInside) {
      action(e);
    }
  }
};
<commit_msg>allow named param "event"<commit_after>import { setModifierManager } from '@ember/modifier';
import { closest, documentOrBodyContains, ios } from './utils';

export default setModifierManager(
  () => ({
    createModifier(factory, args) {
      return {
        element: null,
        eventHandler: null,
        action: null,
        event: null,
      };
    },

    installModifier(state, element, args) {
      let [action] = args.positional;
      let { exceptSelector } = args.named;
      let { event = 'click' } = args.named;

      if (action) {
        state.action = action;
        state.element = element;
        state.event = event;
        state.eventHandler = createHandler(element, action, exceptSelector);

        document.addEventListener(event, state.eventHandler);
      }

      if (ios()) {
        document.body.style.cursor = 'pointer';
      }
    },

    updateModifier(state, args) {
      let [action] = args.positional;
      let { exceptSelector } = args.named;
      let { event = 'click' } = args.named;

      if (state.action) {
        document.removeEventListener('click', state.eventHandler);
      }

      if (action) {
        state.action = action;
        state.event = event;
        state.eventHandler = createHandler(state.element, action, exceptSelector);

        document.addEventListener(event, state.eventHandler);
      }
    },

    destroyModifier(state, element) {
      if (state.action) {
        document.removeEventListener(state.event, state.eventHandler);
      }

      if (ios()) {
        document.body.style.cursor = '';
      }
    }
  }),
  class OnClickOutsideModifier {}
);

const createHandler = (element, action, exceptSelector) => (e) => {
  if (exceptSelector && closest(e.target, exceptSelector)) {
    return;
  }

  let path = e.path || (e.composedPath && e.composedPath());

  if (path) {
    path.includes(element) || action(e);
  } else {
    // Check if the click target still is in the DOM.
    // If not, there is no way to know if it was inside the element or not.
    let isRemoved = !e.target || !documentOrBodyContains(e.target);

    // Check the element is found as a parent of the click target.
    let isInside = element === e.target || element.contains(e.target);

    if (!isRemoved && !isInside) {
      action(e);
    }
  }
};
<|endoftext|>


<commit_before>(function($) {

    /**
     * .slider
     *
     * Begins the slideshow by choosing the type of slide and duration
     *
     * type        Type of slideshow to run; Defaults to 'fade'
     * duration    Time in miliseconds that each element is visible; Defaults to
     *                 5000
     */
    $.fn.slider = function(type, duration) {
        type = typeof type !== 'undefined' ? type : 'Fade';
        duration = typeof duration !== 'undefined' ? duration : 5000;

        var $container = this;
        var count = 0;
        var validTypes = ['Fade','FadeInto','FadeIntoForever'];

        if(validTypes.indexOf(type) !== -1) {
            this["init"+type]();

            var intervalID = setInterval(function() {
                count = $container["slide"+type](intervalID, count);
            }, duration);
        } else {
            alert(type+" is not a supported slideshow type.");
            return false;
        }
    };

    /**
     * Sets the initial state for the FadeInto slideshow
     *
     * start    z-index for top-most element in slideshow; Defaults to 100
     */
    $.fn.initFadeIntoForever = function(start) {
        start = typeof start !== 'undefined' ? start : 100

        // Adds .active to first element in 'this'
        this.children(":first").addClass('active');

        // Iterates through all children of 'this'
        //     sets initiale z-index (start - order in 'this')
        //     sets position: absolute
        //     shows child
        for(var i=1; i<=this.children().length; i=i+1) {
            this.find(":nth-child("+i+")")
            .css({
                'z-index':start-i,
                'position':'absolute'
            })
            .show();
        }
    };

    $.fn.slideFadeIntoForever = function (intervalID, count, fadeSpeed) {
        // if(count == 6) clearInterval(intervalID);
        // if(count !== 0 && count%7 == 0 ) this.reset();

        fadeSpeed = typeof fadeSpeed !== 'undefined' ? fadeSpeed : 'slow';
        var $swap = this.swapForever();
        var $container = this;

        $swap["active"].fadeOut(fadeSpeed, function() {
            $swap["active"].hide(function() {
                $swap["next"].addClass('active');
                var $element = $swap["next"];

                for(var count = this.children.length; count>0; count = count -1) {
                    alert(count);
                    $element.css({'z-index':count}).show();

                    $element = $element.next().length ? element.next()
                        : this.children(":first");
                }
            });
        });

        return count+1;
    };

    $.fn.swapForever = function () {
        var $active = this.children(".active").toggleClass('active');
        var $next = $active.next().length ? $active.next()
            : this.children(":first");

        return {"active":$active,"next":$next};
    };

    $.fn.initFade = function() {
        this.children().hide().fadeOut();
        this.children(":first").addClass('active').show();
    };

    $.fn.slideFade = function (fadeSpeed) {
        fadeSpeed = typeof fadeSpeed !== 'undefined' ? fadeSpeed : 'slow';
        var $swap = this.swap();

        $swap["active"].fadeOut(fadeSpeed, function () {
            $swap["active"].hide(function () {
                $swap["next"].addClass('active')
                    .fadeIn(fadeSpeed);
            });
        });
    };

    /**
     * Sets the initial state for the FadeInto slideshow
     *
     * start    z-index for top-most element in slideshow; Defaults to 100
     */
    $.fn.initFadeInto = function(start) {
        start = typeof start !== 'undefined' ? start : 100

        // Adds .active to first element in 'this'
        this.children(":first").addClass('active');

        // Iterates through all children of 'this'
        //     sets initiale z-index (start - order in 'this')
        //     sets position: absolute
        //     shows child
        for(var i=1; i<=this.children().length; i=i+1) {
            this.find(":nth-child("+i+")")
            .css({
                'z-index':start-i,
                'position':'absolute'
            })
            .show();
        }
    };

    $.fn.slideFadeInto = function (intervalID, count, fadeSpeed) {
        // if(count == 6) clearInterval(intervalID);
        // if(count !== 0 && count%7 == 0 ) this.reset();

        fadeSpeed = typeof fadeSpeed !== 'undefined' ? fadeSpeed : 'slow';
        var $swap = this.swap();
        var $container = this;

        $swap["active"].fadeOut(fadeSpeed, function() {
                $swap["active"].hide(function() {
                   $swap["next"].addClass('active');
                   var nextZ = $container.nextZ();
                   $swap["active"].css({'z-index':nextZ}).show();
                });
            })

        return count+1;
    };

    $.fn.swap = function () {
        var $active = this.children(".active").toggleClass('active');
        if($active.length == 0)
            $active = this.children(":last");
        var $next = $active.next().length ? $active.next()
            : this.children(":first");

        return {"active":$active,"next":$next};
    };

    $.fn.nextZ = function(){
        var nextZ = 999;
        var length = this.children().length;
        for(var count=1; count<=length; count = count +1) {
            if(nextZ>this.find(":nth-child("+count+")").css("z-index"))
                nextZ = this.find(":nth-child("+count+")").css("z-index");
        }
        return nextZ-1;
    };

}) (jQuery);
<commit_msg>FadeIntoForever marches through elements and assigns z-index<commit_after>(function($) {

    /**
     * .slider
     *
     * Begins the slideshow by choosing the type of slide and duration
     *
     * type        Type of slideshow to run; Defaults to 'fade'
     * duration    Time in miliseconds that each element is visible; Defaults to
     *                 5000
     */
    $.fn.slider = function(type, duration) {
        type = typeof type !== 'undefined' ? type : 'Fade';
        duration = typeof duration !== 'undefined' ? duration : 5000;

        var $container = this;
        var count = 0;
        var validTypes = ['Fade','FadeInto','FadeIntoForever'];

        if(validTypes.indexOf(type) !== -1) {
            this["init"+type]();

            var intervalID = setInterval(function() {
                count = $container["slide"+type](intervalID, count);
            }, duration);
        } else {
            alert(type+" is not a supported slideshow type.");
            return false;
        }
    };

    /**
     * Sets the initial state for the FadeInto slideshow
     *
     * start    z-index for top-most element in slideshow; Defaults to 100
     */
    $.fn.initFadeIntoForever = function(start) {
        start = typeof start !== 'undefined' ? start : 100

        // Adds .active to first element in 'this'
        this.children(":first").addClass('active');

        // Iterates through all children of 'this'
        //     sets initiale z-index (start - order in 'this')
        //     sets position: absolute
        //     shows child
        for(var i=1; i<=this.children().length; i=i+1) {
            this.find(":nth-child("+i+")")
            .css({
                'z-index':start-i,
                'position':'absolute'
            })
            .show();
        }
    };

    $.fn.slideFadeIntoForever = function (intervalID, count, fadeSpeed) {
        // if(count == 6) clearInterval(intervalID);
        // if(count !== 0 && count%7 == 0 ) this.reset();

        fadeSpeed = typeof fadeSpeed !== 'undefined' ? fadeSpeed : 'slow';
        var $swap = this.swapForever();
        var $container = this;

        $swap["active"].fadeOut(fadeSpeed, function() {
            $swap["active"].hide(function() {
                $swap["next"].addClass('active');
                var $element = $swap["next"];

                for(var count = this.children().length; count>0; count = count -1) {
                    alert(count);
                    $element.css({'z-index':count}).show();

                    $element = $element.next().length ? element.next()
                        : this.children(":first");
                }
            });
        });

        return count+1;
    };

    $.fn.swapForever = function () {
        var $active = this.children(".active").toggleClass('active');
        var $next = $active.next().length ? $active.next()
            : this.children(":first");

        return {"active":$active,"next":$next};
    };

    $.fn.initFade = function() {
        this.children().hide().fadeOut();
        this.children(":first").addClass('active').show();
    };

    $.fn.slideFade = function (fadeSpeed) {
        fadeSpeed = typeof fadeSpeed !== 'undefined' ? fadeSpeed : 'slow';
        var $swap = this.swap();

        $swap["active"].fadeOut(fadeSpeed, function () {
            $swap["active"].hide(function () {
                $swap["next"].addClass('active')
                    .fadeIn(fadeSpeed);
            });
        });
    };

    /**
     * Sets the initial state for the FadeInto slideshow
     *
     * start    z-index for top-most element in slideshow; Defaults to 100
     */
    $.fn.initFadeInto = function(start) {
        start = typeof start !== 'undefined' ? start : 100

        // Adds .active to first element in 'this'
        this.children(":first").addClass('active');

        // Iterates through all children of 'this'
        //     sets initiale z-index (start - order in 'this')
        //     sets position: absolute
        //     shows child
        for(var i=1; i<=this.children().length; i=i+1) {
            this.find(":nth-child("+i+")")
            .css({
                'z-index':start-i,
                'position':'absolute'
            })
            .show();
        }
    };

    $.fn.slideFadeInto = function (intervalID, count, fadeSpeed) {
        // if(count == 6) clearInterval(intervalID);
        // if(count !== 0 && count%7 == 0 ) this.reset();

        fadeSpeed = typeof fadeSpeed !== 'undefined' ? fadeSpeed : 'slow';
        var $swap = this.swap();
        var $container = this;

        $swap["active"].fadeOut(fadeSpeed, function() {
                $swap["active"].hide(function() {
                   $swap["next"].addClass('active');
                   var nextZ = $container.nextZ();
                   $swap["active"].css({'z-index':nextZ}).show();
                });
            })

        return count+1;
    };

    $.fn.swap = function () {
        var $active = this.children(".active").toggleClass('active');
        if($active.length == 0)
            $active = this.children(":last");
        var $next = $active.next().length ? $active.next()
            : this.children(":first");

        return {"active":$active,"next":$next};
    };

    $.fn.nextZ = function(){
        var nextZ = 999;
        var length = this.children().length;
        for(var count=1; count<=length; count = count +1) {
            if(nextZ>this.find(":nth-child("+count+")").css("z-index"))
                nextZ = this.find(":nth-child("+count+")").css("z-index");
        }
        return nextZ-1;
    };

}) (jQuery);
<|endoftext|>


<commit_before>define(["pat-registry", "pat-clone"], function(registry) {

    describe("pat-clone", function() {
        beforeEach(function() {
            $("div#lab").remove();
            $("
", {id: "lab"}).appendTo(document.body);
        });
        afterEach(function() {
            $("#lab").remove();
        });

        it("clones the node's first child when .clone-trigger is clicked and places the clone after the cloned element", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
Clone Me
' +
                '    <button class="clone-trigger">Clone!</button>' +
                '
');
            registry.scan($lab);
            expect($('div.item').length).toBe(1);
            $lab.find('.clone-trigger').click();
            expect($('div.item').length).toBe(2);

            // Try now a different variation with the trigger inside the cloned
            // element.
            $lab.empty().html(
                '
' +
                '
' +
                '       <button class="clone-trigger">Clone!</button>' +
                '
' +
                '
');
            registry.scan($lab);
            expect($('div.item').length).toBe(1);
            $lab.find('.clone-trigger').click();
            expect($('div.item').length).toBe(2);
            $lab.find('.clone-trigger:last').click();
            expect($('div.item').length).toBe(3);
            $lab.find('.clone-trigger:first').click();
            expect($('div.item').length).toBe(4);
        });

        it("allows the trigger element to be configured", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
Clone Me
' +
                '    <button class="clone-trigger">Will not Clone!</button>' +
                '    <button class="real-clone-trigger">Clone!</button>' +
                '
');
            registry.scan($lab);
            expect($('div.item').length).toBe(1);
            $lab.find('.clone-trigger').click();
            expect($('div.item').length).toBe(1);
            $lab.find('.real-clone-trigger').click();
            expect($('div.item').length).toBe(2);
        });

        it("allows the cloned element to be configured", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
Original item
' +
                '
Clone template
' +
                '
' +
                '<button class="clone-trigger">Clone!</button>');
            registry.scan($lab);
            expect($('div.item').length).toBe(2);
            $lab.find('.clone-trigger').click();
            expect($('div.item').length).toBe(3);
            expect($('div.item:last').text()).toBe('Clone template');
            expect($("div.item:contains('Clone template')").length).toBe(2);
        });

        it("will automatically increment any number in name and value attributes.", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
Family member #{1}
' +
                '
' +
                '<button class="clone-trigger">Clone!</button>');
            registry.scan($lab);
            expect($('p.legend').length).toBe(1);

            $lab.find('.clone-trigger').click();
            expect($('p.legend').length).toBe(2);
            expect($('p.legend:last').attr('name')).toBe('item-2');

            $lab.find('.clone-trigger').click();
            expect($('p.legend').length).toBe(3);
            expect($('p.legend:last').attr('name')).toBe('item-3');
        });

        it("will remove a clone when .remove-clone inside the clone is clicked.", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
<button type="button" class="remove-clone">Remove</button>
' +
                '
' +
                '<button class="clone-trigger">Clone!</button>');
            registry.scan($lab);
            expect($('div.item').length).toBe(1);

            $lab.find('.clone-trigger').click();
            expect($('div.item').length).toBe(2);

            $lab.find('.remove-clone:last').click();
            expect($('div.item').length).toBe(1);

            $lab.find('.remove-clone').click();
            expect($('div.item').length).toBe(0);
        });

        it("allows the remove element to be configured", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
<button type="button" class="custom-remove-class">Remove</button>
' +
                '
' +
                '<button class="clone-trigger">Clone!</button>');
            registry.scan($lab);
            expect($('div.item').length).toBe(1);

            $lab.find('.clone-trigger').click();
            expect($('div.item').length).toBe(2);

            $lab.find('.custom-remove-class:last').click();
            expect($('div.item').length).toBe(1);

            $lab.find('.custom-remove-class').click();
            expect($('div.item').length).toBe(0);
        });
    });
});
<commit_msg>Fix tests after rename of argument.<commit_after>define(["pat-registry", "pat-clone"], function(registry) {

    describe("pat-clone", function() {
        beforeEach(function() {
            $("div#lab").remove();
            $("
", {id: "lab"}).appendTo(document.body);
        });
        afterEach(function() {
            $("#lab").remove();
        });

        it("clones the node's first child when .add-clone is clicked and places the clone after the cloned element", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
Clone Me
' +
                '    <button class="add-clone">Clone!</button>' +
                '
');
            registry.scan($lab);
            expect($('div.item').length).toBe(1);
            $lab.find('.add-clone').click();
            expect($('div.item').length).toBe(2);

            // Try now a different variation with the trigger inside the cloned
            // element.
            $lab.empty().html(
                '
' +
                '
' +
                '       <button class="add-clone">Clone!</button>' +
                '
' +
                '
');
            registry.scan($lab);
            expect($('div.item').length).toBe(1);
            $lab.find('.add-clone').click();
            expect($('div.item').length).toBe(2);
            $lab.find('.add-clone:last').click();
            expect($('div.item').length).toBe(3);
            $lab.find('.add-clone:first').click();
            expect($('div.item').length).toBe(4);
        });

        it("allows the trigger element to be configured", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
Clone Me
' +
                '    <button class="add-clone">Will not Clone!</button>' +
                '    <button class="real-add-clone">Clone!</button>' +
                '
');
            registry.scan($lab);
            expect($('div.item').length).toBe(1);
            $lab.find('.add-clone').click();
            expect($('div.item').length).toBe(1);
            $lab.find('.real-add-clone').click();
            expect($('div.item').length).toBe(2);
        });

        it("allows the cloned element to be configured", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
Original item
' +
                '
Clone template
' +
                '
' +
                '<button class="add-clone">Clone!</button>');
            registry.scan($lab);
            expect($('div.item').length).toBe(2);
            $lab.find('.add-clone').click();
            expect($('div.item').length).toBe(3);
            expect($('div.item:last').text()).toBe('Clone template');
            expect($("div.item:contains('Clone template')").length).toBe(2);
        });

        it("will automatically increment any number in name and value attributes.", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
Family member #{1}
' +
                '
' +
                '<button class="add-clone">Clone!</button>');
            registry.scan($lab);
            expect($('p.legend').length).toBe(1);

            $lab.find('.add-clone').click();
            expect($('p.legend').length).toBe(2);
            expect($('p.legend:last').attr('name')).toBe('item-2');

            $lab.find('.add-clone').click();
            expect($('p.legend').length).toBe(3);
            expect($('p.legend:last').attr('name')).toBe('item-3');
        });

        it("will remove a clone when .remove-clone inside the clone is clicked.", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
<button type="button" class="remove-clone">Remove</button>
' +
                '
' +
                '<button class="add-clone">Clone!</button>');
            registry.scan($lab);
            expect($('div.item').length).toBe(1);

            $lab.find('.add-clone').click();
            expect($('div.item').length).toBe(2);

            $lab.find('.remove-clone:last').click();
            expect($('div.item').length).toBe(1);

            $lab.find('.remove-clone').click();
            expect($('div.item').length).toBe(0);
        });

        it("allows the remove element to be configured", function() {
            var $lab = $('#lab');
            $lab.html(
                '
' +
                '
<button type="button" class="custom-remove-class">Remove</button>
' +
                '
' +
                '<button class="add-clone">Clone!</button>');
            registry.scan($lab);
            expect($('div.item').length).toBe(1);

            $lab.find('.add-clone').click();
            expect($('div.item').length).toBe(2);

            $lab.find('.custom-remove-class:last').click();
            expect($('div.item').length).toBe(1);

            $lab.find('.custom-remove-class').click();
            expect($('div.item').length).toBe(0);
        });
    });
});
<|endoftext|>


<commit_before>(window.n2 || (window.n2 = {})).FileUpload = function (maxFileSize, ticket, selected, refreshFrames) {
	"use strict";

	function onFileUploaded(e) {
		var fileupload = this;
		setTimeout(function () {
			$(".complete", fileupload).parent().fadeOut();
			if ($(".error", fileupload).length > 0)
				if (!confirm("Failed to upload some files, confirm to refresh"))
					return;

			if ($(".cancel", fileupload).length == 0)
				onUploadComplete();
		}, 10);
	}
	function onUploadComplete() {
		$("#fileupload").removeClass("uploading");
		$("#uploadcontrols").slideDown();
		refreshFrames();
		window.location = window.location;
	}
	function onUploadStart() {
		$("#uploadcontrols").slideUp();
		$("#fileupload").addClass("uploading");
	}

	if (typeof FileReader == "undefined") {
		$("#fileupload em").hide();
	}

	// Initialize the jQuery File Upload widget:
	$('#fileupload').fileupload({
		url: "UploadFile.ashx",
		maxFileSize: maxFileSize,
		previewMaxWidth: 48,
		previewMaxHeight: 48,
		autoUpload: true,
		sequentialUploads: true,
		formData: { ticket: ticket, selected: selected }
	})
    .bind('fileuploadstart', onUploadStart)
    .bind('fileuploaddone', onFileUploaded)
    .bind('fileuploadfail', function () { });

	//        // Load existing files:
	//        $.getJSON($('form').attr("enctype", "multipart/form-data").prop('action'), function (files) {
	//            var fu = $('#fileupload').data('fileupload');
	//            fu._adjustMaxNumberOfFiles(-files.length);
	//            fu._renderDownload(files)
	//            .appendTo($('#fileupload .files'))
	//            .fadeIn(function () {
	//                // Fix for IE7 and lower:
	//                $(this).show();
	//            });
	//        });

	//        // Open download dialogs via iframes,
	//        // to prevent aborting current uploads:
	//        $('#fileupload .files').delegate('a:not([target^=_blank])', 'click', function (e) {
	//            e.preventDefault();
	//            $('')
	//                .prop('src', this.href)
	//                .appendTo('body');
	//        });
};<commit_msg>Basic error handling<commit_after>(window.n2 || (window.n2 = {})).FileUpload = function (maxFileSize, ticket, selected, refreshFrames) {
	"use strict";

	function onFileUploaded(e) {
		var fileupload = this;
		setTimeout(function () {
			$(".complete", fileupload).parent().fadeOut();
			if ($(".error", fileupload).length > 0)
				if (!confirm("Failed to upload some files, confirm to refresh"))
					return;

			if ($(".cancel", fileupload).length == 0)
				onUploadComplete();
		}, 10);
	}
	function onUploadComplete() {
		$("#fileupload").removeClass("uploading");
		$("#uploadcontrols").slideDown();
		refreshFrames();
		window.location = window.location;
	}
	function onUploadFailed() {
		$("#fileupload").removeClass("uploading");
		$("#uploadcontrols").slideDown();
		$("#uploadcontrols").prepend("
<button type='button' class='close' data-dismiss='alert'>×</button>Failed uploading
");
	}
	function onUploadStart() {
		$("#uploadcontrols").slideUp();
		$("#fileupload").addClass("uploading");
	}

	if (typeof FileReader == "undefined") {
		$("#fileupload em").hide();
	}

	// Initialize the jQuery File Upload widget:
	$('#fileupload').fileupload({
		url: "UploadFile.ashx",
		maxFileSize: maxFileSize,
		previewMaxWidth: 48,
		previewMaxHeight: 48,
		autoUpload: true,
		sequentialUploads: true,
		formData: { ticket: ticket, selected: selected }
	})
    .bind('fileuploadstart', onUploadStart)
    .bind('fileuploaddone', onFileUploaded)
    .bind('fileuploadfail', onUploadFailed);

	//        // Load existing files:
	//        $.getJSON($('form').attr("enctype", "multipart/form-data").prop('action'), function (files) {
	//            var fu = $('#fileupload').data('fileupload');
	//            fu._adjustMaxNumberOfFiles(-files.length);
	//            fu._renderDownload(files)
	//            .appendTo($('#fileupload .files'))
	//            .fadeIn(function () {
	//                // Fix for IE7 and lower:
	//                $(this).show();
	//            });
	//        });

	//        // Open download dialogs via iframes,
	//        // to prevent aborting current uploads:
	//        $('#fileupload .files').delegate('a:not([target^=_blank])', 'click', function (e) {
	//            e.preventDefault();
	//            $('')
	//                .prop('src', this.href)
	//                .appendTo('body');
	//        });
};<|endoftext|>