<commit_before>/*
TK102 GPS server for Node.js

License: COPYLEFT
This code is released under COPYLEFT meaning you can do with it
anything you like except copyrighting it. If possible it would
be nice to include the source URL for future reference:

https://github.com/fvdm/nodejs-tk102
*/

// INIT
var	net = require('net'),
	EventEmitter = require('events').EventEmitter

var tk102 = new EventEmitter()

// defaults
tk102.settings = {
	ip:				'0.0.0.0',	// default listen on all IPs
	port:			0,			// 0 = random, 'listening' event reports port
	connections:	10,			// 10 simultaneous connections
	timeout:		10			// 10 seconds idle timeout
}

// Create server
tk102.createServer = function( vars ) {

	// override settings
	if( typeof vars == 'object' && Object.keys(vars).length >= 1 ) {
		for( var key in vars ) {
			tk102.settings[ key ] = vars[ key ]
		}
	}

	// start server
	tk102.server = net.createServer( function( socket ) {

		// socket idle timeout
		if( tk102.settings.timeout > 0 ) {
			socket.setTimeout( tk102.settings.timeout * 1000, function() {
				tk102.emit( 'timeout', socket )
				socket.end()
			})
		}

	}).listen( tk102.settings.port, tk102.settings.ip, function() {

		// server ready
		tk102.emit( 'listening', tk102.server.address() )

	})

	// maximum number of slots
	tk102.server.maxConnections = tk102.settings.connections

	// inbound connection
	tk102.server.on( 'connection', function( socket ) {

		tk102.emit( 'connection', socket )
		socket.setEncoding( 'utf8' )
		var data = ''

		// receiving data
		socket.on( 'data', function( chunk ) {
			tk102.emit( 'data', chunk )
			data += chunk
		})

		// complete
		socket.on( 'close', function() {

			var gps = {}
			gps = tk102.parse( data )
			if( data != '' ) {
				var gps = tk102.parse( data )
				if( gps ) {
					tk102.emit( 'track', gps )
				} else {
					tk102.emit( 'fail', {
						reason:	'Cannot parse GPS data from device',
						socket:	socket,
						input:	data
					})
				}
			}

		})

	})
}

