<commit_before> /* *** GOAL: TURN USER'S INPUT INTO OUTPUT ***
 * set variable for entrie form
 * set variable for each element that will return data inside of form
 * wrtie function for each element? that will log the form?
 * add event listener?
 **/

// var form = document.getElementsByClassName('.cbp-mc-form');
// console.log(form);
var inputIds = document.querySelectorAll('input'); // create array of all id's in input tag
for (i > 0; i < inputIds.length; i++){
  inputsId[i].addEventListener('input', function(){
    for (i > 0; inputIds.length; i++){
      console.log(inputIds[i].value);
    }
  });
}

// console.log(data.value);
// fName.addEventListener('input', data);
//
// function data (){ //fuction to loop through array `inputIds` and return output
//
// }
<commit_msg>trying to add click listener to submit button<commit_after> /* *** GOAL: TURN USER'S INPUT INTO OUTPUT ***
 * set variable for entrie form
 * set variable for each element that will return data inside of form
 * wrtie function for each element? that will log the form?
 * add event listener?
 **/

// var form = document.getElementsByClassName('.cbp-mc-form');
// console.log(form);

var inputIds = document.querySelectorAll('input'); // create array of all id's in input tag
console.log(inputIds);
var sendData = document.querySelector(".cbp-mc-submit"); // targets `send your data button`

for (var i = 0; i < inputIds.length; i++){
  inputsId[i].addEventListener('input', function(){
    for (i > 0; inputIds.length; i++){
      output = inputsId[i].element.value;
      console.log(output);
    }
  });
}

//
// function data (){
//   for (var i = 0; i < inputIds.length; i++){
//     inputIds[i].addEventListener('input', data);
//     output = inputIds[i].value;
//     console.log(output);
//   }
// }

//POSSIBLE FOR LOOP STRUCTURE-
// for (var i = 0; i < inputIds.length; i++){
//   inputsId[i].addEventListener('input', function(){
//     for (i > 0; inputIds.length; i++){
//       output = inputsId[i].element.value;
//       console.log(output);
//     }
//   });
// }

//MAYBE USE THIS STUFF?
// console.log(data.value);
// fName.addEventListener('input', data);
//
// function data (){ //fuction to loop through array `inputIds` and return output
//
// }
<|endoftext|>


<commit_before>
// For this challenge, you'll focus on the JavaScript that would take a user's input and
// turn it into output. You need to find a way to capture input from the form. You then
// want to output that input to the console using console.log.
//
// This is a tough problem, so tackle it as a group, practicing breaking down baby steps.
// Youll need the Event reference on MDN to find the correct event to listen for and how to
// make it do your bidding (instead of its default behavior).
//
// When turning in this assignment, make sure you put your scripts.js code in the repo,
// but also put the result of the output as a comment in your WIP Issue. Just for good
// measure, drop a few of those comments and be sure to use code fences!
// -------------------------------------------------------------------------------------

// need to grab input from input boxes and selections from the drop down menus and
// print them to the console when the "send your data" button at the bottom is pushed.
//
// will start with getting it to work on one input field then refactor for the whole page.

// setup an even listener that grabs the input from the "first name" box and log it
// to the console.
var firstName = document.getElementById("first_name"); // gets the first name input box
var lastName = document.getElementById("last_name"); //gets the last name input box
var email = document.getElementById("email"); //gets the email input box
var country = document.getElementById("country"); //yep...gets the counrty input box
var bio = document.getElementById("bio");//i'm seeing a pattern here

//setup event listeners for the input boxes to grab the inputs
firstName.addEventListener('change', function(){
  console.log("changed the first name");  //tracer bullet yo
  console.log("first name: ",firstName.value); //tracer bullet...thank you Google
});

lastName.addEventListener('change', function(){
  console.log("changed the last name");  //tracer bullet
  console.log("last name: ",lastName.value); //tracer bullet
});

email.addEventListener('change', function(){
  console.log("changed the email box"); // pew pew
  console.log("email address: ",email.value); //more tracers
});

country.addEventListener('change', function(){
  console.log("selected the country");
  console.log("country: ", country.value);
})

bio.addEventListener('change', function(){
  console.log("changed the bio box");
  console.log("biography: ", bio.value);
});

// var submitButton = document.querySelector(".cbp-mc-submit");
//
// submitButton.addEventListener('click', function(){
//   console.log("clicking the submit button")
// });
<commit_msg>logs first name to console on submit<commit_after>
// For this challenge, you'll focus on the JavaScript that would take a user's input and
// turn it into output. You need to find a way to capture input from the form. You then
// want to output that input to the console using console.log.
//
// This is a tough problem, so tackle it as a group, practicing breaking down baby steps.
// Youll need the Event reference on MDN to find the correct event to listen for and how to
// make it do your bidding (instead of its default behavior).
//
// When turning in this assignment, make sure you put your scripts.js code in the repo,
// but also put the result of the output as a comment in your WIP Issue. Just for good
// measure, drop a few of those comments and be sure to use code fences!
// -------------------------------------------------------------------------------------

// need to grab input from input boxes and selections from the drop down menus and
// print them to the console when the "send your data" button at the bottom is pushed.
//
// will start with getting it to work on one input field then refactor for the whole page.

// setup an even listener that grabs the input from the "first name" box and log it
// to the console.
var firstName = document.getElementById("first_name"); // gets the first name input box
var lastName = document.getElementById("last_name"); //gets the last name input box
var email = document.getElementById("email"); //gets the email input box
var country = document.getElementById("country"); //yep...gets the counrty input box
var bio = document.getElementById("bio");//i'm seeing a pattern here

//this pattern seems to be working but i want dump the inputs to the console when
//i click submit, not after each input -- my evil plan is to write the value of each
//input to a variable when that box/selection is changed. when the submit button is clicked
//i'll console.log all of the input and try to make it look pretty

//variables to capture the input of each field.
//i'll make them default to "no input given" or something similiar
var firstNameInput = "no input given"; //place holder for firs name value

//setup event listeners for the input boxes to grab the inputs
firstName.addEventListener('change', function(){
  //console.log("changed the first name");  //tracer bullet, yo!
  //console.log("first name: ",firstName.value); //tracer bullet...thank you Google
  firstNameInput = firstName.value;
  console.log("tracer", firstNameInput); //tracer bullet
});

// lastName.addEventListener('change', function(){
//   console.log("changed the last name");  //tracer bullet
//   console.log("last name: ",lastName.value); //tracer bullet
// });
//
// email.addEventListener('change', function(){
//   console.log("changed the email box"); // pew pew
//   console.log("email address: ",email.value); //more tracers
// });
//
// country.addEventListener('change', function(){
//   console.log("selected the country");
//   console.log("country: ", country.value);
// })
//
// bio.addEventListener('change', function(){
//   console.log("changed the bio box");
//   console.log("biography: ", bio.value);
// });

var submitButton = document.querySelector(".cbp-mc-submit");

submitButton.addEventListener('click', function(){
  console.log("clicking the submit button") // tracerbullet
  console.log(firstNameInput);
  console.log(firstName.value);
});
<|endoftext|>


<commit_before>
define(['gotoEasy'], function($easy) {

	return function(){

		// 定义数据
		var data = {
			details: [{ id: 1, name: '电风扇', price: 200, count: 2 },
					{ id: 2, name: '剃须刀', price: 198, count: 1 },
					{ id: 3, name: '电视', price: 2000, count: 3 },
					{ id: 4, name: '鼠标', price: 100, count: 1 },
					{ id: 5, name: '电吹风', price: 199, count: 1 }
				],

			fns : {
				push : function (){
					var ary = data.details;
					ary.push({id:new Date()-1, price:999, count:0});
				}
				,pop : function (){
					data.details.pop();
				}
				,shift : function (){
					data.details.shift();
				}
				,unshift : function (){
					data.details.unshift({id:new Date()-1,name:'unshift???1',price:90,count:1}
									, {id:new Date()-1,name:'unshift???2',price:90,count:1});
				}
				,reverse : function (){
					data.details.reverse();
				}
				,copyAdd : function ($data){
					var ary = data.details;
					ary.push({id:new Date()-1, name:$data.name, price:$data.price, count:$data.count});
				}
				,del : function ($data){
					if (confirm("确认要删除编号为 " + $data.id + " 的数据吗？")){
						var ary = data.details;
						ary.splice(ary.indexOf($data), 1);
					}
				}
				,sortByPrice : function (){
					var ary = data.details;
					ary.sort(function (o1,o2){
								return  o1.price > o2.price ? 1 : (o1.price == o2.price ? 0:-1); // 升序
							});
				}
			},

			fnSubmit: function() {
				alert(JSON.stringify(data, null, '  '));
			}
		};

		// 绑定数据（按自定义配置进行绑定）
		$easy.bind(data, '', {
			domAttrBind : 'bind-key-as-you-like',
			bindRefData : '$this',
			bindKeyValue : 'v',
			bindKeyInnerText : 't',
			bindKeyInnerHtml : 'h',
			bindKeyClick : 'clk',
			bindKeyForeach : 'loop',
			bindKeyChecked : 'chk',
		});

		/*$easy.on('datachange', function(data, key, value){
			if (key == 'selectAll'){
				var checkeVal = data['selectAll']? '1':'0';
				var ary = data.details;
				for (var i=0; i<ary.length; i++){
					$easy.set(ary[i], 'checked', checkeVal);
				}
			}
		});*/
	};

});
<commit_msg>Update demo-customize.js<commit_after>
define(['gotoEasy'], function($easy) {

	return function(){

		// 定义数据
		var data = {
			details: [{ id: 1, name: '电风扇', price: 200, count: 2 },
					{ id: 2, name: '剃须刀', price: 198, count: 1 },
					{ id: 3, name: '电视', price: 2000, count: 3 },
					{ id: 4, name: '鼠标', price: 100, count: 1 },
					{ id: 5, name: '电吹风', price: 199, count: 1 }
				],

			fns : {
				push : function (){
					var ary = data.details;
					ary.push({id:new Date()-1, price:999, count:0});
				}
				,pop : function (){
					data.details.pop();
				}
				,shift : function (){
					data.details.shift();
				}
				,unshift : function (){
					data.details.unshift({id:new Date()-1,name:'unshift???1',price:90,count:1}
									, {id:new Date()-1,name:'unshift???2',price:90,count:1});
				}
				,reverse : function (){
					data.details.reverse();
				}
				,copyAdd : function ($data){
					var ary = data.details;
					ary.push({id:new Date()-1, name:$data.name, price:$data.price, count:$data.count});
				}
				,del : function ($data){
					if (confirm("确认要删除编号为 " + $data.id + " 的数据吗？")){
						var ary = data.details;
						ary.splice(ary.indexOf($data), 1);
					}
				}
				,sortByPrice : function (){
					var ary = data.details;
					ary.sort(function (o1,o2){
								return  o1.price > o2.price ? 1 : (o1.price == o2.price ? 0:-1); // 升序
							});
				}
			},

			fnSubmit: function() {
				alert(JSON.stringify(data, null, '  '));
			}
		};

		// 绑定数据（按自定义配置进行绑定）
		$easy.bind(data, '', {
			domAttrBind : 'bind-key-as-you-like',
			bindRefData : '$this',
			bindKeyValue : 'v',
			bindKeyInnerText : 't',
			bindKeyInnerHtml : 'h',
			bindKeyClick : 'clk',
			bindKeyForeach : 'loop',
			bindKeyChecked : 'chk',
		});

	};

});
<|endoftext|>


<commit_before>'use strict';

/*
 * Ugh, this is a mess. Known broken thing that's a pain to fix with the current
 * design: collision events may trigger twice for a given collision.
 */

var compo = require('compo'),
    Tile = require('./tile'),
    CollisionGrid = require('./grid'),
    Collidable = require('./collidable'),
    Point = require('../data/point'),
    Rect = require('../data/rect');

