<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  //Article = mongoose.model('Article'),
  Place = mongoose.model('Place'),
  Feed = mongoose.model('Feed'),
  _ = require('lodash');

/**
 * Find article by id
 *
 * heres the deal : dont know how to make a new api call just yet
 * so we're overloading article and changing based off if id is really an _id
 * or if its something else like a '(lat,lng),(lat,lng)' ...
 */
exports.article = function(req, res, next, id) {
	console.log('exports.article');
	if ( id.substr(0,1) === '(' ) {
		//console.log('overloaded :: looking for bounds');
		//console.log(id);
		var parsedok = false;
		var nelat, nelng, swlat, swlng;

		var commasplit = id.indexOf( '),(' );
		if ( commasplit > 0 ) {
			var comma = id.indexOf( ',' );
			if ( comma > 0 ) {
				nelat = parseFloat( id.substr( 1, comma - 1 ) ); // 33.1
				nelng = parseFloat( id.substr( comma + 2, ( commasplit - comma ) - 2 ) ); // -116
				comma = id.lastIndexOf( ',' );
				swlat = parseFloat( id.substr( commasplit + 3, ( comma - commasplit ) - 3 ) ); // 32.7
				swlng = parseFloat( id.substr( comma + 2, id.length - comma - 3 ) ); // -117
				//console.log('= |'+ nelat +'|'+ nelng +'|'+ swlat +'|'+ swlng);
				parsedok = true;
			} else {
				console.log('looking for bounds, but no inbetween comma found : '+ id);
			}
		} else {
			console.log('no commasplit to be found in '+ id);
		}
		// and return
		if ( parsedok ) {
			Place.find()
				.where('lat').lt(nelat)
				.where('lng').lt(nelng)
				.where('lat').gt(swlat)
				.where('lng').gt(swlng)
				.exec(function(err, places) {
				if (err) {
					return res.json(500, {
						error: 'Cannot list the places'
					});
				}
				res.json(places);
			});
		}
	} else {
		if ( id === 'findbad' ) {
			Place.find()
				.exec(function(err, places) {
				if (err) {
					return res.json(500, {
						error: 'Cannot list the places'
					});
				}
				res.json(places);
			});
		} else {
			console.log('looking for article id '+ id);
			Place.load(id, function(err, place) {
				if (err) return next(err);
				if (!place) return next(new Error('Failed to load article place ' + id));
				// else : its ok?
				req.place = place;
				console.log(place);
				next();
			});
		}
	}
};

/**
 * Create an article
 */
exports.create = function(req, res) {
  var place = new Place(req.body);
  //article.user = req.user;
	console.log('server : create a new Place :');
	console.log(place);
  place.save(function(err) {
    if (err) {
      return res.json(500, {
        error: 'Cannot save the place'
      });
    }
    res.json(place);
  });
};

/**
 * Update an article
 */
exports.update = function(req, res) {
  var article = req.article;

  article = _.extend(article, req.body);

  article.save(function(err) {
    if (err) {
      return res.json(500, {
        error: 'Cannot update the article'
      });
    }
    res.json(article);
  });
};

/**
 * Delete an article
 */
exports.destroy = function(req, res) {
  var article = req.article;

  article.remove(function(err) {
    if (err) {
      return res.json(500, {
        error: 'Cannot delete the article'
      });
    }
    res.json(article);
  });
};

/**
 * Show an article
 */
exports.show = function(req, res) {
	console.log('exports.show');
  res.json(req.article);
  console.log('---EXP---');
};

/**
 * List of Places
 */
exports.all = function(req, res) {
  Place.find().exec(function(err, places) {
    if (err) {
      return res.json(500, {
        error: 'Cannot list the places'
      });
    }
	//console.log('--- loaded all Places ---');
	//console.log(places);
	//console.log('----');
    res.json(places);
  });
};

/**
 * full Feed list from the db?!
 * right now this just loads the first chunk, and we have no pagination yet
 */
exports.fullFeed = function(req, res) {
  //console.log('GET /feed ( articles.fullFeed )');
  //console.log(req.params);

  Feed.getFeed(0,0, function(err) {
    return res.json(500, {
      error: 'Cannot list Feed items'
    });
  }, function( items ) {
    res.json(items);
  });
};

/**
 * Show a single Place
 */
exports.placed = function(req, res) {
	console.log('GET /articles/:id ' );
	console.log(req.params);
	res.json(req.place);
};

/**
 * Update a Place
 */
exports.updatePlace = function(req, res) {
	var pid = req.params.id;
	console.log( 'check it : PUT /places/:id = updatePlace '+ pid );
	return Place.load( pid, function(err, place) {
		console.log( 'updatePlace > load finished, now save?' );
		if ( !place ) {
			res.statusCode = 404;
			return res.send({ error: 'Not found' });
		}
		// otherwise, should be ok to continue
		place = _.extend(place, req.body);
		/*
		console.log('updating to..');
		console.log(place);
		*/
		place.save(function(err) {
			if ( err ) {
				console.log( 'Internal error(%d): %s', res.statusCode, err.message);
				res.statusCode = 500;
				return res.send( { error: 'some kind of error' } );
			} else {
				console.log('place saved!');
				return res.send({ status: 'OK', place: place });
			}
		});
	});
};<commit_msg>change "articles.fullFeed" to ".loadFeed" and allow taking in a ID + page & skip, to load either chunk of feed items from everywhere, or just from particular ID<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  //Article = mongoose.model('Article'),
  Place = mongoose.model('Place'),
  Feed = mongoose.model('Feed'),
  _ = require('lodash');

/**
 * Find article by id
 *
 * heres the deal : dont know how to make a new api call just yet
 * so we're overloading article and changing based off if id is really an _id
 * or if its something else like a '(lat,lng),(lat,lng)' ...
 */
exports.article = function(req, res, next, id) {
	console.log('exports.article');
	if ( id.substr(0,1) === '(' ) {
		//console.log('overloaded :: looking for bounds');
		//console.log(id);
		var parsedok = false;
		var nelat, nelng, swlat, swlng;

		var commasplit = id.indexOf( '),(' );
		if ( commasplit > 0 ) {
			var comma = id.indexOf( ',' );
			if ( comma > 0 ) {
				nelat = parseFloat( id.substr( 1, comma - 1 ) ); // 33.1
				nelng = parseFloat( id.substr( comma + 2, ( commasplit - comma ) - 2 ) ); // -116
				comma = id.lastIndexOf( ',' );
				swlat = parseFloat( id.substr( commasplit + 3, ( comma - commasplit ) - 3 ) ); // 32.7
				swlng = parseFloat( id.substr( comma + 2, id.length - comma - 3 ) ); // -117
				//console.log('= |'+ nelat +'|'+ nelng +'|'+ swlat +'|'+ swlng);
				parsedok = true;
			} else {
				console.log('looking for bounds, but no inbetween comma found : '+ id);
			}
		} else {
			console.log('no commasplit to be found in '+ id);
		}
		// and return
		if ( parsedok ) {
			Place.find()
				.where('lat').lt(nelat)
				.where('lng').lt(nelng)
				.where('lat').gt(swlat)
				.where('lng').gt(swlng)
				.exec(function(err, places) {
				if (err) {
					return res.status(500).json({
						error: 'Cannot list the places'
					});
				}
				res.json(places);
			});
		}
	} else {
		if ( id === 'findbad' ) {
			Place.find()
				.exec(function(err, places) {
				if (err) {
					return res.status(500).json({
						error: 'Cannot list the places'
					});
				}
				res.json(places);
			});
		} else {
			//console.log('looking for article id '+ id +' ( length '+ id.length +' )');
			Place.load(id, function(err, place) {
				if (err) return next(err);
				if (!place) return next(new Error('Failed to load article place ' + id));
				// else : its ok?
				req.place = place;
				//console.log(place);
				next();
			});
		}
	}
};

/**
 * Create an article
 */
exports.create = function(req, res) {
  var place = new Place(req.body);
  //article.user = req.user;
	console.log('server : create a new Place :');
	console.log(place);
  place.save(function(err) {
    if (err) {
      return res.status(500).json({
        error: 'Cannot save the place'
      });
    }
    res.json(place);
  });
};

/**
 * Update an article
 */
exports.update = function(req, res) {
  var article = req.article;

  article = _.extend(article, req.body);

  article.save(function(err) {
    if (err) {
      return res.status(500).json({
        error: 'Cannot update the article'
      });
    }
    res.json(article);
  });
};