// Parse GPRMC string
tk102.parse = function( raw ) {

	// 1203292316,0031698765432,GPRMC,211657.000,A,5213.0247,N,00516.7757,E,0.00,273.30,290312,,,A*62,F,imei:123456789012345,123
	var raw = raw.trim()
	var str = raw.split(',')
	var data = false

	// only continue with correct input, else the server may quit...
	if( str.length == 18 && str[2] == 'GPRMC' ) {

		// parse
		var datetime = str[0].replace( /([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/, function( match, year, month, day, hour, minute ) {
			return '20'+ year +'-'+ month +'-'+ day +' '+ hour +':'+ minute
		})

		var gpsdate = str[11].replace( /([0-9]{2})([0-9]{2})([0-9]{2})/, function( match, day, month, year ) {
			return '20'+ year +'-'+ month +'-'+ day
		})

		var gpstime = str[3].replace( /([0-9]{2})([0-9]{2})([0-9]{2})\.([0-9]{3})/, function( match, hour, minute, second, ms ) {
			return hour +':'+ minute +':'+ second +'.'+ ms
		})

		data = {
			'raw':		raw,
			'datetime':	datetime,
			'phone':	str[1],
			'gps': {
				'date':			gpsdate,
				'time':			gpstime,
				'signal':		str[15] == 'F' ? 'full' : 'low',
				'fix':			str[4] == 'A' ? 'active' : 'invalid'
			},
			'geo': {
				'latitude':		tk102.fixGeo( str[5], str[6] ),
				'longitude':	tk102.fixGeo( str[7], str[8] ),
				'bearing':		parseInt( str[10] )
			},
			'speed': {
				'knots':		Math.round( str[9] * 1000 ) / 1000,
				'kmh':			Math.round( str[9] * 1.852 * 1000 ) / 1000,
				'mph':			Math.round( str[9] * 1.151 * 1000 ) / 1000
			},
			'imei':		str[16].replace( 'imei:', '' )
		}
	}

	// done
	return data
}

// Clean geo positions, with 6 decimals
tk102.fixGeo = function( one, two ) {
	var minutes = one.substr(-7, 7)
	var degrees = parseInt( one.replace( minutes, '' ) )
	var one = degrees + (minutes / 60)

	var one = parseFloat( (two == 'S' || two == 'W' ? '-' : '') + one )
	return Math.round( one * 1000000 ) / 1000000
}

// ready
module.exports = tk102<commit_msg>Cleanup code<commit_after>/*
TK102 GPS server for Node.js

License: COPYLEFT
This code is released under COPYLEFT meaning you can do with it
anything you like except copyrighting it. If possible it would
be nice to include the source URL for future reference:

https://github.com/fvdm/nodejs-tk102
*/

// INIT
var net = require('net'),
    EventEmitter = require('events').EventEmitter

var tk102 = new EventEmitter()

// defaults
tk102.settings = {
	ip:		'0.0.0.0',	// default listen on all IPs
	port:		0,		// 0 = random, 'listening' event reports port
	connections:	10,		// 10 simultaneous connections
	timeout:	10		// 10 seconds idle timeout
}

// Create server
tk102.createServer = function( vars ) {

	// override settings
	if( typeof vars == 'object' && Object.keys(vars).length >= 1 ) {
		for( var key in vars ) {
			tk102.settings[ key ] = vars[ key ]
		}
	}

	// start server
	tk102.server = net.createServer( function( socket ) {

		// socket idle timeout
		if( tk102.settings.timeout > 0 ) {
			socket.setTimeout( tk102.settings.timeout * 1000, function() {
				tk102.emit( 'timeout', socket )
				socket.end()
			})
		}

	}).listen( tk102.settings.port, tk102.settings.ip, function() {

		// server ready
		tk102.emit( 'listening', tk102.server.address() )

	})

	// maximum number of slots
	tk102.server.maxConnections = tk102.settings.connections

	// inbound connection
	tk102.server.on( 'connection', function( socket ) {

		tk102.emit( 'connection', socket )
		socket.setEncoding( 'utf8' )
		var data = ''

		// receiving data
		socket.on( 'data', function( chunk ) {
			tk102.emit( 'data', chunk )
			data += chunk
		})

		// complete
		socket.on( 'close', function() {

			var gps = {}
			gps = tk102.parse( data )
			if( data != '' ) {
				var gps = tk102.parse( data )
				if( gps ) {
					tk102.emit( 'track', gps )
				} else {
					tk102.emit( 'fail', {
						reason:	'Cannot parse GPS data from device',
						socket:	socket,
						input:	data
					})
				}
			}

		})

	})
}

// Parse GPRMC string
tk102.parse = function( raw ) {

	// 1203292316,0031698765432,GPRMC,211657.000,A,5213.0247,N,00516.7757,E,0.00,273.30,290312,,,A*62,F,imei:123456789012345,123
	var raw = raw.trim()
	var str = raw.split(',')
	var data = false

	// only continue with correct input, else the server may quit...
	if( str.length == 18 && str[2] == 'GPRMC' ) {

		// parse
		var datetime = str[0].replace( /([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/, function( match, year, month, day, hour, minute ) {
			return '20'+ year +'-'+ month +'-'+ day +' '+ hour +':'+ minute
		})

		var gpsdate = str[11].replace( /([0-9]{2})([0-9]{2})([0-9]{2})/, function( match, day, month, year ) {
			return '20'+ year +'-'+ month +'-'+ day
		})

		var gpstime = str[3].replace( /([0-9]{2})([0-9]{2})([0-9]{2})\.([0-9]{3})/, function( match, hour, minute, second, ms ) {
			return hour +':'+ minute +':'+ second +'.'+ ms
		})

		data = {
			'raw':		raw,
			'datetime':	datetime,
			'phone':	str[1],
			'gps': {
				'date':		gpsdate,
				'time':		gpstime,
				'signal':	str[15] == 'F' ? 'full' : 'low',
				'fix':		str[4] == 'A' ? 'active' : 'invalid'
			},
			'geo': {
				'latitude':	tk102.fixGeo( str[5], str[6] ),
				'longitude':	tk102.fixGeo( str[7], str[8] ),
				'bearing':		parseInt( str[10] )
			},
			'speed': {
				'knots':	Math.round( str[9] * 1000 ) / 1000,
				'kmh':		Math.round( str[9] * 1.852 * 1000 ) / 1000,
				'mph':		Math.round( str[9] * 1.151 * 1000 ) / 1000
			},
			'imei':		str[16].replace( 'imei:', '' )
		}
	}

	// done
	return data
}

// Clean geo positions, with 6 decimals
tk102.fixGeo = function( one, two ) {
	var minutes = one.substr(-7, 7)
	var degrees = parseInt( one.replace( minutes, '' ) )
	var one = degrees + (minutes / 60)

	var one = parseFloat( (two == 'S' || two == 'W' ? '-' : '') + one )
	return Math.round( one * 1000000 ) / 1000000
}

// ready
module.exports = tk102<|endoftext|>


<commit_before>var _ = require("underscore");

function empty(xs) {
  return _.size(xs) < 1;
}

function not(x) {
  return !x;
}

function min(a, b) {
  if (a < b) {
    return 1;
  }
  else if (a > b) {
    return -1;
  }
  else {
    return 0;
  }
}

function max(a, b) {
  if (a > b) {
    return 1;
  }
  else if (a < b) {
    return -1;
  }
  else {
    return 0;
  }
}

function groupOps(ops) {
  return _.groupBy(ops.sort(), _.isEqual);
}

function find(f, haystack) {
  for(var i = 0; i < haystack.length; i++) {
    if (f(haystack[i])) {
      return i;
    }
  }
  return false;
}

function dict(pairs) {
  var o = {};
  pairs.map(function(p) {
    o[p[0]] = p[1];
  });
  return o;
}

function extend(xs, ys) {
  var result = _.clone(xs);
  result.push.apply(result, ys);
  return result;
}

RegExp.escape= function(s) {
      return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};

function operatorMatch(ops) {
  ops = _.filter(ops,
                 function (op) {
                   return op.length > 0;
                 });
  ops.sort(min);
  var rstring = ops.reduce(
  function(acc, x) {
    if (!x || x.length < 1) {
      return "";
    }
    return acc + "(" + RegExp.escape(x) + ")|";
  }, "");
  var reg = new RegExp(rstring);
  return function(x) {
    var matched = reg.exec(x);
    if ((!(_.isNull(matched))) && matched[0]) {
      return matched[0];
    }
    else {
      return false;
    }
  };
}

module.exports = {
  not  : not,
  groupOps : groupOps,
  opMatch : operatorMatch,
  dict: dict,
  extend : extend,
  empty : empty,
};
<commit_msg>style fixes<commit_after>var _ = require("underscore");

function empty(xs) {
  return _.size(xs) < 1;
}

function not(x) {
  return !x;
}

function min(a, b) {
  if (a < b) {
    return 1;
  }
  else if (a > b) {
    return -1;
  }
  else {
    return 0;
  }
}

function max(a, b) {
  if (a > b) {
    return 1;
  }
  else if (a < b) {
    return -1;
  }
  else {
    return 0;
  }
}

function groupOps(ops) {
  return _.groupBy(ops.sort(), _.isEqual);
}

function find(f, haystack) {
  for(var i = 0; i < haystack.length; i++) {
    if (f(haystack[i])) {
      return i;
    }
  }
  return false;
}

function dict(pairs) {
  var o = {};
  pairs.map(function(p) {
    o[p[0]] = p[1];
  });
  return o;
}

function extend(xs, ys) {
  var result = _.clone(xs);
  result.push.apply(result, ys);
  return result;
}

RegExp.escape= function(s) {
      return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
};

function operatorMatch(ops) {
  ops = _.filter(ops,
                 function (op) {
                   return op.length > 0;
                 });
  ops.sort(min);
  var rstring = ops.reduce(
  function(acc, x) {
    if (!x || x.length < 1) {
      return "";
    }
    return acc + "(" + RegExp.escape(x) + ")|";
  }, "");
  var reg = new RegExp(rstring);
  return function(x) {
    var matched = reg.exec(x);
    if ((!(_.isNull(matched))) && matched[0]) {
      return matched[0];
    }
    else {
      return false;
    }
  };
}

function debugPrint(stx) {

module.exports = {
  not  : not,
  groupOps : groupOps,
  opMatch : operatorMatch,
  dict: dict,
  extend : extend,
  empty : empty,
};
<|endoftext|>


<commit_before>/* ===========================================================================

	trace.js

	Copyright 2012 John Dunning.
	fw@johndunning.com
	http://johndunning.com/fireworks

	trace.js is released under the MIT license.

   ======================================================================== */

/*
	First, install trace.js in a known location, like in the
	Fireworks/Configuration/Commands folder.

	fw.runScript(fw.appJsCommandsDir + "/trace.js");

	function myBuggyFunc(count)
	{
		return trace();

		var dom = fw.getDocumentDOM();
		dom.selectAll();
		dom.deleteSelection();

		for (var i = 0; i < count; i++) {
			dom.clipPaste();
			dom.moveSelectionTo({ x: i * 10, y: i * 10 });
		}
	}

	myBuggyFunc();

	watch variables
	pass in a name for the function
	if you see an if statement logged, means that branch was entered
	don't pass in the dom

	To do:
		- maybe have an option to wrap everything in a try/catch and only log
			on exceptions
			return 'try {' + inWholeLine + '} catch (e) { log("' + functionName + 'ERROR: ' + inStatement + '"); throw(e); }\n' + logCall;
			problem is, we'd have to understand the block structure of the code
			to not wrap try/catch around just the opening of a for loop, say

		- try tracing a recursive function

		- maybe use watch() to track the watched variables and log only when
			they change

		- should probably pass log in as a parameter to the module
			would also need a string to supply the name for the function
			or possibly store a reference to it, then add it to the scope facade

		- make it work with module calls
			function.toString sometimes puts all the statements on one line,
			so the regex doesn't match anything

		- put watched vars on one line?
			gets tricky when you have tests and don't want to show anything
			if the test doesn't match

	Done:
		- make sure returning a function from a function and then tracing the
			returned one has the right scope

		- escape quotation marks

		- put logs after if and for/while loops

		- capture the return value and display it

		- call it trace

*/

try { (function() {
	if (typeof log != "function") {
		alert("Before using the trace() library, the Fireworks Console extension must be installed.  It can be downloaded from here:\n\n" +
			"http://johndunning.com/fireworks/about/FWConsole");
		return;
	}

	// =======================================================================
	function forEach(obj, iterator, context) {
		if (obj == null) { return; }
		if (obj.length === +obj.length) {
			for (var i = 0, l = obj.length; i < l; i++) {
					// i in obj seems to be false when it's an array extracted
					// from customData
				if (iterator.call(context, obj[i], i, obj) === false) { return; }
			}
		} else {
			for (var key in obj) {
				if (hasOwnProperty.call(obj, key)) {
					if (iterator.call(context, obj[key], key, obj) === false) { return; }
				}
			}
		}
	}

	// =======================================================================
	function map(obj, iterator, context) {
		var	results	= [];
		if (obj	== null) { return results; }

		forEach(obj, function(value, index, list) {
			results[results.length] = iterator.call(context, value, index, list);
		});

		return results;
	}

	// =======================================================================
	function logWatched(
		inExpression,
		inFunctionName)
	{
		inFunctionName = inFunctionName.slice(0, -1);

		var test = inExpression,
			prefix = "     ";

		if (/[<>=]+/.test(test)) {
			test = '(' + test + ')';
			return '(' + test + ' ? log("' + inFunctionName + prefix + test +
				' :", ' + test + ') : "");';
		} else {
			return 'log("' + inFunctionName + prefix + test + ':", ' + test + ');';
		}
	}

	// =======================================================================
	function getScopeFacade(
		inCaller)
	{
		function Facade()
		{
			// this is an empty class that we use just to check whether a scope
			// we encounter is actually a Facade
		}

		function createGetter(
			inName,
			inScope)
		{
			return function()
			{
					// get the value from the scope that contains this variable
				return inScope[inName];
			}
		}

		function createSetter(
			inName,
			inScope)
		{
			return function(
				inValue)
			{
					// set the value on the scope that contains this variable
				inScope[inName] = inValue;
			}
		}

		function addScope(
			inScope,
			inFacade)
		{
				// add a getter and setter for every variable in this scope.
				// these functions will get/set the values from/in the scope
				// the var is originally from, rather than the inFacade object.
			for (var name in inScope) {
				inFacade.__defineGetter__(name, createGetter(name, inScope));
				inFacade.__defineSetter__(name, createSetter(name, inScope));
			}
		}

		function walkCallerChain(
			inCaller,
			inFacade)
		{
			var callerScope = inCaller.__parent__;

			if (callerScope instanceof Facade) {
					// we've hit a scope that was created by an earlier call to
					// trace().  if we tried to add that scope to our facade,
					// we'd get in an endless loop, so flee!
				return inFacade;
			} else if (inCaller.caller) {
					// add the variables from the caller's caller's scope first,
					// in case we shadow some vars that are also defined in the
					// parent scope
				inFacade = arguments.callee(inCaller.caller, inFacade);
			}

				// add the caller's scope to the facade
			addScope(callerScope, inFacade);

			return inFacade;
		}

			// we use an empty Facade object to store the scope values so that
			// we can tell we created it, using instanceof.  that way, if the
			// function we're tracing calls another function that is also
			// traced, we won't get into an infinite loop.
		var facade = new Facade();

			// first add all the parent scopes from our call chain
		walkCallerChain(inCaller, facade);

			// then add the local variables from our call, so that they can
			// shadow ones in the parent scope, if needed
		addScope(inCaller.__call__, facade);

		return facade;
	}

	// =======================================================================
	trace = function(
		inWatched,
		inFunctionName)
	{
		function logStatement(
			inWholeLine,
			inStatement)
		{
				// display the function name and statement in the console
			var logCall = 'log(' + (functionName + inStatement).quote() + ');\n' +
				watchedVars;

			if (/^(return|continue|break)[\s;]/.test(inStatement)) {
					// since putting a log call after return, continue or break
					// is pointless, put it before the statement
				return logCall + inWholeLine;
			} else {
					// put the log call after the statement, so that it won't
					// be logged if the statement throws an exception
				return inWholeLine + logCall;
			}
		}

			// adjust the optional parameters
		if (typeof inWatched == "string") {
			inFunctionName = inWatched;
			inWatched = [];
		}

				// we can't call this "caller", because that creates a property
				// called "caller" on our function object, which then overwrites
				// the arguments.callee.caller property.  ffs.
		var callerFunc = arguments.callee.caller,
			callerSource = arguments.callee.caller.toString(),
				// ignore the calling function's name if one was passed in
			functionName = inFunctionName || callerFunc.name,
				// pull out the body and params of the function
			codeMatch = callerSource.match(/function\s+([^(]+)?\(([^)]*)\)\s*\{([\s\S]*)\}/),
			params = codeMatch[2] ? codeMatch[2].split(/\s*,\s*/) : [],
			body = codeMatch[3],
			paramLog,
			watchedVars = "",
			traceMatch;

			// add a colon after the function name, if there is one
		functionName = functionName ? functionName + ": " : "";

		if (inWatched) {
			watchedVars = map(inWatched, function(watched) {
					// argh, there's some global native function called "watch"?
					// and we can't shadow it with a local var?  wtf?  ah, it's
					// actually an incredibly useful watch() function to get
					// callbacks when a property changes.  booyah.
				return logWatched(watched, functionName);
			});
			watchedVars = watchedVars.join("\n") + "\n";
		}

			// create a log statement to display the function's parameters.
			// include the function name as the first string in the log call.
		paramLog = [(functionName + "(").quote()].concat(map(params, function(param) {
			return [(param + ":").quote(), param];
		}));

		paramLog.push(")".quote());
		paramLog = 'log(' + paramLog.join(", ") + ');\n' + watchedVars;

		traceMatch = body.match(/return\s+trace\s*\([^)]*\)\s*;/);

		if (!traceMatch) {
				// the caller must have set a var to trace and then called us
				// through that var.  but we can't trace if we can't find the
				// trace call and strip it out.
			alert('A "return trace();" statement could not be found in the calling function. The trace function must be called directly, not through a reference.');
			return;
		}

			// start tracing from the statement after the trace() call, and
			// remove any other calls to trace that happen to be in the function.
			// also, the array returned by match() doesn't have a lastIndex
			// property on it.  ffs.
		body = body.slice(traceMatch.index + traceMatch[0].length);
		body = body.replace(/return\s+trace\s*\([^)]*\)\s*;/g, "");

			// add a log call after each ;\n to display the previous statement
		body = body.replace(/^\s*([^\n]+;)\s*\n/mg,
			logStatement);

			// add a log call after the opening brace of an if/for/while block.
			// but do so only if there's a space in front of the if, to avoid
			// sticking log calls in the middle of another log call, which can
			// happen with a nested function definition.  FW returns the body of
			// the nested function all on one line when doing toString, so the
			// replace call above will log the whole line.  but then this if
			// replace will see if statements inside the log string and replace
			// them, breaking the code.  requiring a space before the keyword
			// won't match in the nested function case, since FW removes all
			// the whitespace from the function body.
		body = body.replace(/\s((?:if|for|while)\s*\([^{]+\)\s*\{)/g,
			logStatement);

			// wrap the body in an anonymous function so our caller can execute
			// it in the caller's scope.  then capture that function's return
			// value, log it, and return it from another anonymous function.
		body = '(function(){ var returnValue = (function(){' +
			paramLog + body +
			'})(); log("' + functionName + 'return", returnValue); return returnValue; })();';

			// create a facade object that maps all of the identifiers in the
			// our caller's scope chain to the owning scope, and then eval the
			// caller's code within that fake scope.  this is where all the
			// magic happens.
		with (getScopeFacade(callerFunc)) {
			return eval(body);
		}
	}
})(); } catch (exception) {
	if (exception.lineNumber) {
		alert([exception, exception.lineNumber, exception.fileName].join("\n"));
	} else {
		throw exception;
	}
}
<commit_msg>Fixed up the comments.<commit_after>/* ===========================================================================

	trace.js

	Copyright 2012 John Dunning.
	fw@johndunning.com
	http://johndunning.com/fireworks

	trace.js is released under the MIT license.

   ======================================================================== */

/*
	First, install the Fireworks Console extension from here:
	http://johndunning.com/fireworks/about/FWConsole

	Then restart Fireworks and open the console panel.

	Install trace.js in a known location, like in the Fireworks/Configuration/Commands
	folder.  In your script, call runScript to load the trace command:

		fw.runScript(fw.appJsCommandsDir + "/trace.js");

	Then add `return trace();` to the functions whose execution you want to trace:

		function myBuggyFunc(count)
		{
			return trace();

			var dom = fw.getDocumentDOM();
			dom.selectAll();
			dom.deleteSelection();

			for (var i = 0; i < count; i++) {
				dom.clipPaste();
				dom.moveSelectionTo({ x: i * 10, y: i * 10 });
			}
		}

		myBuggyFunc();

	See the readme for more information about the parameters that can be
	passed to trace().

	To do:
		- maybe have an option to wrap everything in a try/catch and only log
			on exceptions
			return 'try {' + inWholeLine + '} catch (e) { log("' + functionName +
				'ERROR: ' + inStatement + '"); throw(e); }\n' + logCall;
			problem is, we'd have to understand the block structure of the code
			to not wrap try/catch around just the opening of a for loop, say

		- try tracing a recursive function

		- maybe use watch() to track the watched variables and log only when
			they change

		- should probably pass log in as a parameter to the module
			would also need a string to supply the name for the function
			or possibly store a reference to it, then add it to the scope facade

		- make it work with module calls
			function.toString sometimes puts all the statements on one line,
			so the regex doesn't match anything

		- put watched vars on one line?
			gets tricky when you have tests and don't want to show anything
			if the test doesn't match

	Done:
		- make sure returning a function from a function and then tracing the
			returned one has the right scope

		- escape quotation marks

		- put logs after if and for/while loops

		- capture the return value and display it

		- call it trace

*/

try { (function() {
	if (typeof log != "function") {
		alert("Before trace() can be called, the Fireworks Console extension must be installed and the panel must be open.  The extension can be downloaded from here:\n\n" +
			"http://johndunning.com/fireworks/about/FWConsole");
		return;
	}

	// =======================================================================
	function forEach(obj, iterator, context) {
		if (obj == null) { return; }
		if (obj.length === +obj.length) {
			for (var i = 0, l = obj.length; i < l; i++) {
					// i in obj seems to be false when it's an array extracted
					// from customData
				if (iterator.call(context, obj[i], i, obj) === false) { return; }
			}
		} else {
			for (var key in obj) {
				if (hasOwnProperty.call(obj, key)) {
					if (iterator.call(context, obj[key], key, obj) === false) { return; }
				}
			}
		}
	}

	// =======================================================================
	function map(obj, iterator, context) {
		var	results	= [];
		if (obj	== null) { return results; }

		forEach(obj, function(value, index, list) {
			results[results.length] = iterator.call(context, value, index, list);
		});

		return results;
	}

	// =======================================================================
	function logWatched(
		inExpression,
		inFunctionName)
	{
		inFunctionName = inFunctionName.slice(0, -1);

		var test = inExpression,
			prefix = "     ";

		if (/[<>=]+/.test(test)) {
			test = '(' + test + ')';
			return '(' + test + ' ? log("' + inFunctionName + prefix + test +
				' :", ' + test + ') : "");';
		} else {
			return 'log("' + inFunctionName + prefix + test + ':", ' + test + ');';
		}
	}

	// =======================================================================
	function getScopeFacade(
		inCaller)
	{
		function Facade()
		{
			// this is an empty class that we use just to check whether a scope
			// we encounter is actually a Facade
		}

		function createGetter(
			inName,
			inScope)
		{
			return function()
			{
					// get the value from the scope that contains this variable
				return inScope[inName];
			}
		}

		function createSetter(
			inName,
			inScope)
		{
			return function(
				inValue)
			{
					// set the value on the scope that contains this variable
				inScope[inName] = inValue;
			}
		}

		function addScope(
			inScope,
			inFacade)
		{
				// add a getter and setter for every variable in this scope.
				// these functions will get/set the values from/in the scope
				// the var is originally from, rather than the inFacade object.
			for (var name in inScope) {
				inFacade.__defineGetter__(name, createGetter(name, inScope));
				inFacade.__defineSetter__(name, createSetter(name, inScope));
			}
		}

		function walkCallerChain(
			inCaller,
			inFacade)
		{
			var callerScope = inCaller.__parent__;

			if (callerScope instanceof Facade) {
					// we've hit a scope that was created by an earlier call to
					// trace().  if we tried to add that scope to our facade,
					// we'd get in an endless loop, so flee!
				return inFacade;
			} else if (inCaller.caller) {
					// add the variables from the caller's caller's scope first,
					// in case we shadow some vars that are also defined in the
					// parent scope
				inFacade = arguments.callee(inCaller.caller, inFacade);
			}

				// add the caller's scope to the facade
			addScope(callerScope, inFacade);

			return inFacade;
		}

			// we use an empty Facade object to store the scope values so that
			// we can tell we created it, using instanceof.  that way, if the
			// function we're tracing calls another function that is also
			// traced, we won't get into an infinite loop.
		var facade = new Facade();

			// first add all the parent scopes from our call chain
		walkCallerChain(inCaller, facade);

			// then add the local variables from our call, so that they can
			// shadow ones in the parent scope, if needed
		addScope(inCaller.__call__, facade);

		return facade;
	}

	// =======================================================================
	trace = function(
		inWatched,
		inFunctionName)
	{
		function logStatement(
			inWholeLine,
			inStatement)
		{
				// display the function name and statement in the console
			var logCall = 'log(' + (functionName + inStatement).quote() + ');\n' +
				watchedVars;

			if (/^(return|continue|break)[\s;]/.test(inStatement)) {
					// since putting a log call after return, continue or break
					// is pointless, put it before the statement
				return logCall + inWholeLine;
			} else {
					// put the log call after the statement, so that it won't
					// be logged if the statement throws an exception
				return inWholeLine + logCall;
			}
		}

			// adjust the optional parameters
		if (typeof inWatched == "string") {
			inFunctionName = inWatched;
			inWatched = [];
		}

				// we can't call this "caller", because that creates a property
				// called "caller" on our function object, which then overwrites
				// the arguments.callee.caller property.  ffs.
		var callerFunc = arguments.callee.caller,
			callerSource = arguments.callee.caller.toString(),
				// ignore the calling function's name if one was passed in
			functionName = inFunctionName || callerFunc.name,
				// pull out the body and params of the function
			codeMatch = callerSource.match(/function\s+([^(]+)?\(([^)]*)\)\s*\{([\s\S]*)\}/),
			params = codeMatch[2] ? codeMatch[2].split(/\s*,\s*/) : [],
			body = codeMatch[3],
			paramLog,
			watchedVars = "",
			traceMatch;

			// add a colon after the function name, if there is one
		functionName = functionName ? functionName + ": " : "";

		if (inWatched) {
			watchedVars = map(inWatched, function(watched) {
					// argh, there's some global native function called "watch"?
					// and we can't shadow it with a local var?  wtf?  ah, it's
					// actually an incredibly useful watch() function to get
					// callbacks when a property changes.  booyah.
				return logWatched(watched, functionName);
			});
			watchedVars = watchedVars.join("\n") + "\n";
		}

			// create a log statement to display the function's parameters.
			// include the function name as the first string in the log call.
		paramLog = [(functionName + "(").quote()].concat(map(params, function(param) {
			return [(param + ":").quote(), param];
		}));

			// add the log calls for the watched variables to the end of the
			// param log call, so that the current state of the watched vars is
			// shown as soon as the function is entered
		paramLog.push(")".quote());
		paramLog = 'log(' + paramLog.join(", ") + ');\n' + watchedVars;

		traceMatch = body.match(/return\s+trace\s*\([^)]*\)\s*;/);

		if (!traceMatch) {
				// the caller must have set a var to trace and then called us
				// through that var.  but we can't trace if we can't find the
				// trace call and strip it out.
			alert('A "return trace();" statement could not be found in the calling function. The trace function must be called directly, not through a reference.');
			return;
		}

			// start tracing from the statement after the trace() call, and
			// remove any other calls to trace that happen to be in the function.
			// also, the array returned by match() doesn't have a lastIndex
			// property on it.  ffs.
		body = body.slice(traceMatch.index + traceMatch[0].length);
		body = body.replace(/return\s+trace\s*\([^)]*\)\s*;/g, "");

			// add a log call after each ;\n to display the previous statement
		body = body.replace(/^\s*([^\n]+;)\s*\n/mg,
			logStatement);

			// add a log call after the opening brace of an if/for/while block.
			// but do so only if there's a space in front of the if, to avoid
			// sticking log calls in the middle of another log call, which can
			// happen with a nested function definition.  FW returns the body of
			// the nested function all on one line when doing toString, so the
			// replace call above will log the whole line.  but then this if
			// replace will see if statements inside the log string and replace
			// them, breaking the code.  requiring a space before the keyword
			// won't match in the nested function case, since FW removes all
			// the whitespace from the function body.
		body = body.replace(/\s((?:if|for|while)\s*\([^{]+\)\s*\{)/g,
			logStatement);

			// wrap the body in an anonymous function so our caller can execute
			// it in the caller's scope.  then capture that function's return
			// value, log it, and return it from another anonymous function.
		body = '(function(){ var returnValue = (function(){' +
			paramLog + body +
			'})(); log("' + functionName + 'return", returnValue); return returnValue; })();';

			// create a facade object that maps all of the identifiers in the
			// our caller's scope chain to the owning scope, and then eval the
			// caller's code within that fake scope.  this is where all the
			// magic happens.
		with (getScopeFacade(callerFunc)) {
			return eval(body);
		}
	}
})(); } catch (exception) {
	if (exception.lineNumber) {
		alert([exception, exception.lineNumber, exception.fileName].join("\n"));
	} else {
		throw exception;
	}
}
<|endoftext|>


<commit_before>;(function($, _, Modernizr) {

    'use strict';

    var w = window;
    var d = document;

    var transitionProperty = Modernizr.prefixed('transition');

    var transitionEndEvent = {
        WebkitTransition: 'webkitTransitionEnd',
        MozTransition: 'transitionend',
        OTransition: 'otransitionend',
        transition: 'transitionend'
    }[transitionProperty];

    var splitCommasOutside = function(str) {
        return str.split(/(?:,+\s)(?=(?:[^\(\)]|[\(\)|\(\)][^\(\)]*[\(|\)])*$)/g);
    };

    var addStyleTag = function(css) {
        var tag = doc.createElement('style');
        tag.setAttribute('type', 'text/css');
        doc.getElementsByTagName('head')[0].appendChild(tag);
        if (tag.styleSheet) {
            tag.styleSheet.cssText = css;
        } else {
            tag.appendChild(doc.createTextNode(css));
        }
    };

    function Trans($el, opts) {
        var ins = $el.data('trans');
        var _this = ins || this;
        var optsIsFn = $.isFunction(opts);

        _this.$el = $el;
        _this.el = $el[0];
        _this.opts = {};

        !optsIsFn && (_this.opts = opts || {});
        optsIsFn && (_this.opts.endAll = opts);

        if (!ins) {
            _this.$el.data('trans', _this.init());
        } else {
            return ins;
        }
    }

    Trans.css = '.js-notransition {' +
                '  -webkit-transition: none !important;' +
                '  -moz-transition: none !important;' +
                '  -o-transition: none !important;' +
                '  -ms-transition: none !important;' +
                '  transition: none !important;' +
                '}';

    Trans.autoProps = {
        'height': true,
        'width': true,
        'opacity': true,
    };

    Trans.maps = {
        'dimension': {
            'from': {
                '0px': '*',
                '*': '*'
            },
            'to': {
                '0px': '',
                '*': ''
            }
        },
        'display': {
            'opacity': {
                'from': {
                    '0': 'block',
                    '1': 'block'
                },
                'to': {
                    '0': 'none',
                    '1': 'block'
                }
            },
            'dimension': {
                'from': {
                    '0px': 'block',
                    '*': 'block'
                },
                'to': {
                    '0px': '',
                    '*': 'block'
                }
            }
        }
    };

    Trans.methods = {
        'add': $.fn.addClass,
        'remove': $.fn.removeClass
    };

    _.extend(Trans.prototype, {
        init: function() {
            this.transClass = '';
            this.transProps = {};
            this.transPrefix = _.filter(Modernizr._cssomPrefixes, function(prfx) {
                return Modernizr.prefixed(prfx + 'Transition');
            })[0];
            return this;
        },

        repaint: function() {
            this.$el.width();
        },

        manageAutoProps: function(point, props) {
            props || (props = this.transProps);
            var i, css = {};

            if (!_.intersection(_.keys(Trans.autoProps), _.keys(props)).length) {
                return;
            }

            var _display = function(prop) {
                var i = props[prop][point];
                i === '0px' || (i = '*');
                var val = Trans.maps.display.dimension[point][i];
                css['display'] = val;
            };

            var _dimension = function(prop) {
                var fromVal, toVal, i, val, size, z;
                fromVal = props[prop]['from'];
                toVal = props[prop]['to'];

                if ((fromVal == 'auto' || toVal == 'auto') ||
                    (fromVal == '0px' || toVal == '0px')) {
                    i = props[prop][point];
                    size = i !== '0px' ? fromVal : toVal;
                    z = i === '0px' ? '0px' : '*';
                    val = Trans.maps.dimension[point][z];
                    if (val === '*') { val = size; }
                    css[prop] = val;
                }
            };

            if (props['opacity']) {
                i = props['opacity'][point];
                css['display'] = Trans.maps.display.opacity[point][i];
            }

            _.each(['width', 'height'], function(prop) {
                if (props[prop]) {
                    _display(prop);
                    _dimension(prop);
                }
            });

            if (_.size(css)) {
                this.$el.css(css);
                this.repaint();
            }
        },

        getTransitionValue: function() {
            var style = w.getComputedStyle(this.el, null);
            this.transitionValue = style.getPropertyValue(transitionProperty);

            // firefox doesn't return data in shorthand CSS props
            if (!this.transitionValue || !this.transitionValue.length) {
                // TODO: move this to a test method fired after init
                var prefix = this.transPrefix;
                var properties = this.$el.css(prefix + 'TransitionProperty').split(', ');
                var durations = this.$el.css(prefix + 'TransitionDuration').split(', ');
                var delays = this.$el.css(prefix + 'TransitionDelay').split(', ');
                var timings = splitCommasOutside(this.$el.css(prefix + 'TransitionTimingFunction'));

                var transitions = [];
                for (var i = properties.length - 1; i >= 0; i--) {
                    transitions.push(properties[i] + ' ' + durations[i] + ' ' + timings[i] + ' ' + (delays[i] || '0s'));
                }
                this.transitionValue = transitions.join(', ');
            }

            this.transitionValue = splitCommasOutside(this.transitionValue);
        },

        getTransProps: function(method) {
            var fProp, tProp;
            var res = {};

            this.getTransitionValue();

            this.$el.addClass('js-notransition');
            var fromProps = this.getFromProps(method);
            var toProps = this.getToProps(method === 'add' ? 'remove' : 'add');
            this.$el.removeClass('js-notransition');

            for (var propKey in fromProps) {
                fProp = fromProps[propKey];
                tProp = toProps[propKey];

                if (fProp.from !== tProp.to) {
                    fProp.to = tProp.to;
                    res[propKey] = fProp;
                }
            }
            return res;
        },

        getFromProps: function(method) {
            var props = this.getCurrentProps('from');
            Trans.methods[method].call(this.$el, this.transClass);
            this.repaint();
            return props;
        },

        getToProps: function(method) {
            var props = this.getCurrentProps('to');
            Trans.methods[method].call(this.$el, this.transClass);
            this.repaint();
            return props;
        },

        getCurrentProps: function(point) {
            var prop, propKey, transProps, resProp;
            var res = {};
            var style = w.getComputedStyle(this.el, null);
            var propKeys = 'property duration timing-function delay'.split(' ');
            var props = this.transitionValue;

            if (!props.length) { return false; }

            for (var i = props.length - 1; i >= 0; i--) {
                transProps = props[i].split(' ');
                propKey = transProps[0];
                resProp = {};
                resProp[point] = style.getPropertyValue(propKey);
                for (var j = propKeys.length - 1; j >= 0; j--) {
                    resProp[propKeys[j]] = transProps[j];
                }
                res[propKey] = resProp;
            }

            return res;
        },

        addTransClass: function(transClass) {
            this.transClass = transClass;
            this.transition('add');
        },

        removeTransClass: function(transClass) {
            this.transClass = transClass;
            this.transition('remove');
        },

        transition: function(method) {
            this.stop();

            this.transProps = this.getTransProps(method);

            this.$el.on(transitionEndEvent + '.trans', {
                endAll: _.after(_.size(this.transProps), _.bind(this.endAll, this))
            }, _.bind(this.end, this));

            // transition start
            this.transitionActive = true;
            this.manageAutoProps('from');
            Trans.methods[method].call(this.$el, this.transClass);
        },

        stop: function() {
            if (!this.transitionActive) { return; }

            this.$el.addClass('js-notransition');
            this.repaint();
            this.$el.removeClass('js-notransition');
            this.endAll();
        },

        // e.originalEvent[type || propertyName || elapsedTime || eventPhase]
        end: function(e) {
            var propKey = e.originalEvent.propertyName;

            // ignore other transitionEnd events bubbling up
            if (e.handleObj.namespace !== 'trans' ||
                !this.transProps[propKey] ||
                e.target !== this.el
            ) {
                return;
            }

            var args = [propKey, this];
            this.$el.trigger('trans:end', args);
            this.$el.trigger('trans:end:' + propKey, args);
            this.opts.end && this.opts.end.apply(this.$el, args);
            this.transitionActive && e.data.endAll.call(this, e);
        },

        endAll: function(e) {
            var propKey = e && e.originalEvent.propertyName;
            this.transitionActive = false;

            /* Not called in end method because Firefox stops transition if
             * display property is changed during animation */
            this.manageAutoProps('to');

            this.$el.trigger('trans:endAll', [this]);
            this.opts.endAll && this.opts.endAll.call(this.$el, this);

            this.$el.off('.trans');
            delete this.transProps;
            delete this.completedTransitions;
        },

        destroy: function() {
            this.stop();
            this.$el.removeData('trans');
        }
    });

    addStyleTag(Trans.css);

    // jquerify
    $.fn.addTransClass = function(transClass, opts) {
        var t = new Trans(this.eq(0), opts);
        t.addTransClass(transClass);
        return t.$el;
    };

    $.fn.removeTransClass = function(transClass, opts) {
        var t = new Trans(this.eq(0), opts);
        t.removeTransClass(transClass);
        return t.$el;
    };

    return Trans;

})(this, jQuery, _, Modernizr);<commit_msg>feat(ie-support): support for browsers without csstransitions<commit_after>;(function($, _, Modernizr) {

    'use strict';

    var w = window;
    var doc = document;

    var hasCSSTransitions = Modernizr.csstransitions;

    var transitionProperty = Modernizr.prefixed('transition');

    var transitionEndEvent = {
        WebkitTransition: 'webkitTransitionEnd',
        MozTransition: 'transitionend',
        OTransition: 'otransitionend',
        transition: 'transitionend'
    }[transitionProperty];

    var splitCommasOutside = function(str) {
        return str.split(/(?:,+\s)(?=(?:[^\(\)]|[\(\)|\(\)][^\(\)]*[\(|\)])*$)/g);
    };

    var addStyleTag = function(css) {
        var tag = doc.createElement('style');
        tag.setAttribute('type', 'text/css');
        doc.getElementsByTagName('head')[0].appendChild(tag);
        if (tag.styleSheet) {
            tag.styleSheet.cssText = css;
        } else {
            tag.appendChild(doc.createTextNode(css));
        }
    };

    function Trans($el, opts) {
        var ins = $el.data('trans');
        var _this = ins || this;
        var optsIsFn = $.isFunction(opts);

        _this.$el = $el;
        _this.el = $el[0];
        _this.opts = {};

        !optsIsFn && (_this.opts = opts || {});
        optsIsFn && (_this.opts.endAll = opts);

        if (!ins) {
            _this.$el.data('trans', _this.init());
        } else {
            return ins;
        }
    }

    Trans.css = '.js-notransition {' +
                '  -webkit-transition: none !important;' +
                '  -moz-transition: none !important;' +
                '  -o-transition: none !important;' +
                '  -ms-transition: none !important;' +
                '  transition: none !important;' +
                '}';

    Trans.autoProps = {
        'height': true,
        'width': true,
        'opacity': true,
    };

    Trans.maps = {
        'dimension': {
            'from': {
                '0px': '*',
                '*': '*'
            },
            'to': {
                '0px': '',
                '*': ''
            }
        },
        'display': {
            'opacity': {
                'from': {
                    '0': 'block',
                    '1': 'block'
                },
                'to': {
                    '0': 'none',
                    '1': 'block'
                }
            },
            'dimension': {
                'from': {
                    '0px': 'block',
                    '*': 'block'
                },
                'to': {
                    '0px': '',
                    '*': 'block'
                }
            }
        }
    };

    Trans.methods = {
        'add': $.fn.addClass,
        'remove': $.fn.removeClass
    };

    _.extend(Trans.prototype, {
        init: function() {
            this.transClass = '';
            this.transProps = {};
            this.transPrefix = _.filter(Modernizr._cssomPrefixes, function(prfx) {
                return Modernizr.prefixed(prfx + 'Transition');
            })[0];
            return this;
        },

        repaint: function() {
            this.$el.width();
        },

        manageAutoProps: function(point, props) {
            props || (props = this.transProps);
            var i, css = {};

            if (!_.intersection(_.keys(Trans.autoProps), _.keys(props)).length) {
                return;
            }

            var _display = function(prop) {
                var i = props[prop][point];
                i === '0px' || (i = '*');
                var val = Trans.maps.display.dimension[point][i];
                css['display'] = val;
            };

            var _dimension = function(prop) {
                var fromVal, toVal, i, val, size, z;
                fromVal = props[prop]['from'];
                toVal = props[prop]['to'];

                if ((fromVal == 'auto' || toVal == 'auto') ||
                    (fromVal == '0px' || toVal == '0px')) {
                    i = props[prop][point];
                    size = i !== '0px' ? fromVal : toVal;
                    z = i === '0px' ? '0px' : '*';
                    val = Trans.maps.dimension[point][z];
                    if (val === '*') { val = size; }
                    css[prop] = val;
                }
            };

            if (props['opacity']) {
                i = props['opacity'][point];
                css['display'] = Trans.maps.display.opacity[point][i];
            }

            _.each(['width', 'height'], function(prop) {
                if (props[prop]) {
                    _display(prop);
                    _dimension(prop);
                }
            });

            if (_.size(css)) {
                this.$el.css(css);
                this.repaint();
            }
        },

        getTransitionValue: function() {
            var style = w.getComputedStyle(this.el, null);
            this.transitionValue = style.getPropertyValue(transitionProperty);

            if (!hasCSSTransitions) {
                this.transitionValue = splitCommasOutside(this.$el.css('transition'));
                return;
            }

            // firefox doesn't return data in shorthand CSS props
            if (!this.transitionValue || !this.transitionValue.length) {
                // TODO: move this to a test method fired after init
                var prefix = this.transPrefix;
                var properties = this.$el.css(prefix + 'TransitionProperty').split(', ');

                var transitions = [];
                for (var i = properties.length - 1; i >= 0; i--) {
                    transitions.push(properties[i]);
                }
                // whitespace after comma is required
                this.transitionValue = transitions.join(', ');
            }

            this.transitionValue = splitCommasOutside(this.transitionValue);
        },

        getTransProps: function(method) {
            var fProp, tProp;
            var res = {};

            this.getTransitionValue();

            this.$el.addClass('js-notransition');
            var fromProps = this.getFromProps(method);
            var toProps = this.getToProps(method === 'add' ? 'remove' : 'add');
            this.$el.removeClass('js-notransition');

            for (var propKey in fromProps) {
                fProp = fromProps[propKey];
                tProp = toProps[propKey];

                if (fProp.from !== tProp.to) {
                    fProp.to = tProp.to;
                    res[propKey] = fProp;
                }
            }
            return res;
        },

        getFromProps: function(method) {
            var props = this.getCurrentProps('from');
            Trans.methods[method].call(this.$el, this.transClass);
            this.repaint();
            return props;
        },

        getToProps: function(method) {
            var props = this.getCurrentProps('to');
            Trans.methods[method].call(this.$el, this.transClass);
            this.repaint();
            return props;
        },

        getCurrentProps: function(point) {
            var prop, propKey, transProps, resProp;
            var res = {};
            var style = w.getComputedStyle(this.el, null);
            var propKeys = 'property duration timing-function delay'.split(' ');
            var props = this.transitionValue;

            if (!props.length) { return false; }

            for (var i = props.length - 1; i >= 0; i--) {
                transProps = props[i].split(' ');
                propKey = transProps[0];
                resProp = {};
                resProp[point] = style.getPropertyValue(propKey);
                for (var j = propKeys.length - 1; j >= 0; j--) {
                    resProp[propKeys[j]] = transProps[j];
                }
                res[propKey] = resProp;
            }

            return res;
        },

        addTransClass: function(transClass) {
            this.transClass = transClass;
            this.transition('add');
        },

        removeTransClass: function(transClass) {
            this.transClass = transClass;
            this.transition('remove');
        },

        _transitionFallback: function() {
            $.each(this.transProps, function(propKey, val) {
                this._end(propKey);
            }.bind(this));

            this.endAll();
        },

        transition: function(method) {
            this.stop();

            this.transProps = this.getTransProps(method);

            if (hasCSSTransitions) {
                this.$el.on(transitionEndEvent + '.trans', {
                    endAll: _.after(_.size(this.transProps), _.bind(this.endAll, this))
                }, _.bind(this.end, this));

                this.manageAutoProps('from');
            }

            // transition start
            this.transitionActive = true;
            Trans.methods[method].call(this.$el, this.transClass);
            // fire end events when no csstransitions support
            !hasCSSTransitions && this._transitionFallback();
        },

        stop: function() {
            if (!this.transitionActive) { return; }

            this.$el.addClass('js-notransition');
            this.repaint();
            this.$el.removeClass('js-notransition');
            this.endAll();
        },

        _end: function(propKey) {
            var args = [propKey, this];
            this.$el.trigger('trans:end', args);
            this.$el.trigger('trans:end:' + propKey, args);
            this.opts.end && this.opts.end.apply(this.$el, args);
        },

        // e.originalEvent[type || propertyName || elapsedTime || eventPhase]
        end: function(e) {
            var propKey = e.originalEvent.propertyName;

            // ignore other transitionEnd events bubbling up
            if (e.handleObj.namespace !== 'trans' ||
                !this.transProps[propKey] ||
                e.target !== this.el
            ) {
                return;
            }

            this._end(propKey);
            this.transitionActive && e.data.endAll.call(this, e);
        },

        endAll: function(e) {
            var propKey = e && e.originalEvent.propertyName;
            this.transitionActive = false;

            /* Not called in end method because Firefox stops transition if
             * display property is changed during animation */
            hasCSSTransitions && this.manageAutoProps('to');

            this.$el.trigger('trans:endAll', [this]);
            this.opts.endAll && this.opts.endAll.call(this.$el, this);

            this.$el.off('.trans');
            delete this.transProps;
        },

        destroy: function() {
            this.stop();
            this.$el.removeData('trans');
        }
    });

    addStyleTag(Trans.css);

    // jquerify
    $.fn.addTransClass = function(transClass, opts) {
        var t = new Trans(this.eq(0), opts);
        t.addTransClass(transClass);
        return t.$el;
    };

    $.fn.removeTransClass = function(transClass, opts) {
        var t = new Trans(this.eq(0), opts);
        t.removeTransClass(transClass);
        return t.$el;
    };

    return Trans;

})(jQuery, _, Modernizr);<|endoftext|>


<commit_before>'use strict'

const fs = require('fs-extra')

exports._log_ = (log, name) => {
  let d = new Date()
  if (!name) {
    name = d.getMonth() + 1
    if (name < 10) name = `0${name}`
  }

  fs.appendFile(`./logs/${d.getFullYear()}_${name}`, `${d}: ${log}\n`, (err) => {
    if (err) throw err
  })
}
<commit_msg>Add logging to cron.log<commit_after>'use strict'

const fs = require('fs-extra')

exports._log_ = (log, name) => {
  let d = new Date()
  if (!name) {
    name = d.getMonth() + 1
    if (name < 10) name = `0${name}`
  }

  fs.appendFile(`./logs/${d.getFullYear()}_${name}`, `${d}: ${log}\n`, (err) => {
    if (err) throw err
  })

  console.log(log)
}
<|endoftext|>


<commit_before>var NanoEvents = require('nanoevents')

/**
 * Stores actions with time marks. Log is main idea in Logux.
 * In most end-user tools you will work with log and should know log API.
 *
 * @param {object} opts Options.
 * @param {Store} opts.store Store for log.
 * @param {string|number} opts.nodeId Unique current machine name.
 *
 * @example
 * import Log from 'logux-core/log'
 * const log = new Log({
 *   store: new MemoryStore(),
 *   nodeId: 'client:134'
 * })
 *
 * log.on('add', beeper)
 * log.add({ type: 'beep' })
 *
 * @class
 */
function Log (opts) {
  if (!opts) opts = { }

  if (typeof opts.nodeId === 'undefined') {
    throw new Error('Expected node ID')
  }
  if (typeof opts.store !== 'object') {
    throw new Error('Expected store')
  }
  if (opts.nodeId.indexOf(' ') !== -1) {
    throw new Error('Space is prohibited in node ID')
  }

  /**
   * Unique node ID. It is used in action IDs.
   * @type {string|number}
   */
  this.nodeId = opts.nodeId

  this.lastTime = 0
  this.sequence = 0

  this.store = opts.store

  this.emitter = new NanoEvents()
}

Log.prototype = {

  /**
   * Subscribe for log events. It implements nanoevents API. Supported events:
   *
   * * `preadd`: when somebody try to add action to log.
   *   It fires before ID check. The best place to add reason.
   * * `add`: when new action was added to log.
   * * `clean`: when action was cleaned from store.
   *
   * @param {"preadd"|"add"|"clean"} event The event name.
   * @param {listener} listener The listener function.
   *
   * @return {function} Unbind listener from event.
   *
   * @example
   * const unbind = log.on('add', (action, meta) => {
   *   if (action.type === 'beep') beep()
   * })
   * function disableBeeps () {
   *   unbind()
   * }
   */
  on: function (event, listener) {
    return this.emitter.on(event, listener)
  },

  /**
   * Add action to log.
   *
   * It will set `id`, `time` (if they was missed) and `added` property
   * to `meta` and call all listeners.
   *
   * @param {Action} action The new action.
   * @param {Meta} [meta] Open structure for action metadata.
   * @param {string} [meta.id] Unique action ID.
   * @param {number} [meta.time] Action created time.
   *                             Milliseconds since UNIX epoch.
   * @param {string[]} [meta.reasons] Why action should be kept in log.
   *                                  Action without reasons will be removed.
   * @param {string} [meta.keepLast] Set code as reason and remove this reasons
   *                                 from previous actions.
   * @return {Promise<Meta|fale>} Promise with `meta` if action was added
   *                              to log or `false` if action was already in log
   *
   * @example
   * removeButton.addEventListener('click', () => {
   *   log.add({ type: 'users:remove', user: id })
   * })
   */
  add: function add (action, meta) {
    if (typeof action.type === 'undefined') {
      throw new Error('Expected "type" in action')
    }

    if (!meta) meta = { }

    var newId = false
    if (typeof meta.id === 'undefined') {
      newId = true
      meta.id = this.generateId()
    }

    if (typeof meta.time === 'undefined') {
      meta.time = parseInt(meta.id)
    }

    if (typeof meta.reasons === 'undefined') {
      meta.reasons = []
    } else if (!Array.isArray(meta.reasons)) {
      meta.reasons = [meta.reasons]
    }

    meta.reasons.forEach(function (reason) {
      if (typeof reason !== 'string') {
        throw new Error('Expected "reasons" to be strings')
      }
    })

    var log = this
    this.emitter.emit('preadd', action, meta)

    if (meta.keepLast) {
      this.removeReason(meta.keepLast, { olderThan: meta })
      meta.reasons.push(meta.keepLast)
    }

    if (meta.reasons.length === 0 && newId) {
      this.emitter.emit('add', action, meta)
      this.emitter.emit('clean', action, meta)
      return Promise.resolve(meta)
    } else if (meta.reasons.length === 0) {
      return this.store.byId(meta.id).then(function (result) {
        if (result[0]) {
          return false
        } else {
          log.emitter.emit('add', action, meta)
          log.emitter.emit('clean', action, meta)
          return meta
        }
      })
    } else {
      return this.store.add(action, meta).then(function (addedMeta) {
        if (addedMeta === false) {
          return false
        } else {
          log.emitter.emit('add', action, addedMeta)
          return addedMeta
        }
      })
    }
  },

  /**
   * Generate next unique action ID.
   *
   * @return {string} Unique action ID.
   *
   * @example
   * const id = log.generateId()
   */
  generateId: function generateId () {
    var now = Date.now()
    if (now <= this.lastTime) {
      now = this.lastTime
      this.sequence += 1
    } else {
      this.lastTime = now
      this.sequence = 0
    }
    return now + ' ' + this.nodeId + ' ' + this.sequence
  },

  /**
   * Iterates through all actions, from last to first.
   *
   * Return false from callback if you want to stop iteration.
   *
   * @param {object} [opts] Iterator options.
   * @param {'added'|'created'} [opts.order='created'] Sort entries by created
   *                                                   time or when they was
   *                                                   added to this log.
   * @param {iterator} callback Function will be executed on every action.
   *
   * @return {Promise} When iteration will be finished
   *                   by iterator or end of actions.
   *
   * @example
   * log.each((action, meta) => {
   *   if (compareTime(meta.id, lastBeep) <= 0) {
   *     return false;
   *   } else if (action.type === 'beep') {
   *     beep()
   *     lastBeep = meta.id
   *     return false;
   *   }
   * })
   */
  each: function each (opts, callback) {
    if (!callback) {
      callback = opts
      opts = { order: 'created' }
    }

    var store = this.store
    return new Promise(function (resolve) {
      function nextPage (get) {
        get().then(function (page) {
          var result
          for (var i = page.entries.length - 1; i >= 0; i--) {
            var entry = page.entries[i]
            result = callback(entry[0], entry[1])
            if (result === false) break
          }

          if (result === false || !page.next) {
            resolve()
          } else {
            nextPage(page.next)
          }
        })
      }

      nextPage(store.get.bind(store, opts))
    })
  },

  /**
   * Change action metadata. You will remove action by setting `reasons: []`.
   *
   * @param {string} id Action ID.
   * @param {object} diff Object with values to change in action metadata.
   *
   * @return {Promise<boolean>} Promise with `true` if metadata was changed
   *                            or `false` on unknown ID.
   *
   * @example
   * await process(action)
   * log.changeMeta(action, { status: 'processed' })
   */
  changeMeta: function changeMeta (id, diff) {
    var k
    for (k in diff) {
      if (k === 'id' || k === 'added' || k === 'time' || k === 'subprotocol') {
        throw new Error('Meta "' + k + '" is read-only')
      }
    }

    var emitter = this.emitter
    if (diff.reasons && diff.reasons.length === 0) {
      return this.store.remove(id).then(function (entry) {
        if (entry) {
          for (k in diff) entry[1][k] = diff[k]
          emitter.emit('clean', entry[0], entry[1])
        }
        return !!entry
      })
    } else {
      return this.store.changeMeta(id, diff)
    }
  },

  /**
   * Remove reason tag from action’s metadata and remove actions without reason
   * from log.
   *
   * @param {string} reason Reason’s name.
   * @param {object} [criteria] Actions criteria.
   * @param {number} [criteria.minAdded] Remove reason only for actions
   *                                     with bigger `added`.
   * @param {number} [criteria.maxAdded] Remove reason only for actions
   *                                     with lower `added`.
   * @param {string} [criteria.olderThan] Remove reasons only for actions
   *                                     with bigger `id`.
   * @param {string} [criteria.youngerThan] Remove reason only for actions
   *                                       with lower `id`.
   * @param {string} [criteria.id] Remove reason only for action with `id`.
   *
   * @return {Promise} Promise when cleaning will be finished.
   *
   * @example
   * onSync(lastSent) {
   *   log.removeReason('unsynchronized', { maxAdded: lastSent })
   * }
   */
  removeReason: function removeReason (reason, criteria) {
    if (!criteria) criteria = { }
    var log = this
    return this.store.removeReason(reason, criteria, function (action, meta) {
      log.emitter.emit('clean', action, meta)
    })
  },

  /**
   * Does log already has action with this ID.
   *
   * @param {string} id Action ID.
   *
   * @return {Promise<Entry|Nope>} Promise with entry.
   *
   * @example
   * if (action.type === 'logux/undo') {
   *   const [undidAction, undidMeta] = await log.byId(action.id)
   *   log.changeMeta(meta.id, { reasons: undidMeta.reasons })
   * }
   */
  byId: function byId (id) {
    return this.store.byId(id)
  }
}

module.exports = Log

/**
 * @callback iterator
 * @param {Action} action Next action.
 * @param {Meta} meta Next action’s metadata.
 * @return {boolean} returning `false` will stop iteration.
 */
<commit_msg>Fix indent<commit_after>var NanoEvents = require('nanoevents')

/**
 * Stores actions with time marks. Log is main idea in Logux.
 * In most end-user tools you will work with log and should know log API.
 *
 * @param {object} opts Options.
 * @param {Store} opts.store Store for log.
 * @param {string|number} opts.nodeId Unique current machine name.
 *
 * @example
 * import Log from 'logux-core/log'
 * const log = new Log({
 *   store: new MemoryStore(),
 *   nodeId: 'client:134'
 * })
 *
 * log.on('add', beeper)
 * log.add({ type: 'beep' })
 *
 * @class
 */
function Log (opts) {
  if (!opts) opts = { }

  if (typeof opts.nodeId === 'undefined') {
    throw new Error('Expected node ID')
  }
  if (typeof opts.store !== 'object') {
    throw new Error('Expected store')
  }
  if (opts.nodeId.indexOf(' ') !== -1) {
    throw new Error('Space is prohibited in node ID')
  }

  /**
   * Unique node ID. It is used in action IDs.
   * @type {string|number}
   */
  this.nodeId = opts.nodeId

  this.lastTime = 0
  this.sequence = 0

  this.store = opts.store

  this.emitter = new NanoEvents()
}

Log.prototype = {

  /**
   * Subscribe for log events. It implements nanoevents API. Supported events:
   *
   * * `preadd`: when somebody try to add action to log.
   *   It fires before ID check. The best place to add reason.
   * * `add`: when new action was added to log.
   * * `clean`: when action was cleaned from store.
   *
   * @param {"preadd"|"add"|"clean"} event The event name.
   * @param {listener} listener The listener function.
   *
   * @return {function} Unbind listener from event.
   *
   * @example
   * const unbind = log.on('add', (action, meta) => {
   *   if (action.type === 'beep') beep()
   * })
   * function disableBeeps () {
   *   unbind()
   * }
   */
  on: function (event, listener) {
    return this.emitter.on(event, listener)
  },

  /**
   * Add action to log.
   *
   * It will set `id`, `time` (if they was missed) and `added` property
   * to `meta` and call all listeners.
   *
   * @param {Action} action The new action.
   * @param {Meta} [meta] Open structure for action metadata.
   * @param {string} [meta.id] Unique action ID.
   * @param {number} [meta.time] Action created time.
   *                             Milliseconds since UNIX epoch.
   * @param {string[]} [meta.reasons] Why action should be kept in log.
   *                                  Action without reasons will be removed.
   * @param {string} [meta.keepLast] Set code as reason and remove this reasons
   *                                 from previous actions.
   * @return {Promise<Meta|fale>} Promise with `meta` if action was added
   *                              to log or `false` if action was already in log
   *
   * @example
   * removeButton.addEventListener('click', () => {
   *   log.add({ type: 'users:remove', user: id })
   * })
   */
  add: function add (action, meta) {
    if (typeof action.type === 'undefined') {
      throw new Error('Expected "type" in action')
    }

    if (!meta) meta = { }

    var newId = false
    if (typeof meta.id === 'undefined') {
      newId = true
      meta.id = this.generateId()
    }

    if (typeof meta.time === 'undefined') {
      meta.time = parseInt(meta.id)
    }

    if (typeof meta.reasons === 'undefined') {
      meta.reasons = []
    } else if (!Array.isArray(meta.reasons)) {
      meta.reasons = [meta.reasons]
    }

    meta.reasons.forEach(function (reason) {
      if (typeof reason !== 'string') {
        throw new Error('Expected "reasons" to be strings')
      }
    })

    var log = this
    this.emitter.emit('preadd', action, meta)

    if (meta.keepLast) {
      this.removeReason(meta.keepLast, { olderThan: meta })
      meta.reasons.push(meta.keepLast)
    }

    if (meta.reasons.length === 0 && newId) {
      this.emitter.emit('add', action, meta)
      this.emitter.emit('clean', action, meta)
      return Promise.resolve(meta)
    } else if (meta.reasons.length === 0) {
      return this.store.byId(meta.id).then(function (result) {
        if (result[0]) {
          return false
        } else {
          log.emitter.emit('add', action, meta)
          log.emitter.emit('clean', action, meta)
          return meta
        }
      })
    } else {
      return this.store.add(action, meta).then(function (addedMeta) {
        if (addedMeta === false) {
          return false
        } else {
          log.emitter.emit('add', action, addedMeta)
          return addedMeta
        }
      })
    }
  },

  /**
   * Generate next unique action ID.
   *
   * @return {string} Unique action ID.
   *
   * @example
   * const id = log.generateId()
   */
  generateId: function generateId () {
    var now = Date.now()
    if (now <= this.lastTime) {
      now = this.lastTime
      this.sequence += 1
    } else {
      this.lastTime = now
      this.sequence = 0
    }
    return now + ' ' + this.nodeId + ' ' + this.sequence
  },

  /**
   * Iterates through all actions, from last to first.
   *
   * Return false from callback if you want to stop iteration.
   *
   * @param {object} [opts] Iterator options.
   * @param {'added'|'created'} [opts.order='created'] Sort entries by created
   *                                                   time or when they was
   *                                                   added to this log.
   * @param {iterator} callback Function will be executed on every action.
   *
   * @return {Promise} When iteration will be finished
   *                   by iterator or end of actions.
   *
   * @example
   * log.each((action, meta) => {
   *   if (compareTime(meta.id, lastBeep) <= 0) {
   *     return false;
   *   } else if (action.type === 'beep') {
   *     beep()
   *     lastBeep = meta.id
   *     return false;
   *   }
   * })
   */
  each: function each (opts, callback) {
    if (!callback) {
      callback = opts
      opts = { order: 'created' }
    }

    var store = this.store
    return new Promise(function (resolve) {
      function nextPage (get) {
        get().then(function (page) {
          var result
          for (var i = page.entries.length - 1; i >= 0; i--) {
            var entry = page.entries[i]
            result = callback(entry[0], entry[1])
            if (result === false) break
          }

          if (result === false || !page.next) {
            resolve()
          } else {
            nextPage(page.next)
          }
        })
      }

      nextPage(store.get.bind(store, opts))
    })
  },

  /**
   * Change action metadata. You will remove action by setting `reasons: []`.
   *
   * @param {string} id Action ID.
   * @param {object} diff Object with values to change in action metadata.
   *
   * @return {Promise<boolean>} Promise with `true` if metadata was changed
   *                            or `false` on unknown ID.
   *
   * @example
   * await process(action)
   * log.changeMeta(action, { status: 'processed' })
   */
  changeMeta: function changeMeta (id, diff) {
    var k
    for (k in diff) {
      if (k === 'id' || k === 'added' || k === 'time' || k === 'subprotocol') {
        throw new Error('Meta "' + k + '" is read-only')
      }
    }

    var emitter = this.emitter
    if (diff.reasons && diff.reasons.length === 0) {
      return this.store.remove(id).then(function (entry) {
        if (entry) {
          for (k in diff) entry[1][k] = diff[k]
          emitter.emit('clean', entry[0], entry[1])
        }
        return !!entry
      })
    } else {
      return this.store.changeMeta(id, diff)
    }
  },

  /**
   * Remove reason tag from action’s metadata and remove actions without reason
   * from log.
   *
   * @param {string} reason Reason’s name.
   * @param {object} [criteria] Actions criteria.
   * @param {number} [criteria.minAdded] Remove reason only for actions
   *                                     with bigger `added`.
   * @param {number} [criteria.maxAdded] Remove reason only for actions
   *                                     with lower `added`.
   * @param {string} [criteria.olderThan] Remove reasons only for actions
   *                                      with bigger `id`.
   * @param {string} [criteria.youngerThan] Remove reason only for actions
   *                                        with lower `id`.
   * @param {string} [criteria.id] Remove reason only for action with `id`.
   *
   * @return {Promise} Promise when cleaning will be finished.
   *
   * @example
   * onSync(lastSent) {
   *   log.removeReason('unsynchronized', { maxAdded: lastSent })
   * }
   */
  removeReason: function removeReason (reason, criteria) {
    if (!criteria) criteria = { }
    var log = this
    return this.store.removeReason(reason, criteria, function (action, meta) {
      log.emitter.emit('clean', action, meta)
    })
  },

  /**
   * Does log already has action with this ID.
   *
   * @param {string} id Action ID.
   *
   * @return {Promise<Entry|Nope>} Promise with entry.
   *
   * @example
   * if (action.type === 'logux/undo') {
   *   const [undidAction, undidMeta] = await log.byId(action.id)
   *   log.changeMeta(meta.id, { reasons: undidMeta.reasons })
   * }
   */
  byId: function byId (id) {
    return this.store.byId(id)
  }
}

module.exports = Log

/**
 * @callback iterator
 * @param {Action} action Next action.
 * @param {Meta} meta Next action’s metadata.
 * @return {boolean} returning `false` will stop iteration.
 */
<|endoftext|>


<commit_before>'use strict';
var exec = require('child_process').exec;
var extend = require('node.extend');

var parseArgs = function(required, takes, config){
	var all = Object.keys(config);
	// console.log(all)
	for(var i=required.length; i--;){
		if(all.indexOf(required[i]) !== -1){
			required.splice(i, 1);
		}
	}

	if(required.length !== 0) return false;

	var out = '';
	for(var i=0; i< takes.length; i++){
		if(all.indexOf(takes[i]) !== -1){
			out += '--'+takes[i]+' '+config[takes[i]]+' ';
		}
	}

	return out;
};

function sysExec(command, callback){
	command = 'unset XDG_SESSION_ID XDG_RUNTIME_DIR; cgm movepid all virt $$; ' + command;

	return exec(command, (function(callback){
		return function(err,data,stderr){
			if(callback){
				return callback(data, err, stderr);
			}
		}
	})(callback));
};

var Container = function(config){
	this.name = config.name;
	this.state = config.state || 'STOPPED';
	this.ip = config.ip || (config.ipv4 || '').replace('-', '') || null ;
	this.overlayfs = null
}

Container.prototype.clone = function(callback){
	var overlayfs = this.overlayfs ? ' -B overlayfs -s ' : '';

	return sysExec('lxc-clone -o '+this.orig+ ' -n '+this.name + overlayfs, callback);
};

Container.prototype.start = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name'],
		defaults: extend({}, this)

	});

	return sysExec('lxc-start --daemon '+args, callback);
};

Container.prototype.startEphemeral = function(callback){
	args = parseArgs({
		required: ['orig'],
		takes: ['orig', 'name', 'key', 'union-type', 'keep-data'],
		defaults: extend({}, this)

	});

	var command = 'lxc-start-ephemeral --daemon '+args;
	return sysExec(command, function(data){
		console.log('startEphemeral', arguments);
		if(data.match("doesn't exist.")){
			return callback({status: 500, error: "doesn't exist."});
		}
		if(data.match('already exists.')){
			return callback({status: 500, error: 'already exists'});
		}
		if(data.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)){
			return callback({status: 200, state:'RUNNING', ip: data.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)[0]});
		}

		callback({'?': '?', data: data, name: name, base_name: base_name});
	});
};