var X_AXIS = 'x',
    X_DIMENSION = 'width',
    Y_AXIS = 'y',
    Y_DIMENSION = 'height';

var TilePhysics = compo.extend(compo.System, function() {
  this.tiles = null;
  this.grids = null;
  this._typedColliders = {};
});

TilePhysics.prototype.onAttach = function(db) {
  this.tiles = db.table();
  this.grids = db.table();
};

TilePhysics.prototype.onDetach = function(db) {
  db.drop(this.tiles);
  db.drop(this.grids);
};

TilePhysics.prototype.restrictCollisions = function(type, types) {
  this._typedColliders[type] = types;
};

TilePhysics.prototype.update = function(delta) {
  var i, l,
      tiles = this.tiles.getAttached(),
      grids = this.grids.getAttached();

  for(i = 0, l = tiles.length; i < l; i++) {
    if(tiles[i]) {
      attemptMove(delta, tiles[i], tiles, grids, this._typedColliders);
    }
  }
};

function attemptMove(delta, tile, tiles, grids, typedColliders) {
  if(tile.immovable) return;
  attemptX(delta, tile, tiles, grids, typedColliders);
  attemptY(delta, tile, tiles, grids, typedColliders);
}

// Don't reallocate this constantly
var savedMovementHitbox = new Rect;
function attemptX(delta, component, components, grids, typedColliders) {
  var collider,
      v = absClamp(component.velocity.x, component.maxVelocity.x),
      h = component.collidable.hitbox,
      loc = component.collidable.loc,
      deltaSeconds = delta / 1000,
      absMove = Math.abs(v * deltaSeconds),
      positive = v > 0,
      xDir = positive ? 1 : (v === 0 ? 0 : -1),
      // left edge of a hitbox the size of the movement area
      startingEdge = positive ? h.x + h.width : h.x - absMove;

  if(!component.collidable.active) {
    resolveX(xDir, delta, component, null);
    return;
  }

  // hitbox the size of the movement area
  overwriteHitbox(savedMovementHitbox, h.x, h.y, h.width, h.height);
  savedMovementHitbox.x = startingEdge;
  savedMovementHitbox.width = absMove;
  copyOffsetHitbox(savedMovementHitbox, savedMovementHitbox, loc);

  collider = collideAlongX(
    component, savedMovementHitbox, components, grids, xDir, typedColliders
  );
  resolveX(xDir, delta, component, collider);
}

function resolveX(dir, delta, component, collidable) {
  var max, notAccelerating, noGravity, hasVelocity, cL, cH,
      v = component.velocity,
      h = component.collidable.hitbox,
      a = component.acceleration,
      d = component.drag,
      g = component.gravity,
      m = component.maxVelocity,
      loc = component.collidable.loc,
      deltaSeconds = delta / 1000,
      max = m.x * deltaSeconds,
      movement = absClamp(v.x, m.x) * deltaSeconds,
      aDir = a.x > 0 ? 1 : (a.x < 0 ? -1 : 0);

  // No collider? Cool, move freely.
  if(!collidable) {
    loc.x += absClamp(movement, max);
    v.x = absClamp(
      v.x + (a.x * deltaSeconds) + (g.x * deltaSeconds),
      m.x
    );
    notAccelerating = (aDir === 0 || (aDir !== dir && dir !== 0));
    noGravity = g.x === 0;
    hasVelocity = v.x !== 0;
    if(notAccelerating && noGravity && hasVelocity) {
      v.x -= dir * d.x * deltaSeconds;
      if(dir === 1 && v.x < 0) v.x = 0;
      if(dir !== 1 && v.x > 0) v.x = 0;
    }
  } else {
    // Resolve the collision.
    cL = collidable.loc;
    cH = collidable.hitbox;
    if(dir === 1) {
      loc.x = cL.x + cH.x - h.width - h.x;
      component.emitter.trigger('collide:right', collidable);
      component.emitter.trigger('collide', collidable);
      collidable.emitter.trigger('collide:left', component.collidable);
      collidable.emitter.trigger('collide', component.collidable);
    } else {
      loc.x = cL.x + cH.x + cH.width - h.x;
      component.emitter.trigger('collide:left', collidable);
      component.emitter.trigger('collide', collidable);
      collidable.emitter.trigger('collide:right', component.collidable);
      collidable.emitter.trigger('collide', component.collidable);
    }
    v.x = 0;
  }
}

function attemptY(delta, component, components, grids, typedColliders) {
  var collider,
      v = absClamp(component.velocity.y, component.maxVelocity.y),
      h = component.collidable.hitbox,
      loc = component.collidable.loc,
      deltaSeconds = delta / 1000,
      absMove = Math.abs(v * deltaSeconds),
      positive = v > 0,
      dir = positive ? 1 : (v === 0 ? 0 : -1),
      // left edge of a hitbox the size of the movement area
      startingEdge = positive ? h.y + h.height : h.y - absMove;

  if(!component.collidable.active) {
    resolveY(dir, delta, component, null);
    return;
  }

  // hitbox the size of the movement area
  overwriteHitbox(savedMovementHitbox, h.x, h.y, h.width, h.height);
  savedMovementHitbox.y = startingEdge;
  savedMovementHitbox.height = absMove;
  copyOffsetHitbox(savedMovementHitbox, savedMovementHitbox, loc);

  collider = collideAlongY(
    component, savedMovementHitbox, components, grids, dir, typedColliders
  );
  resolveY(dir, delta, component, collider);
}

function resolveY(dir, delta, component, collidable) {
  var max, notAccelerating, noGravity, hasVelocity, cL, cH,
      v = component.velocity,
      h = component.collidable.hitbox,
      a = component.acceleration,
      d = component.drag,
      g = component.gravity,
      m = component.maxVelocity,
      loc = component.collidable.loc,
      deltaSeconds = delta / 1000,
      max = m.y * deltaSeconds,
      movement = absClamp(v.y, m.y) * deltaSeconds,
      aDir = a.y > 0 ? 1 : (a.y < 0 ? -1 : 0);

  // No collider? Cool, move freely.
  if(!collidable) {
    loc.y += absClamp(movement, max);
    v.y = absClamp(
      v.y + (a.y * deltaSeconds) + (g.y * deltaSeconds),
      m.y
    );
    notAccelerating = (aDir === 0 || (aDir !== dir && dir !== 0));
    noGravity = g.y === 0;
    hasVelocity = v.y !== 0;
    if(notAccelerating && noGravity && hasVelocity) {
      v.y -= dir * d.y * deltaSeconds;
      if(dir === 1 && v.y < 0) v.y = 0;
      if(dir !== 1 && v.y > 0) v.y = 0;
    }
  } else {
    // Resolve the collision.
    cL = collidable.loc;
    cH = collidable.hitbox;
    if(dir === 1) {
      loc.y = cL.y + cH.y - h.height - h.y;
      component.emitter.trigger('collide:bottom', collidable);
      component.emitter.trigger('collide', collidable);
      collidable.emitter.trigger('collide:top', component.collidable);
      collidable.emitter.trigger('collide', component.collidable);
    } else {
      loc.y = cL.y + cH.y + cH.height - h.y;
      component.emitter.trigger('collide:top', collidable);
      component.emitter.trigger('collide', collidable);
      collidable.emitter.trigger('collide:bottom', component.collidable);
      collidable.emitter.trigger('collide', component.collidable);
    }
    v.y = 0;
  }
}

function absClamp(val, max) {
  if(val > max) return max;
  if(val < -max) return -max;
  return val;
}

/*
 * Given a component, hitbox, set of components, a set of
 * grids, and a collision direction, returns the closests `Collidable` from
 * the set of components or grids that overlaps the given component.
 *
 * Oof. This thing could be refactored.
 */
function collideAlongX(component, hitbox, components, grids, dir, typedColliders) {
  var i, l, curr, minDistance, currDistance, startingEdge,
      min = null,
      colliders = collide(component, hitbox, components, grids, typedColliders);

  if(colliders.length === 0) return null;

  for(i = 0, l = colliders.length; i < l; i++) {
    curr = colliders[i];
    if(!curr || !curr.active) continue;

    if(dir < 0) startingEdge = hitbox.x;
    else startingEdge = hitbox.x + hitbox.width;

    currDistance = directionalDistance(
      startingEdge,
      curr.hitbox.x + curr.loc.x,
      curr.hitbox.width,
      dir
    );

    if(min === null || currDistance < minDistance) {
      min = curr;
      minDistance = currDistance;
    }
  }

  return min;
}

function collideAlongY(component, hitbox, components, grids, dir, typedColliders) {
  var i, l, curr, minDistance, currDistance, startingEdge,
      min = null,
      colliders = collide(component, hitbox, components, grids, typedColliders);

  if(colliders.length === 0) return null;

  for(i = 0, l = colliders.length; i < l; i++) {
    curr = colliders[i];
    if(!curr || !curr.active) continue;

    if(dir < 0) startingEdge = hitbox.y;
    else startingEdge = hitbox.y + hitbox.height;

    currDistance = directionalDistance(
      startingEdge,
      curr.hitbox.y + curr.loc.y,
      curr.hitbox.height,
      dir
    );

    if(min === null || currDistance < minDistance) {
      min = curr;
      minDistance = currDistance;
    }
  }

  return min;
}

/*
 * Given a component, a movement hitbox, a set of components, and a set of
 * grids, returns the subset of collidables that collide with the given
 * component.
 */
var computedHitbox = new Rect;
function collide(component, movementHitbox, components, grids, typedColliders) {
  var i, l, curr, collidable, grid, gridCollisions, g, gL,
      collidables = [];

  if(movementHitbox.width === 0 || movementHitbox.height === 0) {
    return collidables;
  }

  for(i = 0, l = components.length; i < l; i++) {
    curr = components[i];
    if(!curr) continue;

    collidable = curr.collidable;
    if(!collisionAllowed(component.collidable, collidable, typedColliders)) {
      continue;
    }

    copyOffsetHitbox(computedHitbox, collidable.hitbox, collidable.loc);

    if(component !== curr && doesCollide(movementHitbox, computedHitbox)) {
      collidables.push(curr.collidable);
    }
  }

  for(i = 0, l = grids.length; i < l; i++) {
    grid = grids[i];
    if(!grid) continue;
    gridCollisions = gridCollide(movementHitbox, grid);
    for(g = 0, gL = gridCollisions.length; g < gL; g++) {
      collidable = gridCollisions[g];
      if(!collisionAllowed(component.collidable, collidable, typedColliders)) {
        continue;
      }
      collidables.push(collidable);
    }
  }

  return collidables;
}

function collisionAllowed(a, b, typedColliders) {
  return leftCollisionAllowed(a, b, typedColliders) &&
         leftCollisionAllowed(b, a, typedColliders);
}

function leftCollisionAllowed(a, b, typedColliders) {
  var types = typedColliders[a.type],
      target = b.type;
  if(!types) return true;
  for(var i = 0, l = types.length; i < l; i++) {
    if(types[i] === target) return true;
  }
  return false;
}

function overwriteHitbox(hitbox, x, y, width, height) {
  hitbox.x = x;
  hitbox.y = y;
  hitbox.width = width;
  hitbox.height = height;
}

function copyOffsetHitbox(dest, src, offset) {
  dest.x = offset.x + src.x;
  dest.y = offset.y + src.y;
  dest.width = src.width;
  dest.height = src.height;
}

function directionalDistance(a, b, offset, dir) {
  if(dir > 0) return b - a;
  return a - (b + offset);
}

// Given two hitboxes, returns true if they collide, false otherwise.
function doesCollide(a, b) {
  if(a.x + a.width <= b.x) return false;
  if(a.x >= b.x + b.width) return false;
  if(a.y + a.height <= b.y) return false;
  if(a.y >= b.y + b.height) return false;
  return true;
}