/**
 * Delete an article
 */
exports.destroy = function(req, res) {
  var article = req.article;

  article.remove(function(err) {
    if (err) {
      return res.status(500).json({
        error: 'Cannot delete the article'
      });
    }
    res.json(article);
  });
};

/**
 * Show an article
 */
exports.show = function(req, res) {
	console.log('exports.show');
  res.json(req.article);
  console.log('---EXP---');
};

/**
 * List of Places
 */
exports.all = function(req, res) {
  Place.find().exec(function(err, places) {
    if (err) {
      return res.status(500).json({
        error: 'Cannot list the places'
      });
    }
	//console.log('--- loaded all Places ---');
	//console.log(places);
	//console.log('----');
    res.json(places);
  });
};

/**
 * full Feed list from the db?!
 * right now this just loads the first chunk, and we have no pagination yet
 */
exports.loadFeed = function(req, res) {
  console.log('GET /feed ( articles.getFeed )');
  console.log(req.params);

  var id = '',
      p = 0,
      s = 0;

  if ( req.params.hasOwnProperty('id') ) {
    id = req.params.id;
    if ( id === 'all' ) {
      id = '';
    }
  }
  if ( req.params.hasOwnProperty('page') ) {
    p = parseInt( req.params.page, 10 );
  }
  if ( req.params.hasOwnProperty('skip') ) {
    s = parseInt( req.params.skip, 10 );
  }

  console.log('fullFeed : getFeed /'+ id +'/'+ p +'/'+ s );
  Feed.getFeed(id, p, s, function(err) {
    return res.status(500).json({
      error: 'Cannot list Feed items'
    });
  }, function( items ) {
    res.json(items);
  });
};

/**
 * Show a single Place
 */
exports.placed = function(req, res) {
	console.log('GET /articles/:id ' );
	console.log(req.params);
	res.json(req.place);
};

/**
 * Update a Place
 */
exports.updatePlace = function(req, res) {
	var pid = req.params.id;
	console.log( 'check it : PUT /places/:id = updatePlace '+ pid );
	return Place.load( pid, function(err, place) {
		console.log( 'updatePlace > load finished, now save?' );
		if ( !place ) {
			res.statusCode = 404;
			return res.send({ error: 'Not found' });
		}
		// otherwise, should be ok to continue
		place = _.extend(place, req.body);
		/*
		console.log('updating to..');
		console.log(place);
		*/
		place.save(function(err) {
			if ( err ) {
				console.log( 'Internal error(%d): %s', res.statusCode, err.message);
				res.statusCode = 500;
				return res.send( { error: 'some kind of error' } );
			} else {
				console.log('place saved!');
				return res.send({ status: 'OK', place: place });
			}
		});
	});
};<|endoftext|>


<commit_before>/**
 * @File: calculator.js
 * @authors:
 * @Date:
 */

var expression = ""; //global expression to be evaluated
var isNegative = false; //check if current expression is negative
var isParenthesis = false; //check if current expression has unclosed parenthesis
var isExponent = false; //check if current expression is in an exponent (only allow 0-9)
var isDecimal = false; //check if current expression is already a floating point number

/*	Main Calculator Function	*/
function calculator() {

	displayScreen();
}
/*	Screen Display	*/
function displayScreen() {
	document.getElementById("screen").innerHTML = expression;
}

/*	Checks if expression ends with an operator, returns false if it does, true if it doesn't	*/
function checkValidExpression(expr)
{
	if (expr.endsWith(".") || expr.endsWith("^") || expr.endsWith("+") || expr.endsWith("-") || expr.endsWith("*") || expr.endsWith("/"))
	{
		return false;
	}
	return true;
}
/*	Event Listeners for 0-9, +, -, /, *, (), ., x, ^, clear
*	Each event listener will only add its variable if valid conditions are met
*/
document.getElementById("One").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("One").value;
	}
	displayScreen();
});
document.getElementById("Two").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Two").value;
	}
	displayScreen();
});
document.getElementById("Three").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Three").value;
	}
	displayScreen();
});
document.getElementById("Four").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Four").value;
	}
	displayScreen();
});
document.getElementById("Five").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Five").value;
	}
	displayScreen();
});
document.getElementById("Six").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Six").value;
	}
	displayScreen();
});
document.getElementById("Seven").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Seven").value;
	}
	displayScreen();
});
document.getElementById("Eight").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
		if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Eight").value;
	}
	displayScreen();
});
document.getElementById("Nine").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
		if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Nine").value;
	}
	displayScreen();
});
document.getElementById("Zero").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
		if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Zero").value;
	}
	displayScreen();
});
document.getElementById("Plus").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "")
	{

		expression += document.getElementById("Plus").value;
		isDecimal = false;
	}
	displayScreen();
});
document.getElementById("Minus").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "")
	{

		expression += document.getElementById("Minus").value;
		isDecimal = false;
	}

	displayScreen();
});
document.getElementById("Multiply").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "")
	{

		expression += document.getElementById("Multiply").value;
		isDecimal = false;
	}
	displayScreen();
});
document.getElementById("Divide").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "")
	{

		expression += document.getElementById("Divide").value;
		isDecimal = false;
	}
	displayScreen();
});
document.getElementById("Parenthesis").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "" && !expression.endsWith(")"))
	{
		expression = "(" + expression + ")";
	}

	displayScreen();
});
document.getElementById("Decimal").addEventListener('click', function() {
	if (checkValidExpression(expression) && !expression.endsWith("x") && expression != "" && !isDecimal && !expression.endsWith(")") && !expression.endsWith("x"))
	{
		expression += document.getElementById("Decimal").value;
		isDecimal = true;
	}

	displayScreen();
});
document.getElementById("ToClear").addEventListener('click', function() {
	expression = "";	//clears expression
	document.getElementById("results").innerHTML = ""; //clears results
	isNegative = false; //resets values
	isParenthesis = false;
	isExponent = false;
	isDecimal = false;
	displayScreen();

});
document.getElementById("Variable").addEventListener('click', function() {
	if (!expression.endsWith("x") && !expression.endsWith("."))
	{
		expression += document.getElementById("Variable").value;
	}
	displayScreen();

});
document.getElementById("Exponent").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "" && !isExponent)
	{

		expression += document.getElementById("Exponent").value;
		isExponent = true;
	}

	displayScreen();
});
document.getElementById("ToEvaluate").addEventListener('click', function() {
	if (expression.endsWith(".") || expression.endsWith("+") || expression.endsWith("-"))
	{
		expression += "0";
	}
	if (expression.endsWith("/") || expression.endsWith("^") || expression.endsWith("*"))
	{
		expression += "1";
	}
	if (!expression.endsWith(")"))
	{
		expression = "("+expression+")";
	}

	displayScreen();
});

//call calculator
calculator();
<commit_msg>Update calculator.js<commit_after>/**
 * @File: calculator.js
 * @authors:
 * @Date:
 */

var expression = ""; //global expression to be evaluated
var isNegative = false; //check if current expression is negative
var isParenthesis = false; //check if current expression has unclosed parenthesis
var isExponent = false; //check if current expression is in an exponent (only allow 0-9)
var isDecimal = false; //check if current expression is already a floating point number

/*	Main Calculator Function	*/
function calculator() {

	displayScreen();
}
/*	Screen Display	*/
function displayScreen() {
	document.getElementById("screen").innerHTML = expression;
}