Container.prototype.destroy = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name', 'force'],
		defaults: extend({}, this)
	});

	return sysExec('lxc-destroy '+ args, function(data){
		var info = data.match(/Destroyed container/);
		console.log('destroy info:', info);
		var args = [true].concat(Array.prototype.slice.call(arguments, 1));
		return callback.apply(this, args);
	});
},

Container.prototype.stop = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name', 'reboot', 'nowait', 'timeout', 'kill'],
		defaults: extend({}, this)

	});
	return sysExec('lxc-stop '+args, callback);
};

Container.prototype.freeze = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name', 'force'],
		defaults: extend({}, this)
	});
	return sysExec('lxc-freeze -n '+name, callback);
};

Container.prototype.unfreeze = function(callback){

	return sysExec('lxc-unfreeze --name '+this.name, callback);
};

Container.prototype.info = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name', 'reboot', 'nowait', 'timeout', 'kill'],
		defaults: extend({}, this)

	});
	return sysExec('lxc-stop '+args, callback);
};

Container.prototype.freeze = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name', 'force'],
		defaults: extend({}, this)
	});
	return sysExec('lxc-freeze -n '+name, callback);
};

Container.prototype.unfreeze = function(callback){

	return sysExec('lxc-unfreeze --name '+this.name, callback);
};

