<commit_before>var maze2 = [
[1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,5,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,1,1,1,1],
[1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1],
[1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
[1,1,1,0,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1],
[1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
[1,1,1,0,0,0,0,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1],
[1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
[1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1],
[1,1,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1],
[1,1,1,0,0,0,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,4,1,1,1,1],
[1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];
var maze = [
[1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,5,0,0,1,0,1,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,1],
[1,1,1,0,1,0,1,0,1,0,1,0,1,0,0,0,0,1,0,1,1,1,0,1,1,0,1,1,0,1,1,1],
[1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1],
[1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1],
[0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0],
[1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,4,0,0,0,0,0,1,1,1,1],
[1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1],
[1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,4,0,0,0,0,0,1,1,1,1],
[1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1],
[0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
[1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,4,0,0,0,0,0,1,1,1,1],
[1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];
var maze3 = [
[1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1],
[1,1,1,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,1],
[1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,1],
[1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,0,0,0,1,0,1,1,1,0,1,1],
[1,1,1,0,0,0,0,0,1,0,0,0,1,1,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,1,1],
[1,1,1,1,1,1,1,0,1,0,1,0,1,1,1,1,1,1,0,1,0,1,1,0,1,0,1,1,1,0,1,1],
[1,1,1,1,1,1,1,0,1,0,1,0,1,1,1,1,1,1,0,0,0,1,1,0,1,0,1,1,1,0,1,1],
[1,1,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,0,0,1,1],
[1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1],
[1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1],
[1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
[1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];
var maze4 = [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1],
[1,1,1,5,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,1,1,0,0,0,0,1,1],
[1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,0,1,1,1,0,0,0,0,1,1,0,0,1],
[1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1],
[0,0,0,0,0,1,1,1,0,0,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1,1,0,1,1,1,0,0],
[1,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,0,0,0,0,0,1,1,0,1,1,1,0,1],
[1,1,1,1,0,0,1,0,0,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1],
[1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1,1,0,1,1,0,0,1],
[1,1,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,1,1,0,0,0,0,1,1],
[1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];
var maze5 = [
[1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1],
[1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1],
[1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1],
[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1],
[1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1],
[1,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1],
[1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
[1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1],
[1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1],
[1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1],
[1,0,0,0,0,0,1,1,1,0,1,1,1,0,0,0,0,0,1,0,1,1,1,1,1,0,0,0,1,0,1,1],
[1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1],
[1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1]
];

var pos = {};
pos.x = 3;
pos.y = 1;

var count = 0;

var g1_pos = {};
g1_pos.x = 21;
g1_pos.y = 5;

var g2_pos = {};
g2_pos.x = 21;
g2_pos.y = 7;

var g3_pos = {};
g2_pos.x = 21;
g2_pos.y = 9;

var g4_pos = {};
g2_pos.x = 21;
g2_pos.y = 12;
var pacman;
pacman = document.createElement('img');
pacman.setAttribute('id','pacman');
pacman.setAttribute('src', 'https://forum.infinitymu.net/images/smilies/insania/pacman.png');
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}
async function g_move(ghost){
	switch (getRandomInt(1, 4)){
		case 1://left
		if(maze[ghost.y][ghost.x-1] == 0){
		maze[ghost.y][ghost.x] = 0;
		maze[ghost.y][ghost.x-1] = 4;
		ghost.x -= 1;
		await sleep(150);
		console.log(maze[ghost.y][ghost.x-1]);}
		case 2://right
		if(maze[ghost.y][ghost.x+1] == 0){
		maze[ghost.y][ghost.x] = 0;
		maze[ghost.y][ghost.x+1] = 4;
		ghost.x += 1;
		await sleep(150);
		console.log(maze[ghost.y][ghost.x+1]);}
		case 3://up
		if(maze[ghost.y-1][ghost.x] == 0){
		maze[ghost.y][ghost.x] = 0;
		maze[ghost.y-1][ghost.x] = 4;
		ghost.y -= 1;
		await sleep(150);
		console.log(maze[ghost.y-1][ghost.x]);}
		case 4://down
		if(maze[ghost.y+1][ghost.x] == 0){
		maze[ghost.y][ghost.x] = 0;
		maze[ghost.y+1][ghost.x] = 4;
		ghost.y += 1;
		await sleep(150);
		console.log(maze[ghost.y][ghost.x-1]);
	}
}
}

function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

function maze_generate(){
  mydiv = document.createElement('div');
  mydiv.setAttribute('id', 'mydiv');
  if(count == 160) alert("Congratulations. You won!");
  	for(i=0;i<14;i++){
          mytr = document.createElement('tr');
  		for(j=0;j<32;j++){
              if(maze[i][j] == "1"){
                  var mytd = document.createElement('td');
          			var square = document.createElement('img');
                      square.setAttribute('src', 'wall.png');
                      square.setAttribute('id', String(i).concat(String(j)));
                      mytd.appendChild(square);
                      mytr.appendChild(mytd);
              }
              else if (maze[i][j] == "5"){
                   var mytd = document.createElement('td');
                      mytd.appendChild(pacman);
                      mytr.appendChild(mytd);
              }
              else if(maze[i][j] == "0"){
                   var mytd = document.createElement('td');
                      var square = document.createElement('img');
                      square.setAttribute('src', 'dot.png');
                      square.setAttribute('id', String(i).concat(String(j)));
                      square.setAttribute('width', '60%');
                      mytd.appendChild(square);
                      mytr.appendChild(mytd);
              }
              else if(maze[i][j] == "2"){
                   var mytd = document.createElement('td');
                      var square = document.createElement('img');
                      square.setAttribute('src', 'https://www.pawbe.com/images/Blank.png');
                      square.setAttribute('id', String(i).concat(String(j)));
                      mytd.appendChild(square);
                      mytr.appendChild(mytd);
              }
               else if(maze[i][j] == "4"){
                   var mytd = document.createElement('td');
                      var square = document.createElement('img');
                      square.setAttribute('src', 'http://got-djent.com/kidman/img/okubo.png');
                      square.setAttribute('id', String(i).concat(String(j)));
                      mytd.appendChild(square);
                      mytr.appendChild(mytd);
              }
  		}
      mydiv.appendChild(mytr);
  	}
    document.body.appendChild(mydiv)
}

window.onload = maze_generate;

document.addEventListener("keydown",move);

 async function move(e){
	e = e || window.event;
    keycode = e.which || e.keyCode;
    g_move(g1_pos);
	g_move(g2_pos);
	g_move(g3_pos);
	g_move(g4_pos);
    console.log(count);
    switch(keycode){

        case 65: //left
			while((maze[pos.y][pos.x-1] == 0 || maze[pos.y][pos.x-1] == 2)&& keycode == 65){
				  if(maze[pos.y][pos.x-1] != 1){
				  	if(maze[pos.y][pos.x-1] == 0)
				  		count+=1;
					maze[pos.y][pos.x] = 2;
					maze[pos.y][pos.x-1] = 5;
					pos.x -= 1;
					await sleep(150);
				  }
    			  if(count == 164) alert("We have a winner!");
				  mydiv.parentNode.removeChild(mydiv);
				  maze_generate();
			}
			break;

        case 87: //up
			while((maze[pos.y-1][pos.x] == 0 || maze[pos.y-1][pos.x] == 2)&& keycode == 87){

				  if(maze[pos.y-1][pos.x] != 1){
				  	if(maze[pos.y-1][pos.x] == 0)
				  		count+=1;
					maze[pos.y][pos.x] = 2;
					maze[pos.y-1][pos.x] = 5;
					pos.y -= 1;
					await sleep(150);
				  }
				  if(count == 164) alert("We have a winner!");
			 	  mydiv.parentNode.removeChild(mydiv);
			  	  maze_generate();
			}
          break;

        case 68: //right
			while((maze[pos.y][pos.x+1] == 0 || maze[pos.y][pos.x+1] == 2)&& keycode == 68){

				  if(maze[pos.y][pos.x+1] != 1){
				  	if(maze[pos.y][pos.x+1] == 0)
				  		count+=1;
					maze[pos.y][pos.x] = 2;
					maze[pos.y][pos.x+1] = 5;
					pos.x += 1;
					await sleep(150);
				  }
			      if(count == 164) alert("We have a winner!");
				  mydiv.parentNode.removeChild(mydiv);
				  maze_generate();
		}

          break;

        case 83: //down
			while((maze[pos.y+1][pos.x] == 0 || maze[pos.y+1][pos.x] == 2)&& keycode == 83){

				  if(maze[pos.y+1][pos.x] != 1){
				  	if(maze[pos.y+1][pos.x] == 0)
				  		count+=1;
					maze[pos.y][pos.x] = 2;
					maze[pos.y+1][pos.x] = 5;
					pos.y += 1;
					await sleep(150);
				  }
				  if(count == 164) alert("We have a winner!");
		          mydiv.parentNode.removeChild(mydiv);
		          maze_generate();
			}
		break;
	}
}

<commit_msg>Delete game.js<commit_after><|endoftext|>


<commit_before>// Load required engine components
Engine.include("/rendercontexts/context.canvascontext.js");
Engine.include("/rendercontexts/context.scrollingbackground.js");
Engine.include("/spatial/container.spatialgrid.js");
Engine.include("/engine/engine.timers.js");
Engine.include("/textrender/text.vector.js");
Engine.include("/textrender/text.renderer.js");
Engine.include("/resourceloaders/loader.sprite.js");
Engine.include("/resourceloaders/loader.level.js");

// Load game objects
Game.load("/rock.js");
Game.load("/player.js");
Game.load("/bullet.js");
Game.load("/particle.js");

Engine.initObject("Spaceroids", "Game", function() {

/**
 * @class The game.
 */
var Spaceroids = Game.extend({

	constructor: null,

	renderContext: null,

	fieldBox: null,
	centerPoint: null,
	areaScale: $.browser.Wii ? 0.7 : 0.93,

	engineFPS: 30,

	collisionModel: null,

	rocks: 0,
	snowTimer: null,
	snowFallRate: 0,
	snowFallInterval: 100,
	groundY: 498,

	fieldWidth: 500,
	fieldHeight: 580,
	level: null,

	debug: true,
	playerObj: null,

	showStart: false,

	pEngine: null,

	spriteLoader: null,
	levelLoader: null,
	loadTimeout: null,

	gravityVector: Vector2D.create(0, 0.6),
	gravityTimer: null,
	gravityInterval: 100,

	/**
	 * A simple mode where the title, game over message,
	 * and start message are displayed with asteroids in the background
	 */
	attractMode: function() {
		Spaceroids.isAttractMode = true;

		var pWidth = this.fieldWidth;
		var pHeight = this.fieldHeight;

		// var flash = function() {
		// 	if (!Spaceroids.showStart)
		// 	{
		// 		Spaceroids.start.setDrawMode(TextRenderer.DRAW_TEXT);
		// 		Spaceroids.showStart = true;
		// 		Spaceroids.intv.restart();
		// 	}
		// 	else
		// 	{
		// 		Spaceroids.start.setDrawMode(TextRenderer.NO_DRAW);
		// 		Spaceroids.showStart = false;
		// 		Spaceroids.intv.restart();
		// 	}
		// };
		//
		// Spaceroids.intv = Timeout.create("startkey", 1000, flash);

    this.level = Spaceroids.levelLoader.getLevel("level1");

		this.renderContext = ScrollingBackground.create("bkg", this.level, this.fieldWidth, this.fieldHeight);
		this.renderContext.setWorldScale(this.areaScale);
		this.renderContext.setBackgroundColor("#000000");
		Engine.getDefaultContext().add(this.renderContext);

		// Start up the particle engine
		this.pEngine = ParticleEngine.create()
		this.renderContext.add(this.pEngine);

		this.playerObj = SpaceroidsPlayer.create();
		this.renderContext.add(this.playerObj);
		this.playerObj.setup(pWidth, pHeight);

		//snow machine
		Spaceroids.snowTimer = Interval.create("snow", this.snowFallInterval,
			function() {
				// if(Spaceroids.snowFallRate >= 1 || Spaceroids.snowFallRate > Math.random())
					Spaceroids.pEngine.addParticle(SnowParticle.create(Spaceroids.level.getWidth()));
				// else
				// 					Spaceroids.snowFallRate += 0.0001;
		});

		// gravity machine
		Spaceroids.gravityTimer = Interval.create("snow", this.gravityInterval,
			function() {
				Spaceroids.applyGravity(Spaceroids.playerObj);
		});
	},

	applyGravity: function(obj) {
		obj.velocity = obj.velocity.add(this.gravityVector);
	},

	updatePosition: function(obj) {
		var potentialNewPos = Point2D.create(obj.getPosition()).add(obj.velocity); // get pos COULD end up in
		var solidGround = this.solidGround(potentialNewPos); // either false or ground pos
		if(solidGround == false)
			obj.setPosition(potentialNewPos);
		else
			obj.endFall(solidGround);
	},

	// if not on solid ground, return false, otherwise return pos of solid ground
	solidGround: function(pos) {
		if(pos.y >= this.groundY)
			return Point2D.create(pos.x, this.groundY);
		else
			return false;
	},

	/**
	 * Called to set up the game, download any resources, and initialize
	 * the game to its running state.
	 */
	setup: function() {
		$("#loading").remove();

		// Set the FPS of the game
		Engine.setFPS(this.engineFPS);

		// Create the 2D context
		this.fieldBox = Rectangle2D.create(0, 0, this.fieldWidth, this.fieldHeight);
		this.centerPoint = this.fieldBox.getCenter();

		// We'll need something to detect collisions
		this.collisionModel = SpatialGrid.create(this.fieldWidth, this.fieldHeight, 7);

		this.spriteLoader = SpriteLoader.create();
		this.levelLoader = LevelLoader.create();

		// load sprites
		this.spriteLoader.load("girl", this.getFilePath("resources/girl.js"));

		// level
		this.levelLoader.load("level1", this.getFilePath("resources/level1.js"));

		// Don't start until all of the resources are loaded
		Spaceroids.loadTimeout = Timeout.create("wait", 250, Spaceroids.waitForResources);
		this.waitForResources();
	},

  waitForResources: function(){
		if (Spaceroids.spriteLoader.isReady() && Spaceroids.levelLoader.isReady()) {
			Spaceroids.loadTimeout.destroy();
			Spaceroids.attractMode();
			return;
	  }
	  else
	  	Spaceroids.loadTimeout.restart();
  },

	/**
	 * Called when the game is being shut down to allow the game
	 * the chance to clean up any objects, remove event handlers, and
	 * destroy the rendering context.
	 */
	teardown: function() {
		this.renderContext.destroy();
	},

	/**
	 * A simple method that determines if the position is within the supplied bounding
	 * box.
	 *
	 * @param pos {Point2D} The position to test
	 * @param bBox {Rectangle2D} The bounding box of the playfield
	 * @type Boolean
	 */
	inLevel: function(pos) {
		return Math2D.boxPointCollision(this.level.getFrame(), pos);
	},

	// updates the position of the view frame
	updateFramePosition: function(vector, centralObj) {
		var centralObjWindowX = centralObj.getRenderPosition().x;
		var minScroll = 0;
		var maxScroll = this.level.getWidth() - this.fieldWidth;
		var potentialNewHorizontalScroll = this.renderContext.getHorizontalScroll() + vector.x;

		var movingPastCentrePoint = false;
		if(vector.x > 0 && centralObjWindowX > this.centerPoint.x)
			movingPastCentrePoint = true;
		else if(vector.x < 0 && centralObjWindowX < this.centerPoint.x)
			movingPastCentrePoint = true;

		if(movingPastCentrePoint && potentialNewHorizontalScroll >= minScroll && potentialNewHorizontalScroll <= maxScroll)
			this.renderContext.setHorizontalScroll(potentialNewHorizontalScroll);
	},

	/**
	 * Called to wrap an object around the edges of the playfield.
	 *
	 * @param pos {Point2D} The position of the object
	 * @param bBox {Rectangle2D} The bounding box of the playfield
	 */
	wrap: function(pos, bBox) {

		var rX = bBox.len_x();
		var rY = bBox.len_y();

		// Wrap if it's off the playing field
		var p = new Point2D(pos);
		var x = p.x;
		var y = p.y;
		var fb = this.renderContext.getViewport().get();

		//console.debug(p, fb);

		if (pos.x < fb.x || pos.x > fb.r ||
			 pos.y < fb.y || pos.y > fb.b)
		{
			if (pos.x > fb.r + rX)
			{
				x = (fb.x - (rX - 1));
			}
			if (pos.y > fb.b + rY)
			{
				y = (fb.y - (rY - 1));
			}
			if (pos.x < fb.x - rX)
			{
				x = (fb.r + (rX - 1));
			}
			if (pos.y < fb.y - rY)
			{
				y = (fb.b + (rY - 1));
			}
			p.set(x,y);
		}
		return p;
	}

});

return Spaceroids;

});
<commit_msg>grav vec only applied when not on solid ground<commit_after>// Load required engine components
Engine.include("/rendercontexts/context.canvascontext.js");
Engine.include("/rendercontexts/context.scrollingbackground.js");
Engine.include("/spatial/container.spatialgrid.js");
Engine.include("/engine/engine.timers.js");
Engine.include("/textrender/text.vector.js");
Engine.include("/textrender/text.renderer.js");
Engine.include("/resourceloaders/loader.sprite.js");
Engine.include("/resourceloaders/loader.level.js");

// Load game objects
Game.load("/rock.js");
Game.load("/player.js");
Game.load("/bullet.js");
Game.load("/particle.js");

Engine.initObject("Spaceroids", "Game", function() {

/**
 * @class The game.
 */
var Spaceroids = Game.extend({

	constructor: null,

	renderContext: null,

	fieldBox: null,
	centerPoint: null,
	areaScale: $.browser.Wii ? 0.7 : 0.93,

	engineFPS: 30,

	collisionModel: null,

	rocks: 0,
	snowTimer: null,
	snowFallRate: 0,
	snowFallInterval: 100,
	groundY: 498,

	fieldWidth: 500,
	fieldHeight: 580,
	level: null,

	debug: true,
	playerObj: null,

	showStart: false,

	pEngine: null,

	spriteLoader: null,
	levelLoader: null,
	loadTimeout: null,

	gravityVector: Vector2D.create(0, 0.6),
	gravityTimer: null,
	gravityInterval: 100,

	/**
	 * A simple mode where the title, game over message,
	 * and start message are displayed with asteroids in the background
	 */
	attractMode: function() {
		Spaceroids.isAttractMode = true;

		var pWidth = this.fieldWidth;
		var pHeight = this.fieldHeight;

		// var flash = function() {
		// 	if (!Spaceroids.showStart)
		// 	{
		// 		Spaceroids.start.setDrawMode(TextRenderer.DRAW_TEXT);
		// 		Spaceroids.showStart = true;
		// 		Spaceroids.intv.restart();
		// 	}
		// 	else
		// 	{
		// 		Spaceroids.start.setDrawMode(TextRenderer.NO_DRAW);
		// 		Spaceroids.showStart = false;
		// 		Spaceroids.intv.restart();
		// 	}
		// };
		//
		// Spaceroids.intv = Timeout.create("startkey", 1000, flash);

    this.level = Spaceroids.levelLoader.getLevel("level1");

		this.renderContext = ScrollingBackground.create("bkg", this.level, this.fieldWidth, this.fieldHeight);
		this.renderContext.setWorldScale(this.areaScale);
		this.renderContext.setBackgroundColor("#000000");
		Engine.getDefaultContext().add(this.renderContext);

		// Start up the particle engine
		this.pEngine = ParticleEngine.create()
		this.renderContext.add(this.pEngine);

		this.playerObj = SpaceroidsPlayer.create();
		this.renderContext.add(this.playerObj);
		this.playerObj.setup(pWidth, pHeight);

		//snow machine
		Spaceroids.snowTimer = Interval.create("snow", this.snowFallInterval,
			function() {
				// if(Spaceroids.snowFallRate >= 1 || Spaceroids.snowFallRate > Math.random())
					Spaceroids.pEngine.addParticle(SnowParticle.create(Spaceroids.level.getWidth()));
				// else
				// 					Spaceroids.snowFallRate += 0.0001;
		});

		// gravity machine
		Spaceroids.gravityTimer = Interval.create("snow", this.gravityInterval,
			function() {
				Spaceroids.applyGravity(Spaceroids.playerObj);
		});
	},

	applyGravity: function(obj) {
		console.log(this.solidGround(obj.getPosition()))
		if(this.solidGround(obj.getPosition()) == false)
			obj.velocity = obj.velocity.add(this.gravityVector);
	},

	updatePosition: function(obj) {
		var potentialNewPos = Point2D.create(obj.getPosition()).add(obj.velocity); // get pos COULD end up in
		var solidGround = this.solidGround(potentialNewPos); // either false or ground pos
		if(solidGround == false)
			obj.setPosition(potentialNewPos);
		else
			obj.endFall(solidGround);
	},

	// if not on solid ground, return false, otherwise return pos of solid ground
	solidGround: function(pos) {
		if(pos.y >= this.groundY)
			return Point2D.create(pos.x, this.groundY);
		else
			return false;
	},

	/**
	 * Called to set up the game, download any resources, and initialize
	 * the game to its running state.
	 */
	setup: function() {
		$("#loading").remove();

		// Set the FPS of the game
		Engine.setFPS(this.engineFPS);

		// Create the 2D context
		this.fieldBox = Rectangle2D.create(0, 0, this.fieldWidth, this.fieldHeight);
		this.centerPoint = this.fieldBox.getCenter();

		// We'll need something to detect collisions
		this.collisionModel = SpatialGrid.create(this.fieldWidth, this.fieldHeight, 7);

		this.spriteLoader = SpriteLoader.create();
		this.levelLoader = LevelLoader.create();

		// load sprites
		this.spriteLoader.load("girl", this.getFilePath("resources/girl.js"));

		// level
		this.levelLoader.load("level1", this.getFilePath("resources/level1.js"));

		// Don't start until all of the resources are loaded
		Spaceroids.loadTimeout = Timeout.create("wait", 250, Spaceroids.waitForResources);
		this.waitForResources();
	},

  waitForResources: function(){
		if (Spaceroids.spriteLoader.isReady() && Spaceroids.levelLoader.isReady()) {
			Spaceroids.loadTimeout.destroy();
			Spaceroids.attractMode();
			return;
	  }
	  else
	  	Spaceroids.loadTimeout.restart();
  },

	/**
	 * Called when the game is being shut down to allow the game
	 * the chance to clean up any objects, remove event handlers, and
	 * destroy the rendering context.
	 */
	teardown: function() {
		this.renderContext.destroy();
	},

	/**
	 * A simple method that determines if the position is within the supplied bounding
	 * box.
	 *
	 * @param pos {Point2D} The position to test
	 * @param bBox {Rectangle2D} The bounding box of the playfield
	 * @type Boolean
	 */
	inLevel: function(pos) {
		return Math2D.boxPointCollision(this.level.getFrame(), pos);
	},

	// updates the position of the view frame
	updateFramePosition: function(vector, centralObj) {
		var centralObjWindowX = centralObj.getRenderPosition().x;
		var minScroll = 0;
		var maxScroll = this.level.getWidth() - this.fieldWidth;
		var potentialNewHorizontalScroll = this.renderContext.getHorizontalScroll() + vector.x;

		var movingPastCentrePoint = false;
		if(vector.x > 0 && centralObjWindowX > this.centerPoint.x)
			movingPastCentrePoint = true;
		else if(vector.x < 0 && centralObjWindowX < this.centerPoint.x)
			movingPastCentrePoint = true;

		if(movingPastCentrePoint && potentialNewHorizontalScroll >= minScroll && potentialNewHorizontalScroll <= maxScroll)
			this.renderContext.setHorizontalScroll(potentialNewHorizontalScroll);
	},

	/**
	 * Called to wrap an object around the edges of the playfield.
	 *
	 * @param pos {Point2D} The position of the object
	 * @param bBox {Rectangle2D} The bounding box of the playfield
	 */
	wrap: function(pos, bBox) {

		var rX = bBox.len_x();
		var rY = bBox.len_y();

		// Wrap if it's off the playing field
		var p = new Point2D(pos);
		var x = p.x;
		var y = p.y;
		var fb = this.renderContext.getViewport().get();

		//console.debug(p, fb);

		if (pos.x < fb.x || pos.x > fb.r ||
			 pos.y < fb.y || pos.y > fb.b)
		{
			if (pos.x > fb.r + rX)
			{
				x = (fb.x - (rX - 1));
			}
			if (pos.y > fb.b + rY)
			{
				y = (fb.y - (rY - 1));
			}
			if (pos.x < fb.x - rX)
			{
				x = (fb.r + (rX - 1));
			}
			if (pos.y < fb.y - rY)
			{
				y = (fb.b + (rY - 1));
			}
			p.set(x,y);
		}
		return p;
	}

});

return Spaceroids;

});
<|endoftext|>


<commit_before>/** @license MIT License (c) copyright B Cavalier & J Hann */

/**
 * wire/plugin-base/on
 *
 * wire is part of the cujo.js family of libraries (http://cujojs.com/)
 *
 * Licensed under the MIT License at:
 * http://www.opensource.org/licenses/mit-license.php
 */
(function (define) {
define(function (require) {
'use strict';

	var when, apply, functional, connection,
		theseAreNotEvents, thisLooksLikeCssRx, eventSplitterRx, undef;

	when = require('when');
	apply = require('when/apply');
	functional = require('../functional');
	connection = require('../connection');

	theseAreNotEvents = {
		selector: 1,
		transform: 1,
		preventDefault: 1,
		stopPropagation: 1
	};

	thisLooksLikeCssRx = /#|\.|-|[^,]\s[^,]/;
	eventSplitterRx = /\s*,\s*/;

	return function createOnPlugin (options) {
		var on;

		on = options.on;

		return function eventsPlugin (options) {

			var removers = [];

			if (!options) {
				options = {};
			}

			function createConnection(nodeProxy, eventsString, handler) {
				var events, node, prevent, stop;

				events = splitEventSelectorString(eventsString);
				node = nodeProxy.target;
				prevent = options.preventDefault;
				stop = options.stopPropagation;

				removers = removers.concat(
					registerHandlers(events, node, handler, prevent, stop)
				);
			}

			function parseIncomingOn(srcProxy, targetProxy, connections, wire) {

				// NOTE: Custom parsing for incoming connections

				// target is the node to which to connect, and
				// right hand side is a specification of an event
				// and a handler method on the current component
				//
				//	component: {
				//		on: {
				//			otherComponent: {
				//				selector: 'a.nav',
				//				transform: { $ref: 'myTransformFunc' }, // optional
				//				click: 'handlerMethodOnComponent',
				//				keypress: 'anotherHandlerOnComponent'
				//			}
				//		}
				//	}
				var target, event, events, selector, prevent, stop, method, transform, promises;

				target = targetProxy.target;
				promises = [];

				// Extract options
				selector = connections.selector;
				transform = connections.transform;
				prevent = connections.preventDefault || options.preventDefault;
				stop = connections.stopPropagation || options.stopPropagation;

				/**
				 * Compose a transform pipeline and then pass it to addConnection
				 */
				function createTransformedConnection(events, targetMethod, transformPromise) {
					return when(transformPromise, function(transform) {
						var composed, node;

						node = srcProxy.target;
						composed = functional.compose([transform, targetMethod]);
							//.bind(targetProxy.target);

						removers = removers.concat(
							registerHandlers(events, node, function() {
								return targetProxy.invoke(composed, arguments);
							}, prevent, stop)
						);
					});
				}

				for (event in connections) {
					// Skip reserved names, such as 'selector'
					if (!(event in theseAreNotEvents)) {
						// If there's an explicit transform, compose a transform pipeline manually,
						// Otherwise, let the connection lib do it's thing
						if(transform) {
							// TODO: Remove this long form?  It'd simplify the code a lot
							events = splitEventSelectorString(event, selector);
							method = connections[event];
							promises.push(createTransformedConnection(events, target[method], wire(transform)));
						} else {
							promises.push(connection.parseIncoming(srcProxy, event, targetProxy, options, connections[event], wire, createConnection));
						}
					}
				}

				return when.all(promises);
			}

			function parseOn (proxy, refName, connections, wire) {
				// First, figure out if the left-hand-side is a ref to
				// another component, or an event/delegation string
				return when(wire.getProxy(refName),
					function (srcProxy) {
						// It's an incoming connection, parse it as such
						return parseIncomingOn(srcProxy, proxy, connections, wire);
					},
					function () {
						// Failed to resolve refName as a reference, assume it
						// is an outgoing event with the current component (which
						// must be a Node) as the source
						return connection.parseOutgoing(proxy, refName, connections, wire, createConnection);
					}
				);

			}

			function onFacet (wire, facet) {
				var promises, connections;

				connections = facet.options;
				promises = [];

				for (var ref in connections) {
					promises.push(parseOn(facet, ref, connections[ref], wire));
				}

				return when.all(promises);
			}

			return {
				context: {
					destroy: function(resolver) {
						removers.forEach(function(remover) {
							remover();
						});
						resolver.resolve();
					}
				},
				facets: {
					on: {
						connect: function (resolver, facet, wire) {
							resolver.resolve(onFacet(wire, facet));
						}
					}
				},
				resolvers: {
					on: function(resolver, name /*, refObj, wire*/) {
						resolver.resolve(name ? createOnResolver(name) : on);
					}
				}
			};
		};

		function registerHandlers (events, node, callback, prevent, stop) {
			var removers, handler;
			removers = [];
			for (var i = 0, len = events.length; i < len; i++) {
				handler = makeEventHandler(callback, prevent, stop);
				removers.push(on(node, events[i], handler, events.selector));
			}
			return removers;
		}

		/**
		 * Returns a function that creates event handlers.  The event handlers
		 * are pre-configured with one or more selectors and one
		 * or more event types.  The syntax is identical to the "on" facet.
		 * Note that the returned handler does not auto-magically call
		 * event.preventDefault() or event.stopPropagation() like the "on"
		 * facet does.
		 * @private
		 * @param eventSelector {String} event/selector string that can be
		 *   parsed by splitEventSelectorString()
		 * @return {Function} a function that can be used to create event
		 *   handlers. It returns an "unwatch" function and takes any of
		 *   the following argument signatures:
		 *     function (handler) {}
		 *     function (rootNode, handler) {}
		 */
		function createOnResolver (eventSelector) {
			var events;
			// split event/selector string
			events = splitEventSelectorString(eventSelector, '');
			return function () {
				var args, node, handler, unwatches;
				// resolve arguments
				args = Array.prototype.slice.call(arguments, 0, 3);
				node = args.length > 1 ? args.shift() : document;
				handler = args[0];

				unwatches = [];
				events.forEach(function (event) {
					// create a handler for each event
					unwatches.push(on(node, event, handler, events.selector));
				});
				// return unwatcher of all events
				return function () {
					unwatches.forEach(function (unwatch) { unwatch(); });
				};
			};
		}

	};

	function preventDefaultIfNav (e) {
		var node, nodeName, nodeType, isNavEvent;
		node = e.selectorTarget || e.target || e.srcElement;
		if (node) {
			nodeName = node.tagName;
			nodeType = node.type && node.type.toLowerCase();
			// catch links and submit buttons/inputs in forms
			isNavEvent = ('click' == e.type && 'A' == nodeName)
				|| ('submit' == nodeType && node.form)
				|| ('submit' == e.type && 'FORM' == nodeName);
			if (isNavEvent) {
				preventDefaultAlways(e);
			}
		}
	}

	function preventDefaultAlways (e) {
		e.preventDefault();
	}

	function stopPropagationAlways (e) {
		e.stopPropagation();
	}

	function never () {}

	function makeEventHandler (handler, prevent, stop) {
		var preventer, stopper;
		preventer = prevent == undef || prevent == 'auto'
			? preventDefaultIfNav
			: prevent ? preventDefaultAlways : never;
		stopper = stop ? stopPropagationAlways : never;

		// Use proxy.invoke instead of trying to call methods
		// directly on proxy.target
		return function (e) {
			preventer(e);
			stopper(e);
			return handler.apply(this, arguments);
		};
	}

	/**
	 * Splits an event-selector string into one or more combinations of
	 * selectors and event types.
	 * Examples:
	 *   ".target:click" --> {selector: '.target', event: 'click' }
	 *   ".mylist:first-child:click, .mylist:last-child:click" --> [
	 *     { selector: '.mylist:first-child', event: 'click' },
	 *     { selector: '.mylist:last-child', event: 'click' }
	 *   ]
	 *   ".mylist:first-child, .mylist:last-child:click" --> {
	 *     selector: '.mylist:first-child, .mylist:last-child',
	 *     event: 'click'
	 *   }
	 * @private
	 * @param string {String}
	 * @param defaultSelector {String}
	 * @returns {Array} an array of event names. if a selector was specified
	 *   the array has a selectors {String} property
	 */
	function splitEventSelectorString (string, defaultSelector) {
		var split, events, selectors;

		// split on first colon to get events and selectors
		split = string.split(':', 2);
		events = split[0];
		selectors = split[1] || defaultSelector;

		// look for css stuff in event (dev probably forgot event?)
		// css stuff: hash, dot, spaces without a comma
		if (thisLooksLikeCssRx.test(events)) {
			throw new Error('on! resolver: malformed event-selector string (event missing?)');
		}

		// split events
		events = events.split(eventSplitterRx);
		if (selectors) {
			events.selector = selectors;
		}

		return events;
	}

});
}(typeof define == 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
<commit_msg>Improve handling of submit buttons when determining when to preventDefault to avoid navigation.<commit_after>/** @license MIT License (c) copyright B Cavalier & J Hann */

/**
 * wire/plugin-base/on
 *
 * wire is part of the cujo.js family of libraries (http://cujojs.com/)
 *
 * Licensed under the MIT License at:
 * http://www.opensource.org/licenses/mit-license.php
 */
(function (define) {
define(function (require) {
'use strict';

	var when, apply, functional, connection,
		theseAreNotEvents, thisLooksLikeCssRx, eventSplitterRx, undef;

	when = require('when');
	apply = require('when/apply');
	functional = require('../functional');
	connection = require('../connection');

	theseAreNotEvents = {
		selector: 1,
		transform: 1,
		preventDefault: 1,
		stopPropagation: 1
	};

	thisLooksLikeCssRx = /#|\.|-|[^,]\s[^,]/;
	eventSplitterRx = /\s*,\s*/;

	return function createOnPlugin (options) {
		var on;

		on = options.on;

		return function eventsPlugin (options) {

			var removers = [];

			if (!options) {
				options = {};
			}

			function createConnection(nodeProxy, eventsString, handler) {
				var events, node, prevent, stop;

				events = splitEventSelectorString(eventsString);
				node = nodeProxy.target;
				prevent = options.preventDefault;
				stop = options.stopPropagation;

				removers = removers.concat(
					registerHandlers(events, node, handler, prevent, stop)
				);
			}

			function parseIncomingOn(srcProxy, targetProxy, connections, wire) {

				// NOTE: Custom parsing for incoming connections

				// target is the node to which to connect, and
				// right hand side is a specification of an event
				// and a handler method on the current component
				//
				//	component: {
				//		on: {
				//			otherComponent: {
				//				selector: 'a.nav',
				//				transform: { $ref: 'myTransformFunc' }, // optional
				//				click: 'handlerMethodOnComponent',
				//				keypress: 'anotherHandlerOnComponent'
				//			}
				//		}
				//	}
				var target, event, events, selector, prevent, stop, method, transform, promises;

				target = targetProxy.target;
				promises = [];

				// Extract options
				selector = connections.selector;
				transform = connections.transform;
				prevent = connections.preventDefault || options.preventDefault;
				stop = connections.stopPropagation || options.stopPropagation;

				/**
				 * Compose a transform pipeline and then pass it to addConnection
				 */
				function createTransformedConnection(events, targetMethod, transformPromise) {
					return when(transformPromise, function(transform) {
						var composed, node;

						node = srcProxy.target;
						composed = functional.compose([transform, targetMethod]);
							//.bind(targetProxy.target);

						removers = removers.concat(
							registerHandlers(events, node, function() {
								return targetProxy.invoke(composed, arguments);
							}, prevent, stop)
						);
					});
				}

				for (event in connections) {
					// Skip reserved names, such as 'selector'
					if (!(event in theseAreNotEvents)) {
						// If there's an explicit transform, compose a transform pipeline manually,
						// Otherwise, let the connection lib do it's thing
						if(transform) {
							// TODO: Remove this long form?  It'd simplify the code a lot
							events = splitEventSelectorString(event, selector);
							method = connections[event];
							promises.push(createTransformedConnection(events, target[method], wire(transform)));
						} else {
							promises.push(connection.parseIncoming(srcProxy, event, targetProxy, options, connections[event], wire, createConnection));
						}
					}
				}

				return when.all(promises);
			}

			function parseOn (proxy, refName, connections, wire) {
				// First, figure out if the left-hand-side is a ref to
				// another component, or an event/delegation string
				return when(wire.getProxy(refName),
					function (srcProxy) {
						// It's an incoming connection, parse it as such
						return parseIncomingOn(srcProxy, proxy, connections, wire);
					},
					function () {
						// Failed to resolve refName as a reference, assume it
						// is an outgoing event with the current component (which
						// must be a Node) as the source
						return connection.parseOutgoing(proxy, refName, connections, wire, createConnection);
					}
				);

			}

			function onFacet (wire, facet) {
				var promises, connections;

				connections = facet.options;
				promises = [];

				for (var ref in connections) {
					promises.push(parseOn(facet, ref, connections[ref], wire));
				}

				return when.all(promises);
			}

			return {
				context: {
					destroy: function(resolver) {
						removers.forEach(function(remover) {
							remover();
						});
						resolver.resolve();
					}
				},
				facets: {
					on: {
						connect: function (resolver, facet, wire) {
							resolver.resolve(onFacet(wire, facet));
						}
					}
				},
				resolvers: {
					on: function(resolver, name /*, refObj, wire*/) {
						resolver.resolve(name ? createOnResolver(name) : on);
					}
				}
			};
		};

		function registerHandlers (events, node, callback, prevent, stop) {
			var removers, handler;
			removers = [];
			for (var i = 0, len = events.length; i < len; i++) {
				handler = makeEventHandler(callback, prevent, stop);
				removers.push(on(node, events[i], handler, events.selector));
			}
			return removers;
		}

		/**
		 * Returns a function that creates event handlers.  The event handlers
		 * are pre-configured with one or more selectors and one
		 * or more event types.  The syntax is identical to the "on" facet.
		 * Note that the returned handler does not auto-magically call
		 * event.preventDefault() or event.stopPropagation() like the "on"
		 * facet does.
		 * @private
		 * @param eventSelector {String} event/selector string that can be
		 *   parsed by splitEventSelectorString()
		 * @return {Function} a function that can be used to create event
		 *   handlers. It returns an "unwatch" function and takes any of
		 *   the following argument signatures:
		 *     function (handler) {}
		 *     function (rootNode, handler) {}
		 */
		function createOnResolver (eventSelector) {
			var events;
			// split event/selector string
			events = splitEventSelectorString(eventSelector, '');
			return function () {
				var args, node, handler, unwatches;
				// resolve arguments
				args = Array.prototype.slice.call(arguments, 0, 3);
				node = args.length > 1 ? args.shift() : document;
				handler = args[0];

				unwatches = [];
				events.forEach(function (event) {
					// create a handler for each event
					unwatches.push(on(node, event, handler, events.selector));
				});
				// return unwatcher of all events
				return function () {
					unwatches.forEach(function (unwatch) { unwatch(); });
				};
			};
		}

	};

	function preventDefaultIfNav (e) {
		var node, nodeName, nodeType, isNavEvent;
		node = e.selectorTarget || e.target || e.srcElement;
		if (node) {
			nodeName = node.tagName;
			nodeType = node.type && node.type.toLowerCase();
			// catch links and submit buttons/inputs in forms
			isNavEvent = ('click' == e.type && 'A' == nodeName)
				|| ('click' == e.type && 'submit' == nodeType && node.form)
				|| ('submit' == e.type && 'FORM' == nodeName);
			if (isNavEvent) {
				preventDefaultAlways(e);
			}
		}
	}

	function preventDefaultAlways (e) {
		e.preventDefault();
	}

	function stopPropagationAlways (e) {
		e.stopPropagation();
	}

	function never () {}

	function makeEventHandler (handler, prevent, stop) {
		var preventer, stopper;
		preventer = prevent == undef || prevent == 'auto'
			? preventDefaultIfNav
			: prevent ? preventDefaultAlways : never;
		stopper = stop ? stopPropagationAlways : never;

		// Use proxy.invoke instead of trying to call methods
		// directly on proxy.target
		return function (e) {
			preventer(e);
			stopper(e);
			return handler.apply(this, arguments);
		};
	}

	/**
	 * Splits an event-selector string into one or more combinations of
	 * selectors and event types.
	 * Examples:
	 *   ".target:click" --> {selector: '.target', event: 'click' }
	 *   ".mylist:first-child:click, .mylist:last-child:click" --> [
	 *     { selector: '.mylist:first-child', event: 'click' },
	 *     { selector: '.mylist:last-child', event: 'click' }
	 *   ]
	 *   ".mylist:first-child, .mylist:last-child:click" --> {
	 *     selector: '.mylist:first-child, .mylist:last-child',
	 *     event: 'click'
	 *   }
	 * @private
	 * @param string {String}
	 * @param defaultSelector {String}
	 * @returns {Array} an array of event names. if a selector was specified
	 *   the array has a selectors {String} property
	 */
	function splitEventSelectorString (string, defaultSelector) {
		var split, events, selectors;

		// split on first colon to get events and selectors
		split = string.split(':', 2);
		events = split[0];
		selectors = split[1] || defaultSelector;

		// look for css stuff in event (dev probably forgot event?)
		// css stuff: hash, dot, spaces without a comma
		if (thisLooksLikeCssRx.test(events)) {
			throw new Error('on! resolver: malformed event-selector string (event missing?)');
		}

		// split events
		events = events.split(eventSplitterRx);
		if (selectors) {
			events.selector = selectors;
		}

		return events;
	}

});
}(typeof define == 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
<|endoftext|>


<commit_before>$(window).ready(function() {

// Safari compatibility
window.URL = window.URL || window.webkitURL

var files = {}
var rcvFile = {}
var fileMIME = new RegExp('^(image\/(png|jpeg|gif))|(application\/((x-compressed)|(x-zip-compressed)|(zip)'
	+ '|(x-zip)|(x-zip-compressed)|(x-compress)|(x-compressed)))|(multipart/x-zip)$'
)

function cn(to) {
	return Cryptocat.conversationName + '@' + Cryptocat.conferenceServer + '/' + to
}

Cryptocat.beginSendFile = function(data) {
	if (!data.file.type.match(fileMIME)) {
		$('#fileInfoField').text(Cryptocat.language['chatWindow']['fileTypeError'])
		return
	}
	else if (data.file.size > (Cryptocat.fileSize * 1024)) {
		$('#fileInfoField').text(Cryptocat.language['chatWindow']['fileSizeError'])
		return
	}
	else {
		window.setTimeout(function() {
			$('#dialogBoxClose').click()
		}, 500)
	}
	var sid = Cryptocat.connection.getUniqueId()
	files[sid] = {
		to: data.to,
		position: 0,
		file: data.file,
		key: data.key,
		total: Math.ceil(data.file.size / Cryptocat.chunkSize),
		ctr: -1
	}
	/*jshint -W106 */
	Cryptocat.connection.si_filetransfer.send(
	/*jshint +W106 */
		cn(data.to),
		sid,
		data.filename,
		data.file.size,
		data.file.type,
		function(err) {
			if (err) {
				return console.log(err)
			}
			Cryptocat.connection.ibb.open(cn(data.to), sid, Cryptocat.chunkSize, function(err) {
				if (err) {
					return console.log(err)
				}
				Cryptocat.addToConversation(sid, Cryptocat.myNickname, data.to, 'file')
				Cryptocat.sendFileData({
					start: true,
					to: data.to,
					sid: sid
				})
			})
		}
	)
}

Cryptocat.sendFileData = function(data) {
	var sid = data.sid
	var seq = data.start ? 0 : parseInt(data.seq, 10) + 1
	if (seq > 65535) {
		seq = 0
	}
	if (files[sid].position > files[sid].file.size) {
		Cryptocat.connection.ibb.close(cn(data.to), sid, function(err) {
			if (err) {
				return console.log(err)
			}
		})
		Cryptocat.updateFileProgressBar(sid, files[sid].ctr + 1, files[sid].file.size, data.to)
		return
	}
	// Split into chunk
	var end = files[sid].position + Cryptocat.chunkSize
	// Check for slice function on file
	var sliceStr = files[sid].file.slice ? 'slice' : 'webkitSlice'
	var chunk = files[sid].file[sliceStr](files[sid].position, end)
	files[sid].position = end
	files[sid].ctr += 1
	var reader = new FileReader()
	reader.onload = function(event) {
		var msg = event.target.result
		// Remove dataURL header
		msg = msg.split(',')[1]
		// Encrypt
		// don't use seq as a counter
		// it repeats after 65535 above
		var opts = {
			mode: CryptoJS.mode.CTR,
			iv: CryptoJS.enc.Latin1.parse(OTR.HLP.packCtr(files[sid].ctr)),
			padding: CryptoJS.pad.NoPadding
		}
		var aesctr = CryptoJS.AES.encrypt (
			CryptoJS.enc.Base64.parse(msg),
			CryptoJS.enc.Latin1.parse(files[sid].key[0]),
			opts
		)
		msg = aesctr.toString()
		// Then mac
		var prefix = OTR.HLP.packBytes(files[sid].ctr, 8)
		prefix += OTR.HLP.packBytes(files[sid].total, 8)
		var mac = CryptoJS.HmacSHA512(
			CryptoJS.enc.Base64.parse(prefix + msg),
			CryptoJS.enc.Latin1.parse(files[sid].key[1])
		)
		// Combine ciphertext and mac, then transfer chunk
		msg += mac.toString(CryptoJS.enc.Base64)
		Cryptocat.connection.ibb.data(cn(data.to), sid, seq, msg, function(err) {
			if (err) {
				return console.log(err)
			}
			Cryptocat.sendFileData({
				seq: seq,
				to: data.to,
				sid: sid
			})
		})
		Cryptocat.updateFileProgressBar(sid, files[sid].ctr + 1, files[sid].file.size, data.to)
	}
	reader.readAsDataURL(chunk)
}

// make sure current Safari is at least <version>
function matchSafariVersion(version) {
	var match = navigator.userAgent.match(/\bversion\/(\d+)\.(\d+)\.(\d+)/i)
	if (match == null) {
		return false
	}
	match = match.slice(1).map(function (i) {
		return parseInt(i, 10)
	})
	function ver(arr, pos) {
		if (arr[pos] > version[pos]) {
			return true
		}
		if (arr[pos] === version[pos]) {
			if (pos === version.length) {
				return true
			}
			pos += 1
			return ver(arr, pos)
		}
		return false
	}
	return ver(match, 0)
}

Cryptocat.ibbHandler = function(type, from, sid, data, seq) {
	var nick = from.split('/')[1]
	switch (type) {
		case 'open':
			var file = rcvFile[from][sid].filename
			rcvFile[from][sid].key = Cryptocat.fileKeys[nick][file]
			if (sid.match(/^\w{64}$/) && rcvFile[from][sid].mime.match(fileMIME)) {
				Cryptocat.addToConversation(sid, nick, nick, 'file')
			}
			delete Cryptocat.fileKeys[nick][file]
			break
		case 'data':
			if (rcvFile[from][sid].abort) {
				return
			}
			if (rcvFile[from][sid].ctr > rcvFile[from][sid].total - 1) {
				rcvFile[from][sid].abort = true
				Cryptocat.fileTransferError(sid)
				return
			}
			rcvFile[from][sid].seq = seq
			var key = rcvFile[from][sid].key
			var ss = data.length - 88
			var msg = data.substring(0, ss)
			var mac = data.substring(ss)
			var prefix = OTR.HLP.packBytes(rcvFile[from][sid].ctr, 8)
			prefix += OTR.HLP.packBytes(rcvFile[from][sid].total, 8)
			var cmac = CryptoJS.HmacSHA512(
				CryptoJS.enc.Base64.parse(prefix + msg),
				CryptoJS.enc.Latin1.parse(key[1])
			)
			if (mac !== cmac.toString(CryptoJS.enc.Base64)) {
				rcvFile[from][sid].abort = true
				Cryptocat.fileTransferError(sid)
				console.log('OTR file transfer: MACs do not match.')
				return
			}
			var opts = {
				mode: CryptoJS.mode.CTR,
				iv: CryptoJS.enc.Latin1.parse(OTR.HLP.packCtr(rcvFile[from][sid].ctr)),
				padding: CryptoJS.pad.NoPadding
			}
			msg = CryptoJS.AES.decrypt(msg, CryptoJS.enc.Latin1.parse(key[0]), opts)
			rcvFile[from][sid].data += (msg.toString(CryptoJS.enc.Latin1))
			rcvFile[from][sid].ctr += 1
			Cryptocat.updateFileProgressBar(sid, rcvFile[from][sid].ctr, rcvFile[from][sid].size, nick)
			break
		case 'close':
			if (!rcvFile[from][sid].abort && rcvFile[from][sid].total === rcvFile[from][sid].ctr) {
				var url
				if (navigator.userAgent.match('Safari')) {
					// Safari older than 6.0.5 can only support 128kb
					if (!matchSafariVersion([6, 0, 5]) &&
						rcvFile[from][sid].size >= 131072) {
						Cryptocat.fileTransferError(sid)
						console.log('File size is too large for this version of Safari')
						;delete rcvFile[from][sid]
						return
					}
					url = 'data:application/octet-stream;base64,' +
						CryptoJS.enc.Latin1
							.parse(rcvFile[from][sid].data)
							.toString(CryptoJS.enc.Base64)
				}
				else {
					// Convert data to blob
					var ia = new Uint8Array(rcvFile[from][sid].data.length)
					for (var i = 0; i < rcvFile[from][sid].data.length; i++) {
						ia[i] = rcvFile[from][sid].data.charCodeAt(i)
					}
					var blob = new Blob([ia], { type: rcvFile[from][sid].mime })
					url = window.URL.createObjectURL(blob)
				}
				if (rcvFile[from][sid].filename.match(/^[\w-.]+$/)
				&& rcvFile[from][sid].mime.match(fileMIME)) {
					Cryptocat.addFile(url, sid, nick, rcvFile[from][sid].filename)
				}
				else {
					Cryptocat.fileTransferError(sid)
					console.log('Received file of unallowed file type ' +
						rcvFile[from][sid].mime + ' from ' + nick)
				}
			}
			delete rcvFile[from][sid]
			break
	}
}

Cryptocat.fileHandler = function(from, sid, filename, size, mime) {
	if (!rcvFile[from]) {
		rcvFile[from] = {}
	}
	rcvFile[from][sid] = {
		filename: filename,
		size: size,
		mime: mime,
		seq: 0,
		ctr: 0,
		total: Math.ceil(size / Cryptocat.chunkSize),
		abort: false,
		data: ''
	}
}

})<commit_msg>zero based<commit_after>$(window).ready(function() {

// Safari compatibility
window.URL = window.URL || window.webkitURL

var files = {}
var rcvFile = {}
var fileMIME = new RegExp('^(image\/(png|jpeg|gif))|(application\/((x-compressed)|(x-zip-compressed)|(zip)'
	+ '|(x-zip)|(x-zip-compressed)|(x-compress)|(x-compressed)))|(multipart/x-zip)$'
)

function cn(to) {
	return Cryptocat.conversationName + '@' + Cryptocat.conferenceServer + '/' + to
}

Cryptocat.beginSendFile = function(data) {
	if (!data.file.type.match(fileMIME)) {
		$('#fileInfoField').text(Cryptocat.language['chatWindow']['fileTypeError'])
		return
	}
	else if (data.file.size > (Cryptocat.fileSize * 1024)) {
		$('#fileInfoField').text(Cryptocat.language['chatWindow']['fileSizeError'])
		return
	}
	else {
		window.setTimeout(function() {
			$('#dialogBoxClose').click()
		}, 500)
	}
	var sid = Cryptocat.connection.getUniqueId()
	files[sid] = {
		to: data.to,
		position: 0,
		file: data.file,
		key: data.key,
		total: Math.ceil(data.file.size / Cryptocat.chunkSize),
		ctr: -1
	}
	/*jshint -W106 */
	Cryptocat.connection.si_filetransfer.send(
	/*jshint +W106 */
		cn(data.to),
		sid,
		data.filename,
		data.file.size,
		data.file.type,
		function(err) {
			if (err) {
				return console.log(err)
			}
			Cryptocat.connection.ibb.open(cn(data.to), sid, Cryptocat.chunkSize, function(err) {
				if (err) {
					return console.log(err)
				}
				Cryptocat.addToConversation(sid, Cryptocat.myNickname, data.to, 'file')
				Cryptocat.sendFileData({
					start: true,
					to: data.to,
					sid: sid
				})
			})
		}
	)
}

Cryptocat.sendFileData = function(data) {
	var sid = data.sid
	var seq = data.start ? 0 : parseInt(data.seq, 10) + 1
	if (seq > 65535) {
		seq = 0
	}
	if (files[sid].position > files[sid].file.size) {
		Cryptocat.connection.ibb.close(cn(data.to), sid, function(err) {
			if (err) {
				return console.log(err)
			}
		})
		Cryptocat.updateFileProgressBar(sid, files[sid].ctr + 1, files[sid].file.size, data.to)
		return
	}
	// Split into chunk
	var end = files[sid].position + Cryptocat.chunkSize
	// Check for slice function on file
	var sliceStr = files[sid].file.slice ? 'slice' : 'webkitSlice'
	var chunk = files[sid].file[sliceStr](files[sid].position, end)
	files[sid].position = end
	files[sid].ctr += 1
	var reader = new FileReader()
	reader.onload = function(event) {
		var msg = event.target.result
		// Remove dataURL header
		msg = msg.split(',')[1]
		// Encrypt
		// don't use seq as a counter
		// it repeats after 65535 above
		var opts = {
			mode: CryptoJS.mode.CTR,
			iv: CryptoJS.enc.Latin1.parse(OTR.HLP.packCtr(files[sid].ctr)),
			padding: CryptoJS.pad.NoPadding
		}
		var aesctr = CryptoJS.AES.encrypt (
			CryptoJS.enc.Base64.parse(msg),
			CryptoJS.enc.Latin1.parse(files[sid].key[0]),
			opts
		)
		msg = aesctr.toString()
		// Then mac
		var prefix = OTR.HLP.packBytes(files[sid].ctr, 8)
		prefix += OTR.HLP.packBytes(files[sid].total, 8)
		var mac = CryptoJS.HmacSHA512(
			CryptoJS.enc.Base64.parse(prefix + msg),
			CryptoJS.enc.Latin1.parse(files[sid].key[1])
		)
		// Combine ciphertext and mac, then transfer chunk
		msg += mac.toString(CryptoJS.enc.Base64)
		Cryptocat.connection.ibb.data(cn(data.to), sid, seq, msg, function(err) {
			if (err) {
				return console.log(err)
			}
			Cryptocat.sendFileData({
				seq: seq,
				to: data.to,
				sid: sid
			})
		})
		Cryptocat.updateFileProgressBar(sid, files[sid].ctr + 1, files[sid].file.size, data.to)
	}
	reader.readAsDataURL(chunk)
}

// make sure current Safari is at least <version>
function matchSafariVersion(version) {
	var match = navigator.userAgent.match(/\bversion\/(\d+)\.(\d+)\.(\d+)/i)
	if (match == null) {
		return false
	}
	match = match.slice(1).map(function (i) {
		return parseInt(i, 10)
	})
	function ver(arr, pos) {
		if (arr[pos] > version[pos]) {
			return true
		}
		if (arr[pos] === version[pos]) {
			pos += 1
			if (pos === version.length) {
				return true
			}
			return ver(arr, pos)
		}
		return false
	}
	return ver(match, 0)
}

Cryptocat.ibbHandler = function(type, from, sid, data, seq) {
	var nick = from.split('/')[1]
	switch (type) {
		case 'open':
			var file = rcvFile[from][sid].filename
			rcvFile[from][sid].key = Cryptocat.fileKeys[nick][file]
			if (sid.match(/^\w{64}$/) && rcvFile[from][sid].mime.match(fileMIME)) {
				Cryptocat.addToConversation(sid, nick, nick, 'file')
			}
			delete Cryptocat.fileKeys[nick][file]
			break
		case 'data':
			if (rcvFile[from][sid].abort) {
				return
			}
			if (rcvFile[from][sid].ctr > rcvFile[from][sid].total - 1) {
				rcvFile[from][sid].abort = true
				Cryptocat.fileTransferError(sid)
				return
			}
			rcvFile[from][sid].seq = seq
			var key = rcvFile[from][sid].key
			var ss = data.length - 88
			var msg = data.substring(0, ss)
			var mac = data.substring(ss)
			var prefix = OTR.HLP.packBytes(rcvFile[from][sid].ctr, 8)
			prefix += OTR.HLP.packBytes(rcvFile[from][sid].total, 8)
			var cmac = CryptoJS.HmacSHA512(
				CryptoJS.enc.Base64.parse(prefix + msg),
				CryptoJS.enc.Latin1.parse(key[1])
			)
			if (mac !== cmac.toString(CryptoJS.enc.Base64)) {
				rcvFile[from][sid].abort = true
				Cryptocat.fileTransferError(sid)
				console.log('OTR file transfer: MACs do not match.')
				return
			}
			var opts = {
				mode: CryptoJS.mode.CTR,
				iv: CryptoJS.enc.Latin1.parse(OTR.HLP.packCtr(rcvFile[from][sid].ctr)),
				padding: CryptoJS.pad.NoPadding
			}
			msg = CryptoJS.AES.decrypt(msg, CryptoJS.enc.Latin1.parse(key[0]), opts)
			rcvFile[from][sid].data += (msg.toString(CryptoJS.enc.Latin1))
			rcvFile[from][sid].ctr += 1
			Cryptocat.updateFileProgressBar(sid, rcvFile[from][sid].ctr, rcvFile[from][sid].size, nick)
			break
		case 'close':
			if (!rcvFile[from][sid].abort && rcvFile[from][sid].total === rcvFile[from][sid].ctr) {
				var url
				if (navigator.userAgent.match('Safari')) {
					// Safari older than 6.0.5 can only support 128kb
					if (!matchSafariVersion([6, 0, 5]) &&
						rcvFile[from][sid].size >= 131072) {
						Cryptocat.fileTransferError(sid)
						console.log('File size is too large for this version of Safari')
						;delete rcvFile[from][sid]
						return
					}
					url = 'data:application/octet-stream;base64,' +
						CryptoJS.enc.Latin1
							.parse(rcvFile[from][sid].data)
							.toString(CryptoJS.enc.Base64)
				}
				else {
					// Convert data to blob
					var ia = new Uint8Array(rcvFile[from][sid].data.length)
					for (var i = 0; i < rcvFile[from][sid].data.length; i++) {
						ia[i] = rcvFile[from][sid].data.charCodeAt(i)
					}
					var blob = new Blob([ia], { type: rcvFile[from][sid].mime })
					url = window.URL.createObjectURL(blob)
				}
				if (rcvFile[from][sid].filename.match(/^[\w-.]+$/)
				&& rcvFile[from][sid].mime.match(fileMIME)) {
					Cryptocat.addFile(url, sid, nick, rcvFile[from][sid].filename)
				}
				else {
					Cryptocat.fileTransferError(sid)
					console.log('Received file of unallowed file type ' +
						rcvFile[from][sid].mime + ' from ' + nick)
				}
			}
			delete rcvFile[from][sid]
			break
	}
}

Cryptocat.fileHandler = function(from, sid, filename, size, mime) {
	if (!rcvFile[from]) {
		rcvFile[from] = {}
	}
	rcvFile[from][sid] = {
		filename: filename,
		size: size,
		mime: mime,
		seq: 0,
		ctr: 0,
		total: Math.ceil(size / Cryptocat.chunkSize),
		abort: false,
		data: ''
	}
}

})<|endoftext|>


<commit_before>var exec = require('cordova/exec'),
    utils = require('cordova/utils'),
    timers = {},
    compass = {
        /**
         * Asynchronously acquires the current heading.
         * @param {Function} successCallback The function to call when the heading
         * data is available
         * @param {Function} errorCallback The function to call when there is an error
         * getting the heading data.
         * @param {CompassOptions} options The options for getting the heading data (not used).
         */
        getCurrentHeading:function(successCallback, errorCallback, options) {
            // successCallback required
            if (typeof successCallback !== "function") {
              console.log("Compass Error: successCallback is not a function");
              return;
            }

            // errorCallback optional
            if (errorCallback && (typeof errorCallback !== "function")) {
              console.log("Compass Error: errorCallback is not a function");
              return;
            }

            var win = function(result) {
                if (result.timestamp) {
                    var timestamp = new Date(result.timestamp);
                    result.timestamp = timestamp;
                }
                successCallback(result);
            };

            // Get heading
            exec(win, errorCallback, "Compass", "getHeading", []);
        },

        /**
         * Asynchronously acquires the heading repeatedly at a given interval.
         * @param {Function} successCallback The function to call each time the heading
         * data is available
         * @param {Function} errorCallback The function to call when there is an error
         * getting the heading data.
         * @param {HeadingOptions} options The options for getting the heading data
         * such as timeout and the frequency of the watch.
         */
        watchHeading:function(successCallback, errorCallback, options) {
            // Default interval (100 msec)
            var frequency = (options !== undefined && options.frequency !== undefined) ? options.frequency : 100;

            // successCallback required
            if (typeof successCallback !== "function") {
              console.log("Compass Error: successCallback is not a function");
              return;
            }

            // errorCallback optional
            if (errorCallback && (typeof errorCallback !== "function")) {
              console.log("Compass Error: errorCallback is not a function");
              return;
            }

            // Start watch timer to get headings
            var id = utils.createUUID();
            timers[id] = setInterval(function() {
                var win = function(result) {
                    if (result.timestamp) {
                        var timestamp = new Date(result.timestamp);
                        result.timestamp = timestamp;
                    }
                    successCallback(result);
                 };
                 exec(win, errorCallback, "Compass", "getHeading", []);
            }, frequency);

            return id;
        },

        /**
         * Clears the specified heading watch.
         * @param {String} watchId The ID of the watch returned from #watchHeading.
         */
        clearWatch:function(id) {
            // Stop javascript timer & remove from timer list
            if (id && timers[id]) {
              clearInterval(timers[id]);
              delete timers[id];
            }
        }
    };

module.exports = compass;
<commit_msg>moving function wrapper outside of setinterval, probably dont wanna define a function every execution<commit_after>var exec = require('cordova/exec'),
    utils = require('cordova/utils'),
    timers = {},
    compass = {
        /**
         * Asynchronously acquires the current heading.
         * @param {Function} successCallback The function to call when the heading
         * data is available
         * @param {Function} errorCallback The function to call when there is an error
         * getting the heading data.
         * @param {CompassOptions} options The options for getting the heading data (not used).
         */
        getCurrentHeading:function(successCallback, errorCallback, options) {
            // successCallback required
            if (typeof successCallback !== "function") {
              console.log("Compass Error: successCallback is not a function");
              return;
            }

            // errorCallback optional
            if (errorCallback && (typeof errorCallback !== "function")) {
              console.log("Compass Error: errorCallback is not a function");
              return;
            }

            var win = function(result) {
                if (result.timestamp) {
                    var timestamp = new Date(result.timestamp);
                    result.timestamp = timestamp;
                }
                successCallback(result);
            };

            // Get heading
            exec(win, errorCallback, "Compass", "getHeading", []);
        },

        /**
         * Asynchronously acquires the heading repeatedly at a given interval.
         * @param {Function} successCallback The function to call each time the heading
         * data is available
         * @param {Function} errorCallback The function to call when there is an error
         * getting the heading data.
         * @param {HeadingOptions} options The options for getting the heading data
         * such as timeout and the frequency of the watch.
         */
        watchHeading:function(successCallback, errorCallback, options) {
            // Default interval (100 msec)
            var frequency = (options !== undefined && options.frequency !== undefined) ? options.frequency : 100;

            // successCallback required
            if (typeof successCallback !== "function") {
              console.log("Compass Error: successCallback is not a function");
              return;
            }

            // errorCallback optional
            if (errorCallback && (typeof errorCallback !== "function")) {
              console.log("Compass Error: errorCallback is not a function");
              return;
            }

            // Start watch timer to get headings
            var id = utils.createUUID();
            var win = function(result) {
                if (result.timestamp) {
                    var timestamp = new Date(result.timestamp);
                    result.timestamp = timestamp;
                }
                successCallback(result);
            };
            timers[id] = setInterval(function() {
                 exec(win, errorCallback, "Compass", "getHeading", []);
            }, frequency);

            return id;
        },

        /**
         * Clears the specified heading watch.
         * @param {String} watchId The ID of the watch returned from #watchHeading.
         */
        clearWatch:function(id) {
            // Stop javascript timer & remove from timer list
            if (id && timers[id]) {
              clearInterval(timers[id]);
              delete timers[id];
            }
        }
    };

module.exports = compass;
<|endoftext|>


<commit_before>var fs          = require('fs')
  , EventBroker = require('observer').EventBroker
  , longjohn    = require('longjohn')
  , stacktrace  = require('stack-trace')
  , winston     = require('winston')
  , util        = require('util')
  ;

process.addListener("uncaughtException", function (err) {
  var logger;

  try {
    logger = exports.logger('steward');
    logger.alert('exception', { diagnostic: err.message });
    logger.alert('exception', { stack: JSON.stringify(stacktrace.parse(err)) });
  } catch(ex) {}

  console.log('uncaught exception: ' + err);
  console.trace();

  process.exit(1);
});

// winston.exitErrs = false;

var broker = exports.broker = new EventBroker();
var signals = exports.signals = {};

var beacon_ingress = function(category, level, message, meta) {
  var data = signals[category] || [];

  var datum = { date: new Date().toISOString(), level: level, message: message, meta: meta };

  data.push(datum);
  if (data.length > 50) data.splice(0, 1);

  signals[category] = data;

  if (broker.has('beacon-egress')) broker.publish('beacon-egress', category, datum);
};

exports.start = function() {
  broker.create('beacon-ingress');
  broker.subscribe('beacon-ingress', beacon_ingress);
  broker.create('beacon-egress');
  broker.create('actors');
  broker.create('discovery');
  broker.create('readings');
  broker.create('status');
};

var logconfigs = {
    climate   : { console: { level: 'debug'  } }
  , devices   : { console: { level: 'info'   } }
  , discovery : { console: { level: 'info'   } }
  , gateway   : { console: { level: 'info'   } }
  , indicator : { console: { level: 'notice' } }
  , lighting  : { console: { level: 'notice' } }
  , manage    : { console: { level: 'notice' } }
  , media     : { console: { level: 'debug'  } }
  , motive    : { console: { level: 'debug'  } }
  , presence  : { console: { level: 'info'   } }
  , sensor    : { console: { level: 'info'   } }
  , server    : { console: { level: 'info'   } }
  , steward   : { console: { level: 'notice' } }
  , 'switch'  : { console: { level: 'info'   } }
  , wearable  : { console: { level: 'debug'  } }
};

exports.logger = function(x) {
  if (winston.loggers.has(x)) return winston.loggers.get(x);
  var logger = winston.loggers.add(x, logconfigs[x] || { console: { level: 'debug' } });
  logger.setLevels(winston.config.syslog.levels);

  logger.logaux = logger.log;
  logger.log = function loggerLog(level, msg) {
    var callback, meta;

    if (arguments.length === 3) {
      if (typeof arguments[2] === 'function') {
        meta = {};
        callback = arguments[2];
      }
      else if (typeof arguments[2] === 'object') meta = arguments[2];
    }
    else if (arguments.length === 4) {
      meta = arguments[2];
      callback = arguments[3];
    }

    switch (level) {
      case 'debug':
        break;

      default:
        beacon_ingress(x, level, msg, meta);
        break;
    }

    this.logaux(level, '[' + x + '] ' + msg, meta, callback);
  };

  logger.debug('begin');
  return logger;
};

exports.acquire = function(log, directory, pattern, start, stop, suffix, arg) {
  fs.readdir(directory, function(err, files) {
    var file, i;

    if (err) {
      log.error('readdir', { diagnostic: err.message });
      return;
    }

    for (i = 0; i < files.length; i++) {
      file = files[i];
      if (file.match(pattern)) {
        log.info('loading ' + file.slice(start, stop) + suffix);
        require(directory + '/' + file).start(arg);
       }
    }
  });

};

// http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/

exports.toType = function(obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
};

// http://stackoverflow.com/questions/3177836/how-to-format-time-since-xxx-e-g-4-minutes-ago-similar-to-stack-exchange-site

exports.relativity = function(time) {
  switch (typeof time) {
    case 'number':
      break;

    case 'string':
      time = +new Date(time);
      break;

    case 'object':
      if (time.constructor === Date) time = time.getTime();
      break;

    default:
      time = +new Date();
      break;
  }
  var time_formats = [
    [         60, 's'      ,                   1], // 60
    [        120, '1m',            '1m from now'], // 60*2
    [       3600, 'm',                        60], // 60*60, 60
    [       7200, '1h',            '1h from now'], // 60*60*2
    [      86400, 'h',                      3600], // 60*60*24, 60*60
    [     172800, 'yesterday',        'tomorrow'], // 60*60*24*2
    [     604800, 'd',                     86400], // 60*60*24*7, 60*60*24
    [    1209600, 'last week',       'next week'], // 60*60*24*7*4*2
    [    2419200, 'w',                    604800], // 60*60*24*7*4, 60*60*24*7
    [    4838400, 'last month',     'next month'], // 60*60*24*7*4*2
    [   29030400, 'months',              2419200], // 60*60*24*7*4*12, 60*60*24*7*4
    [   58060800, 'last year',       'next year'], // 60*60*24*7*4*12*2
    [ 2903040000, 'years',              29030400], // 60*60*24*7*4*12*100, 60*60*24*7*4*12
    [ 5806080000, 'last century', 'next century'], // 60*60*24*7*4*12*100*2
    [58060800000, 'centuries',        2903040000]  // 60*60*24*7*4*12*100*20, 60*60*24*7*4*12*100
  ];
  var seconds = (+new Date() - time) / 1000
    , token = 'ago'
    , list_choice = 1;

  if (seconds < 0) {
    seconds = Math.abs(seconds);
    token = 'from now';
    list_choice = 2;
  } else if (seconds < 1) {
    return 'now';
  }

  var i = 0
    , format;
  while (!!(format = time_formats[i++])) {
    if (seconds < format[0]) {
      if (typeof format[2] == 'string') return format[list_choice];
      return Math.floor(seconds / format[2]) + format[1] + ' ' + token;
    }
  }
  return time;
};

var clone = exports.clone = function(o) {
  var prop, result;

  if ((!o) || ((typeof o) !== 'object')) return o;

  result = util.isArray(o) ? [] : {};
  for (prop in o) if (o.hasOwnProperty(prop)) result[prop] = clone(o[prop]);
  return result;
};

exports.keys = function(values) {
  var key, keys;

  keys = [];
  for (key in values) if (values.hasOwnProperty(key)) keys.push(key);
  return keys;
};

exports.key2value = function(values, key) {
  var value = values[key.toLowerCase()];
  return (!!value) ? value : null;
};

exports.value2key = function(values, value) {
  var key;

  for (key in values) if ((values.hasOwnProperty(key)) && (values[key] === value)) return key;
  return null;
};
<commit_msg>remove spurious trace<commit_after>var fs          = require('fs')
  , EventBroker = require('observer').EventBroker
  , longjohn    = require('longjohn')
  , stacktrace  = require('stack-trace')
  , winston     = require('winston')
  , util        = require('util')
  ;

process.addListener("uncaughtException", function (err) {
  var logger;

  try {
    logger = exports.logger('steward');
    logger.alert('exception', { diagnostic: err.message });
    logger.alert('exception', { stack: JSON.stringify(stacktrace.parse(err)) });
  } catch(ex) {}

  console.log('uncaught exception: ' + err);

  process.exit(1);
});

// winston.exitErrs = false;

var broker = exports.broker = new EventBroker();
var signals = exports.signals = {};

var beacon_ingress = function(category, level, message, meta) {
  var data = signals[category] || [];

  var datum = { date: new Date().toISOString(), level: level, message: message, meta: meta };

  data.push(datum);
  if (data.length > 50) data.splice(0, 1);

  signals[category] = data;

  if (broker.has('beacon-egress')) broker.publish('beacon-egress', category, datum);
};

exports.start = function() {
  broker.create('beacon-ingress');
  broker.subscribe('beacon-ingress', beacon_ingress);
  broker.create('beacon-egress');
  broker.create('actors');
  broker.create('discovery');
  broker.create('readings');
  broker.create('status');
};

var logconfigs = {
    climate   : { console: { level: 'debug'  } }
  , devices   : { console: { level: 'info'   } }
  , discovery : { console: { level: 'info'   } }
  , gateway   : { console: { level: 'info'   } }
  , indicator : { console: { level: 'notice' } }
  , lighting  : { console: { level: 'notice' } }
  , manage    : { console: { level: 'notice' } }
  , media     : { console: { level: 'debug'  } }
  , motive    : { console: { level: 'debug'  } }
  , presence  : { console: { level: 'info'   } }
  , sensor    : { console: { level: 'info'   } }
  , server    : { console: { level: 'info'   } }
  , steward   : { console: { level: 'notice' } }
  , 'switch'  : { console: { level: 'info'   } }
  , wearable  : { console: { level: 'debug'  } }
};

exports.logger = function(x) {
  if (winston.loggers.has(x)) return winston.loggers.get(x);
  var logger = winston.loggers.add(x, logconfigs[x] || { console: { level: 'debug' } });
  logger.setLevels(winston.config.syslog.levels);

  logger.logaux = logger.log;
  logger.log = function loggerLog(level, msg) {
    var callback, meta;

    if (arguments.length === 3) {
      if (typeof arguments[2] === 'function') {
        meta = {};
        callback = arguments[2];
      }
      else if (typeof arguments[2] === 'object') meta = arguments[2];
    }
    else if (arguments.length === 4) {
      meta = arguments[2];
      callback = arguments[3];
    }

    switch (level) {
      case 'debug':
        break;

      default:
        beacon_ingress(x, level, msg, meta);
        break;
    }

    this.logaux(level, '[' + x + '] ' + msg, meta, callback);
  };

  logger.debug('begin');
  return logger;
};

exports.acquire = function(log, directory, pattern, start, stop, suffix, arg) {
  fs.readdir(directory, function(err, files) {
    var file, i;

    if (err) {
      log.error('readdir', { diagnostic: err.message });
      return;
    }

    for (i = 0; i < files.length; i++) {
      file = files[i];
      if (file.match(pattern)) {
        log.info('loading ' + file.slice(start, stop) + suffix);
        require(directory + '/' + file).start(arg);
       }
    }
  });

};

// http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/

exports.toType = function(obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
};

// http://stackoverflow.com/questions/3177836/how-to-format-time-since-xxx-e-g-4-minutes-ago-similar-to-stack-exchange-site

exports.relativity = function(time) {
  switch (typeof time) {
    case 'number':
      break;

    case 'string':
      time = +new Date(time);
      break;

    case 'object':
      if (time.constructor === Date) time = time.getTime();
      break;

    default:
      time = +new Date();
      break;
  }
  var time_formats = [
    [         60, 's'      ,                   1], // 60
    [        120, '1m',            '1m from now'], // 60*2
    [       3600, 'm',                        60], // 60*60, 60
    [       7200, '1h',            '1h from now'], // 60*60*2
    [      86400, 'h',                      3600], // 60*60*24, 60*60
    [     172800, 'yesterday',        'tomorrow'], // 60*60*24*2
    [     604800, 'd',                     86400], // 60*60*24*7, 60*60*24
    [    1209600, 'last week',       'next week'], // 60*60*24*7*4*2
    [    2419200, 'w',                    604800], // 60*60*24*7*4, 60*60*24*7
    [    4838400, 'last month',     'next month'], // 60*60*24*7*4*2
    [   29030400, 'months',              2419200], // 60*60*24*7*4*12, 60*60*24*7*4
    [   58060800, 'last year',       'next year'], // 60*60*24*7*4*12*2
    [ 2903040000, 'years',              29030400], // 60*60*24*7*4*12*100, 60*60*24*7*4*12
    [ 5806080000, 'last century', 'next century'], // 60*60*24*7*4*12*100*2
    [58060800000, 'centuries',        2903040000]  // 60*60*24*7*4*12*100*20, 60*60*24*7*4*12*100
  ];
  var seconds = (+new Date() - time) / 1000
    , token = 'ago'
    , list_choice = 1;

  if (seconds < 0) {
    seconds = Math.abs(seconds);
    token = 'from now';
    list_choice = 2;
  } else if (seconds < 1) {
    return 'now';
  }

  var i = 0
    , format;
  while (!!(format = time_formats[i++])) {
    if (seconds < format[0]) {
      if (typeof format[2] == 'string') return format[list_choice];
      return Math.floor(seconds / format[2]) + format[1] + ' ' + token;
    }
  }
  return time;
};

var clone = exports.clone = function(o) {
  var prop, result;

  if ((!o) || ((typeof o) !== 'object')) return o;

  result = util.isArray(o) ? [] : {};
  for (prop in o) if (o.hasOwnProperty(prop)) result[prop] = clone(o[prop]);
  return result;
};

exports.keys = function(values) {
  var key, keys;

  keys = [];
  for (key in values) if (values.hasOwnProperty(key)) keys.push(key);
  return keys;
};

exports.key2value = function(values, key) {
  var value = values[key.toLowerCase()];
  return (!!value) ? value : null;
};

exports.value2key = function(values, value) {
  var key;

  for (key in values) if ((values.hasOwnProperty(key)) && (values[key] === value)) return key;
  return null;
};
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

MODEL({
  name: 'PositionedViewTrait',
  properties: [
    { model_: 'IntProperty', name: 'x',      units: 'px', defaultValue: 0 },
    { model_: 'IntProperty', name: 'y',      units: 'px', defaultValue: 0 },
    { model_: 'IntProperty', name: 'z',      units: 'px', defaultValue: 0 },
    { model_: 'IntProperty', name: 'width',  units: 'px', defaultValue: 100 },
    { model_: 'IntProperty', name: 'height', units: 'px', defaultValue: 100 }
  ]
});

MODEL({
  name: 'PositionedDOMViewTrait',
  traits: ['PositionedViewTrait'],
  methods: {
    initHTML: function() {
      this.SUPER();
      var self = this;
      Events.dynamic(function() { self.x; self.y; self.z; },
                     this.position);
      Events.dynamic(function() { self.width; self.height; },
                     this.resize);
      this.$.style.position = 'absolute';
      this.position();
      this.resize();
    }
  },
  listeners: [
    {
      name: 'position',
      code: function() {
        if ( ! this.$ ) throw EventService.UNSUBSCRIBE_EXCEPTION;
        this.$.style.transform = 'translate3d(' +
          this.x + 'px,' +
          this.y + 'px,' +
          this.z + 'px)';
      }
    },
    {
      name: 'resize',
      code: function() {
        if ( ! this.$ ) throw EventService.UNSUBSCRIBE_EXCEPTION;
        this.$.style.width  = this.width + this.model_.WIDTH.units;
        this.$.style.height = this.height + this.model_.HEIGHT.units;
      }
    }
  ]
});

MODEL({
  name: 'Window',
  properties: [
    { model_: 'IntProperty', name: 'width' },
    { model_: 'IntProperty', name: 'height' },
    {
      name: 'window',
      postSet: function(o, w) {
        o && o.removeEventListener('resize', this.onResize);
        w.addEventListener('resize', this.onResize);
        this.onResize();
      },
      hidden: true
    }
  ],
  listeners: [
    {
      name: 'onResize',
      code: function() {
        this.height = this.window.innerHeight;
        this.width  = this.window.innerWidth;
      }
    }
  ]
});

MODEL({
  name: 'Point',
  properties: [
    { model_: 'IntProperty', name: 'x' },
    { model_: 'IntProperty', name: 'y' }
  ]
});

MODEL({
  name: 'FloatingView',
  extendsModel: 'View',
  traits: ['PositionedDOMViewTrait'],
  properties: [
    { name: 'view' },
    { name: 'width',  defaultValue: 300 },
    { name: 'height', defaultValue: 300 }
  ],
  methods: {
    toInnerHTML: function() {
      return this.view.toHTML();
    },
    initHTML: function() {
      this.SUPER();
      this.$.style.overflow = 'scroll';
      this.view.initHTML();
    }
  }
});
<commit_msg>Expand layout support and add OverlaySlider and ViewSlider.<commit_after>/**
 * @license
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

MODEL({
  name: 'PositionedViewTrait',
  properties: [
    { model_: 'FloatProperty', name: 'x',      units: 'px', defaultValue: 0 },
    { model_: 'FloatProperty', name: 'y',      units: 'px', defaultValue: 0 },
    { model_: 'FloatProperty', name: 'z',      units: 'px', defaultValue: 0 },
    { model_: 'IntProperty', name: 'width',  units: 'px', defaultValue: 100 },
    { model_: 'IntProperty', name: 'height', units: 'px', defaultValue: 100 },
    { model_: 'IntProperty', name: 'preferredWidth', units: 'px', defaultValue: 100 },
    { model_: 'IntProperty', name: 'preferredHeight', units: 'px', defaultValue: 100 }
  ]
});

MODEL({
  name: 'PositionedDOMViewTrait',
  traits: ['PositionedViewTrait'],
  methods: {
    toHTML: function() {
      return '
' +
        this.toInnerHTML() +
        '
';
    },
    initHTML: function() {
      this.SUPER();
      var self = this;
      this.X.dynamic(function() { self.x; self.y; self.z; },
                     this.position);
      this.X.dynamic(function() { self.width; self.height; },
                     this.resize);
      this.$.style.position = 'absolute';
      this.position();
      this.resize();
    },
    transform: function() {
      return 'translate3d(' +
        this.x + 'px,' +
        this.y + 'px,' +
        this.z + 'px)';
    },
    styleWidth: function() {
      return this.width + 'px';
    },
    styleHeight: function() {
      return this.height + 'px';
    }
  },
  listeners: [
    {
      name: 'position',
      code: function() {
        if ( ! this.$ ) return;
        this.$.style.transform = this.transform();
      }
    },
    {
      name: 'resize',
      code: function() {
        if ( ! this.$ ) return;
        this.$.style.width  = this.styleWidth();
        this.$.style.height = this.styleHeight();
      }
    }
  ]
});

MODEL({
  name: 'Window',
  properties: [
    { model_: 'IntProperty', name: 'width' },
    { model_: 'IntProperty', name: 'height' },
    {
      name: 'window',
      postSet: function(o, w) {
        o && o.removeEventListener('resize', this.onResize);
        w.addEventListener('resize', this.onResize);
        this.onResize();
      },
      hidden: true
    },
    {
      name: 'view',
      type: 'View',
      postSet: function(old, v) {
        var self = this;
        v.x = 0;
        v.y = 0;
        this.X.dynamic(function() { self.width; self.height; },
                       function() {
                         v.width = self.width;
                         v.height = self.height;
                       });
        var s = this.window.document.body.style;
        s.padding = 0;
        s.margin = 0;
        s.border = 0;
        this.window.document.body.innerHTML = v.toHTML();
        v.initHTML();
      }
    }
  ],
  listeners: [
    {
      name: 'onResize',
      code: function() {
        this.height = this.window.innerHeight;
        this.width  = this.window.innerWidth;
      }
    }
  ]
});

MODEL({
  name: 'Point',
  properties: [
    { model_: 'IntProperty', name: 'x' },
    { model_: 'IntProperty', name: 'y' }
  ]
});

MODEL({
  name: 'FloatingView',
  extendsModel: 'View',
  traits: ['PositionedDOMViewTrait'],
  properties: [
    { name: 'view' },
    { name: 'width',  defaultValue: 300 },
    { name: 'height', defaultValue: 300 }
  ],
  templates: [
    function toInnerHTML() {/* %%view */}
  ]
});

MODEL({
  name: 'ViewSlider',
  traits: ['PositionedDOMViewTrait'],
  extendsModel: 'View',
  properties: [
    {
      name: 'view'
    },
    {
      name: 'incomingView'
    },
    {
      model_: 'StringEnumProperty',
      name: 'direction',
      choices: ['horizontal', 'vertical'],
      defaultValue: 'horizontal'
    },
    {
      model_: 'BooleanProperty',
      name: 'reverse',
      defaultValue: false
    },
    {
      model_: 'FloatProperty',
      name: 'slideAmount',
      defaultValue: 0
    },
    'latch'
  ],
  methods: {
    init: function() {
      this.SUPER();
      var self = this;
      this.X.dynamic(function() { self.width; self.height; self.direction; self.slideAmount; self.reverse },
                     this.layout);
    },
    toHTML: function() {
      this.children = [];
      return this.SUPER();
    },
    initHTML: function() {
      this.layout();
      this.SUPER();
    },
    setView: function(view) {
      if ( this.view ) {
        this.$.removeChild(this.view.$);
      }
      this.view = view;
      this.layout();
      this.$.insertAdjacentHTML('beforeend', view.toHTML());
      view.initHTML();
    },
    slideView: function(view, opt_interp, opt_time) {
      if ( ! this.$ ) return;

      if ( this.latch ) {
        this.latch();
        this.latch = '';
      }

      this.incomingView = view;
      this.layout();
      this.$.insertAdjacentHTML('beforeend', view.toHTML());
      view.initHTML();

      opt_interp = opt_interp || Movement.easeOut(1);
      opt_time = opt_time || 300;

      var self = this;

      var fn = function() {
        self.slideAmount = 1.0;
      };

      this.latch = Movement.animate(opt_time, fn, opt_interp, function() {
        if ( self.view ) self.$.removeChild(self.view.$);
        self.view = view;
        self.incomingView = '';
        self.latch = '';
        self.slideAmount = 0;
      })();
    }
  },
  templates: [
    function toInnerHTML() {/* <%= this.view %> */}
  ],
  listeners: [
    {
      name: 'layout',
      code: function() {
        this.view.width = this.width;
        this.view.height = this.height;

        if ( this.incomingView ) {
          this.incomingView.width = this.width;
          this.incomingView.height = this.height;
        }

        var r = 1;
        if ( this.reverse ) r = -1;

        if ( this.direction === 'horizontal' ) {
          this.view.x = -(r * this.slideAmount * this.width);
          this.view.y = 0;
          if ( this.incomingView ) {
            this.incomingView.x = r * this.width - (r * this.slideAmount * this.width);
            this.incomingView.y = 0;
          }
        } else {
          this.view.x = 0;
          this.view.y = -(r * this.slideAmount * this.height);
          if ( this.incomingView ) {
            this.incomingView.x = 0;
            this.incomingView.y = r * this.height - (r * this.slideAmount * this.height);
          }
        }
      }
    }
  ]
});

MODEL({
  name: 'OverlaySlider',
  traits: ['PositionedDOMViewTrait'],
  extendsModel: 'View',
  properties: [
    {
      name: 'view',
      postSet: function(old, v) {
        if ( this.$ ) { this.updateHTML(); }
      }
    },
    { model_: 'FloatProperty', name: 'slideAmount', defaultValue: 0 }
  ],
  methods: {
    init: function() {
      this.SUPER();
      var self = this;
      this.X.dynamic(function() { self.z; self.width; self.height; self.slideAmount; }, this.layout);
    },
    updateHTML: function() {
      this.children = [];
      this.layout();
      this.SUPER();
    }
  },
  templates: [
    function toInnerHTML() {/*
      <% this.on('click', this.onClick, this.id + '-slider'); %>
      <div id="<%= this.id %>-slider" class="overlay-slider">
 %%view */},
    function CSS() {/*
      .overlay-slider {
        position: absolute;
        background: black;
      }

      * {
        transform-style: preserve-3d;
        -webkit-transform-style: preserve-3d;
      }
    */}
  ],
  listeners: [
    {
      name: 'onClick',
      code: function() {
        this.publish(['click']);
      }
    },
    {
      name: 'layout',
      code: function() {
        this.z = (this.slideAmount === 0) ? -1 : 1;

        var width = Math.min(this.view.preferredWidth,
                             this.width);

        if ( this.$ ) {
          var overlay = this.X.$(this.id + '-slider');
          overlay.style.transform = 'translate3d(0,0,0px)';
          overlay.style.width = this.width + 'px';
          overlay.style.height = this.height + 'px';
          overlay.style.opacity = this.slideAmount * 0.4;
        }

        if ( this.view ) {
          this.view.width = width;
          this.view.height = this.height;
          this.view.x = -((1 - this.slideAmount) * width);
          this.view.y = 0;
          this.view.z = 1;
        }
      }
    }
  ]
});

<|endoftext|>