var tileHitbox = new Rect;
function gridCollide(hitbox, grid) {
  var collidables = [];
  if(!doesCollide(hitbox, grid.hitbox())) return collidables;

  var westOverlap = hitbox.x - grid.loc.x,
      northOverlap = hitbox.y - grid.loc.y,
      eastOverlap = hitbox.width + westOverlap,
      southOverlap = hitbox.height + northOverlap;

  var startingRow = (northOverlap / grid.tileSize.y) | 0,
      endingRow = (southOverlap / grid.tileSize.y) | 0,
      startingCol = (westOverlap / grid.tileSize.x) | 0,
      endingCol = (eastOverlap / grid.tileSize.x) | 0;

  if(startingRow < 0) startingRow = 0;
  if(startingCol < 0) startingCol = 0;
  if(endingRow >= grid.matrix.numRows) endingRow = grid.matrix.numRows - 1;
  if(endingCol >= grid.matrix.numCols) endingCol = grid.matrix.numCols - 1;

  for(var r = startingRow; r <= endingRow; r++) {
    for(var c = startingCol; c <= endingCol; c++) {
      var collidable = grid.collidable(r, c);
      if(collidable) {
        overwriteHitbox(
          tileHitbox,
          grid.loc.x + (c * grid.tileSize.x),
          grid.loc.y + (r *grid.tileSize.y),
          grid.tileSize.x,
          grid.tileSize.y
        );
        if(doesCollide(hitbox, tileHitbox)) collidables.push(collidable);
      }
    }
  }
  return collidables;
}

module.exports = new TilePhysics;

<commit_msg>Emit events in order of specificity.<commit_after>'use strict';

/*
 * Ugh, this is a mess. Known broken thing that's a pain to fix with the current
 * design: collision events may trigger twice for a given collision.
 */

var compo = require('compo'),
    Tile = require('./tile'),
    CollisionGrid = require('./grid'),
    Collidable = require('./collidable'),
    Point = require('../data/point'),
    Rect = require('../data/rect');

var X_AXIS = 'x',
    X_DIMENSION = 'width',
    Y_AXIS = 'y',
    Y_DIMENSION = 'height';

var TilePhysics = compo.extend(compo.System, function() {
  this.tiles = null;
  this.grids = null;
  this._typedColliders = {};
});

TilePhysics.prototype.onAttach = function(db) {
  this.tiles = db.table();
  this.grids = db.table();
};

TilePhysics.prototype.onDetach = function(db) {
  db.drop(this.tiles);
  db.drop(this.grids);
};

TilePhysics.prototype.restrictCollisions = function(type, types) {
  this._typedColliders[type] = types;
};

TilePhysics.prototype.update = function(delta) {
  var i, l,
      tiles = this.tiles.getAttached(),
      grids = this.grids.getAttached();

  for(i = 0, l = tiles.length; i < l; i++) {
    if(tiles[i]) {
      attemptMove(delta, tiles[i], tiles, grids, this._typedColliders);
    }
  }
};

function attemptMove(delta, tile, tiles, grids, typedColliders) {
  if(tile.immovable) return;
  attemptX(delta, tile, tiles, grids, typedColliders);
  attemptY(delta, tile, tiles, grids, typedColliders);
}

// Don't reallocate this constantly
var savedMovementHitbox = new Rect;
function attemptX(delta, component, components, grids, typedColliders) {
  var collider,
      v = absClamp(component.velocity.x, component.maxVelocity.x),
      h = component.collidable.hitbox,
      loc = component.collidable.loc,
      deltaSeconds = delta / 1000,
      absMove = Math.abs(v * deltaSeconds),
      positive = v > 0,
      xDir = positive ? 1 : (v === 0 ? 0 : -1),
      // left edge of a hitbox the size of the movement area
      startingEdge = positive ? h.x + h.width : h.x - absMove;

  if(!component.collidable.active) {
    resolveX(xDir, delta, component, null);
    return;
  }

  // hitbox the size of the movement area
  overwriteHitbox(savedMovementHitbox, h.x, h.y, h.width, h.height);
  savedMovementHitbox.x = startingEdge;
  savedMovementHitbox.width = absMove;
  copyOffsetHitbox(savedMovementHitbox, savedMovementHitbox, loc);

  collider = collideAlongX(
    component, savedMovementHitbox, components, grids, xDir, typedColliders
  );
  resolveX(xDir, delta, component, collider);
}

function resolveX(dir, delta, component, collidable) {
  var max, notAccelerating, noGravity, hasVelocity, cL, cH,
      v = component.velocity,
      h = component.collidable.hitbox,
      a = component.acceleration,
      d = component.drag,
      g = component.gravity,
      m = component.maxVelocity,
      loc = component.collidable.loc,
      deltaSeconds = delta / 1000,
      max = m.x * deltaSeconds,
      movement = absClamp(v.x, m.x) * deltaSeconds,
      aDir = a.x > 0 ? 1 : (a.x < 0 ? -1 : 0);

  // No collider? Cool, move freely.
  if(!collidable) {
    loc.x += absClamp(movement, max);
    v.x = absClamp(
      v.x + (a.x * deltaSeconds) + (g.x * deltaSeconds),
      m.x
    );
    notAccelerating = (aDir === 0 || (aDir !== dir && dir !== 0));
    noGravity = g.x === 0;
    hasVelocity = v.x !== 0;
    if(notAccelerating && noGravity && hasVelocity) {
      v.x -= dir * d.x * deltaSeconds;
      if(dir === 1 && v.x < 0) v.x = 0;
      if(dir !== 1 && v.x > 0) v.x = 0;
    }
  } else {
    // Resolve the collision.
    cL = collidable.loc;
    cH = collidable.hitbox;
    if(dir === 1) {
      loc.x = cL.x + cH.x - h.width - h.x;
      component.emitter.trigger('collide', collidable);
      component.emitter.trigger('collide:right', collidable);
      collidable.emitter.trigger('collide', component.collidable);
      collidable.emitter.trigger('collide:left', component.collidable);
    } else {
      loc.x = cL.x + cH.x + cH.width - h.x;
      component.emitter.trigger('collide', collidable);
      component.emitter.trigger('collide:left', collidable);
      collidable.emitter.trigger('collide', component.collidable);
      collidable.emitter.trigger('collide:right', component.collidable);
    }
    v.x = 0;
  }
}

function attemptY(delta, component, components, grids, typedColliders) {
  var collider,
      v = absClamp(component.velocity.y, component.maxVelocity.y),
      h = component.collidable.hitbox,
      loc = component.collidable.loc,
      deltaSeconds = delta / 1000,
      absMove = Math.abs(v * deltaSeconds),
      positive = v > 0,
      dir = positive ? 1 : (v === 0 ? 0 : -1),
      // left edge of a hitbox the size of the movement area
      startingEdge = positive ? h.y + h.height : h.y - absMove;

  if(!component.collidable.active) {
    resolveY(dir, delta, component, null);
    return;
  }

  // hitbox the size of the movement area
  overwriteHitbox(savedMovementHitbox, h.x, h.y, h.width, h.height);
  savedMovementHitbox.y = startingEdge;
  savedMovementHitbox.height = absMove;
  copyOffsetHitbox(savedMovementHitbox, savedMovementHitbox, loc);

  collider = collideAlongY(
    component, savedMovementHitbox, components, grids, dir, typedColliders
  );
  resolveY(dir, delta, component, collider);
}

function resolveY(dir, delta, component, collidable) {
  var max, notAccelerating, noGravity, hasVelocity, cL, cH,
      v = component.velocity,
      h = component.collidable.hitbox,
      a = component.acceleration,
      d = component.drag,
      g = component.gravity,
      m = component.maxVelocity,
      loc = component.collidable.loc,
      deltaSeconds = delta / 1000,
      max = m.y * deltaSeconds,
      movement = absClamp(v.y, m.y) * deltaSeconds,
      aDir = a.y > 0 ? 1 : (a.y < 0 ? -1 : 0);

  // No collider? Cool, move freely.
  if(!collidable) {
    loc.y += absClamp(movement, max);
    v.y = absClamp(
      v.y + (a.y * deltaSeconds) + (g.y * deltaSeconds),
      m.y
    );
    notAccelerating = (aDir === 0 || (aDir !== dir && dir !== 0));
    noGravity = g.y === 0;
    hasVelocity = v.y !== 0;
    if(notAccelerating && noGravity && hasVelocity) {
      v.y -= dir * d.y * deltaSeconds;
      if(dir === 1 && v.y < 0) v.y = 0;
      if(dir !== 1 && v.y > 0) v.y = 0;
    }
  } else {
    // Resolve the collision.
    cL = collidable.loc;
    cH = collidable.hitbox;
    if(dir === 1) {
      loc.y = cL.y + cH.y - h.height - h.y;
      component.emitter.trigger('collide', collidable);
      component.emitter.trigger('collide:bottom', collidable);
      collidable.emitter.trigger('collide', component.collidable);
      collidable.emitter.trigger('collide:top', component.collidable);
    } else {
      loc.y = cL.y + cH.y + cH.height - h.y;
      component.emitter.trigger('collide', collidable);
      component.emitter.trigger('collide:top', collidable);
      collidable.emitter.trigger('collide', component.collidable);
      collidable.emitter.trigger('collide:bottom', component.collidable);
    }
    v.y = 0;
  }
}

function absClamp(val, max) {
  if(val > max) return max;
  if(val < -max) return -max;
  return val;
}

/*
 * Given a component, hitbox, set of components, a set of
 * grids, and a collision direction, returns the closests `Collidable` from
 * the set of components or grids that overlaps the given component.
 *
 * Oof. This thing could be refactored.
 */
function collideAlongX(component, hitbox, components, grids, dir, typedColliders) {
  var i, l, curr, minDistance, currDistance, startingEdge,
      min = null,
      colliders = collide(component, hitbox, components, grids, typedColliders);

  if(colliders.length === 0) return null;

  for(i = 0, l = colliders.length; i < l; i++) {
    curr = colliders[i];
    if(!curr || !curr.active) continue;

    if(dir < 0) startingEdge = hitbox.x;
    else startingEdge = hitbox.x + hitbox.width;

    currDistance = directionalDistance(
      startingEdge,
      curr.hitbox.x + curr.loc.x,
      curr.hitbox.width,
      dir
    );

    if(min === null || currDistance < minDistance) {
      min = curr;
      minDistance = currDistance;
    }
  }

  return min;
}

function collideAlongY(component, hitbox, components, grids, dir, typedColliders) {
  var i, l, curr, minDistance, currDistance, startingEdge,
      min = null,
      colliders = collide(component, hitbox, components, grids, typedColliders);

  if(colliders.length === 0) return null;

  for(i = 0, l = colliders.length; i < l; i++) {
    curr = colliders[i];
    if(!curr || !curr.active) continue;

    if(dir < 0) startingEdge = hitbox.y;
    else startingEdge = hitbox.y + hitbox.height;

    currDistance = directionalDistance(
      startingEdge,
      curr.hitbox.y + curr.loc.y,
      curr.hitbox.height,
      dir
    );

    if(min === null || currDistance < minDistance) {
      min = curr;
      minDistance = currDistance;
    }
  }

  return min;
}

/*
 * Given a component, a movement hitbox, a set of components, and a set of
 * grids, returns the subset of collidables that collide with the given
 * component.
 */