Container.prototype.info = function(callback){
	return sysExec('lxc-info --name '+this.name, function(data){
		console.log('info', arguments);
		if(data.match("doesn't exist")){
			return callback({state: 'NULL'});
		}

		var info = {};
		data = data.replace(/\suse/ig, '').replace(/\sbytes/ig, '').split("\n").slice(0,-1);
		for(var i in data){
			var temp = data[i].split(/\:\s+/);
			info[temp[0].toLowerCase().trim()] = temp[1].trim();
		}
		var args = [info].concat(Array.prototype.slice.call(arguments, 1));
		return callback.apply(this, args);
	});
};

Container.prototype.UpdateFromInfo = function(data){
	for(var key in Object.keys(data)){
		this[key] = data[key];
	}

	return this;
}

var lxcORM = function(){
	this.containers = {}
	this.list(function(data){
		for(var idx = data.length; idx--;){
			container[data[idx].name] = new Container(data[idx]);
		}
	});
	this.isReady = false;
	this.whenReady = [];

};

lxcORM.prototype.callReady = function(){
	for(var idx=0; idx<this.whenReady.length; idx--){
		this.whenReady[idx].apply(this);
	}
}

lxcORM.prototype.ready = function(callback){
	if(this.isReady){
		return callback.apply(this);
	}
	else{
		this.whenReady.append(callback);
	}
}