/*	Checks if expression ends with an operator, returns false if it does, true if it doesn't	*/
function checkValidExpression(expr)
{
	if (expr.endsWith(".") || expr.endsWith("^") || expr.endsWith("+") || expr.endsWith("-") || expr.endsWith("*") || expr.endsWith("/"))
	{
		return false;
	}
	return true;
}
/*	Event Listeners for 0-9, +, -, /, *, (), ., x, ^, clear
*	Each event listener will only add its variable if valid conditions are met
*/
document.getElementById("One").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("One").value;
	}
	displayScreen();
});
document.getElementById("Two").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Two").value;
	}
	displayScreen();
});
document.getElementById("Three").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Three").value;
	}
	displayScreen();
});
document.getElementById("Four").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Four").value;
	}
	displayScreen();
});
document.getElementById("Five").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Five").value;
	}
	displayScreen();
});
document.getElementById("Six").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Six").value;
	}
	displayScreen();
});
document.getElementById("Seven").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
	if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Seven").value;
	}
	displayScreen();
});
document.getElementById("Eight").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
		if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Eight").value;
	}
	displayScreen();
});
document.getElementById("Nine").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
		if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Nine").value;
	}
	displayScreen();
});
document.getElementById("Zero").addEventListener('click', function() {
	if (expression.endsWith(")"))
	{
		expression += "*";
		isDecimal = false;
	}
		if (!expression.endsWith("x"))
	{
		expression += document.getElementById("Zero").value;
	}
	displayScreen();
});
document.getElementById("Plus").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "")
	{

		expression += document.getElementById("Plus").value;
		isDecimal = false;
	}
	displayScreen();
});
document.getElementById("Minus").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "")
	{

		expression += document.getElementById("Minus").value;
		isDecimal = false;
	}

	displayScreen();
});
document.getElementById("Multiply").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "")
	{

		expression += document.getElementById("Multiply").value;
		isDecimal = false;
	}
	displayScreen();
});
document.getElementById("Divide").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "")
	{

		expression += document.getElementById("Divide").value;
		isDecimal = false;
	}
	displayScreen();
});
document.getElementById("Parenthesis").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "" && !expression.endsWith(")"))
	{
		expression = "(" + expression + ")";
	}

	displayScreen();
});
document.getElementById("Decimal").addEventListener('click', function() {
	if (checkValidExpression(expression) && !expression.endsWith("x") && expression != "" && !isDecimal && !expression.endsWith(")") && !expression.endsWith("x"))
	{
		expression += document.getElementById("Decimal").value;
		isDecimal = true;
	}

	displayScreen();
});
document.getElementById("ToClear").addEventListener('click', function() {
	expression = "";	//clears expression
	document.getElementById("results").innerHTML = ""; //clears results
	isNegative = false; //resets values
	isParenthesis = false;
	isExponent = false;
	isDecimal = false;
	displayScreen();

});
document.getElementById("Variable").addEventListener('click', function() {
	if (!expression.endsWith("x") && !expression.endsWith("."))
	{
		expression += document.getElementById("Variable").value;
	}
	displayScreen();

});
document.getElementById("Exponent").addEventListener('click', function() {
	if (checkValidExpression(expression) && expression != "")
	{

		expression += document.getElementById("Exponent").value;

	}

	displayScreen();
});
document.getElementById("ToEvaluate").addEventListener('click', function() {
	if (expression.endsWith(".") || expression.endsWith("+") || expression.endsWith("-"))
	{
		expression += "0";
	}
	if (expression.endsWith("/") || expression.endsWith("^") || expression.endsWith("*"))
	{
		expression += "1";
	}
	if (!expression.endsWith(")"))
	{
		expression = "("+expression+")";
	}

	displayScreen();
});

//call calculator
calculator();
<|endoftext|>