var computedHitbox = new Rect;
function collide(component, movementHitbox, components, grids, typedColliders) {
  var i, l, curr, collidable, grid, gridCollisions, g, gL,
      collidables = [];

  if(movementHitbox.width === 0 || movementHitbox.height === 0) {
    return collidables;
  }

  for(i = 0, l = components.length; i < l; i++) {
    curr = components[i];
    if(!curr) continue;

    collidable = curr.collidable;
    if(!collisionAllowed(component.collidable, collidable, typedColliders)) {
      continue;
    }

    copyOffsetHitbox(computedHitbox, collidable.hitbox, collidable.loc);

    if(component !== curr && doesCollide(movementHitbox, computedHitbox)) {
      collidables.push(curr.collidable);
    }
  }

  for(i = 0, l = grids.length; i < l; i++) {
    grid = grids[i];
    if(!grid) continue;
    gridCollisions = gridCollide(movementHitbox, grid);
    for(g = 0, gL = gridCollisions.length; g < gL; g++) {
      collidable = gridCollisions[g];
      if(!collisionAllowed(component.collidable, collidable, typedColliders)) {
        continue;
      }
      collidables.push(collidable);
    }
  }

  return collidables;
}

function collisionAllowed(a, b, typedColliders) {
  return leftCollisionAllowed(a, b, typedColliders) &&
         leftCollisionAllowed(b, a, typedColliders);
}

function leftCollisionAllowed(a, b, typedColliders) {
  var types = typedColliders[a.type],
      target = b.type;
  if(!types) return true;
  for(var i = 0, l = types.length; i < l; i++) {
    if(types[i] === target) return true;
  }
  return false;
}

function overwriteHitbox(hitbox, x, y, width, height) {
  hitbox.x = x;
  hitbox.y = y;
  hitbox.width = width;
  hitbox.height = height;
}

function copyOffsetHitbox(dest, src, offset) {
  dest.x = offset.x + src.x;
  dest.y = offset.y + src.y;
  dest.width = src.width;
  dest.height = src.height;
}

function directionalDistance(a, b, offset, dir) {
  if(dir > 0) return b - a;
  return a - (b + offset);
}

// Given two hitboxes, returns true if they collide, false otherwise.
function doesCollide(a, b) {
  if(a.x + a.width <= b.x) return false;
  if(a.x >= b.x + b.width) return false;
  if(a.y + a.height <= b.y) return false;
  if(a.y >= b.y + b.height) return false;
  return true;
}

var tileHitbox = new Rect;
function gridCollide(hitbox, grid) {
  var collidables = [];
  if(!doesCollide(hitbox, grid.hitbox())) return collidables;

  var westOverlap = hitbox.x - grid.loc.x,
      northOverlap = hitbox.y - grid.loc.y,
      eastOverlap = hitbox.width + westOverlap,
      southOverlap = hitbox.height + northOverlap;

  var startingRow = (northOverlap / grid.tileSize.y) | 0,
      endingRow = (southOverlap / grid.tileSize.y) | 0,
      startingCol = (westOverlap / grid.tileSize.x) | 0,
      endingCol = (eastOverlap / grid.tileSize.x) | 0;

  if(startingRow < 0) startingRow = 0;
  if(startingCol < 0) startingCol = 0;
  if(endingRow >= grid.matrix.numRows) endingRow = grid.matrix.numRows - 1;
  if(endingCol >= grid.matrix.numCols) endingCol = grid.matrix.numCols - 1;

  for(var r = startingRow; r <= endingRow; r++) {
    for(var c = startingCol; c <= endingCol; c++) {
      var collidable = grid.collidable(r, c);
      if(collidable) {
        overwriteHitbox(
          tileHitbox,
          grid.loc.x + (c * grid.tileSize.x),
          grid.loc.y + (r *grid.tileSize.y),
          grid.tileSize.x,
          grid.tileSize.y
        );
        if(doesCollide(hitbox, tileHitbox)) collidables.push(collidable);
      }
    }
  }
  return collidables;
}

module.exports = new TilePhysics;

<|endoftext|>


<commit_before>exports = module.exports = function(app,models){
	var async = require('async');

	var Project = models.Project;
	var Account = models.Account;
	var Status = models.Status;

	app.get('/projects',app.isLogined,function(req,res){
		var page = (!req.query.page || req.query.page < 0) ? 0 : req.query.page;
		var accountId = req.session.accountId;

		async.waterfall(
			[
				function _project(callback){
					Project.getByAccountId(accountId,page,function(data){
						callback(null,data);
					});
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.send(result);
			}
		);
	});

	app.post('/projects', app.isLogined, function(req,res){
		var	name = req.body.name;
		var description = req.body.description;
		var accountId = req.session.accountId;

		async.waterfall(
			[
				function _project(callback){
					Project.add(accountId,{
						name: name,
						description: description
					},function(err,project){
						callback(err,project);
					});
				},
				function _account(project,callback){
					Account.addProject(accountId,project._id,project.name,1,function(err){
						callback(null);
					});
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.sendStatus(200);
			}
		);
	});

	app.get('/projects/:id', app.isLogined, function(req,res){
		var id = req.params.id;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(id,function(data){
						callback(null,data);
					});
				},
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.send(result);
			}
		);
	});

	app.get('/projects/:id/contacts',app.isLogined, function(req,res){
		var page = (!req.query.page || req.query.page < 0) ? 0 : req.query.page;
		var id = req.params.id;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(id,function(project){
						if(!project){
							callback(404);
							return;
						}
						callback(null,project);
					});
				},
				function _account(project,callback){
					Account.findAll(project.contacts, page, function(accounts){
						callback(null,accounts);
					});
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.send(result);
			}
		);
	});

	app.post('/projects/:id/contacts',app.isLogined, function(req,res){
		var projectId = req.params.id || 0;
		var contactId = req.body.contactId;
		var accountId = req.session.accountId;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(projectId,function(project){
						if(!project){
							callback(404);
							return;
						}
						if(accountId != project.accountId){
							callback(401);
							return;
						}
						callback(null,project);
					});
				},
				function _contact(project,callback){
					Project.addContactById(project._id,contactId);
					callback(null,project);
				},
				function _account(project,callback){
					Account.addProject(contactId,project._id,project.name,0,function(err){
						callback(null);
					});
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.sendStatus(200);
			}
		);
	});

	app.delete('/projects/:pid/contacts/:cid', app.isLogined,function(req,res){
		var projectId = req.params.pid;
		var contactId = req.params.cid;
		if(!contactId){
			res.sendStatus(400);
			return;
		}
		var accountId = req.session.accountId;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(projectId,function(project){
						if(!project){
							callback(404);
							return;
						}
						if(accountId != project.accountId){
							callback(401);
							return;
						}
						callback(null,project);
					});
				},
				function _contact(project,callback){
					Project.removeContactById(project._id,contactId);
					callbac(null,project);
				},
				function _account(project,callback){
					Account.removeProject(accountId,project._id);

				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.sendStatus(200);
			}
		);
	});

	app.get('/projects/:id/status',app.isLogined, function(req,res){
		var page = (!req.query.page || req.query.page < 0) ? 0 : req.query.page;
		var id = req.params.id;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(id,function(project){
						if(!project){
							callback(404);
							return;
						}
						callback(null,project);
					});
				},
				function _status(project,callback){
					Status.getAllByToId(project._id,page,function(status){
						callback(null,status);
					});
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.send(result);
			}
		);
	});

	app.post('/projects/:id/status',app.isLogined, function(req,res){
		var projectId = req.params.id || 0;
		var accountId = req.session.accountId;
		var name = req.session.username || '匿名';
		var text = req.body.text || '';
		if(text.length<1){
			res.sendStatus(400);
			return;
		}

		async.waterfall(
			[
				function _project(callback){
					Project.getById(projectId,function(project){
						if(!project){
							callback(404);
							return;
						}
						if(accountId != project.accountId){
							callback(401);
							return;
						}
						callback(null,project);
					});
				},
				function _status(project,callback){
					Status.add(accountId,project._id,name,'',text);
					callback(null);
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.sendStatus(200);
			}
		);
	});

	app.delete('/projects/:id/status', app.isLogined,function(req,res){
		//TODO
		var projectId = req.params.id || 0;
		var accountId = req.session.accountId;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(projectId,function(project){
						if(!project){
							callback(404);
							return;
						}
						if(accountId != project.accountId){
							callback(401);
							return;
						}
						callback(null,project);
					});
				},
				function _status(project,callback){
					Project.removeStatusById(project._id,accountId);
					callback(null);
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.sendStatus(200);
			}
		);
	});
};<commit_msg>fix bug: demo project.<commit_after>exports = module.exports = function(app,models){
	var async = require('async');

	var Project = models.Project;
	var Account = models.Account;
	var Status = models.Status;

	app.get('/projects',app.isLogined,function(req,res){
		var page = (!req.query.page || req.query.page < 0) ? 0 : req.query.page;
		var accountId = req.session.accountId;

		async.waterfall(
			[
				function _project(callback){
					Project.getByAccountId(accountId,page,function(data){
						callback(null,data);
					});
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.send(result);
			}
		);
	});

	app.post('/projects', app.isLogined, function(req,res){
		var	name = req.body.name;
		var description = req.body.description;
		var accountId = req.session.accountId;

		async.waterfall(
			[
				function _project(callback){
					Project.add(accountId,{
						name: name,
						description: description
					},function(project){
						if(!project){
							callback(400);
							return;
						}
						callback(null,project);
					});
				},
				function _account(project,callback){
					Account.addProject(accountId,project._id,project.name,1,function(err){
						callback(null);
					});
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.sendStatus(200);
			}
		);
	});

	app.get('/projects/:id', app.isLogined, function(req,res){
		var id = req.params.id;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(id,function(data){
						callback(null,data);
					});
				},
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.send(result);
			}
		);
	});

	app.get('/projects/:id/contacts',app.isLogined, function(req,res){
		var page = (!req.query.page || req.query.page < 0) ? 0 : req.query.page;
		var id = req.params.id;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(id,function(project){
						if(!project){
							callback(404);
							return;
						}
						callback(null,project);
					});
				},
				function _account(project,callback){
					Account.findAll(project.contacts, page, function(accounts){
						callback(null,accounts);
					});
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.send(result);
			}
		);
	});

	app.post('/projects/:id/contacts',app.isLogined, function(req,res){
		var projectId = req.params.id || 0;
		var contactId = req.body.contactId;
		var accountId = req.session.accountId;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(projectId,function(project){
						if(!project){
							callback(404);
							return;
						}
						if(accountId != project.accountId){
							callback(401);
							return;
						}
						callback(null,project);
					});
				},
				function _contact(project,callback){
					Project.addContactById(project._id,contactId);
					callback(null,project);
				},
				function _account(project,callback){
					Account.addProject(contactId,project._id,project.name,0,function(err){
						callback(null);
					});
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.sendStatus(200);
			}
		);
	});

	app.delete('/projects/:pid/contacts/:cid', app.isLogined,function(req,res){
		var projectId = req.params.pid;
		var contactId = req.params.cid;
		if(!contactId){
			res.sendStatus(400);
			return;
		}
		var accountId = req.session.accountId;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(projectId,function(project){
						if(!project){
							callback(404);
							return;
						}
						if(accountId != project.accountId){
							callback(401);
							return;
						}
						callback(null,project);
					});
				},
				function _contact(project,callback){
					Project.removeContactById(project._id,contactId);
					callbac(null,project);
				},
				function _account(project,callback){
					Account.removeProject(accountId,project._id);

				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.sendStatus(200);
			}
		);
	});

	app.get('/projects/:id/status',app.isLogined, function(req,res){
		var page = (!req.query.page || req.query.page < 0) ? 0 : req.query.page;
		var id = req.params.id;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(id,function(project){
						if(!project){
							callback(404);
							return;
						}
						callback(null,project);
					});
				},
				function _status(project,callback){
					Status.getAllByToId(project._id,page,function(status){
						callback(null,status);
					});
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.send(result);
			}
		);
	});

	app.post('/projects/:id/status',app.isLogined, function(req,res){
		var projectId = req.params.id || 0;
		var accountId = req.session.accountId;
		var name = req.session.username || '匿名';
		var text = req.body.text || '';
		if(text.length<1){
			res.sendStatus(400);
			return;
		}

		async.waterfall(
			[
				function _project(callback){
					Project.getById(projectId,function(project){
						if(!project){
							callback(404);
							return;
						}
						if(accountId != project.accountId){
							callback(401);
							return;
						}
						callback(null,project);
					});
				},
				function _status(project,callback){
					Status.add(accountId,project._id,name,'',text);
					callback(null);
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.sendStatus(200);
			}
		);
	});

	app.delete('/projects/:id/status', app.isLogined,function(req,res){
		//TODO
		var projectId = req.params.id || 0;
		var accountId = req.session.accountId;

		async.waterfall(
			[
				function _project(callback){
					Project.getById(projectId,function(project){
						if(!project){
							callback(404);
							return;
						}
						if(accountId != project.accountId){
							callback(401);
							return;
						}
						callback(null,project);
					});
				},
				function _status(project,callback){
					Project.removeStatusById(project._id,accountId);
					callback(null);
				}
			],
			function _result(err,result){
				if(err){
					res.sendStatus(err);
					return;
				}
				res.sendStatus(200);
			}
		);
	});
};<|endoftext|>