lxcORM.prototype.create = function(args, callback){

	args = parseArgs({
		required: ['name', 'template'],
		takes: ['name', 'template', ' ', 'd', 'r', 'a'],
		defaults: extend({template:'download', ' ': ' ', d: 'ubuntu', r: 'trusty', a: 'amd64'}, args)

	})

	return sysExec('lxc-create '+args, callback);
};

lxcORM.prototype.list= function(callback){
	sysExec('lxc-ls --fancy', function(data){
		var output = data.split("\n");
		var keys = output.splice(0,1)[0].split(/\s+/).slice(0,-1);
		var info = [];

		keys = keys.map(function(v){return v.toLowerCase()});
		output = output.slice(0).slice(0,-1);

		for(var i in output){
			if(output[i].match(/^-/)) continue; // compatibility with 1.x and 2.x output

			var aIn = output[i].split(/\s+/).slice(0,-1);
			var mapOut = {};
			aIn.map(function(value,idx){
				mapOut[keys[idx]] = value;
			});
			info.push(mapOut);

		}
		var args = [info].concat(Array.prototype.slice.call(arguments, 1));
		callback.apply(this, args);
	});
};

// module.exports = lxc;

var orm = new lxcORM()
orm.ready(function(){
	console.log(arguments, this);
})
// setTimeout(function(){console.log(orm)}, 5000)
<commit_msg>runner<commit_after>'use strict';
var exec = require('child_process').exec;
var extend = require('node.extend');