<commit_before>;(function () {
  var warnTextNode
  // extend swal with a function for adding forms
  swal.withForm = function () {
    // initialize with field values supplied on `swal.withForm` call
    var swalForm = new SwalForm(arguments[0].formFields)
    // prevent successive calls to add duplicated form fields
    swalForm.removeSwalForm()
    // make form values inserted by the user available at `doneFunction`
    swalForm.addWayToGetFormValuesInDoneFunction(arguments)

    // forward arguments
    swal.apply({}, arguments)

    var htmlForm = swalForm.generateHtmlForm()
    swalForm.insertFormInSwalModal(htmlForm)
    swalForm.allowClickingDirectlyOnInputs()
    swalForm.focusOnFirstInput()
    swalForm.markFirstRadioButtons()
    swalForm.addTabOrder()
  }

  // constructor for helper object
  function SwalForm (formFields) {
    this.formFields = formFields
  }

  // helper methods
  extend(SwalForm.prototype, {
    formClass: 'swal-form',
    generateHtmlForm: function () {
      var form = {
        clazz: this.formClass,
        innerHtml: this.formFields.map(toFormTag.bind(this)).reduce(toSingleString)
      }

      return t("
{innerHtml}
", form)

      function toFormTag (field) {
        var input = Input(field)
        // to separate groups of checkboxes and radiobuttons in different lines
        var conditionalLineBreak = (input.isRadioOrCheckbox() && this.lastFieldName !== field.name) ? '
' : ''
        this.lastFieldName = field.name

        return conditionalLineBreak + input.toHtml()
      }
    },
    addWayToGetFormValuesInDoneFunction: function (swalArgs) {
      var swalFormInstance = this
      var doneFunction = swalArgs[1]
      swalArgs[1] = function (isConfirm) {
        // make form values available at `this` variable inside doneFunction
        this.swalForm = swalFormInstance.getFormValues(isConfirm)

        if (doneFunction.apply(this, arguments) !== false) {
          // clean form to not interfere in normals sweet alerts
          document.querySelector('.swal-form').innerHTML = ''
        }
      }
    },
    getFormValues: function (isConfirm) {
      var inputHtmlCollection = document.getElementsByClassName('swal-form-field')
      var inputArray = [].slice.call(inputHtmlCollection)

      return inputArray
        .filter(uncheckedRadiosAndCheckboxes)
        .map(toValuableAttrs)
        .reduce(toSingleObject, {})

      function uncheckedRadiosAndCheckboxes (tag) {
        return (isRadioOrCheckbox(tag) ? tag.checked : true)
      }

      function toValuableAttrs (tag) {
        var attr = {}
        attr[tag.id || tag.name] = tag.value
        if (isConfirm && tag.dataset.swalFormsRequired && !tag.value) {
          var warnMsg = 'Missing required attribute: ' + (tag.name || tag.id)
          warnTextNode && warnTextNode.remove && warnTextNode.remove()
          warnTextNode = document.createTextNode(warnMsg)
          document.querySelector('.swal-form').appendChild(warnTextNode)
          throw new Error(warnMsg)
        }
        return attr
      }

      function toSingleObject (obj1, obj2) {
        return extendPreventingOverrides(obj1, obj2)

        // for checkboxes we want to obtain all selected values in an array
        function extendPreventingOverrides (a, b) {
          Object.keys(b).forEach(addContentFromBtoA)
          return a

          function addContentFromBtoA (key) {
            if (a.hasOwnProperty(key)) {
              mergeIntoAnArray(a, b, key)
            } else {
              a[key] = b[key]
            }
          }
        }

        function mergeIntoAnArray (a, b, key) {
          if (Array.isArray(a[key])) {
            a[key].push(b[key])
          } else {
            a[key] = [a[key], b[key]]
          }
        }
      }
    },
    insertFormInSwalModal: function (htmlFormString) {
      var formTag = stringToTag(htmlFormString)
      var sweetAlertModal = document.querySelector('.sweet-alert')
      var buttonContainerTag = sweetAlertModal.querySelector('.sa-button-container') || sweetAlertModal.querySelector('.cancel')
      // insert form before swal bottom buttons
      sweetAlertModal.insertBefore(formTag, buttonContainerTag)

      function stringToTag (string) {
        var div = document.createElement('div')
        div.innerHTML = string
        return div.firstChild
      }
    },
    removeSwalForm: function () {
      var formTag = document.querySelector('.' + this.formClass)
      formTag && document.querySelector('.sweet-alert').removeChild(formTag)
    },
    allowClickingDirectlyOnInputs: function () {
      // sweet-alert attaches an onblur handler which prevents clicks on of non
      // button elements until click is made on the modal
      document.querySelector('.sweet-alert button.confirm').onblur = function () {}
      document.querySelector('.sweet-alert button.cancel').onblur = function () {}
    },
    getSelector: function () {
      var firstField = this.formFields[0]
      return (firstField.id ? t('#{id}', firstField) : t("[name='{name}']", firstField))
    },
    focusOnFirstInput: function () {
      setTimeout(focus.bind(this))

      function focus () {
        document.querySelector(this.getSelector()).focus()
      }
    },
    markFirstRadioButtons: function () {
      setTimeout(markAsChecked.bind(this))

      function markAsChecked () {
        document.querySelector(this.getSelector()).checked = true
      }
    },
    addTabOrder: function () {
      var formFields = Array.prototype.slice.call(document.querySelectorAll('.swal-form .swal-form-field'))
      formFields.forEach(addToTabNavigation)

      function addToTabNavigation (formField, index) {
        var myInput = formField
        var nextInput = formFields[index + 1]

        var keyHandler = function (e) {
          var TABKEY = 9
          if (e.keyCode === TABKEY) {
            var next = this
            setTimeout(function () { next.focus() })
          }
        }

        if (myInput.addEventListener) {
          myInput.addEventListener('keydown', keyHandler.bind(nextInput), false)
        } else if (myInput.attachEvent) {
          myInput.attachEvent('onkeydown', keyHandler.bind(nextInput)) /* damn IE hack */
        }
      }
    }
  })

  function isRadioOrCheckbox (tag) {
    return tag.type === 'radio' || tag.type === 'checkbox'
  }

  function extend (o1, o2) {
    for (var key in o2) {
      if (o2.hasOwnProperty(key)) {
        o1[key] = o2[key]
      }
    }
    return o1
  }

  function Input (field) {
    var input = {
      id: field.id || '',
      name: field.name || '',
      label: field.label || '',
      clazz: field.clazz || '',
      placeholder: field.placeholder || camelCaseToHuman(field.id),
      value: field.value || '',
      type: field.type || 'text',
      options: field.options || [],
      required: field.required,
      isRadioOrCheckbox: function () {
        return isRadioOrCheckbox(input)
      },
      toHtml: function () {
        var inputTag
        if (input.type !== 'select') {
          inputTag = t("<input id='{id}' class='{clazz} swal-form-field' type='{type}' name='{name}'" +
            " value='{value}' title='{placeholder}' placeholder='{placeholder}'" +
            ' data-swal-forms-required={required}>', input)
        } else {
          inputTag = t("<select id='{id}' class='{clazz} swal-form-field' name='{name}'" +
            " value='{value}' title='{placeholder}' style='width:100%'>" +
            ' data-swal-forms-required={}', input) +
              input.options.reduce(toHtmlOptions, '') +
            '</select>'
        }
        var labelTag = t("{label}", input)

        return inputTag + labelTag

        function toHtmlOptions (optionsString, option) {
            option.selected = option.selected ? ' selected' : ''
            return optionsString + t("<option value='{value}'{selected}>{text}</option>", option)
        }
      }
    }
    // Should this label be set to title or id instead of value?
    input.label = input.isRadioOrCheckbox() && input.label === '' ? input.value : input.label
    input.clazz += input.isRadioOrCheckbox() ? ' patch-swal-styles-for-inputs' : ' nice-input'

    return input

    function camelCaseToHuman (arg) {
      if (arg) {
        return arg
          .replace(/([A-Z])/g, ' $1') // insert a space before all caps
          .replace(/^./, function (str) { return str.toUpperCase() }) // uppercase the first character
      } else {
        return ''
      }
    }
  }

  // string interpolation hack
  function t (template, data) {
    for (var key in data) {
      template = template.replace(new RegExp('{' + key + '}', 'g'), data[key] || '')
    }
    return template
  }

  function toSingleString (s1, s2) {
    return s1 + s2
  }

  swal.withFormAsync = function (options) {
    return new Promise(function (resolve, reject) {
      swal.withForm(options, function (isConfirm) {
        this._isConfirm = isConfirm
        resolve(this)
      })
    })
  }
})()
<commit_msg>Fixed incorrect vertical centering by injecting html form as part of the sweet alert arguments on creation. (this allows the sweet alert library to correctly determine the necessary top-margin)<commit_after>;(function () {
  var warnTextNode
  // extend swal with a function for adding forms
  swal.withForm = function () {
    // initialize with field values supplied on `swal.withForm` call
    var swalForm = new SwalForm(arguments[0].formFields)
    // prevent successive calls to add duplicated form fields
    swalForm.removeSwalForm()
    // make form values inserted by the user available at `doneFunction`
    swalForm.addWayToGetFormValuesInDoneFunction(arguments)

    // Prepare arguments with the form html and html flag
    arguments[0].text = swalForm.generateHtmlForm()
    arguments[0].html = true

    // forward arguments
    swal.apply({}, arguments)

    swalForm.allowClickingDirectlyOnInputs()
    swalForm.focusOnFirstInput()
    swalForm.markFirstRadioButtons()
    swalForm.addTabOrder()
  }

  // constructor for helper object
  function SwalForm (formFields) {
    this.formFields = formFields
  }

  // helper methods
  extend(SwalForm.prototype, {
    formClass: 'swal-form',
    generateHtmlForm: function () {
      var form = {
        clazz: this.formClass,
        innerHtml: this.formFields.map(toFormTag.bind(this)).reduce(toSingleString)
      }

      return t("
{innerHtml}
", form)

      function toFormTag (field) {
        var input = Input(field)
        // to separate groups of checkboxes and radiobuttons in different lines
        var conditionalLineBreak = (input.isRadioOrCheckbox() && this.lastFieldName !== field.name) ? '
' : ''
        this.lastFieldName = field.name

        return conditionalLineBreak + input.toHtml()
      }
    },
    addWayToGetFormValuesInDoneFunction: function (swalArgs) {
      var swalFormInstance = this
      var doneFunction = swalArgs[1]
      swalArgs[1] = function (isConfirm) {
        // make form values available at `this` variable inside doneFunction
        this.swalForm = swalFormInstance.getFormValues(isConfirm)

        if (doneFunction.apply(this, arguments) !== false) {
          // clean form to not interfere in normals sweet alerts
          document.querySelector('.swal-form').innerHTML = ''
        }
      }
    },
    getFormValues: function (isConfirm) {
      var inputHtmlCollection = document.getElementsByClassName('swal-form-field')
      var inputArray = [].slice.call(inputHtmlCollection)

      return inputArray
        .filter(uncheckedRadiosAndCheckboxes)
        .map(toValuableAttrs)
        .reduce(toSingleObject, {})

      function uncheckedRadiosAndCheckboxes (tag) {
        return (isRadioOrCheckbox(tag) ? tag.checked : true)
      }

      function toValuableAttrs (tag) {
        var attr = {}
        attr[tag.id || tag.name] = tag.value
        if (isConfirm && tag.dataset.swalFormsRequired && !tag.value) {
          var warnMsg = 'Missing required attribute: ' + (tag.name || tag.id)
          warnTextNode && warnTextNode.remove && warnTextNode.remove()
          warnTextNode = document.createTextNode(warnMsg)
          document.querySelector('.swal-form').appendChild(warnTextNode)
          throw new Error(warnMsg)
        }
        return attr
      }

      function toSingleObject (obj1, obj2) {
        return extendPreventingOverrides(obj1, obj2)

        // for checkboxes we want to obtain all selected values in an array
        function extendPreventingOverrides (a, b) {
          Object.keys(b).forEach(addContentFromBtoA)
          return a

          function addContentFromBtoA (key) {
            if (a.hasOwnProperty(key)) {
              mergeIntoAnArray(a, b, key)
            } else {
              a[key] = b[key]
            }
          }
        }

        function mergeIntoAnArray (a, b, key) {
          if (Array.isArray(a[key])) {
            a[key].push(b[key])
          } else {
            a[key] = [a[key], b[key]]
          }
        }
      }
    },
    insertFormInSwalModal: function (htmlFormString) {
      var formTag = stringToTag(htmlFormString)
      var sweetAlertModal = document.querySelector('.sweet-alert')
      var buttonContainerTag = sweetAlertModal.querySelector('.sa-button-container') || sweetAlertModal.querySelector('.cancel')
      // insert form before swal bottom buttons
      sweetAlertModal.insertBefore(formTag, buttonContainerTag)

      function stringToTag (string) {
        var div = document.createElement('div')
        div.innerHTML = string
        return div.firstChild
      }
    },
    removeSwalForm: function () {
      var formTag = document.querySelector('.' + this.formClass)
      formTag && document.querySelector('.sweet-alert').removeChild(formTag)
    },
    allowClickingDirectlyOnInputs: function () {
      // sweet-alert attaches an onblur handler which prevents clicks on of non
      // button elements until click is made on the modal
      document.querySelector('.sweet-alert button.confirm').onblur = function () {}
      document.querySelector('.sweet-alert button.cancel').onblur = function () {}
    },
    getSelector: function () {
      var firstField = this.formFields[0]
      return (firstField.id ? t('#{id}', firstField) : t("[name='{name}']", firstField))
    },
    focusOnFirstInput: function () {
      setTimeout(focus.bind(this))

      function focus () {
        document.querySelector(this.getSelector()).focus()
      }
    },
    markFirstRadioButtons: function () {
      setTimeout(markAsChecked.bind(this))

      function markAsChecked () {
        document.querySelector(this.getSelector()).checked = true
      }
    },
    addTabOrder: function () {
      var formFields = Array.prototype.slice.call(document.querySelectorAll('.swal-form .swal-form-field'))
      formFields.forEach(addToTabNavigation)

      function addToTabNavigation (formField, index) {
        var myInput = formField
        var nextInput = formFields[index + 1]

        var keyHandler = function (e) {
          var TABKEY = 9
          if (e.keyCode === TABKEY) {
            var next = this
            setTimeout(function () { next.focus() })
          }
        }

        if (myInput.addEventListener) {
          myInput.addEventListener('keydown', keyHandler.bind(nextInput), false)
        } else if (myInput.attachEvent) {
          myInput.attachEvent('onkeydown', keyHandler.bind(nextInput)) /* damn IE hack */
        }
      }
    }
  })

  function isRadioOrCheckbox (tag) {
    return tag.type === 'radio' || tag.type === 'checkbox'
  }

  function extend (o1, o2) {
    for (var key in o2) {
      if (o2.hasOwnProperty(key)) {
        o1[key] = o2[key]
      }
    }
    return o1
  }

  function Input (field) {
    var input = {
      id: field.id || '',
      name: field.name || '',
      label: field.label || '',
      clazz: field.clazz || '',
      placeholder: field.placeholder || camelCaseToHuman(field.id),
      value: field.value || '',
      type: field.type || 'text',
      options: field.options || [],
      required: field.required,
      isRadioOrCheckbox: function () {
        return isRadioOrCheckbox(input)
      },
      toHtml: function () {
        var inputTag
        if (input.type !== 'select') {
          inputTag = t("<input id='{id}' class='{clazz} swal-form-field' type='{type}' name='{name}'" +
            " value='{value}' title='{placeholder}' placeholder='{placeholder}'" +
            ' data-swal-forms-required={required}>', input)
        } else {
          inputTag = t("<select id='{id}' class='{clazz} swal-form-field' name='{name}'" +
            " value='{value}' title='{placeholder}' style='width:100%'>" +
            ' data-swal-forms-required={}', input) +
              input.options.reduce(toHtmlOptions, '') +
            '</select>'
        }
        var labelTag = t("{label}", input)

        return inputTag + labelTag

        function toHtmlOptions (optionsString, option) {
            option.selected = option.selected ? ' selected' : ''
            return optionsString + t("<option value='{value}'{selected}>{text}</option>", option)
        }
      }
    }
    // Should this label be set to title or id instead of value?
    input.label = input.isRadioOrCheckbox() && input.label === '' ? input.value : input.label
    input.clazz += input.isRadioOrCheckbox() ? ' patch-swal-styles-for-inputs' : ' nice-input'

    return input

    function camelCaseToHuman (arg) {
      if (arg) {
        return arg
          .replace(/([A-Z])/g, ' $1') // insert a space before all caps
          .replace(/^./, function (str) { return str.toUpperCase() }) // uppercase the first character
      } else {
        return ''
      }
    }
  }

  // string interpolation hack
  function t (template, data) {
    for (var key in data) {
      template = template.replace(new RegExp('{' + key + '}', 'g'), data[key] || '')
    }
    return template
  }

  function toSingleString (s1, s2) {
    return s1 + s2
  }

  swal.withFormAsync = function (options) {
    return new Promise(function (resolve, reject) {
      swal.withForm(options, function (isConfirm) {
        this._isConfirm = isConfirm
        resolve(this)
      })
    })
  }
})()
<|endoftext|>


<commit_before><commit_msg>handle proxy logic for everything in vector provider<commit_after><|endoftext|>


<commit_before>import {
	InterpolateLinear,
	InterpolateSmooth,
	InterpolateDiscrete
} from '../constants.js';
import { CubicInterpolant } from '../math/interpolants/CubicInterpolant.js';
import { LinearInterpolant } from '../math/interpolants/LinearInterpolant.js';
import { DiscreteInterpolant } from '../math/interpolants/DiscreteInterpolant.js';
import { AnimationUtils } from './AnimationUtils.js';

function KeyframeTrack( name, times, values, interpolation ) {

	if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
	if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );

	this.name = name;

	this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
	this.values = AnimationUtils.convertArray( values, this.ValueBufferType );

	this.setInterpolation( interpolation || this.DefaultInterpolation );

}

// Static methods

Object.assign( KeyframeTrack, {

	// Serialization (in static context, because of constructor invocation
	// and automatic invocation of .toJSON):

	toJSON: function ( track ) {

		const trackType = track.constructor;

		let json;

		// derived classes can define a static toJSON method
		if ( trackType.toJSON !== undefined ) {

			json = trackType.toJSON( track );

		} else {

			// by default, we assume the data can be serialized as-is
			json = {

				'name': track.name,
				'times': AnimationUtils.convertArray( track.times, Array ),
				'values': AnimationUtils.convertArray( track.values, Array )

			};

			const interpolation = track.getInterpolation();

			if ( interpolation !== track.DefaultInterpolation ) {

				json.interpolation = interpolation;

			}

		}

		json.type = track.ValueTypeName; // mandatory

		return json;

	}

} );

Object.assign( KeyframeTrack.prototype, {

	constructor: KeyframeTrack,

	TimeBufferType: Float32Array,

	ValueBufferType: Float32Array,

	DefaultInterpolation: InterpolateLinear,

	InterpolantFactoryMethodDiscrete: function ( result ) {

		return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );

	},

	InterpolantFactoryMethodLinear: function ( result ) {

		return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );

	},

	InterpolantFactoryMethodSmooth: function ( result ) {

		return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );

	},

	setInterpolation: function ( interpolation ) {

		let factoryMethod;

		switch ( interpolation ) {

			case InterpolateDiscrete:

				factoryMethod = this.InterpolantFactoryMethodDiscrete;

				break;

			case InterpolateLinear:

				factoryMethod = this.InterpolantFactoryMethodLinear;

				break;

			case InterpolateSmooth:

				factoryMethod = this.InterpolantFactoryMethodSmooth;

				break;

		}

		if ( factoryMethod === undefined ) {

			const message = 'unsupported interpolation for ' +
				this.ValueTypeName + ' keyframe track named ' + this.name;

			if ( this.createInterpolant === undefined ) {

				// fall back to default, unless the default itself is messed up
				if ( interpolation !== this.DefaultInterpolation ) {

					this.setInterpolation( this.DefaultInterpolation );

				} else {

					throw new Error( message ); // fatal, in this case

				}

			}

			console.warn( 'THREE.KeyframeTrack:', message );
			return this;

		}

		this.createInterpolant = factoryMethod;

		return this;

	},

	getInterpolation: function () {

		switch ( this.createInterpolant ) {

			case this.InterpolantFactoryMethodDiscrete:

				return InterpolateDiscrete;

			case this.InterpolantFactoryMethodLinear:

				return InterpolateLinear;

			case this.InterpolantFactoryMethodSmooth:

				return InterpolateSmooth;

		}

	},

	getValueSize: function () {

		return this.values.length / this.times.length;

	},

	// move all keyframes either forwards or backwards in time
	shift: function ( timeOffset ) {

		if ( timeOffset !== 0.0 ) {

			const times = this.times;

			for ( let i = 0, n = times.length; i !== n; ++ i ) {

				times[ i ] += timeOffset;

			}

		}

		return this;

	},

	// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
	scale: function ( timeScale ) {

		if ( timeScale !== 1.0 ) {

			const times = this.times;

			for ( let i = 0, n = times.length; i !== n; ++ i ) {

				times[ i ] *= timeScale;

			}

		}

		return this;

	},

	// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
	// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
	trim: function ( startTime, endTime ) {

		const times = this.times,
			nKeys = times.length;

		let from = 0,
			to = nKeys - 1;

		while ( from !== nKeys && times[ from ] < startTime ) {

			++ from;

		}

		while ( to !== - 1 && times[ to ] > endTime ) {

			-- to;

		}

		++ to; // inclusive -> exclusive bound

		if ( from !== 0 || to !== nKeys ) {

			// empty tracks are forbidden, so keep at least one keyframe
			if ( from >= to ) {

				to = Math.max( to, 1 );
				from = to - 1;

			}

			const stride = this.getValueSize();
			this.times = AnimationUtils.arraySlice( times, from, to );
			this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );

		}

		return this;

	},

	// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
	validate: function () {

		let valid = true;

		const valueSize = this.getValueSize();
		if ( valueSize - Math.floor( valueSize ) !== 0 ) {

			console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
			valid = false;

		}

		const times = this.times,
			values = this.values,

			nKeys = times.length;

		if ( nKeys === 0 ) {

			console.error( 'THREE.KeyframeTrack: Track is empty.', this );
			valid = false;

		}

		let prevTime = null;

		for ( let i = 0; i !== nKeys; i ++ ) {

			const currTime = times[ i ];

			if ( typeof currTime === 'number' && isNaN( currTime ) ) {

				console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
				valid = false;
				break;

			}

			if ( prevTime !== null && prevTime > currTime ) {

				console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
				valid = false;
				break;

			}

			prevTime = currTime;

		}

		if ( values !== undefined ) {

			if ( AnimationUtils.isTypedArray( values ) ) {

				for ( let i = 0, n = values.length; i !== n; ++ i ) {

					const value = values[ i ];

					if ( isNaN( value ) ) {

						console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
						valid = false;
						break;

					}

				}

			}

		}

		return valid;

	},

	// removes equivalent sequential keys as common in morph target sequences
	// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
	optimize: function () {

		// times or values may be shared with other tracks, so overwriting is unsafe
		const times = AnimationUtils.arraySlice( this.times ),
			values = AnimationUtils.arraySlice( this.values ),
			stride = this.getValueSize(),

			smoothInterpolation = this.getInterpolation() === InterpolateSmooth,

			lastIndex = times.length - 1;

		let writeIndex = 1;

		for ( let i = 1; i < lastIndex; ++ i ) {

			let keep = false;

			const time = times[ i ];
			const timeNext = times[ i + 1 ];

			// remove adjacent keyframes scheduled at the same time

			if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {

				if ( ! smoothInterpolation ) {

					// remove unnecessary keyframes same as their neighbors

					const offset = i * stride,
						offsetP = offset - stride,
						offsetN = offset + stride;

					for ( let j = 0; j !== stride; ++ j ) {

						const value = values[ offset + j ];

						if ( value !== values[ offsetP + j ] ||
							value !== values[ offsetN + j ] ) {

							keep = true;
							break;

						}

					}

				} else {

					keep = true;

				}

			}

			// in-place compaction

			if ( keep ) {

				if ( i !== writeIndex ) {

					times[ writeIndex ] = times[ i ];

					const readOffset = i * stride,
						writeOffset = writeIndex * stride;

					for ( let j = 0; j !== stride; ++ j ) {

						values[ writeOffset + j ] = values[ readOffset + j ];

					}

				}

				++ writeIndex;

			}

		}

		// flush last keyframe (compaction looks ahead)

		if ( lastIndex > 0 ) {

			times[ writeIndex ] = times[ lastIndex ];

			for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {

				values[ writeOffset + j ] = values[ readOffset + j ];

			}

			++ writeIndex;

		}

		if ( writeIndex !== times.length ) {

			this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
			this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );

		} else {

			this.times = times;
			this.values = values;

		}

		return this;

	},

	clone: function () {

		const times = AnimationUtils.arraySlice( this.times, 0 );
		const values = AnimationUtils.arraySlice( this.values, 0 );

		const TypedKeyframeTrack = this.constructor;
		const track = new TypedKeyframeTrack( this.name, times, values );

		// Interpolant argument to constructor is not saved, so copy the factory method directly.
		track.createInterpolant = this.createInterpolant;

		return track;

	}

} );