<commit_before>var WelcomeCard = {
    name: 'WelcomeCard',
    dom_target: undefined,

    render_init: function() {
        if (window.user.applicant && !window.user.student) {
            WSData.fetch_applicant_data(WelcomeCard.render_upon_data(), WelcomeCard.render_error())
        } else {
            this.render_error();
        }
    },

    render_upon_data: function () {
        WelcomeCard._render();
    },

    _render: function () {
        var applicant_info = WSData.applicant_data();
        if(applicant_info.length > 0){
            WelcomeCard.render_error();
        } else {
            var student_info = {};
            var source = $("#welcome_card").html();
            var template = Handlebars.compile(source);

            WelcomeCard.dom_target.html(template(student_info));
            LogUtils.cardLoaded(WelcomeCard.name, WelcomeCard.dom_target);
        }
    },

    _has_all_data: function () {
        return true;
    },

    render_error: function () {
        $("#WelcomeCard").hide();
    }
};

/* node.js exports */
if (typeof exports === "undefined") {
    var exports = {};
}
exports.WelcomeCard = WelcomeCard;
<commit_msg>jshint<commit_after>var WelcomeCard = {
    name: 'WelcomeCard',
    dom_target: undefined,

    render_init: function() {
        if (window.user.applicant && !window.user.student) {
            WSData.fetch_applicant_data(WelcomeCard.render_upon_data(), WelcomeCard.render_error());
        } else {
            this.render_error();
        }
    },

    render_upon_data: function () {
        WelcomeCard._render();
    },

    _render: function () {
        var applicant_info = WSData.applicant_data();
        if(applicant_info.length > 0){
            WelcomeCard.render_error();
        } else {
            var student_info = {};
            var source = $("#welcome_card").html();
            var template = Handlebars.compile(source);

            WelcomeCard.dom_target.html(template(student_info));
            LogUtils.cardLoaded(WelcomeCard.name, WelcomeCard.dom_target);
        }
    },

    _has_all_data: function () {
        return true;
    },

    render_error: function () {
        $("#WelcomeCard").hide();
    }
};

/* node.js exports */
if (typeof exports === "undefined") {
    var exports = {};
}
exports.WelcomeCard = WelcomeCard;
<|endoftext|>


<commit_before>/*
 * Observing proxy
 * https://github.com/ytiurin/observingproxy
 *
 * The MIT License (MIT)
 * https://github.com/ytiurin/observingproxy/blob/master/LICENSE
 *
 * September 30, 2015
 */

'use strict';

!function(){

var tl=function(i,ln,ms){
  return function(ms,f){
    i++;
    if(f()) ln='info',ms='Test '+i+' passed: '+ms;
    else ln='error',ms='Test '+i+' failed: '+ms;
    console[ln](ms)}}(0);
var cl=function(){
  console.log.apply(console,arguments)};

var observingProxy=function(targetStack,proxyStack,changeStack,handlerStack,timeoutStack){

  function getDeepPropertyDescriptors(o)
  {
    var ns;

    if(o){
      ns=getDeepPropertyDescriptors(Object.getPrototypeOf(o))||[];
      Array.prototype.push.apply(ns,
        Object.getOwnPropertyNames(o)
          .filter(function(k){
            return isNaN(parseInt(k))})
          .map(function(k){
            return {name:k,descriptor:Object.getOwnPropertyDescriptor(o,k)}}));
    }

    return ns;
  }

  function newProxy(t)
  {
    var p={},ns=getDeepPropertyDescriptors(t);

    for(var i=ns.length;i--;){
      delete ns[i].descriptor.value;
      delete ns[i].descriptor.writable;

      ns[i].descriptor.get=propertyGetter.bind({target:t,name:ns[i].name});
      ns[i].descriptor.set=propertySetter.bind({target:t,name:ns[i].name});

      try{
        Object.defineProperty(p,ns[i].name,ns[i].descriptor);
      }
      catch(e){}
    }

    return p;
  }

  function notifyObservers(target)
  {
    var i=targetIndex(target);

    for(var l=0;l<handlerStack[i].length;l++)
      handlerStack[i][l].call(this,changeStack[i]);

    changeStack[i]=[];
  }

  function propertyGetter()
  {
    var r=this.target[this.name];

    if(Array.isArray(this.target)&&['pop','push','shift','splice','unshift'].
      indexOf(this.name)>-1)
      r=function(){
        var res=this.target[this.name].apply(this.target,arguments),
          targetInd=targetIndex(this.target);

        changeStack[targetInd].push(({
          'pop':{object:this.target,type:'splice',index:this.target.length-1,
            removed:[res],addedCount:0},
          'push':{object:this.target,type:'splice',index:this.target.length-1,
            removed:[],addedCount:1},
          'shift':{object:this.target,type:'splice',index:0,removed:[res],
            addedCount:0},
          'splice':{object:this.target,type:'splice',index:arguments[0],
            removed:res,addedCount:Array.prototype.slice.call(arguments,2).length},
          'unshift':{object:this.target,type:'splice',index:0,removed:[],
            addedCount:1}
        })[this.name]);

        clearTimeout(timeoutStack[targetInd]);
        timeoutStack[targetInd]=setTimeout(function(){
          notifyObservers(this.target)}.bind(this));
      }.bind(this);

    return r;
  }

  function propertySetter(userVal)
  {
    var val=this.target[this.name],
      targetInd=targetIndex(this.target);

    if(val!==userVal){
      this.target[this.name]=userVal;
      changeStack[targetInd].push(
        {name:this.name,object:this.target,type:'update',oldValue:val});
      clearTimeout(timeoutStack[targetInd]);
      timeoutStack[targetInd]=setTimeout(function(){
        notifyObservers(this.target)}.bind(this));
    }
  }

  function targetIndex(t)
  {
    var i=targetStack.indexOf(t);

    if(i===-1){
      i=targetStack.push(t)-1;
      proxyStack.push(newProxy(t));
      changeStack.push([]);
      handlerStack.push([]);
      timeoutStack.push(0);
    }

    return i;
  }

  function validateTarget(target)
  {
    if(!target)
      throw 'Observing proxy error: invalid target';
  }

  if(this.test_o)
    tl('getDeepPropertyDescriptors',function(){
      return getDeepPropertyDescriptors([1,2,3]).length===42});

  if(this.test_o)
    tl('Property getter',function(){
      var s={p1:1};
      return newProxy(s).p1===s.p1});

  if(this.test_o)
    tl('Property setter',function(){
      var s={p1:1};
      newProxy(s).p1=2;
      return s.p1===2});

  if(this.test_o)
    tl('Array splice',function(){
      var s=[];
      newProxy(s).push(1);
      return s.length===1});

  return {
    addChangeHandler:function(target,changeHandler,callOnInit){
      validateTarget(target);

      var targetInd=targetIndex(target);
      handlerStack[targetInd].indexOf(changeHandler)===-1&&
      handlerStack[targetInd].push(changeHandler);

      if(callOnInit){
        var changes=Object.getOwnPropertyNames(target).map(function(key){
          return {name:key,object:target,type:'update',oldValue:target[key]}
        });
        clearTimeout(timeoutStack[targetInd]);
        timeoutStack[targetInd]=setTimeout(function(){
          changeHandler.call(target,changes)});
      }
    },
    addPropertyHandler:function(target,propertyName,changeHandler,callOnInit){
      var onPropertyChange;

      this.addChangeHandler(target,onPropertyChange=function(changes){
        for(var i=changes.length;i--;)
          if(changes[i].name===propertyName){
            changeHandler.call(changes[i],changes[i].object[changes[i].name]);
            break;
          }
      },callOnInit);

      return {
        destroy:function(){
          this.removeChangeHandler(target,onPropertyChange);
        }.bind(this),
        restore:function(){
          this.addChangeHandler(target,onPropertyChange,callOnInit);
        }.bind(this)
      };
    },
    getProxy:function(target){
      validateTarget(target);

      return proxyStack[targetIndex(target)];
    },
    removeChangeHandler:function(target,changeHandler){
      validateTarget(target);

      var targetInd=targetIndex(target),rmInd;
      if((rmInd=handlerStack[targetInd].indexOf(changeHandler))>-1)
        handlerStack[targetInd].splice(rmInd,1);
      else
        handlerStack[targetInd]=[];

      clearTimeout(timeoutStack[targetInd]);
    }
  }
}.bind(this)([],[],[],[],[]);

function _o(target,changeHandler,callOnInit)
{
  if(changeHandler)
    observingProxy.addChangeHandler(target,changeHandler,callOnInit);

  return observingProxy.getProxy(target);
}

_o.observe=observingProxy.addChangeHandler;
_o.unobserve=observingProxy.removeChangeHandler;

if(typeof Object.defineProperty!=='function')
  throw 'Object.defineProperty is not a function';

if(this.module&&this.module.exports)
  this.module.exports=_o;
else if(this.define&&this.define.amd)
  this.define(function(){return _o});
else
  this._o=_o;

if(this.test_o)
  tl('getProxy',function(){
    var s={p1:1};
    return observingProxy.getProxy(s).p1===s.p1});

if(this.test_o)
  !function(){
    var u;
    var s={p1:1};
    observingProxy.addChangeHandler(s,function(changes){
      clearTimeout(u);
      tl('addChangeHandler',function(){return true});
    });
    observingProxy.getProxy(s).p1=101;
    u=setTimeout(function(){
      tl('addChangeHandler',function(){return false});
    });
  }();

if(this.test_o)
  !function(){
    var u;
    var f=function(){
      clearTimeout(u);
      tl('removeChangeHandler',function(){return false});
    };
    var s={p1:1};
    observingProxy.addChangeHandler(s,f);
    observingProxy.removeChangeHandler(s,f);
    observingProxy.getProxy(s).p1=2;
    u=setTimeout(function(){
      tl('removeChangeHandler',function(){return true});
    });
  }();

if(this.test_o)
  !function(){
    var s={p1:0},proxy=observingProxy.getProxy(s),n=0;
    observingProxy.addChangeHandler(s,function(ch){
      n++;
    });
    for(var i=10;i--;)
      proxy.p1++;
    setTimeout(function(){
      tl('Delayed notify',function(){return n===1});
    })
  }();

if(this.test_o)
  !function(){
    var u;
    var s={p1:1};
    observingProxy.addPropertyHandler(s,'p1',function(value){
      clearTimeout(u);
      tl('addPropertyHandler',function(){return value===2});
    });
    observingProxy.getProxy(s).p1=2;
    u=setTimeout(function(){
      tl('addPropertyHandler',function(){return false});
    });
  }();

if(this.test_o)
  !function(){
    var s={p1:1},proxy=observingProxy.getProxy(s),i=0;
    var observer=observingProxy.addPropertyHandler(s,'p1',function(value){
      i++;
    });

    proxy.p1=2;
    setTimeout(function(){
      observer.destroy();
      proxy.p1=3;
      setTimeout(function(){
        observer.restore();
        proxy.p1=4;
        setTimeout(function(){
          tl('addPropertyHandler destructor',function(){return i==2});
        });
      });
    });
  }();

}.bind(this)()
<commit_msg>Add addPropertyHandler alias to global object<commit_after>/*
 * Observing proxy
 * https://github.com/ytiurin/observingproxy
 *
 * The MIT License (MIT)
 * https://github.com/ytiurin/observingproxy/blob/master/LICENSE
 *
 * September 30, 2015
 */