var parseArgs = function(required, takes, config){
	var all = Object.keys(config);
	// console.log(all)
	for(var i=required.length; i--;){
		if(all.indexOf(required[i]) !== -1){
			required.splice(i, 1);
		}
	}

	if(required.length !== 0) return false;

	var out = '';
	for(var i=0; i< takes.length; i++){
		if(all.indexOf(takes[i]) !== -1){
			out += '--'+takes[i]+' '+config[takes[i]]+' ';
		}
	}

	return out;
};

function sysExec(command, callback){
	command = 'unset XDG_SESSION_ID XDG_RUNTIME_DIR; cgm movepid all virt $$; ' + command;

	return exec(command, (function(callback){
		return function(err,data,stderr){
			if(callback){
				return callback(data, err, stderr);
			}
		}
	})(callback));
};

var Container = function(config){
	this.name = config.name;
	this.state = config.state || 'STOPPED';
	this.ip = config.ip || (config.ipv4 || '').replace('-', '') || null ;
	this.overlayfs = null
}

Container.prototype.clone = function(callback){
	var overlayfs = this.overlayfs ? ' -B overlayfs -s ' : '';

	return sysExec('lxc-clone -o '+this.orig+ ' -n '+this.name + overlayfs, callback);
};

Container.prototype.start = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name'],
		defaults: extend({}, this)

	});

	return sysExec('lxc-start --daemon '+args, callback);
};