export { KeyframeTrack };
<commit_msg>Fix typo in KeyframeTrack.optimize()<commit_after>import {
	InterpolateLinear,
	InterpolateSmooth,
	InterpolateDiscrete
} from '../constants.js';
import { CubicInterpolant } from '../math/interpolants/CubicInterpolant.js';
import { LinearInterpolant } from '../math/interpolants/LinearInterpolant.js';
import { DiscreteInterpolant } from '../math/interpolants/DiscreteInterpolant.js';
import { AnimationUtils } from './AnimationUtils.js';

function KeyframeTrack( name, times, values, interpolation ) {

	if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' );
	if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name );

	this.name = name;

	this.times = AnimationUtils.convertArray( times, this.TimeBufferType );
	this.values = AnimationUtils.convertArray( values, this.ValueBufferType );

	this.setInterpolation( interpolation || this.DefaultInterpolation );

}

// Static methods

Object.assign( KeyframeTrack, {

	// Serialization (in static context, because of constructor invocation
	// and automatic invocation of .toJSON):

	toJSON: function ( track ) {

		const trackType = track.constructor;

		let json;

		// derived classes can define a static toJSON method
		if ( trackType.toJSON !== undefined ) {

			json = trackType.toJSON( track );

		} else {

			// by default, we assume the data can be serialized as-is
			json = {

				'name': track.name,
				'times': AnimationUtils.convertArray( track.times, Array ),
				'values': AnimationUtils.convertArray( track.values, Array )

			};

			const interpolation = track.getInterpolation();

			if ( interpolation !== track.DefaultInterpolation ) {

				json.interpolation = interpolation;

			}

		}

		json.type = track.ValueTypeName; // mandatory

		return json;

	}

} );