'use strict';

!function(){

var tl=function(i,ln,ms){
  return function(ms,f){
    i++;
    if(f()) ln='info',ms='Test '+i+' passed: '+ms;
    else ln='error',ms='Test '+i+' failed: '+ms;
    console[ln](ms)}}(0);
var cl=function(){
  console.log.apply(console,arguments)};

var observingProxy=function(targetStack,proxyStack,changeStack,handlerStack,timeoutStack){

  function getDeepPropertyDescriptors(o)
  {
    var ns;

    if(o){
      ns=getDeepPropertyDescriptors(Object.getPrototypeOf(o))||[];
      Array.prototype.push.apply(ns,
        Object.getOwnPropertyNames(o)
          .filter(function(k){
            return isNaN(parseInt(k))})
          .map(function(k){
            return {name:k,descriptor:Object.getOwnPropertyDescriptor(o,k)}}));
    }

    return ns;
  }

  function newProxy(t)
  {
    var p={},ns=getDeepPropertyDescriptors(t);

    for(var i=ns.length;i--;){
      delete ns[i].descriptor.value;
      delete ns[i].descriptor.writable;

      ns[i].descriptor.get=propertyGetter.bind({target:t,name:ns[i].name});
      ns[i].descriptor.set=propertySetter.bind({target:t,name:ns[i].name});

      try{
        Object.defineProperty(p,ns[i].name,ns[i].descriptor);
      }
      catch(e){}
    }

    return p;
  }

  function notifyObservers(target)
  {
    var i=targetIndex(target);

    for(var l=0;l<handlerStack[i].length;l++)
      handlerStack[i][l].call(this,changeStack[i]);

    changeStack[i]=[];
  }

  function propertyGetter()
  {
    var r=this.target[this.name];

    if(Array.isArray(this.target)&&['pop','push','shift','splice','unshift'].
      indexOf(this.name)>-1)
      r=function(){
        var res=this.target[this.name].apply(this.target,arguments),
          targetInd=targetIndex(this.target);

        changeStack[targetInd].push(({
          'pop':{object:this.target,type:'splice',index:this.target.length-1,
            removed:[res],addedCount:0},
          'push':{object:this.target,type:'splice',index:this.target.length-1,
            removed:[],addedCount:1},
          'shift':{object:this.target,type:'splice',index:0,removed:[res],
            addedCount:0},
          'splice':{object:this.target,type:'splice',index:arguments[0],
            removed:res,addedCount:Array.prototype.slice.call(arguments,2).length},
          'unshift':{object:this.target,type:'splice',index:0,removed:[],
            addedCount:1}
        })[this.name]);

        clearTimeout(timeoutStack[targetInd]);
        timeoutStack[targetInd]=setTimeout(function(){
          notifyObservers(this.target)}.bind(this));
      }.bind(this);

    return r;
  }

  function propertySetter(userVal)
  {
    var val=this.target[this.name],
      targetInd=targetIndex(this.target);

    if(val!==userVal){
      this.target[this.name]=userVal;
      changeStack[targetInd].push(
        {name:this.name,object:this.target,type:'update',oldValue:val});
      clearTimeout(timeoutStack[targetInd]);
      timeoutStack[targetInd]=setTimeout(function(){
        notifyObservers(this.target)}.bind(this));
    }
  }

  function targetIndex(t)
  {
    var i=targetStack.indexOf(t);

    if(i===-1){
      i=targetStack.push(t)-1;
      proxyStack.push(newProxy(t));
      changeStack.push([]);
      handlerStack.push([]);
      timeoutStack.push(0);
    }

    return i;
  }

  function validateTarget(target)
  {
    if(!target)
      throw 'Observing proxy error: invalid target';
  }

  if(this.test_o)
    tl('getDeepPropertyDescriptors',function(){
      return getDeepPropertyDescriptors([1,2,3]).length===42});

  if(this.test_o)
    tl('Property getter',function(){
      var s={p1:1};
      return newProxy(s).p1===s.p1});

  if(this.test_o)
    tl('Property setter',function(){
      var s={p1:1};
      newProxy(s).p1=2;
      return s.p1===2});

  if(this.test_o)
    tl('Array splice',function(){
      var s=[];
      newProxy(s).push(1);
      return s.length===1});

  return {
    addChangeHandler:function(target,changeHandler,callOnInit){
      validateTarget(target);

      var targetInd=targetIndex(target);
      handlerStack[targetInd].indexOf(changeHandler)===-1&&
      handlerStack[targetInd].push(changeHandler);

      if(callOnInit){
        var changes=Object.getOwnPropertyNames(target).map(function(key){
          return {name:key,object:target,type:'update',oldValue:target[key]}
        });
        clearTimeout(timeoutStack[targetInd]);
        timeoutStack[targetInd]=setTimeout(function(){
          changeHandler.call(target,changes)});
      }
    },
    addPropertyHandler:function(target,propertyName,changeHandler,callOnInit){
      var onPropertyChange;

      this.addChangeHandler(target,onPropertyChange=function(changes){
        for(var i=changes.length;i--;)
          if(changes[i].name===propertyName){
            changeHandler.call(changes[i],changes[i].object[changes[i].name]);
            break;
          }
      },callOnInit);

      return {
        destroy:function(){
          this.removeChangeHandler(target,onPropertyChange);
        }.bind(this),
        restore:function(){
          this.addChangeHandler(target,onPropertyChange,callOnInit);
        }.bind(this)
      };
    },
    getProxy:function(target){
      validateTarget(target);

      return proxyStack[targetIndex(target)];
    },
    removeChangeHandler:function(target,changeHandler){
      validateTarget(target);

      var targetInd=targetIndex(target),rmInd;
      if((rmInd=handlerStack[targetInd].indexOf(changeHandler))>-1)
        handlerStack[targetInd].splice(rmInd,1);
      else
        handlerStack[targetInd]=[];

      clearTimeout(timeoutStack[targetInd]);
    }
  }
}.bind(this)([],[],[],[],[]);

function _o(target,changeHandler,callOnInit)
{
  if(changeHandler)
    observingProxy.addChangeHandler(target,changeHandler,callOnInit);

  return observingProxy.getProxy(target);
}

_o.observe=observingProxy.addChangeHandler;
_o.unobserve=observingProxy.removeChangeHandler;
_o.observeProperty=observingProxy.addPropertyHandler;

if(typeof Object.defineProperty!=='function')
  throw 'Object.defineProperty is not a function';

if(this.module&&this.module.exports)
  this.module.exports=_o;
else if(this.define&&this.define.amd)
  this.define(function(){return _o});
else
  this._o=_o;

if(this.test_o)
  tl('getProxy',function(){
    var s={p1:1};
    return observingProxy.getProxy(s).p1===s.p1});

if(this.test_o)
  !function(){
    var u;
    var s={p1:1};
    observingProxy.addChangeHandler(s,function(changes){
      clearTimeout(u);
      tl('addChangeHandler',function(){return true});
    });
    observingProxy.getProxy(s).p1=101;
    u=setTimeout(function(){
      tl('addChangeHandler',function(){return false});
    });
  }();

if(this.test_o)
  !function(){
    var u;
    var f=function(){
      clearTimeout(u);
      tl('removeChangeHandler',function(){return false});
    };
    var s={p1:1};
    observingProxy.addChangeHandler(s,f);
    observingProxy.removeChangeHandler(s,f);
    observingProxy.getProxy(s).p1=2;
    u=setTimeout(function(){
      tl('removeChangeHandler',function(){return true});
    });
  }();

if(this.test_o)
  !function(){
    var s={p1:0},proxy=observingProxy.getProxy(s),n=0;
    observingProxy.addChangeHandler(s,function(ch){
      n++;
    });
    for(var i=10;i--;)
      proxy.p1++;
    setTimeout(function(){
      tl('Delayed notify',function(){return n===1});
    })
  }();

if(this.test_o)
  !function(){
    var u;
    var s={p1:1};
    observingProxy.addPropertyHandler(s,'p1',function(value){
      clearTimeout(u);
      tl('addPropertyHandler',function(){return value===2});
    });
    observingProxy.getProxy(s).p1=2;
    u=setTimeout(function(){
      tl('addPropertyHandler',function(){return false});
    });
  }();

if(this.test_o)
  !function(){
    var s={p1:1},proxy=observingProxy.getProxy(s),i=0;
    var observer=observingProxy.addPropertyHandler(s,'p1',function(value){
      i++;
    });

    proxy.p1=2;
    setTimeout(function(){
      observer.destroy();
      proxy.p1=3;
      setTimeout(function(){
        observer.restore();
        proxy.p1=4;
        setTimeout(function(){
          tl('addPropertyHandler destructor',function(){return i==2});
        });
      });
    });
  }();

}.bind(this)()
<|endoftext|>


<commit_before>import AppDispatcher from '../dispatcher/app';
import Constant from '../constant/app';

export default {
	/**
	 *
	 */
	loginSuccess (user) {
		console.log('login success', user);
		AppDispatcher.dispatch({
			actionType: Constant.LOGIN_SUCCESS,
			user
		});
	},

	/**
	 *
	 */
	loginFail (err) {
		console.log('login fail', err);
		AppDispatcher.dispatch({
			actionType: Constant.LOGIN_FAIL,
			err
		});
	},

	/**
	 *
	 */
	registerSuccess (err, user) {
		AppDispatcher.dispatch({
			actionType: Constant.LOGIN_SUCCESS,
			user
		});
	},

	/**
	 *
	 */
	registerFail (err) {
		AppDispatcher.dispatch({
			actionType: Constant.REGISTER_FAIL,
			err
		});
	},

	/**
	 *
	 */
	logoutSuccess () {
		AppDispatcher.dispatch({
			actionType: Constant.LOGOUT_SUCCESS
		});
	},

	/**
	 *
	 */
	fetchProjectsSuccess (projects) {
		AppDispatcher.dispatch({
			actionType: Constant.FETCH_PROJECTS_SUCCESS,
			projects
		});
	},

	/**
	 *
	 */
	createProjectSuccess (project) {
		AppDispatcher.dispatch({
			actionType: Constant.CREATE_PROJECT_SUCCESS,
			project
		});
	},

	/**
	 *
	 */
	createProjectFail (err) {
		AppDispatcher.dispatch({
			actionType: Constant.CREATE_PROJECT_FAIL,
			err
		});
	},

	/**
	 *
	 */
	deleteProjectSuccess (project) {
		AppDispatcher.dispatch({
			actionType: Constant.DELETE_PROJECT_SUCCESS,
			project
		});
	},

	/**
	 *
	 */
	deleteProjectFail (project) {
		AppDispatcher.dispatch({
			actionType: Constant.DELETE_PROJECT_FAIL,
			project
		});
	}
};<commit_msg>Adding fetchUsers callback and fixing bug with registerSuccess callback<commit_after>import AppDispatcher from '../dispatcher/app';
import Constant from '../constant/app';