Container.prototype.startEphemeral = function(callback){
	args = parseArgs({
		required: ['orig'],
		takes: ['orig', 'name', 'key', 'union-type', 'keep-data'],
		defaults: extend({}, this)

	});

	var command = 'lxc-start-ephemeral --daemon '+args;
	return sysExec(command, function(data){
		console.log('startEphemeral', arguments);
		if(data.match("doesn't exist.")){
			return callback({status: 500, error: "doesn't exist."});
		}
		if(data.match('already exists.')){
			return callback({status: 500, error: 'already exists'});
		}
		if(data.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)){
			return callback({status: 200, state:'RUNNING', ip: data.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)[0]});
		}

		callback({'?': '?', data: data, name: name, base_name: base_name});
	});
};

Container.prototype.destroy = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name', 'force'],
		defaults: extend({}, this)
	});

	return sysExec('lxc-destroy '+ args, function(data){
		var info = data.match(/Destroyed container/);
		console.log('destroy info:', info);
		var args = [true].concat(Array.prototype.slice.call(arguments, 1));
		return callback.apply(this, args);
	});
},

Container.prototype.stop = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name', 'reboot', 'nowait', 'timeout', 'kill'],
		defaults: extend({}, this)

	});
	return sysExec('lxc-stop '+args, callback);
};