Object.assign( KeyframeTrack.prototype, {

	constructor: KeyframeTrack,

	TimeBufferType: Float32Array,

	ValueBufferType: Float32Array,

	DefaultInterpolation: InterpolateLinear,

	InterpolantFactoryMethodDiscrete: function ( result ) {

		return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );

	},

	InterpolantFactoryMethodLinear: function ( result ) {

		return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );

	},

	InterpolantFactoryMethodSmooth: function ( result ) {

		return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );

	},

	setInterpolation: function ( interpolation ) {

		let factoryMethod;

		switch ( interpolation ) {

			case InterpolateDiscrete:

				factoryMethod = this.InterpolantFactoryMethodDiscrete;

				break;

			case InterpolateLinear:

				factoryMethod = this.InterpolantFactoryMethodLinear;

				break;

			case InterpolateSmooth:

				factoryMethod = this.InterpolantFactoryMethodSmooth;

				break;

		}

		if ( factoryMethod === undefined ) {

			const message = 'unsupported interpolation for ' +
				this.ValueTypeName + ' keyframe track named ' + this.name;

			if ( this.createInterpolant === undefined ) {

				// fall back to default, unless the default itself is messed up
				if ( interpolation !== this.DefaultInterpolation ) {

					this.setInterpolation( this.DefaultInterpolation );

				} else {

					throw new Error( message ); // fatal, in this case

				}

			}

			console.warn( 'THREE.KeyframeTrack:', message );
			return this;

		}

		this.createInterpolant = factoryMethod;

		return this;

	},

	getInterpolation: function () {

		switch ( this.createInterpolant ) {

			case this.InterpolantFactoryMethodDiscrete:

				return InterpolateDiscrete;

			case this.InterpolantFactoryMethodLinear:

				return InterpolateLinear;

			case this.InterpolantFactoryMethodSmooth:

				return InterpolateSmooth;

		}

	},

	getValueSize: function () {

		return this.values.length / this.times.length;

	},

	// move all keyframes either forwards or backwards in time
	shift: function ( timeOffset ) {

		if ( timeOffset !== 0.0 ) {

			const times = this.times;

			for ( let i = 0, n = times.length; i !== n; ++ i ) {

				times[ i ] += timeOffset;

			}

		}

		return this;

	},

	// scale all keyframe times by a factor (useful for frame <-> seconds conversions)
	scale: function ( timeScale ) {

		if ( timeScale !== 1.0 ) {

			const times = this.times;

			for ( let i = 0, n = times.length; i !== n; ++ i ) {

				times[ i ] *= timeScale;

			}

		}

		return this;

	},

	// removes keyframes before and after animation without changing any values within the range [startTime, endTime].
	// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values
	trim: function ( startTime, endTime ) {

		const times = this.times,
			nKeys = times.length;

		let from = 0,
			to = nKeys - 1;

		while ( from !== nKeys && times[ from ] < startTime ) {

			++ from;

		}

		while ( to !== - 1 && times[ to ] > endTime ) {

			-- to;

		}

		++ to; // inclusive -> exclusive bound

		if ( from !== 0 || to !== nKeys ) {

			// empty tracks are forbidden, so keep at least one keyframe
			if ( from >= to ) {

				to = Math.max( to, 1 );
				from = to - 1;

			}

			const stride = this.getValueSize();
			this.times = AnimationUtils.arraySlice( times, from, to );
			this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );

		}

		return this;

	},

	// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
	validate: function () {

		let valid = true;

		const valueSize = this.getValueSize();
		if ( valueSize - Math.floor( valueSize ) !== 0 ) {

			console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );
			valid = false;

		}

		const times = this.times,
			values = this.values,

			nKeys = times.length;

		if ( nKeys === 0 ) {

			console.error( 'THREE.KeyframeTrack: Track is empty.', this );
			valid = false;

		}

		let prevTime = null;

		for ( let i = 0; i !== nKeys; i ++ ) {

			const currTime = times[ i ];

			if ( typeof currTime === 'number' && isNaN( currTime ) ) {

				console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );
				valid = false;
				break;

			}

			if ( prevTime !== null && prevTime > currTime ) {

				console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );
				valid = false;
				break;

			}

			prevTime = currTime;

		}

		if ( values !== undefined ) {

			if ( AnimationUtils.isTypedArray( values ) ) {

				for ( let i = 0, n = values.length; i !== n; ++ i ) {

					const value = values[ i ];

					if ( isNaN( value ) ) {

						console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );
						valid = false;
						break;

					}

				}

			}

		}

		return valid;

	},

	// removes equivalent sequential keys as common in morph target sequences
	// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)
	optimize: function () {

		// times or values may be shared with other tracks, so overwriting is unsafe
		const times = AnimationUtils.arraySlice( this.times ),
			values = AnimationUtils.arraySlice( this.values ),
			stride = this.getValueSize(),

			smoothInterpolation = this.getInterpolation() === InterpolateSmooth,

			lastIndex = times.length - 1;

		let writeIndex = 1;

		for ( let i = 1; i < lastIndex; ++ i ) {

			let keep = false;

			const time = times[ i ];
			const timeNext = times[ i + 1 ];

			// remove adjacent keyframes scheduled at the same time

			if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) {

				if ( ! smoothInterpolation ) {

					// remove unnecessary keyframes same as their neighbors

					const offset = i * stride,
						offsetP = offset - stride,
						offsetN = offset + stride;

					for ( let j = 0; j !== stride; ++ j ) {

						const value = values[ offset + j ];

						if ( value !== values[ offsetP + j ] ||
							value !== values[ offsetN + j ] ) {

							keep = true;
							break;

						}

					}

				} else {

					keep = true;

				}

			}

			// in-place compaction

			if ( keep ) {

				if ( i !== writeIndex ) {

					times[ writeIndex ] = times[ i ];

					const readOffset = i * stride,
						writeOffset = writeIndex * stride;

					for ( let j = 0; j !== stride; ++ j ) {

						values[ writeOffset + j ] = values[ readOffset + j ];

					}

				}

				++ writeIndex;

			}

		}

		// flush last keyframe (compaction looks ahead)

		if ( lastIndex > 0 ) {

			times[ writeIndex ] = times[ lastIndex ];

			for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {

				values[ writeOffset + j ] = values[ readOffset + j ];

			}

			++ writeIndex;

		}

		if ( writeIndex !== times.length ) {

			this.times = AnimationUtils.arraySlice( times, 0, writeIndex );
			this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );

		} else {

			this.times = times;
			this.values = values;

		}

		return this;

	},

	clone: function () {

		const times = AnimationUtils.arraySlice( this.times, 0 );
		const values = AnimationUtils.arraySlice( this.values, 0 );

		const TypedKeyframeTrack = this.constructor;
		const track = new TypedKeyframeTrack( this.name, times, values );

		// Interpolant argument to constructor is not saved, so copy the factory method directly.
		track.createInterpolant = this.createInterpolant;

		return track;

	}

} );