export default {
	/**
	 *
	 */
	loginSuccess (user) {
		console.log('login success', user);
		AppDispatcher.dispatch({
			actionType: Constant.LOGIN_SUCCESS,
			user
		});
	},

	/**
	 *
	 */
	loginFail (err) {
		AppDispatcher.dispatch({
			actionType: Constant.LOGIN_FAIL,
			err
		});
	},

	/**
	 *
	 */
	registerSuccess (user) {
		AppDispatcher.dispatch({
			actionType: Constant.LOGIN_SUCCESS,
			user
		});
	},

	/**
	 *
	 */
	registerFail (err) {
		AppDispatcher.dispatch({
			actionType: Constant.REGISTER_FAIL,
			err
		});
	},

	/**
	 *
	 */
	logoutSuccess () {
		AppDispatcher.dispatch({
			actionType: Constant.LOGOUT_SUCCESS
		});
	},

	/**
	 *
	 */
	fetchProjectsSuccess (projects) {
		AppDispatcher.dispatch({
			actionType: Constant.FETCH_PROJECTS_SUCCESS,
			projects
		});
	},

	/**
	 *
	 */
	fetchUsersSuccess (users) {
		AppDispatcher.dispatch({
			actionType: Constant.FETCH_USERS_SUCCESS,
			users
		});
	},

	/**
	 *
	 */
	createProjectSuccess (project) {
		AppDispatcher.dispatch({
			actionType: Constant.CREATE_PROJECT_SUCCESS,
			project
		});
	},

	/**
	 *
	 */
	createProjectFail (err) {
		AppDispatcher.dispatch({
			actionType: Constant.CREATE_PROJECT_FAIL,
			err
		});
	},

	/**
	 *
	 */
	deleteProjectSuccess (project) {
		AppDispatcher.dispatch({
			actionType: Constant.DELETE_PROJECT_SUCCESS,
			project
		});
	},

	/**
	 *
	 */
	deleteProjectFail (project) {
		AppDispatcher.dispatch({
			actionType: Constant.DELETE_PROJECT_FAIL,
			project
		});
	}
};<|endoftext|>


<commit_before>dojo.provide("dojox.charting.action2d.Base");

dojo.require("dojo.fx.easing");
dojo.require("dojox.lang.functional.object");
dojo.require("dojox.gfx.fx");

/*=====
dojox.charting.action2d.__BaseCtorArgs = function(duration, easing){
 	//	summary:
	//		The base keyword arguments object for creating an action2d.
	//	duration: Number?
	//		The amount of time in milliseconds for an animation to last.  Default is 400.
	//	easing: dojox.fx.easing.*?
	//		An easing object (see dojo.fx.easing) for use in an animation.  The
	//		default is dojox.fx.easing.backOut.
	this.duration = duration;
	this.easing = easing;
}
=====*/
(function(){
	var DEFAULT_DURATION = 400,	// ms
		DEFAULT_EASING   = dojo.fx.easing.backOut,
		df = dojox.lang.functional;

	dojo.declare("dojox.charting.action2d.Base", null, {

		overOutEvents: {onmouseover: 1, onmouseout: 1},

		constructor: function(chart, plot, kwargs){
			//	summary:
			//		Create a new base Action.
			//	chart: dojox.charting.Chart2D
			//		The chart this action applies to.
			//	plot: String?
			//		The name of the plot this action belongs to.  If none is passed "default" is assumed.
			//	kwargs: dojox.charting.action2d.__BaseCtorArgs?
			//		Optional arguments for the action.
			this.chart = chart;
			this.plot = plot ? plot : "default";
			this.anim = {};

			// process common optional named parameters
			if(!kwargs){ kwargs = {}; }
			this.duration = kwargs.duration ? kwargs.duration : DEFAULT_DURATION;
			this.easing   = kwargs.easing   ? kwargs.easing   : DEFAULT_EASING;
		},

		connect: function(){
			//	summary:
			//		Connect this action to the given plot.
			this.handle = this.chart.connectToPlot(this.plot, this, "process");
		},

		disconnect: function(){
			//	summary:
			//		Disconnect this action from the given plot, if connected.
			if(this.handle){
				dojo.disconnect(this.handle);
				this.handle = null;
			}
		},

		reset: function(){
			//	summary:
			//		Reset the action.
		},

		destroy: function(){
			//	summary:
			//		Do any cleanup needed when destroying parent elements.
			if(this.handle){
				this.disconnect();
			}
			df.forIn(this.anim, function(o){
				df.forIn(o, function(anim){
					anim.action.stop(true);
				});
			});
			this.anim = {};
		}
	});
})();
<commit_msg>charting: minor reformulation, !strict, refs #8086.<commit_after>dojo.provide("dojox.charting.action2d.Base");

dojo.require("dojo.fx.easing");
dojo.require("dojox.lang.functional.object");
dojo.require("dojox.gfx.fx");

/*=====
dojox.charting.action2d.__BaseCtorArgs = function(duration, easing){
 	//	summary:
	//		The base keyword arguments object for creating an action2d.
	//	duration: Number?
	//		The amount of time in milliseconds for an animation to last.  Default is 400.
	//	easing: dojox.fx.easing.*?
	//		An easing object (see dojo.fx.easing) for use in an animation.  The
	//		default is dojox.fx.easing.backOut.
	this.duration = duration;
	this.easing = easing;
}
=====*/
(function(){
	var DEFAULT_DURATION = 400,	// ms
		DEFAULT_EASING   = dojo.fx.easing.backOut,
		df = dojox.lang.functional;

	dojo.declare("dojox.charting.action2d.Base", null, {

		overOutEvents: {onmouseover: 1, onmouseout: 1},

		constructor: function(chart, plot, kwargs){
			//	summary:
			//		Create a new base Action.
			//	chart: dojox.charting.Chart2D
			//		The chart this action applies to.
			//	plot: String?
			//		The name of the plot this action belongs to.  If none is passed "default" is assumed.
			//	kwargs: dojox.charting.action2d.__BaseCtorArgs?
			//		Optional arguments for the action.
			this.chart = chart;
			this.plot = plot || "default";
			this.anim = {};

			// process common optional named parameters
			if(!kwargs){ kwargs = {}; }
			this.duration = kwargs.duration ? kwargs.duration : DEFAULT_DURATION;
			this.easing   = kwargs.easing   ? kwargs.easing   : DEFAULT_EASING;
		},

		connect: function(){
			//	summary:
			//		Connect this action to the given plot.
			this.handle = this.chart.connectToPlot(this.plot, this, "process");
		},

		disconnect: function(){
			//	summary:
			//		Disconnect this action from the given plot, if connected.
			if(this.handle){
				dojo.disconnect(this.handle);
				this.handle = null;
			}
		},

		reset: function(){
			//	summary:
			//		Reset the action.
		},

		destroy: function(){
			//	summary:
			//		Do any cleanup needed when destroying parent elements.
			if(this.handle){
				this.disconnect();
			}
			df.forIn(this.anim, function(o){
				df.forIn(o, function(anim){
					anim.action.stop(true);
				});
			});
			this.anim = {};
		}
	});
})();
<|endoftext|>