Container.prototype.freeze = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name', 'force'],
		defaults: extend({}, this)
	});
	return sysExec('lxc-freeze -n '+name, callback);
};

Container.prototype.unfreeze = function(callback){

	return sysExec('lxc-unfreeze --name '+this.name, callback);
};

Container.prototype.info = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name', 'reboot', 'nowait', 'timeout', 'kill'],
		defaults: extend({}, this)

	});
	return sysExec('lxc-stop '+args, callback);
};

Container.prototype.freeze = function(callback){
	args = parseArgs({
		required: ['name'],
		takes: ['name', 'force'],
		defaults: extend({}, this)
	});
	return sysExec('lxc-freeze -n '+name, callback);
};

Container.prototype.unfreeze = function(callback){

	return sysExec('lxc-unfreeze --name '+this.name, callback);
};

Container.prototype.info = function(callback){
	return sysExec('lxc-info --name '+this.name, function(data){
		console.log('info', arguments);
		if(data.match("doesn't exist")){
			return callback({state: 'NULL'});
		}

		var info = {};
		data = data.replace(/\suse/ig, '').replace(/\sbytes/ig, '').split("\n").slice(0,-1);
		for(var i in data){
			var temp = data[i].split(/\:\s+/);
			info[temp[0].toLowerCase().trim()] = temp[1].trim();
		}
		var args = [info].concat(Array.prototype.slice.call(arguments, 1));
		return callback.apply(this, args);
	});
};

Container.prototype.UpdateFromInfo = function(data){
	for(var key in Object.keys(data)){
		this[key] = data[key];
	}

	return this;
}

var lxcORM = function(){
	this.containers = {}
	this.list(function(data){
		for(var idx = data.length; idx--;){
			container[data[idx].name] = new Container(data[idx]);
		}
	});
	this.isReady = false;
	this.whenReady = [];

};

lxcORM.prototype.callReady = function(){
	for(var idx=0; idx<this.whenReady.length; idx--){
		this.whenReady[idx].apply(this);
	}
}

lxcORM.prototype.ready = function(callback){
	if(this.isReady){
		return callback.apply(this);
	}
	else{
		this.whenReady.push(callback);
	}
}

lxcORM.prototype.create = function(args, callback){

	args = parseArgs({
		required: ['name', 'template'],
		takes: ['name', 'template', ' ', 'd', 'r', 'a'],
		defaults: extend({template:'download', ' ': ' ', d: 'ubuntu', r: 'trusty', a: 'amd64'}, args)

	})

	return sysExec('lxc-create '+args, callback);
};

lxcORM.prototype.list= function(callback){
	sysExec('lxc-ls --fancy', function(data){
		var output = data.split("\n");
		var keys = output.splice(0,1)[0].split(/\s+/).slice(0,-1);
		var info = [];

		keys = keys.map(function(v){return v.toLowerCase()});
		output = output.slice(0).slice(0,-1);

		for(var i in output){
			if(output[i].match(/^-/)) continue; // compatibility with 1.x and 2.x output

			var aIn = output[i].split(/\s+/).slice(0,-1);
			var mapOut = {};
			aIn.map(function(value,idx){
				mapOut[keys[idx]] = value;
			});
			info.push(mapOut);

		}
		var args = [info].concat(Array.prototype.slice.call(arguments, 1));
		callback.apply(this, args);
	});
};

// module.exports = lxc;

var orm = new lxcORM()
orm.ready(function(){
	console.log(arguments, this);
})
// setTimeout(function(){console.log(orm)}, 5000)
<|endoftext|>


<commit_before>'use strict';
var exec = require('child_process').exec;

function sysExec(command, callback){
	command = 'unset XDG_SESSION_ID XDG_RUNTIME_DIR; cgm movepid all virt $$; ' + command;

	return exec(command, (function(){
        return function(err,data,stderr){
            if(!callback) return;
            callback(data, err, stderr);
        }
    })(callback));
};

var lxc = {
	create: function(name, template, config, callback){
		return sysExec('lxc-create -n '+name+' -t '+template, callback);
	},

	clone: function(name, base_name, callback){
		return sysExec('lxc-clone -o '+base_name+ ' -n '+name +' -B overlayfs -s', callback);
	},

	destroy: function(name, callback){
		return sysExec('lxc-destroy -n '+ name, function(data){
			callback(!data.match(/Destroyed container/));
		});
	},

	start: function(name, callback){
		var cmd = 'lxc-start --name '+name+' --daemon';
		return sysExec(cmd, callback);
	},

	startEphemeral: function(name, base_name, callback){
		var command = 'lxc-start-ephemeral -o '+base_name+ ' -n '+name +' --union-type overlayfs -d';
		return sysExec(command, function(data){
			console.log('startEphemeral', arguments);
			if(data.match("doesn't exist.")){
				return callback({status: 500, error: "doesn't exist."});
			}
			if(data.match("already exists.")){
				return callback({status: 500, error: "already exists"});
			}
			if(data.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)){
				return callback({status: 200, state:'RUNNING', ip: data.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)[0]});
			}

			callback({'?': '?', data: data, name: name, base_name: base_name});
		});
	},

	stop: function(name, callback){
		return sysExec('lxc-stop -n '+ name, callback);
	},

	freeze: function(name, callback){
		return sysExec('lxc-freeze -n '+name, callback);
	},

	unfreeze: function(name, callback){
		return sysExec('lxc-unfreeze -n '+name, callback);
	},

	info: function(name, callback){
		return sysExec('lxc-info -n '+name, function(data){
			console.log('info', arguments);
			if(data.match("doesn't exist")){
				return callback({state: 'NULL'});
			}

			var info = {};
			data = data.replace(/\suse/ig, '').replace(/\sbytes/ig, '').split("\n").slice(0,-1);
			for(var i in data){
				var temp = data[i].split(/\:\s+/);
				info[temp[0].toLowerCase().trim()] = temp[1].trim();
			}
			callback(info);
		});
	},

	list: function(callback){
		sysExec('lxc-ls --fancy', function(data){
			var output = data.split("\n");
			var keys = output.splice(0,1)[0].split(/\s+/).slice(0,-1);
			var info = [];

			keys = keys.map(function(v){return v.toLowerCase()});
			output = output.slice(0).splice(1).slice(0,-1);

			for(var i in output){

				var aIn = output[i].split(/\s+/).slice(0,-1);
				var mapOut = {};
				aIn.map(function(value,idx){
					mapOut[keys[idx]] = value;
				});
				info.push(mapOut);

			}
			callback(info);
		});
	}
};

module.exports = lxc;
<commit_msg>testing<commit_after>'use strict';
var exec = require('child_process').exec;

function sysExec(command, callback){
	command = 'unset XDG_SESSION_ID XDG_RUNTIME_DIR; cgm movepid all virt $$; ' + command;

	return exec(command, (function(){
        return function(err,data,stderr){
            if(callback){
            	return callback(data, err, stderr);
            }
        }
    })(callback));
};

var lxc = {
	create: function(name, template, config, callback){
		return sysExec('lxc-create -n '+name+' -t '+template, callback);
	},

	clone: function(name, base_name, callback){
		return sysExec('lxc-clone -o '+base_name+ ' -n '+name +' -B overlayfs -s', callback);
	},

	destroy: function(name, callback){
		return sysExec('lxc-destroy -n '+ name, function(data){
			callback(!data.match(/Destroyed container/));
		});
	},

	start: function(name, callback){
		var cmd = 'lxc-start --name '+name+' --daemon';
		return sysExec(cmd, callback);
	},

	startEphemeral: function(name, base_name, callback){
		var command = 'lxc-start-ephemeral -o '+base_name+ ' -n '+name +' --union-type overlayfs -d';
		return sysExec(command, function(data){
			console.log('startEphemeral', arguments);
			if(data.match("doesn't exist.")){
				return callback({status: 500, error: "doesn't exist."});
			}
			if(data.match("already exists.")){
				return callback({status: 500, error: "already exists"});
			}
			if(data.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)){
				return callback({status: 200, state:'RUNNING', ip: data.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)[0]});
			}

			callback({'?': '?', data: data, name: name, base_name: base_name});
		});
	},

	stop: function(name, callback){
		return sysExec('lxc-stop -n '+ name, callback);
	},

	freeze: function(name, callback){
		return sysExec('lxc-freeze -n '+name, callback);
	},

	unfreeze: function(name, callback){
		return sysExec('lxc-unfreeze -n '+name, callback);
	},

	info: function(name, callback){
		return sysExec('lxc-info -n '+name, function(data){
			console.log('info', arguments);
			if(data.match("doesn't exist")){
				return callback({state: 'NULL'});
			}

			var info = {};
			data = data.replace(/\suse/ig, '').replace(/\sbytes/ig, '').split("\n").slice(0,-1);
			for(var i in data){
				var temp = data[i].split(/\:\s+/);
				info[temp[0].toLowerCase().trim()] = temp[1].trim();
			}
			callback(info);
		});
	},

	list: function(callback){
		sysExec('lxc-ls --fancy', function(data){
			var output = data.split("\n");
			var keys = output.splice(0,1)[0].split(/\s+/).slice(0,-1);
			var info = [];

			keys = keys.map(function(v){return v.toLowerCase()});
			output = output.slice(0).splice(1).slice(0,-1);

			for(var i in output){

				var aIn = output[i].split(/\s+/).slice(0,-1);
				var mapOut = {};
				aIn.map(function(value,idx){
					mapOut[keys[idx]] = value;
				});
				info.push(mapOut);

			}
			callback(info);
		});
	}
};

module.exports = lxc;
<|endoftext|>