export { KeyframeTrack };
<|endoftext|>


<commit_before>describe('Add Repository Form Modal', function () {

  beforeEach(function () {
    cy
      .configureCluster({
        mesos: '1-task-healthy',
        universePackages: true
      })
      .visitUrl({url: '/system/overview/repositories'})
      .get('.page-content .button.button-success')
      .contains('Add Repository')
      .click();
  });

  it('displays modal for adding repository', function () {
    cy
      .get('.modal h2')
      .should('contain', 'Add Repository');
  });

  it('displays three fields', function () {
    cy
      .get('.modal input')
      .should('to.have.length', 3);
  });

  it('should display error if both fields aren\'t filled out', function () {
    cy
      .get('.modal .modal-footer .button.button-success')
      .contains('Add')
      .click();

    cy.get('.modal .form-help-block')
      .eq(0)
      .should('contain', 'Field cannot be empty.');

    cy.get('.modal .form-help-block')
      .eq(1)
      .should('contain', 'Must be a valid url with http:// or https://');
  });

  it('should display error if not a valid url', function () {
    cy
      .get('.modal .modal-footer .button.button-success')
      .contains('Add')
      .click();

    cy.get('.modal .form-help-block')
      .should('contain', 'Must be a valid url with http:// or https://');
  });

  it('closes modal after add is successful', function () {
    cy
      .get('.modal input')
      .eq(0).type('Here we go!');
    cy
      .get('.modal input')
      .eq(1).type('http://there-is-no-stopping.us');
    cy
      .get('.modal .modal-footer .button.button-success')
      .contains('Add')
      .click();

    cy.get('.modal').should(function ($modal) {
      expect($modal).to.not.exist;
    });

    // Clean up
    cy.clusterCleanup(function () {
      cy
        .get('.page-content')
        .contains('tr', 'Here we go!')
        .find('.button.button-link.button-danger')
        .invoke('show')
        .click({force: true});
      cy
        .get('.modal .modal-footer .button.button-danger')
        .contains('Remove Repository')
        .click();
    });
  });

  xit('displays error in modal after add causes an error', function () {
    // We need to add a fixture for this test to pass.
    cy
      .get('tr .text-overflow-break-word')
      .then(function ($urlField) {
        var url = $urlField[0].textContent;
        cy
          .get('.modal input')
          .eq(0).type('Here we go!')
          .get('.modal input')
          .eq(1).type(url);
        cy
          .get('.modal .modal-footer .button.button-success')
          .contains('Add')
          .click();

        cy
          .get('.modal h4.text-danger')
          .should('contain', url);
      });
  });

  // TODO: Turn into unit test
  xit('displays generic error in modal if no message is provided', function () {
    cy
      .route({
        method: 'POST',
        url: /repository\/add/,
        status: 400,
        response: {}
      })
      .get('.modal input')
      .eq(0).type('Here we go!');
    cy
      .get('.modal input')
      .eq(1).type('http://there-is-no-stopping.us');
    cy
      .get('.modal .modal-footer .button.button-success')
      .contains('Add')
      .click();

    cy
      .get('.modal h4.text-danger')
      .should('contain', 'An error has occurred');
  });

});
<commit_msg>Fixing modal requirement in integration test<commit_after>describe('Add Repository Form Modal', function () {

  beforeEach(function () {
    cy
      .configureCluster({
        mesos: '1-task-healthy',
        universePackages: true
      })
      .visitUrl({url: '/system/overview/repositories'})
      .get('.page-content .button.button-success')
      .contains('Add Repository')
      .click();
  });

  it('displays modal for adding repository', function () {
    cy
      .get('.modal h2')
      .should('contain', 'Add Repository');
  });

  it('displays three fields', function () {
    cy
      .get('.modal input')
      .should('to.have.length', 3);
  });

  it('should display error if both fields aren\'t filled out', function () {
    cy
      .get('.modal .modal-footer .button.button-success')
      .contains('Add')
      .click();

    cy.get('.modal .form-help-block')
      .eq(0)
      .should('contain', 'Field cannot be empty.');

    cy.get('.modal .form-help-block')
      .eq(1)
      .should('contain', 'Must be a valid url with http:// or https://');
  });

  it('should display error if not a valid url', function () {
    cy
      .get('.modal .modal-footer .button.button-success')
      .contains('Add')
      .click();

    cy.get('.modal .form-help-block')
      .should('contain', 'Must be a valid url with http:// or https://');
  });

  it('closes modal after add is successful', function () {
    cy
      .get('.modal input')
      .eq(0).type('Here we go!')
      .get('.modal input')
      .eq(1).type('http://there-is-no-stopping.us')
      .get('.modal input')
      .eq(2).type('0')
      .get('.modal .modal-footer .button.button-success')
      .contains('Add')
      .click();

    cy.get('.modal').should(function ($modal) {
      expect($modal).to.not.exist;
    });

    // Clean up
    cy.clusterCleanup(function () {
      cy
        .get('.page-content')
        .contains('tr', 'Here we go!')
        .find('.button.button-link.button-danger')
        .invoke('show')
        .click({force: true});
      cy
        .get('.modal .modal-footer .button.button-danger')
        .contains('Remove Repository')
        .click();
    });
  });

  xit('displays error in modal after add causes an error', function () {
    // We need to add a fixture for this test to pass.
    cy
      .get('tr .text-overflow-break-word')
      .then(function ($urlField) {
        var url = $urlField[0].textContent;
        cy
          .get('.modal input')
          .eq(0).type('Here we go!')
          .get('.modal input')
          .eq(1).type(url);
        cy
          .get('.modal .modal-footer .button.button-success')
          .contains('Add')
          .click();

        cy
          .get('.modal h4.text-danger')
          .should('contain', url);
      });
  });

  // TODO: Turn into unit test
  xit('displays generic error in modal if no message is provided', function () {
    cy
      .route({
        method: 'POST',
        url: /repository\/add/,
        status: 400,
        response: {}
      })
      .get('.modal input')
      .eq(0).type('Here we go!');
    cy
      .get('.modal input')
      .eq(1).type('http://there-is-no-stopping.us');
    cy
      .get('.modal .modal-footer .button.button-success')
      .contains('Add')
      .click();

    cy
      .get('.modal h4.text-danger')
      .should('contain', 'An error has occurred');
  });

});
<|endoftext|>