<commit_before>(function (w, d) {
    var
        atc_url = '//addtocalendar.com/atc/',
        atc_version = '1.5';

    if (!Array.indexOf) {
        Array.prototype.indexOf = function (obj) {
            for (var i = 0, l = this.length; i < l; i++) {
                if (this[i] == obj) {
                    return i
                }
            }
            return -1
        }
    }

    if (!Array.prototype.map) {
        Array.prototype.map = function (f) {
            var result = [];
            for (var i = 0, l = this.length; i < l; i++) {
                result.push(f(this[i]))
            }
            return result
        }
    }

    var isArray = function (obj) {
        return Object.prototype.toString.call(obj) === "[object Array]"
    };

    var isFunc = function (obj) {
        return Object.prototype.toString.call(obj) === "[object Function]"
    };

    var ready = function (w, d) {
        var inited = false,
            loaded = false,
            queue = [],
            done, old;

        function go() {
            if (!inited) {
                if (!d.body) return setTimeout(go, 13);
                inited = true;
                if (queue) {
                    var j, k = 0;
                    while (j = queue[k++]) j.call(null);
                    queue = null
                }
            }
        }

        function check() {
            if (loaded) return;
            loaded = true;
            if (d.readyState === "complete") return go();
            if (d.addEventListener) {
                d.addEventListener("DOMContentLoaded", done, false);
                w.addEventListener("load", go, false)
            } else {
                if (d.attachEvent) {
                    d.attachEvent("onreadystatechange", done);
                    w.attachEvent("onload", go);
                    var k = false;
                    try {
                        k = w.frameElement == null
                    } catch (j) {}
                    if (b.doScroll && k) ie()
                } else {
                    old = w.onload;
                    w.onload = function (e) {
                        old(e);
                        go()
                    }
                }
            }
        }
        if (d.addEventListener) {
            done = function () {
                d.removeEventListener("DOMContentLoaded", done, false);
                go()
            }
        } else {
            if (d.attachEvent) {
                done = function () {
                    if (d.readyState === "complete") {
                        d.detachEvent("onreadystatechange", done);
                        go()
                    }
                }
            }
        }

        function ie() {
            if (inited) return;
            try {
                b.doScroll("left")
            } catch (j) {
                setTimeout(ie, 1);
                return
            }
            go()
        }
        return function (callback) {
            check();
            if (inited) {
                callback.call(null)
            } else {
                queue.push(callback)
            }
        }
    }(w, d);

    if (w.addtocalendar && typeof w.addtocalendar.start == "function") return;
    if (!w.addtocalendar) w.addtocalendar = {};

    addtocalendar.languages = {
        'de': 'In den Kalender',
        'en': 'Add to Calendar',
        'es': 'Añadir al Calendario',
        'fr': 'Ajouter au calendrier',
        'hi': 'कैलेंडर में जोड़ें',
        'in': 'Tambahkan ke Kalender',
        'ja': 'カレンダーに追加',
        'ko': '캘린더에 추가',
        'pt': 'Adicionar ao calendário',
        'ru': 'Добавить в календарь',
        'uk': 'Додати в календар',
        'zh': '添加到日历'
    };

    addtocalendar.calendar_urls = {

    }

    addtocalendar.loadSettings = function(element){
        var settings = {
            'language':'auto',
            'show-list-on':'click',
            'calendars':[
                'iCalendar',
                'Google Calendar',
                'Outlook',
                'Outlook Online',
                'Yahoo! Calendar'
            ],
            'secure':'auto',
            'on-button-click':function(){},
            'on-calendar-click':function(){}
        };

        for (var option in settings){
            var pname = 'data-' + option;
            var eattr = element.getAttribute(pname);
            if(eattr != null){

                if(isArray(settings[option])){
                    settings[option] = eattr.replace(/\s*,\s*/g,',').replace(/^\s+|\s+$/g, '').split(',');
                    continue;
                }

                if(isFunc(settings[option])){
                    var fn = window[eattr];
                    if(isFunc(fn)) {
                        settings[option]=fn;
                    }else {
                        settings[option]=eval('(function(mouseEvent){'+eattr+'})');
                    }
                    continue;
                }

                settings[option]=element.getAttribute(pname);
            }
        }

        return settings;
    };

    addtocalendar.load = function () {

        var calendarsUrl = {
            'iCalendar':'ical',
            'Google Calendar':'google',
            'Outlook':'outlook',
            'Outlook Online':'outlookonline',
            'Yahoo! Calendar':'yahoo'
        };
        var utz = (-(new Date()).getTimezoneOffset().toString());

        var languages = addtocalendar.languages;

        var dom = document.getElementsByTagName('*');
        for (var tagnum = 0; tagnum < dom.length; tagnum++) {
            var tag_class = dom[tagnum].className;

            if (tag_class.length && tag_class.split(" ").indexOf('addtocalendar') != -1) {

                var settings = addtocalendar.loadSettings(dom[tagnum]);

                var protocol = 'http:';
                if(settings['secure'] == 'auto'){
                    protocol = location.protocol == 'https:' ? 'https:' : 'http:';
                } else if(settings['secure'] == 'true'){
                    protocol = 'https:';
                }

                var tag_id = dom[tagnum].id;
                var atc_button_title = languages['en'];
                if(settings['language'] == 'auto'){
                    var user_lang = "no_lang";
					if (typeof navigator.language === "string") {
					    user_lang = navigator.language.substr(0, 2)
					} else if (typeof navigator.browserLanguage === "string") {
					    user_lang = navigator.browserLanguage.substr(0, 2)
					}

                    if(languages.hasOwnProperty(user_lang)){
                        atc_button_title = languages[user_lang];
                    }
                }else if(languages.hasOwnProperty(settings['language'])){
                    atc_button_title = languages[settings['language']];
                }

                var url_paramteres = [
                    'utz=' + utz,
                    'uln=' + navigator.language,
                    'vjs=' + atc_version
                ];

                var addtocalendar_div = dom[tagnum].getElementsByTagName('var');
                var event_number = -1;
                for (var varnum = 0; varnum < addtocalendar_div.length; varnum++) {
                    var param_name = addtocalendar_div[varnum].className.replace("atc_","").split(" ")[0];
                    var param_value = addtocalendar_div[varnum].innerHTML;

                    if(param_name == 'event'){
                        event_number++;
                        continue;
                    }

                    if(param_name == addtocalendar_div[varnum].className){
                        if(param_name == 'atc-body'){
                            atc_button_title = param_value;
                        }
                        continue;
                    }

                    if(event_number == -1){
                        continue;
                    }

                    url_paramteres.push('e['+event_number+']['+param_name+']' + '=' + encodeURIComponent(param_value));
                }

                var atcb_link_id_val = (tag_id == ''?'':(tag_id + '_link') );
                var atcb_list = document.createElement('ul');
                atcb_list.className = 'atcb-list';

                var menu_links = '';
                for (var cnum in settings['calendars']){
                    if(!calendarsUrl.hasOwnProperty(settings['calendars'][cnum])){
                        continue;
                    }
                    var cal_id = calendarsUrl[settings['calendars'][cnum]];
                    var atcb_cal_link_id = (tag_id == '' ? '' : ('id="'+tag_id + '_' + cal_id + '_link"') );
                    menu_links += '
' + settings['calendars'][cnum] + '
';
                }
                atcb_list.innerHTML = menu_links;

                if(dom[tagnum].getElementsByClassName('atcb-link')[0] == undefined){
                    var atcb_link = document.createElement('a');
                    atcb_link.className = 'atcb-link';
                    atcb_link.innerHTML = atc_button_title;
                    atcb_link.id = atcb_link_id_val;
                    atcb_link.tabIndex = 1;

                    dom[tagnum].appendChild(atcb_link);
                    dom[tagnum].appendChild(atcb_list);
                }else{
                    var atcb_link = dom[tagnum].getElementsByClassName('atcb-link')[0];
                    atcb_link.parentNode.appendChild(atcb_list);
                    atcb_link.tabIndex=1;
                    if(atcb_link.id == ''){
                        atcb_link.id = atcb_link_id_val;
                    }
                }

                dom[tagnum]
                    .getElementsByClassName('atcb-link')[0]
                    .addEventListener("click", settings['on-button-click'], false);

                var item_links = dom[tagnum].getElementsByClassName('atcb-item-link');

                for (var varnum = 0; varnum < item_links.length; varnum++) {
                    item_links[varnum].addEventListener("click", settings['on-calendar-click'], false);
                }

            }
        }
    };
    addtocalendar.load();
})(window, document);
<commit_msg>Fast fix<commit_after>(function (w, d) {
    var
        atc_url = '//addtocalendar.com/atc/',
        atc_version = '1.5';

    if (!Array.indexOf) {
        Array.prototype.indexOf = function (obj) {
            for (var i = 0, l = this.length; i < l; i++) {
                if (this[i] == obj) {
                    return i
                }
            }
            return -1
        }
    }

    if (!Array.prototype.map) {
        Array.prototype.map = function (f) {
            var result = [];
            for (var i = 0, l = this.length; i < l; i++) {
                result.push(f(this[i]))
            }
            return result
        }
    }

    var isArray = function (obj) {
        return Object.prototype.toString.call(obj) === "[object Array]"
    };

    var isFunc = function (obj) {
        return Object.prototype.toString.call(obj) === "[object Function]"
    };

    var ready = function (w, d) {
        var inited = false,
            loaded = false,
            queue = [],
            done, old;

        function go() {
            if (!inited) {
                if (!d.body) return setTimeout(go, 13);
                inited = true;
                if (queue) {
                    var j, k = 0;
                    while (j = queue[k++]) j.call(null);
                    queue = null
                }
            }
        }

        function check() {
            if (loaded) return;
            loaded = true;
            if (d.readyState === "complete") return go();
            if (d.addEventListener) {
                d.addEventListener("DOMContentLoaded", done, false);
                w.addEventListener("load", go, false)
            } else {
                if (d.attachEvent) {
                    d.attachEvent("onreadystatechange", done);
                    w.attachEvent("onload", go);
                    var k = false;
                    try {
                        k = w.frameElement == null
                    } catch (j) {}
                    if (b.doScroll && k) ie()
                } else {
                    old = w.onload;
                    w.onload = function (e) {
                        old(e);
                        go()
                    }
                }
            }
        }
        if (d.addEventListener) {
            done = function () {
                d.removeEventListener("DOMContentLoaded", done, false);
                go()
            }
        } else {
            if (d.attachEvent) {
                done = function () {
                    if (d.readyState === "complete") {
                        d.detachEvent("onreadystatechange", done);
                        go()
                    }
                }
            }
        }

        function ie() {
            if (inited) return;
            try {
                b.doScroll("left")
            } catch (j) {
                setTimeout(ie, 1);
                return
            }
            go()
        }
        return function (callback) {
            check();
            if (inited) {
                callback.call(null)
            } else {
                queue.push(callback)
            }
        }
    }(w, d);

    if (w.addtocalendar && typeof w.addtocalendar.start == "function") return;
    if (!w.addtocalendar) w.addtocalendar = {};

    addtocalendar.languages = {
        'de': 'In den Kalender',
        'en': 'Add to Calendar',
        'es': 'Añadir al Calendario',
        'fr': 'Ajouter au calendrier',
        'hi': 'कैलेंडर में जोड़ें',
        'in': 'Tambahkan ke Kalender',
        'ja': 'カレンダーに追加',
        'ko': '캘린더에 추가',
        'pt': 'Adicionar ao calendário',
        'ru': 'Добавить в календарь',
        'uk': 'Додати в календар',
        'zh': '添加到日历'
    };

    addtocalendar.calendar_urls = {

    }

    addtocalendar.loadSettings = function(element){
        var settings = {
            'language':'auto',
            'show-list-on':'click',
            'calendars':[
                'iCalendar',
                'Google Calendar',
                'Outlook',
                'Outlook Online',
                'Yahoo! Calendar'
            ],
            'secure':'auto',
            'on-button-click':function(){},
            'on-calendar-click':function(){}
        };

        for (var option in settings){
            var pname = 'data-' + option;
            var eattr = element.getAttribute(pname);
            if(eattr != null){

                if(isArray(settings[option])){
                    settings[option] = eattr.replace(/\s*,\s*/g,',').replace(/^\s+|\s+$/g, '').split(',');
                    continue;
                }

                if(isFunc(settings[option])){
                    var fn = window[eattr];
                    if(isFunc(fn)) {
                        settings[option]=fn;
                    }else {
                        settings[option]=eval('(function(mouseEvent){'+eattr+'})');
                    }
                    continue;
                }

                settings[option]=element.getAttribute(pname);
            }
        }

        return settings;
    };

    addtocalendar.load = function () {

        var calendarsUrl = {
            'iCalendar':'ical',
            'Google Calendar':'google',
            'Outlook':'outlook',
            'Outlook Online':'outlookonline',
            'Yahoo! Calendar':'yahoo'
        };
        var utz = (-(new Date()).getTimezoneOffset().toString());

        var languages = addtocalendar.languages;

        var dom = document.getElementsByTagName('*');
        for (var tagnum = 0; tagnum < dom.length; tagnum++) {
            var tag_class = dom[tagnum].className;

            if (tag_class && tag_class.length && tag_class.split(" ").indexOf('addtocalendar') != -1) {

                var settings = addtocalendar.loadSettings(dom[tagnum]);

                var protocol = 'http:';
                if(settings['secure'] == 'auto'){
                    protocol = location.protocol == 'https:' ? 'https:' : 'http:';
                } else if(settings['secure'] == 'true'){
                    protocol = 'https:';
                }

                var tag_id = dom[tagnum].id;
                var atc_button_title = languages['en'];
                if(settings['language'] == 'auto'){
                    var user_lang = "no_lang";
					if (typeof navigator.language === "string") {
					    user_lang = navigator.language.substr(0, 2)
					} else if (typeof navigator.browserLanguage === "string") {
					    user_lang = navigator.browserLanguage.substr(0, 2)
					}

                    if(languages.hasOwnProperty(user_lang)){
                        atc_button_title = languages[user_lang];
                    }
                }else if(languages.hasOwnProperty(settings['language'])){
                    atc_button_title = languages[settings['language']];
                }

                var url_paramteres = [
                    'utz=' + utz,
                    'uln=' + navigator.language,
                    'vjs=' + atc_version
                ];

                var addtocalendar_div = dom[tagnum].getElementsByTagName('var');
                var event_number = -1;
                for (var varnum = 0; varnum < addtocalendar_div.length; varnum++) {
                    var param_name = addtocalendar_div[varnum].className.replace("atc_","").split(" ")[0];
                    var param_value = addtocalendar_div[varnum].innerHTML;

                    if(param_name == 'event'){
                        event_number++;
                        continue;
                    }

                    if(param_name == addtocalendar_div[varnum].className){
                        if(param_name == 'atc-body'){
                            atc_button_title = param_value;
                        }
                        continue;
                    }

                    if(event_number == -1){
                        continue;
                    }

                    url_paramteres.push('e['+event_number+']['+param_name+']' + '=' + encodeURIComponent(param_value));
                }

                var atcb_link_id_val = (tag_id == ''?'':(tag_id + '_link') );
                var atcb_list = document.createElement('ul');
                atcb_list.className = 'atcb-list';

                var menu_links = '';
                for (var cnum in settings['calendars']){
                    if(!calendarsUrl.hasOwnProperty(settings['calendars'][cnum])){
                        continue;
                    }
                    var cal_id = calendarsUrl[settings['calendars'][cnum]];
                    var atcb_cal_link_id = (tag_id == '' ? '' : ('id="'+tag_id + '_' + cal_id + '_link"') );
                    menu_links += '
' + settings['calendars'][cnum] + '
';
                }
                atcb_list.innerHTML = menu_links;

                if(dom[tagnum].getElementsByClassName('atcb-link')[0] == undefined){
                    var atcb_link = document.createElement('a');
                    atcb_link.className = 'atcb-link';
                    atcb_link.innerHTML = atc_button_title;
                    atcb_link.id = atcb_link_id_val;
                    atcb_link.tabIndex = 1;

                    dom[tagnum].appendChild(atcb_link);
                    dom[tagnum].appendChild(atcb_list);
                }else{
                    var atcb_link = dom[tagnum].getElementsByClassName('atcb-link')[0];
                    atcb_link.parentNode.appendChild(atcb_list);
                    atcb_link.tabIndex=1;
                    if(atcb_link.id == ''){
                        atcb_link.id = atcb_link_id_val;
                    }
                }

                dom[tagnum]
                    .getElementsByClassName('atcb-link')[0]
                    .addEventListener("click", settings['on-button-click'], false);

                var item_links = dom[tagnum].getElementsByClassName('atcb-item-link');

                for (var varnum = 0; varnum < item_links.length; varnum++) {
                    item_links[varnum].addEventListener("click", settings['on-calendar-click'], false);
                }

            }
        }
    };
    addtocalendar.load();
})(window, document);
<|endoftext|>