<commit_before>/**
 *
 * Displays the list of users of your app.
 *
 * Access to this component is limited to the administrators, you will need to be logged in to your admin on hullapp.io to access data.
 *
 * @name Users List
 * @template {users}     Displays the list of the users.
 * @template {forbidden} A message to be displayed when the credentials don't allow access to the data
 * @datasource {users} The list of users (Only readable by admins)
 * @example

 */

Hull.component({
  type: 'Hull',

  templates: ['users_list'],

  renderError: function(err) {
    if (err.message.status === 401) {
      this.html('You are not authorized to list users');
    }
  },

  datasources: {
    users: 'users'
  },

  initialize: function() {
    this.query = {};
    this.currentQuery = {};
  },

  beforeRender: function(data){
    var datasource = this.datasources.users;

    data.showPagination = datasource.isPaginable();
    data.showNextButton = !datasource.isLast();
    data.showPreviousButton = !datasource.isFirst();

    data.currentQuery = this.currentQuery;

    data.filters = {
      All: { action: 'resetFilter', isActive: this.query.approved == null },
      Approved: { action: 'filterApproved', isActive: this.query.approved === true },
      Unapproved: { action: 'filterUnapproved', isActive: this.query.approved === false }
    };
  },

  afterRender: function() {
    var $searchForm = this.$('.js-hull-users-search');
    $searchForm.on('submit', this.sandbox.util._.bind(function(e) {
      e.preventDefault();
      this.search($searchForm.find('.js-hull-users-search-query').val());
    }, this));
  },

  actions: {
    nextPage: function() {
      var datasource = this.datasources.users;
      if (!datasource.isLast()) {
        datasource.next();
        this.render();
      }
    },

    previousPage: function() {
      var datasource = this.datasources.users;
      if (!datasource.isFirst()) {
        datasource.previous();
        this.render();
      }
    },

    selectUser: function(event, action) {
      this.sandbox.emit('hull.user.select', action.data.id);
    },

    sort: function(event, action) {
      this.sort(action.data.field, action.data.direction);
    },

    resetSearch: function() {
      delete this.query.email;
      this.filter();
    },

    resetFilter: function() {
      delete this.query.approved;
      this.filter();
    },

    filterApproved: function() {
      this.query.approved = true;
      this.filter();
    },

    filterUnapproved: function() {
      this.query.approved = false;
      this.filter();
    }
  },

  sort: function(field, direction) {
    this.datasources.users.sort(field, direction);
    this.render();
  },

  filter: function() {
    if(this.queryHasChanged()) {
      this.datasources.users.where(this.query);
      this.render();

      this.currentQuery = this.sandbox.util._.clone(this.query);
    }
  },

  queryHasChanged: function() {
    var _ = this.sandbox.util._;

    if (_.isEmpty(this.query) && _.isEmpty(this.currentQuery)) { return false; }
    if (_.size(this.query) !== _.size(this.currentQuery)) { return true; }

    return !this.sandbox.util._.every(this.query, function(v, k) {
      return this.currentQuery[k] === v;
    }, this);
  },

  search: function(email) {
    var query;
    if (!this.sandbox.util._.string.isBlank(email)) {
      this.query.email = email;
    } else {
      delete this.query.email;
    }

    this.filter();
  }
});
<commit_msg>Refreshes when the user changes<commit_after>/**
 *
 * Displays the list of users of your app.
 *
 * Access to this component is limited to the administrators, you will need to be logged in to your admin on hullapp.io to access data.
 *
 * @name Users List
 * @template {users}     Displays the list of the users.
 * @template {forbidden} A message to be displayed when the credentials don't allow access to the data
 * @datasource {users} The list of users (Only readable by admins)
 * @example

 */

Hull.component({
  type: 'Hull',

  templates: ['users_list'],

  refreshEvents: ['model.hull.me.change'],

  renderError: function(err) {
    if (err.message.status === 401) {
      this.html('You are not authorized to list users');
    }
  },

  datasources: {
    users: 'users'
  },

  initialize: function() {
    this.query = {};
    this.currentQuery = {};
  },

  beforeRender: function(data){
    var datasource = this.datasources.users;

    data.showPagination = datasource.isPaginable();
    data.showNextButton = !datasource.isLast();
    data.showPreviousButton = !datasource.isFirst();

    data.currentQuery = this.currentQuery;

    data.filters = {
      All: { action: 'resetFilter', isActive: this.query.approved == null },
      Approved: { action: 'filterApproved', isActive: this.query.approved === true },
      Unapproved: { action: 'filterUnapproved', isActive: this.query.approved === false }
    };
  },

  afterRender: function() {
    var $searchForm = this.$('.js-hull-users-search');
    $searchForm.on('submit', this.sandbox.util._.bind(function(e) {
      e.preventDefault();
      this.search($searchForm.find('.js-hull-users-search-query').val());
    }, this));
  },

  actions: {
    nextPage: function() {
      var datasource = this.datasources.users;
      if (!datasource.isLast()) {
        datasource.next();
        this.render();
      }
    },

    previousPage: function() {
      var datasource = this.datasources.users;
      if (!datasource.isFirst()) {
        datasource.previous();
        this.render();
      }
    },

    selectUser: function(event, action) {
      this.sandbox.emit('hull.user.select', action.data.id);
    },

    sort: function(event, action) {
      this.sort(action.data.field, action.data.direction);
    },

    resetSearch: function() {
      delete this.query.email;
      this.filter();
    },

    resetFilter: function() {
      delete this.query.approved;
      this.filter();
    },

    filterApproved: function() {
      this.query.approved = true;
      this.filter();
    },

    filterUnapproved: function() {
      this.query.approved = false;
      this.filter();
    }
  },

  sort: function(field, direction) {
    this.datasources.users.sort(field, direction);
    this.render();
  },

  filter: function() {
    if(this.queryHasChanged()) {
      this.datasources.users.where(this.query);
      this.render();

      this.currentQuery = this.sandbox.util._.clone(this.query);
    }
  },

  queryHasChanged: function() {
    var _ = this.sandbox.util._;

    if (_.isEmpty(this.query) && _.isEmpty(this.currentQuery)) { return false; }
    if (_.size(this.query) !== _.size(this.currentQuery)) { return true; }

    return !this.sandbox.util._.every(this.query, function(v, k) {
      return this.currentQuery[k] === v;
    }, this);
  },

  search: function(email) {
    var query;
    if (!this.sandbox.util._.string.isBlank(email)) {
      this.query.email = email;
    } else {
      delete this.query.email;
    }

    this.filter();
  }
});
<|endoftext|>