<commit_before>Frog = function (game, pos, physicalGroup, knugen) {
	this.game = game;
	this.knugen = knugen;
	this.speed = 30;
	this.frog = true;
	this.physicalGroup = physicalGroup;
	this.croakSound = this.game.add.audio('croak', 0.9, false);

	var bmd = game.make.bitmapData(360, 16);
	bmd.load('frog');
	// Color tone
	var tonesList = [{
			r: 128,
			g: 255,
			b: 0
		},
		{
			r: 58,
			g: 205,
			b: 100
		},
		{
			r: 150,
			g: 150,
			b: 0
		}];
	this.tone = game.rnd.pick(tonesList);
	bmd.replaceRGB(255, 150, 255, 255,
		this.tone.r, this.tone.g, this.tone.b, 255);
	game.cache.addSpriteSheet('dynamicFrog', '', bmd.canvas, 15, 14, 24, 0, 0);
	Phaser.Sprite.call(this, game, pos.x, pos.y - 1, 'dynamicFrog');
	// All animations, frame 0 is "idle"
	this.animations.add('north', [4, 5, 6, 7, 8], 10, true);
	this.animations.add('west', [9, 10, 11, 12, 13], 10, true);
	this.animations.add('south', [14, 15, 16, 17, 18], 10, true);
	this.animations.add('east', [19, 20, 21, 22, 23], 10, true);
	this.frame = 2;

	// Death animation
	var bmd2 = game.make.bitmapData(448, 14);
	bmd2.load('explodingFrog');
	bmd2.replaceRGB(255, 150, 255, 255,
		this.tone.r, this.tone.g, this.tone.b, 255);
	game.cache.addSpriteSheet('dynamicFrogDeath', '', bmd2.canvas, 14, 14, 32, 0, 0);
	this.death = game.add.sprite(0, 0, 'dynamicFrogDeath');
	this.death.visible = false;
	this.death.anchor.setTo(0.5, 0.5);
	this.death.animations.add('north', [0, 1, 2, 3, 4, 5, 6, 7], 10, false, true);
	this.death.animations.add('west', [8, 9, 10, 11, 12, 13, 14, 16], 10, false, true);
	this.death.animations.add('south', [17, 18, 19, 20, 21, 22, 23, 24], 10, false, true);
	this.death.animations.add('east', [25, 26, 27, 28, 29, 30, 31, 32], 10, false, true);

	game.add.existing(this);
	game.physics.arcade.enable(this);

	this.anchor.setTo(0.5, 1);
	this.body.collideWorldBounds = true;
	this.body.height = 9;
	this.body.width = 14;

	this.allLines = [];

	this.physicalGroup.forEach(function (sprite) {
		if (!sprite.frog && !sprite.knugen) {

			topLeftCoord = Utils.getTopLeft(sprite);
			this.allLines.push(new Phaser.Line(topLeftCoord.x,
				topLeftCoord.y,
				topLeftCoord.x + sprite.body.width,
				topLeftCoord.y));
			this.allLines.push(new Phaser.Line(topLeftCoord.x,
				topLeftCoord.y,
				topLeftCoord.x,
				topLeftCoord.y + sprite.body.height));
			this.allLines.push(new Phaser.Line(topLeftCoord.x + sprite.body.width,
				topLeftCoord.y,
				topLeftCoord.x + sprite.body.width,
				topLeftCoord.y + sprite.body.height));
			this.allLines.push(new Phaser.Line(topLeftCoord.x,
				topLeftCoord.y + sprite.body.height,
				topLeftCoord.x + sprite.body.width,
				topLeftCoord.y + sprite.body.height));
		}
	}, this);

	this.line1 = new Phaser.Line(0, 0, 0, 0);
	this.line2 = new Phaser.Line(0, 0, 0, 0);

	this.game.time.events.add(1000, this.firstJump, this);
}

Frog.prototype = Object.create(Phaser.Sprite.prototype);
Frog.prototype.constructor = Frog;

Frog.prototype.update = function () {}

Frog.prototype.firstJump = function () {
	this.body.velocity.x = 0;
	this.body.velocity.y = 1 * this.speed;
	this.setAnimation(90);

	this.croak();
	this.idleTimer = this.game.time.events.add(1000, this.setIdle, this);
}

Frog.prototype.jump = function () {

	var degStep = 1;
	var rotStart = 0;
	var changeDir = false;

	if (Phaser.Math.chanceRoll()) {
		rotStart = 1;
	} else {
		rotStart = -1;
	}

	var totalAdded = 0;

	this.angle = this.game.physics.arcade.angleBetween(Utils.getTopLeft(this),
		Utils.getTopLeft(this.knugen));

	if (this.knugen.super) {
		this.angle += Math.PI;
	}

	// Add a bit of random
	var diff = Math.PI / 4;
	this.angle += this.game.rnd.integerInRange(-diff/2, diff/2);

	this.updateLines(this.angle);

	while (this.checkIntersection() && totalAdded < (2 * Math.PI)) {
		if (changeDir) {
			changeDir = false;
			rotStart *= -1;
		} else {
			totalAdded += Phaser.Math.degToRad(degStep);
			changeDir = true;
		}

		this.updateLines(this.angle + (rotStart * totalAdded));
	}

	if (totalAdded >= (2 * Math.PI)) {
		totalAdded = Phaser.Math.degToRad(this.game.rnd.integerInRange(0, 360));
	}

	this.angle += rotStart * totalAdded;

	this.body.velocity.x = Math.cos(this.angle) * this.speed;
	this.body.velocity.y = Math.sin(this.angle) * this.speed;

	this.setAnimation(Phaser.Math.radToDeg(Phaser.Math.normalizeAngle(this.angle)));
	this.croak();
	this.idleTimer = this.game.time.events.add(1000, this.setIdle, this);
}

Frog.prototype.setIdle = function (forGood) {
	this.body.velocity.x = 0;
	this.body.velocity.y = 0;

	switch (this.animations.name) {
	case 'north':
		this.frame = 0;
		break;
	case 'west':
		this.frame = 1;
		break;
	case 'south':
		this.frame = 2;
		break;
	case 'east':
		this.frame = 3;
		break;
	}
	this.animations.stop();

	// setup next jump
	if (!forGood) {
		var nextJump = this.game.rnd.integerInRange(500, 2000);
		this.jumpTimer = this.game.time.events.add(nextJump, this.jump, this);
	}
}

Frog.prototype.explode = function () {
	this.body.enable = false;
	this.setIdle(true);

	this.game.time.events.remove(this.idleTimer);
	this.game.time.events.remove(this.jumpTimer);

	this.visible = false;
	this.death.visible = true;
	this.death.x = this.x;
	this.death.y = this.y;

	if (this.frame = 0)
		this.death.animations.play('north');
	else if (this.frame = 1)
		this.death.animations.play('west');
	else if (this.frame = 2)
		this.death.animations.play('south');
	else
		this.death.animations.play('east');

	// Give the animation time to play
	this.game.time.events.add(500, this.cleanFrogMush, this);
}

Frog.prototype.cleanFrogMush = function (deg) {
	this.destroy();
	this.death.destroy();
}

Frog.prototype.setAnimation = function (deg) {

	if (deg >= 225.0 && deg <= 315.0)
		this.animations.play('north');
	else if (deg >= 135.0 && deg <= 225.0)
		this.animations.play('west');
	else if (deg >= 45.0 && deg <= 135.0)
		this.animations.play('south');
	else
		this.animations.play('east');
}

Frog.prototype.croak = function () {
	if (this.game.rnd.integerInRange(0, 5) > 4)
		this.croakSound.play();
}

Frog.prototype.checkIntersection = function () {

	for (var i = 0, len = this.allLines.length; i < len; i++) {
		if (Phaser.Line.intersects(this.line1, this.allLines[i]) ||
			Phaser.Line.intersects(this.line2, this.allLines[i])) {
			return true;
		}
	}

	return false;
}

Frog.prototype.updateLines = function (angle) {

		var line1Start;
		var line2Start;
		normAngle = Phaser.Math.normalizeAngle(angle);

		if ((normAngle >= Math.PI / 2 && normAngle <= Math.PI) || (normAngle >= (3 * Math.PI / 2) && normAngle <= 2 * Math.PI)) {
			line1Start = Utils.getTopLeft(this);
			line2Start = Utils.getBottomRight(this);
		} else if ((normAngle >= Math.PI && normAngle <= (3 * Math.PI / 2)) || (normAngle >= 0 && normAngle <= Math.PI / 2)) {
			line1Start = Utils.getTopRight(this);
			line2Start = Utils.getBottomLeft(this);
		}

		this.line1.fromAngle(line1Start.x, line1Start.y, angle, this.speed);
		this.line2.fromAngle(line2Start.x, line2Start.y, angle, this.speed);
	}
	// Frog.prototype.render = function() {
	//    this.game.debug.body(this);
	//    this.game.debug.geom(this.line1);
	//    this.game.debug.geom(this.line2);
	// }<commit_msg>Changed radomness of jumping frogs<commit_after>Frog = function (game, pos, physicalGroup, knugen) {
	this.game = game;
	this.knugen = knugen;
	this.speed = 30;
	this.frog = true;
	this.physicalGroup = physicalGroup;
	this.croakSound = this.game.add.audio('croak', 0.9, false);

	var bmd = game.make.bitmapData(360, 16);
	bmd.load('frog');
	// Color tone
	var tonesList = [{
			r: 128,
			g: 255,
			b: 0
		},
		{
			r: 58,
			g: 205,
			b: 100
		},
		{
			r: 150,
			g: 150,
			b: 0
		}];
	this.tone = game.rnd.pick(tonesList);
	bmd.replaceRGB(255, 150, 255, 255,
		this.tone.r, this.tone.g, this.tone.b, 255);
	game.cache.addSpriteSheet('dynamicFrog', '', bmd.canvas, 15, 14, 24, 0, 0);
	Phaser.Sprite.call(this, game, pos.x, pos.y - 1, 'dynamicFrog');
	// All animations, frame 0 is "idle"
	this.animations.add('north', [4, 5, 6, 7, 8], 10, true);
	this.animations.add('west', [9, 10, 11, 12, 13], 10, true);
	this.animations.add('south', [14, 15, 16, 17, 18], 10, true);
	this.animations.add('east', [19, 20, 21, 22, 23], 10, true);
	this.frame = 2;

	// Death animation
	var bmd2 = game.make.bitmapData(448, 14);
	bmd2.load('explodingFrog');
	bmd2.replaceRGB(255, 150, 255, 255,
		this.tone.r, this.tone.g, this.tone.b, 255);
	game.cache.addSpriteSheet('dynamicFrogDeath', '', bmd2.canvas, 14, 14, 32, 0, 0);
	this.death = game.add.sprite(0, 0, 'dynamicFrogDeath');
	this.death.visible = false;
	this.death.anchor.setTo(0.5, 0.5);
	this.death.animations.add('north', [0, 1, 2, 3, 4, 5, 6, 7], 10, false, true);
	this.death.animations.add('west', [8, 9, 10, 11, 12, 13, 14, 16], 10, false, true);
	this.death.animations.add('south', [17, 18, 19, 20, 21, 22, 23, 24], 10, false, true);
	this.death.animations.add('east', [25, 26, 27, 28, 29, 30, 31, 32], 10, false, true);

	game.add.existing(this);
	game.physics.arcade.enable(this);

	this.anchor.setTo(0.5, 1);
	this.body.collideWorldBounds = true;
	this.body.height = 9;
	this.body.width = 14;

	this.allLines = [];

	this.physicalGroup.forEach(function (sprite) {
		if (!sprite.frog && !sprite.knugen) {

			topLeftCoord = Utils.getTopLeft(sprite);
			this.allLines.push(new Phaser.Line(topLeftCoord.x,
				topLeftCoord.y,
				topLeftCoord.x + sprite.body.width,
				topLeftCoord.y));
			this.allLines.push(new Phaser.Line(topLeftCoord.x,
				topLeftCoord.y,
				topLeftCoord.x,
				topLeftCoord.y + sprite.body.height));
			this.allLines.push(new Phaser.Line(topLeftCoord.x + sprite.body.width,
				topLeftCoord.y,
				topLeftCoord.x + sprite.body.width,
				topLeftCoord.y + sprite.body.height));
			this.allLines.push(new Phaser.Line(topLeftCoord.x,
				topLeftCoord.y + sprite.body.height,
				topLeftCoord.x + sprite.body.width,
				topLeftCoord.y + sprite.body.height));
		}
	}, this);

	this.line1 = new Phaser.Line(0, 0, 0, 0);
	this.line2 = new Phaser.Line(0, 0, 0, 0);

	this.game.time.events.add(1000, this.firstJump, this);
}

Frog.prototype = Object.create(Phaser.Sprite.prototype);
Frog.prototype.constructor = Frog;

Frog.prototype.update = function () {}

Frog.prototype.firstJump = function () {
	this.body.velocity.x = 0;
	this.body.velocity.y = 1 * this.speed;
	this.setAnimation(90);

	this.croak();
	this.idleTimer = this.game.time.events.add(1000, this.setIdle, this);
}

Frog.prototype.jump = function () {

	var degStep = 1;
	var rotStart = 0;
	var changeDir = false;
   var totalAdded = 0;
   var diff = 0;

	if (Phaser.Math.chanceRoll()) {
		rotStart = 1;
	} else {
		rotStart = -1;
	}

	this.angle = this.game.physics.arcade.angleBetween(Utils.getTopLeft(this),
		Utils.getTopLeft(this.knugen));

	if (this.knugen.super) {
		this.angle += Math.PI;
      diff = Phaser.Math.degToRad(45.0);
	}
   else {
      diff = Phaser.Math.degToRad(10.0);
   }

	// Add a bit of random
	this.angle += this.game.rnd.integerInRange(-diff/2, diff/2);

	this.updateLines(this.angle);

	while (this.checkIntersection() && totalAdded < (2 * Math.PI)) {
		if (changeDir) {
			changeDir = false;
			rotStart *= -1;
		} else {
			totalAdded += Phaser.Math.degToRad(degStep);
			changeDir = true;
		}

		this.updateLines(this.angle + (rotStart * totalAdded));
	}

	if (totalAdded >= (2 * Math.PI)) {
		totalAdded = Phaser.Math.degToRad(this.game.rnd.integerInRange(0, 360));
	}

	this.angle += rotStart * totalAdded;

	this.body.velocity.x = Math.cos(this.angle) * this.speed;
	this.body.velocity.y = Math.sin(this.angle) * this.speed;

	this.setAnimation(Phaser.Math.radToDeg(Phaser.Math.normalizeAngle(this.angle)));
	this.croak();
	this.idleTimer = this.game.time.events.add(1000, this.setIdle, this);
}

Frog.prototype.setIdle = function (forGood) {
	this.body.velocity.x = 0;
	this.body.velocity.y = 0;

	switch (this.animations.name) {
	case 'north':
		this.frame = 0;
		break;
	case 'west':
		this.frame = 1;
		break;
	case 'south':
		this.frame = 2;
		break;
	case 'east':
		this.frame = 3;
		break;
	}
	this.animations.stop();

	// setup next jump
	if (!forGood) {
		var nextJump = this.game.rnd.integerInRange(500, 2000);
		this.jumpTimer = this.game.time.events.add(nextJump, this.jump, this);
	}
}

Frog.prototype.explode = function () {
	this.body.enable = false;
	this.setIdle(true);

	this.game.time.events.remove(this.idleTimer);
	this.game.time.events.remove(this.jumpTimer);

	this.visible = false;
	this.death.visible = true;
	this.death.x = this.x;
	this.death.y = this.y;

	if (this.frame = 0)
		this.death.animations.play('north');
	else if (this.frame = 1)
		this.death.animations.play('west');
	else if (this.frame = 2)
		this.death.animations.play('south');
	else
		this.death.animations.play('east');

	// Give the animation time to play
	this.game.time.events.add(500, this.cleanFrogMush, this);
}

Frog.prototype.cleanFrogMush = function (deg) {
	this.destroy();
	this.death.destroy();
}

Frog.prototype.setAnimation = function (deg) {

	if (deg >= 225.0 && deg <= 315.0)
		this.animations.play('north');
	else if (deg >= 135.0 && deg <= 225.0)
		this.animations.play('west');
	else if (deg >= 45.0 && deg <= 135.0)
		this.animations.play('south');
	else
		this.animations.play('east');
}

Frog.prototype.croak = function () {
	if (this.game.rnd.integerInRange(0, 5) > 4)
		this.croakSound.play();
}

Frog.prototype.checkIntersection = function () {

	for (var i = 0, len = this.allLines.length; i < len; i++) {
		if (Phaser.Line.intersects(this.line1, this.allLines[i]) ||
			Phaser.Line.intersects(this.line2, this.allLines[i])) {
			return true;
		}
	}

	return false;
}

Frog.prototype.updateLines = function (angle) {

		var line1Start;
		var line2Start;
		normAngle = Phaser.Math.normalizeAngle(angle);

		if ((normAngle >= Math.PI / 2 && normAngle <= Math.PI) || (normAngle >= (3 * Math.PI / 2) && normAngle <= 2 * Math.PI)) {
			line1Start = Utils.getTopLeft(this);
			line2Start = Utils.getBottomRight(this);
		} else if ((normAngle >= Math.PI && normAngle <= (3 * Math.PI / 2)) || (normAngle >= 0 && normAngle <= Math.PI / 2)) {
			line1Start = Utils.getTopRight(this);
			line2Start = Utils.getBottomLeft(this);
		}

		this.line1.fromAngle(line1Start.x, line1Start.y, angle, this.speed);
		this.line2.fromAngle(line2Start.x, line2Start.y, angle, this.speed);
	}
	// Frog.prototype.render = function() {
	//    this.game.debug.body(this);
	//    this.game.debug.geom(this.line1);
	//    this.game.debug.geom(this.line2);
	// }<|endoftext|>


<commit_before>(function() {
  var input;
  var Game = {
    user: "X",
    computer: "O",

    visualAfterChoice: function() {
      if ($(event.target).attr('class') == "btn btn-start") {
        UI.toggleDisplayedButton(".btn-start", ".btn-new");
      }
      else {
        UI.toggleDisplayedButton(".btn-restart", ".btn-new");
      }
    },

    visualAfterGameOver: function() {
      $("tr td").unbind();
      UI.toggleDisplayedButton(".btn-new", ".btn-restart");
      this.restartGame();
    },

    winner: function(currentPlayer) {
      return currentPlayer == "X" ? "Player" : "Computer";
    },

    firstMove: function() {
      var input = UI.askFirstMove();
      if (input === null || input === "") {
        return true;
      }
      else if(input == "y" || input == "n") {
        this.visualAfterChoice();
        return input;
      }
      else {
        UI.inputErrorMessage();
        this.firstMove();
      }
    },

    nextTurn: function(currentPlayer) {
      if(GameRules.gameWin(GameBoard)) {
        UI.winMessage(this.winner(currentPlayer));
        this.visualAfterGameOver();
      }
      else if(GameRules.gameTie(GameBoard)) {
        UI.tieMessage();
        this.visualAfterGameOver();
      }
    },

    humanPlay: function(e) {
      Human.choiceSpot(e, GameBoard, this.user);
      this.nextTurn(this.user);
    },

    computerPlay: function() {
      var _this = this;
      $("#Computer").show(220, function() {
        Computer.chooseTheBestSpot(_this.computer);
        _this.nextTurn(_this.computer);
      });
    },

    play: function() {
      var _this = this;
      this.newGame();
      var firstmove = this.firstMove();
      if (firstmove === true) {
        return;
      }
      else if (firstmove === "y") {
        $("tr td").click(function(e) {
          _this.humanPlay(e);
          if (GameRules.gameOver(GameBoard)) {
            return $("tr td").unbind("click");
          }
          _this.computerPlay();
        });
      }
      else {
        this.computerPlay(function() {
          $("tr td").click(function(e) {
            _this.humanPlay(e);
            if (GameRules.gameOver(GameBoard)) {
              return $("tr td").unbind("click");
            }
          });
        });
      }
    },

    startGame: function() {
      var _this = this;
      UI.hideButton(".btn-restart", ".btn-new");
      UI.hideComputerMessage();
      $(".btn-start").click(function(e) {
        _this.play();
        e.stopPropagation();
      });
    },

    resetGame: function() {
      $("tr td").empty();
      GameBoard.resetBoard();
    },

    newGame: function() {
      var _this = this;
      $(".btn-new").click(function(e) {
        $(".btn-new").unbind("click");
        _this.resetGame();
        $("tr td").unbind("click");
        _this.play();
        e.stopPropagation();
      });
    },

    restartGame: function() {
      var _this = this;
      $(".btn-restart").click(function(e) {
        _this.resetGame();
        _this.play();
        e.stopPropagation();
      });
    }
  };
  window.Game = Game;
})();
<commit_msg>fixed humanPlay() in Game<commit_after>(function() {
  var input;
  var Game = {
    user: "X",
    computer: "O",

    visualAfterChoice: function() {
      if ($(event.target).attr('class') == "btn btn-start") {
        UI.toggleDisplayedButton(".btn-start", ".btn-new");
      }
      else {
        UI.toggleDisplayedButton(".btn-restart", ".btn-new");
      }
    },

    visualAfterGameOver: function() {
      $("tr td").unbind();
      UI.toggleDisplayedButton(".btn-new", ".btn-restart");
      this.restartGame();
    },

    winner: function(currentPlayer) {
      return currentPlayer == "X" ? "Player" : "Computer";
    },

    firstMove: function() {
      var input = UI.askFirstMove();
      if (input === null || input === "") {
        return true;
      }
      else if(input == "y" || input == "n") {
        this.visualAfterChoice();
        return input;
      }
      else {
        UI.inputErrorMessage();
        this.firstMove();
      }
    },

    nextTurn: function(currentPlayer) {
      if(GameRules.gameWin(GameBoard)) {
        UI.winMessage(this.winner(currentPlayer));
        this.visualAfterGameOver();
      }
      else if(GameRules.gameTie(GameBoard)) {
        UI.tieMessage();
        this.visualAfterGameOver();
      }
    },

    humanPlay: function(e) {
      var _this = this;
      $("#Computer").show(220, function() {
        Human.choiceSpot(e, GameBoard, _this.user);
        _this.nextTurn(_this.user);
      });
    },

    computerPlay: function() {
      var _this = this;
      $("#Computer").show(220, function() {
        Computer.chooseTheBestSpot(_this.computer);
        _this.nextTurn(_this.computer);
      });
    },

    play: function() {
      var _this = this;
      this.newGame();
      var firstmove = this.firstMove();
      if (firstmove === true) {
        return;
      }
      else if (firstmove === "y") {
        $("tr td").click(function(e) {
          _this.humanPlay(e);
          if (GameRules.gameOver(GameBoard)) {
            return $("tr td").unbind("click");
          }
          _this.computerPlay();
        });
      }
      else {
        this.computerPlay(function() {
          $("tr td").click(function(e) {
            _this.humanPlay(e);
            if (GameRules.gameOver(GameBoard)) {
              return $("tr td").unbind("click");
            }
          });
        });
      }
    },

    startGame: function() {
      var _this = this;
      UI.hideButton(".btn-restart", ".btn-new");
      UI.hideComputerMessage();
      $(".btn-start").click(function(e) {
        _this.play();
        e.stopPropagation();
      });
    },

    resetGame: function() {
      $("tr td").empty();
      GameBoard.resetBoard();
    },

    newGame: function() {
      var _this = this;
      $(".btn-new").click(function(e) {
        $(".btn-new").unbind("click");
        _this.resetGame();
        $("tr td").unbind("click");
        _this.play();
        e.stopPropagation();
      });
    },

    restartGame: function() {
      var _this = this;
      $(".btn-restart").click(function(e) {
        _this.resetGame();
        _this.play();
        e.stopPropagation();
      });
    }
  };
  window.Game = Game;
})();
<|endoftext|>


<commit_before>describe("less.js error tests", function() {
    testLessErrorsInDocument();
});<commit_msg>Fix browser tests<commit_after>less.strictUnits = true;

describe("less.js error tests", function() {
    testLessErrorsInDocument();
});<|endoftext|>


<commit_before>define(function(require, exports, module) {
    "use strict";

    main.consumes = [
        "Plugin", "tabManager", "settings", "preferences"
    ];
    main.provides = ["closeconfirmation"];
    return main;

    function main(options, imports, register) {
        var Plugin      = imports.Plugin;
        var tabs        = imports.tabManager;
        var settings    = imports.settings;
        var prefs       = imports.preferences;

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        var emit   = plugin.getEmitter();

        var loaded = false;
        function load(callback){
            if (loaded) return false;
            loaded = true;

            // when unloading the window
            window.onbeforeunload = onBeforeUnloadHandler;

            settings.on("read", function(){
                settings.setDefaults("user/general", [
                    ["confirmexit", "false"]
                ]);
            }, plugin);

            prefs.add({
                "General" : {
                    "General" : {
                        "Warn Before Exiting" : {
                            type     : "checkbox",
                            position : 8000,
                            path     : "user/general/@confirmexit"
                        }
                    }
                }
            }, plugin);
        }

        function unload() {
            if (window.onbeforeunload === onBeforeUnloadHandler)
                window.onbeforeunload = null;
        }

        /***** Methods *****/

        function onBeforeUnloadHandler() {
            var changed = tabs.getTabs().some(function(tab){
                return tab.document.value && tab.document.changed;
            });

            emit("exit", { changed: changed });

            if (changed)
                return "You have unsaved changes. Your changes will be lost if you don't save them";

            // see what's in the settings
            var confirmExit = settings.getBool("user/general/@confirmexit");
            if (confirmExit)
                return "You're about to leave Cloud9 IDE.";
        }

        /***** Lifecycle *****/

        plugin.on("load", function(){
            load();
        });
        plugin.on("enable", function(){

        });
        plugin.on("disable", function(){

        });
        plugin.on("unload", function(){
            unload();
            loaded = false;
        });

        /***** Register and define API *****/
        /**
         * Shows a 'close confirmation' popup when closing the IDE
         * @singleton
         */
        plugin.freezePublicAPI({
        });

        register(null, {
            closeconfirmation: plugin
        });
    }
});
<commit_msg>move gravatar to util<commit_after>define(function(require, exports, module) {
    "use strict";

    main.consumes = [
        "Plugin", "tabManager", "settings", "preferences"
    ];
    main.provides = ["closeconfirmation"];
    return main;

    function main(options, imports, register) {
        var Plugin      = imports.Plugin;
        var tabs        = imports.tabManager;
        var settings    = imports.settings;
        var prefs       = imports.preferences;

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        var emit   = plugin.getEmitter();

        var loaded = false;
        function load(callback){
            if (loaded) return false;
            loaded = true;

            // when unloading the window
            window.onbeforeunload = onBeforeUnloadHandler;
            window.onunload = unload;

            settings.on("read", function(){
                settings.setDefaults("user/general", [
                    ["confirmexit", "false"]
                ]);
            }, plugin);

            prefs.add({
                "General" : {
                    "General" : {
                        "Warn Before Exiting" : {
                            type     : "checkbox",
                            position : 8000,
                            path     : "user/general/@confirmexit"
                        }
                    }
                }
            }, plugin);
        }

        function unload() {
            if (window.onbeforeunload === onBeforeUnloadHandler)
                window.onbeforeunload = null;
        }

        /***** Methods *****/

        function onBeforeUnloadHandler() {
            var changed = tabs.getTabs().some(function(tab){
                return tab.document.value && tab.document.changed;
            });

            emit("exit", { changed: changed });

            if (changed)
                return "You have unsaved changes. Your changes will be lost if you don't save them";

            // see what's in the settings
            var confirmExit = settings.getBool("user/general/@confirmexit");
            if (confirmExit)
                return "You're about to leave Cloud9 IDE.";
        }

        /***** Lifecycle *****/

        plugin.on("load", function(){
            load();
        });
        plugin.on("enable", function(){

        });
        plugin.on("disable", function(){

        });
        plugin.on("unload", function(){
            unload();
            loaded = false;
        });

        /***** Register and define API *****/
        /**
         * Shows a 'close confirmation' popup when closing the IDE
         * @singleton
         */
        plugin.freezePublicAPI({
        });

        register(null, {
            closeconfirmation: plugin
        });
    }
});
<|endoftext|>


<commit_before>/**
 * CG Space Invaders
 * CG45179 16'17
 *
 * @author: Rui Ventura ( ist181045 )
 * @author: Diogo Freitas ( ist181586 )
 * @author: Sara Azinhal ( ist181700 )
 */

import './lib/threejs/polyfills.js';

import { Scene } from './lib/threejs/scenes/Scene';
import { WebGLRenderer } from './lib/threejs/renderers/WebGLRenderer';

import { OrthographicCamera } from './lib/threejs/cameras/OrthographicCamera';
import { PerspectiveCamera } from './lib/threejs/cameras/PerspectiveCamera';

import { DirectionalLight } from './lib/threejs/lights/DirectionalLight';
import { PointLight } from './lib/threejs/lights/PointLight';

import { Clock } from './lib/threejs/core/Clock';

import { WIDTH, HEIGHT } from './Constants';
import { WINDOW_PIXEL_RATIO, WINDOW_WIDTH, WINDOW_HEIGHT } from './Constants';

import Field from './objects/Field';
import EnemyShip from './entities/EnemyShip';
import PlayerShip from './entities/PlayerShip';

import * as Keyboard from './Keyboard';

class Game {

	constructor () {

		this.scene = new Scene();
		this.renderer = (function () {

			let renderer = new WebGLRenderer();

			renderer.setPixelRatio( WINDOW_PIXEL_RATIO );
			renderer.setSize( WINDOW_WIDTH(), WINDOW_HEIGHT() );

			return renderer;

		})();

		this.gameClock = new Clock( false );

		this.field = new Field( 0, 0, 0, WIDTH - 10, HEIGHT - 10 );

		this.cameras = (function ( self ) {

			let cameras = new Array();

			/* Ortho camera (bird's eye) */
			cameras.push( function () {

				let camera = new OrthographicCamera(
					~WIDTH >> 1, WIDTH >> 1, HEIGHT >> 1, ~HEIGHT >> 1, 1, 200
				);

				camera.position.set( 0, 100, 0 );
				camera.lookAt( self.scene.position );

				camera.updateProjectionMatrix();

				return camera;

			}());

			/* Back perspective camera */
			cameras.push( function () {

				let camera = new PerspectiveCamera(
					75, WINDOW_WIDTH() / WINDOW_HEIGHT(), 1, 1000
				);

				camera.position.set( 0, 250, ( self.field.height >> 1 ) + 150 );
				camera.lookAt( self.scene.position );

				camera.updateProjectionMatrix();

				return camera;

			}());

			return cameras;

		})( this );
		this.camera = this.cameras[0];

		this.gameObjects = new Array();

		this.playerShip = new PlayerShip( 0, 0, ( this.field.height >> 1 ) - 50,
			new PerspectiveCamera( 75, WINDOW_WIDTH() / WINDOW_HEIGHT(), 1, 1000 ) );

		this.sun = (function ( self ) {

			let sun = new DirectionalLight( 0xffffff, 2 );

			sun.position.set( ~self.field.width >> 2, 100, self.field.height >> 2 );
			sun.target  = self.scene;

			return sun;

		})( this );
		this.stars = (function ( self, n ) {

			let stars = new Array();

			for ( let i = 0; i < n; ++i ) {

				stars.push( new PointLight( 0xffffff, 0.4 ) );

			}

			return stars;

		}( this, 6 ));

		this.lightsOn = false;

		this.gameOver = false;
		this.gameWon = true;

	}

	start () {

		document.body.appendChild( this.renderer.domElement );

		window.addEventListener( 'resize',  this.resize.bind( this ) );
		window.addEventListener( 'keydown', this.keyDown.bind( this ) );
		window.addEventListener( 'keyup',   this.keyUp.bind( this ) );

		this.setup();

		/* HACK: Force a first resize */
		this.resize();

		this.update();

	}

	setup () {

		/* Clear the scene */
		for ( let i = 0; i < this.scene.children.length; ++i ) {

			this.scene.remove( this.scene.children[i] );

		}

		this.gameObjects = new Array();

		/* Build the scene */

		this.field.children.forEach( function ( b ) {

			b.type === 'Barrier' && this.gameObjects.push( b );

		}, this );

		this.field.changeMaterial( 0 );
		this.scene.add( this.field );

		this.playerShip.moving = false;
		this.playerShip.updateBoundries = true;
		this.playerShip.velocity.setScalar( 0 );
		this.playerShip.position.set( 0, 0, ( this.field.height >> 1 ) - 50 );
		this.playerShip.changeMaterial( 0 );

		this.cameras.length > 2 && this.cameras.pop();
		this.cameras.push( this.playerShip.camera );

		this.gameObjects.push( this.playerShip );
		this.scene.add( this.playerShip );

		let [ nx, nz ] = [ 5, 2 ];
		let [ segX, segZ ] = [
			( this.field.width - 120 ) / nx,
			( ( this.field.height - 120 ) >> 1 ) / nz
		];

		for ( let i = 0; i < nz; ++i ) {

			for ( let j = 0; j < nx; ++j ) {

				let [ posX, posZ ] = [
					segX * ( j - ( ( nx - 1 ) / 2 ) ),
					segZ * ( i - ( ( nz + 1 ) / 2 ) )
				];

				let alien = new EnemyShip( posX, 0, posZ );

				this.gameObjects.push( alien );
				this.scene.add( alien );

			}

		}

		this.lightsOn = false;
		this.sun.visible = false;
		this.scene.add( this.sun );

		this.stars.forEach( function ( star ) {

			star.position.set(
				this.field.width * ( Math.random() - 0.5 ),
				100,
				this.field.height * ( Math.random() - 0.5 )
			);

			star.visible = false;
			this.scene.add( star );

		}, this );

		this.gameOver = false;
		this.gameWon = true;

	}

	update () {

		if ( this.gameClock.running ) {

			let dt = this.gameClock.getDelta();

			if ( EnemyShip.count === 0 || !this.playerShip.alive ) {

				this.gameOver = true;
				this.gameWon = this.playerShip.alive;
				this.gameClock.stop();

			} else {

				if ( this.playerShip.shooting ) {

					let playerBullet = this.playerShip.fire();

					if ( playerBullet !== null ) {

						this.scene.add( playerBullet );
						this.gameObjects.push( playerBullet );

					}

				}

				for ( let i = 0; i < this.gameObjects.length; ++i ) {

					let o1 = this.gameObjects[i];

					if ( o1.isEntity && !o1.alive ) {

						this.scene.remove( o1 );
						this.gameObjects.splice( i, 1 );

					} else {

						o1.update( dt );

					}

					for ( let j = i + 1; j < this.gameObjects.length; ++j ) {

						let o2 = this.gameObjects[j];

						o1.intersect( o2 ) && o1.handleCollision( o2, dt );

					}

				}

			}

		}

		this.renderer.render( this.scene, this.camera );

		window.requestAnimationFrame( this.update.bind( this ) );

	}

	updateMaterials () {

		this.gameObjects.forEach( function ( obj ) {

			let index = this.lightsOn ? (obj.phong ? 1 : 2) : 0;

			obj.phong = !obj.phong;

			obj.changeMaterial( index );

		}, this );

	}

	resize () {

		let ratio = WINDOW_WIDTH() / WINDOW_HEIGHT();

		if ( this.camera.type === 'OrthographicCamera' ) {

			if ( ratio > ( WIDTH / HEIGHT ) ) {

				this.camera.left   = ~( HEIGHT * ratio ) >> 1;
				this.camera.right  = ( HEIGHT * ratio ) >> 1;
				this.camera.top    = HEIGHT >> 1;
				this.camera.bottom = ~HEIGHT >> 1;

			} else {

				this.camera.left   = ~WIDTH >> 1;
				this.camera.right  = WIDTH >> 1;
				this.camera.top    = ( WIDTH / ratio ) >> 1;
				this.camera.bottom = ~( WIDTH / ratio ) >> 1;

			}

		} else {

			this.camera.aspect = ratio;

		}

		this.camera.updateProjectionMatrix();
		this.renderer.setSize( WINDOW_WIDTH(), WINDOW_HEIGHT() );

	}

	keyDown ( event ) {

		if ( this.gameOver ) {

			/* Restart the game */
			if ( event.keyCode === Keyboard.KEY_R ) {

				this.gameOver = false;
				this.setup();

			}

		} else {

			switch ( event.keyCode ) {

				/* Toggle cameras */
				case Keyboard.KEY_1: /* Orthographic (top bird's eye camera) */
				case Keyboard.KEY_2: /* Perspective (back camera) */
				case Keyboard.KEY_3: /* Perspective (player view camera) */

					if ( !this.gameOver ) {

						this.camera = this.cameras[ event.keyCode - Keyboard.KEY_1 ];
						this.resize();

					}

					break;

				/* Player movement: Left */
				case Keyboard.KEY_A:
				case Keyboard.KEY_LEFT:

					if ( !this.playerShip.moving ) this.playerShip.moving = true;
					this.playerShip.setDirection( -1, 0, 0 );

					break;

				/* Player movement: Right */
				case Keyboard.KEY_D:
				case Keyboard.KEY_RIGHT:

					if ( !this.playerShip.moving ) this.playerShip.moving = true;
					this.playerShip.setDirection( 1, 0, 0 );

					break;

				/* Player action: Toggle shooting */
				case Keyboard.KEY_B:
				case Keyboard.KEY_SPACEBAR:

					this.playerShip.shooting = true;

					break;

				/* Show / hide stars */
				case Keyboard.KEY_C:

					this.stars.forEach( function( star ) {

						star.visible = !star.visible;

					});

					break;

				/* Toggle lights */
				case Keyboard.KEY_L:

					this.lightsOn = !this.lightsOn;
					this.updateMaterials();

					break;

				/* Toggle Gouraud / Lambert Shading */
				case Keyboard.KEY_G:

					this.updateMaterials();
					break;

				/* Toggle the sun (day/night modes) */
				case Keyboard.KEY_N:

					this.sun.visible = !this.sun.visible;

					break;

				/* Start / Stop the game (clock) */
				case Keyboard.KEY_S:

					this.gameClock.running ? this.gameClock.stop() : this.gameClock.start();

					break;

				/* Toggle wireframe of the objects in the scene */
				case Keyboard.KEY_W:

					this.scene.traverse( function( node ) {

						if ( node.isMesh ) {

							node.material.wireframe = !node.material.wireframe;

						}

					});

					break;

				default: break;

			}
		}

	}

	keyUp ( event ) {

		switch ( event.keyCode ) {

			case Keyboard.KEY_A:
			case Keyboard.KEY_LEFT:
			case Keyboard.KEY_D:
			case Keyboard.KEY_RIGHT:

				this.playerShip.moving = false;

				break;

			case Keyboard.KEY_B:
			case Keyboard.KEY_SPACEBAR:

				this.playerShip.shooting = false;

				break;

			default: break;

		}
	}

}

new Game().start();
<commit_msg>Remove gameWon (rely on playerShip.alive)<commit_after>/**
 * CG Space Invaders
 * CG45179 16'17
 *
 * @author: Rui Ventura ( ist181045 )
 * @author: Diogo Freitas ( ist181586 )
 * @author: Sara Azinhal ( ist181700 )
 */

import './lib/threejs/polyfills.js';

import { Scene } from './lib/threejs/scenes/Scene';
import { WebGLRenderer } from './lib/threejs/renderers/WebGLRenderer';

import { OrthographicCamera } from './lib/threejs/cameras/OrthographicCamera';
import { PerspectiveCamera } from './lib/threejs/cameras/PerspectiveCamera';

import { DirectionalLight } from './lib/threejs/lights/DirectionalLight';
import { PointLight } from './lib/threejs/lights/PointLight';

import { Clock } from './lib/threejs/core/Clock';

import { WIDTH, HEIGHT } from './Constants';
import { WINDOW_PIXEL_RATIO, WINDOW_WIDTH, WINDOW_HEIGHT } from './Constants';

import Field from './objects/Field';
import EnemyShip from './entities/EnemyShip';
import PlayerShip from './entities/PlayerShip';

import * as Keyboard from './Keyboard';

class Game {

	constructor () {

		this.scene = new Scene();
		this.renderer = (function () {

			let renderer = new WebGLRenderer();

			renderer.setPixelRatio( WINDOW_PIXEL_RATIO );
			renderer.setSize( WINDOW_WIDTH(), WINDOW_HEIGHT() );

			return renderer;

		})();

		this.gameClock = new Clock( false );

		this.field = new Field( 0, 0, 0, WIDTH - 10, HEIGHT - 10 );

		this.cameras = (function ( self ) {

			let cameras = new Array();

			/* Ortho camera (bird's eye) */
			cameras.push( function () {

				let camera = new OrthographicCamera(
					~WIDTH >> 1, WIDTH >> 1, HEIGHT >> 1, ~HEIGHT >> 1, 1, 200
				);

				camera.position.set( 0, 100, 0 );
				camera.lookAt( self.scene.position );

				camera.updateProjectionMatrix();

				return camera;

			}());

			/* Back perspective camera */
			cameras.push( function () {

				let camera = new PerspectiveCamera(
					75, WINDOW_WIDTH() / WINDOW_HEIGHT(), 1, 1000
				);

				camera.position.set( 0, 250, ( self.field.height >> 1 ) + 150 );
				camera.lookAt( self.scene.position );

				camera.updateProjectionMatrix();

				return camera;

			}());

			return cameras;

		})( this );
		this.camera = this.cameras[0];

		this.gameObjects = new Array();

		this.playerShip = new PlayerShip( 0, 0, ( this.field.height >> 1 ) - 50,
			new PerspectiveCamera( 75, WINDOW_WIDTH() / WINDOW_HEIGHT(), 1, 1000 ) );

		this.sun = (function ( self ) {

			let sun = new DirectionalLight( 0xffffff, 2 );

			sun.position.set( ~self.field.width >> 2, 100, self.field.height >> 2 );
			sun.target  = self.scene;

			return sun;

		})( this );
		this.stars = (function ( self, n ) {

			let stars = new Array();

			for ( let i = 0; i < n; ++i ) {

				stars.push( new PointLight( 0xffffff, 0.4 ) );

			}

			return stars;

		}( this, 6 ));

		this.lightsOn = false;

		this.gameOver = false;

	}

	start () {

		document.body.appendChild( this.renderer.domElement );

		window.addEventListener( 'resize',  this.resize.bind( this ) );
		window.addEventListener( 'keydown', this.keyDown.bind( this ) );
		window.addEventListener( 'keyup',   this.keyUp.bind( this ) );

		this.setup();

		/* HACK: Force a first resize */
		this.resize();

		this.update();

	}

	setup () {

		/* Clear the scene */
		for ( let i = 0; i < this.scene.children.length; ++i ) {

			this.scene.remove( this.scene.children[i] );

		}

		this.gameObjects = new Array();

		/* Build the scene */

		this.field.children.forEach( function ( b ) {

			b.type === 'Barrier' && this.gameObjects.push( b );

		}, this );

		this.field.changeMaterial( 0 );
		this.scene.add( this.field );

		this.playerShip.moving = false;
		this.playerShip.updateBoundries = true;
		this.playerShip.velocity.setScalar( 0 );
		this.playerShip.position.set( 0, 0, ( this.field.height >> 1 ) - 50 );
		this.playerShip.changeMaterial( 0 );

		this.cameras.length > 2 && this.cameras.pop();
		this.cameras.push( this.playerShip.camera );

		this.gameObjects.push( this.playerShip );
		this.scene.add( this.playerShip );

		let [ nx, nz ] = [ 5, 2 ];
		let [ segX, segZ ] = [
			( this.field.width - 120 ) / nx,
			( ( this.field.height - 120 ) >> 1 ) / nz
		];

		for ( let i = 0; i < nz; ++i ) {

			for ( let j = 0; j < nx; ++j ) {

				let [ posX, posZ ] = [
					segX * ( j - ( ( nx - 1 ) / 2 ) ),
					segZ * ( i - ( ( nz + 1 ) / 2 ) )
				];

				let alien = new EnemyShip( posX, 0, posZ );

				this.gameObjects.push( alien );
				this.scene.add( alien );

			}

		}

		this.lightsOn = false;
		this.sun.visible = false;
		this.scene.add( this.sun );

		this.stars.forEach( function ( star ) {

			star.position.set(
				this.field.width * ( Math.random() - 0.5 ),
				100,
				this.field.height * ( Math.random() - 0.5 )
			);

			star.visible = false;
			this.scene.add( star );

		}, this );

		this.gameOver = false;

	}

	update () {

		if ( this.gameClock.running ) {

			let dt = this.gameClock.getDelta();

			if ( EnemyShip.count === 0 || !this.playerShip.alive ) {

				this.gameOver = true;
				this.gameClock.stop();

			} else {

				if ( this.playerShip.shooting ) {

					let playerBullet = this.playerShip.fire();

					if ( playerBullet !== null ) {

						this.scene.add( playerBullet );
						this.gameObjects.push( playerBullet );

					}

				}

				for ( let i = 0; i < this.gameObjects.length; ++i ) {

					let o1 = this.gameObjects[i];

					if ( o1.isEntity && !o1.alive ) {

						this.scene.remove( o1 );
						this.gameObjects.splice( i, 1 );

					} else {

						o1.update( dt );

					}

					for ( let j = i + 1; j < this.gameObjects.length; ++j ) {

						let o2 = this.gameObjects[j];

						o1.intersect( o2 ) && o1.handleCollision( o2, dt );

					}

				}

			}

		}

		this.renderer.render( this.scene, this.camera );

		window.requestAnimationFrame( this.update.bind( this ) );

	}

	updateMaterials () {

		this.gameObjects.forEach( function ( obj ) {

			let index = this.lightsOn ? (obj.phong ? 1 : 2) : 0;

			obj.phong = !obj.phong;

			obj.changeMaterial( index );

		}, this );

	}

	resize () {

		let ratio = WINDOW_WIDTH() / WINDOW_HEIGHT();

		if ( this.camera.type === 'OrthographicCamera' ) {

			if ( ratio > ( WIDTH / HEIGHT ) ) {

				this.camera.left   = ~( HEIGHT * ratio ) >> 1;
				this.camera.right  = ( HEIGHT * ratio ) >> 1;
				this.camera.top    = HEIGHT >> 1;
				this.camera.bottom = ~HEIGHT >> 1;

			} else {

				this.camera.left   = ~WIDTH >> 1;
				this.camera.right  = WIDTH >> 1;
				this.camera.top    = ( WIDTH / ratio ) >> 1;
				this.camera.bottom = ~( WIDTH / ratio ) >> 1;

			}

		} else {

			this.camera.aspect = ratio;

		}

		this.camera.updateProjectionMatrix();
		this.renderer.setSize( WINDOW_WIDTH(), WINDOW_HEIGHT() );

	}

	keyDown ( event ) {

		if ( this.gameOver ) {

			/* Restart the game */
			if ( event.keyCode === Keyboard.KEY_R ) {

				this.gameOver = false;
				this.setup();

			}

		} else {

			switch ( event.keyCode ) {

				/* Toggle cameras */
				case Keyboard.KEY_1: /* Orthographic (top bird's eye camera) */
				case Keyboard.KEY_2: /* Perspective (back camera) */
				case Keyboard.KEY_3: /* Perspective (player view camera) */

					if ( !this.gameOver ) {

						this.camera = this.cameras[ event.keyCode - Keyboard.KEY_1 ];
						this.resize();

					}

					break;

				/* Player movement: Left */
				case Keyboard.KEY_A:
				case Keyboard.KEY_LEFT:

					if ( !this.playerShip.moving ) this.playerShip.moving = true;
					this.playerShip.setDirection( -1, 0, 0 );

					break;

				/* Player movement: Right */
				case Keyboard.KEY_D:
				case Keyboard.KEY_RIGHT:

					if ( !this.playerShip.moving ) this.playerShip.moving = true;
					this.playerShip.setDirection( 1, 0, 0 );

					break;

				/* Player action: Toggle shooting */
				case Keyboard.KEY_B:
				case Keyboard.KEY_SPACEBAR:

					this.playerShip.shooting = true;

					break;

				/* Show / hide stars */
				case Keyboard.KEY_C:

					this.stars.forEach( function( star ) {

						star.visible = !star.visible;

					});

					break;

				/* Toggle lights */
				case Keyboard.KEY_L:

					this.lightsOn = !this.lightsOn;
					this.updateMaterials();

					break;

				/* Toggle Gouraud / Lambert Shading */
				case Keyboard.KEY_G:

					this.updateMaterials();
					break;

				/* Toggle the sun (day/night modes) */
				case Keyboard.KEY_N:

					this.sun.visible = !this.sun.visible;

					break;

				/* Start / Stop the game (clock) */
				case Keyboard.KEY_S:

					this.gameClock.running ? this.gameClock.stop() : this.gameClock.start();

					break;

				/* Toggle wireframe of the objects in the scene */
				case Keyboard.KEY_W:

					this.scene.traverse( function( node ) {

						if ( node.isMesh ) {

							node.material.wireframe = !node.material.wireframe;

						}

					});

					break;

				default: break;

			}
		}

	}

	keyUp ( event ) {

		switch ( event.keyCode ) {

			case Keyboard.KEY_A:
			case Keyboard.KEY_LEFT:
			case Keyboard.KEY_D:
			case Keyboard.KEY_RIGHT:

				this.playerShip.moving = false;

				break;

			case Keyboard.KEY_B:
			case Keyboard.KEY_SPACEBAR:

				this.playerShip.shooting = false;

				break;

			default: break;

		}
	}

}

new Game().start();
<|endoftext|>


<commit_before>/*
 * jQuery Microdata v1.3
 * https://github.com/hubgit/jquery-microdata
 *
 * Copyright 2014 Alf Eaton
 * Released under the MIT license
 * http://git.macropus.org/mit-license/
 *
 * Date: 2014-01-13
 */
 (function($) {
	// get all items of a certain type
	$.fn.items = function(itemtype) {
		return this.find('[itemscope]').filter(function() {
			return attrs.call(this, 'itemType').get().indexOf(itemtype) !== -1;
		});
	};

	// all nodes with a certain property name
	$.fn.property = function(name) {
		return propertyNodes.apply(this).filter(function(item) {
			return attrs.call(this, 'itemProp').get().indexOf(name) !== -1;
		});
	};

	// get/set the value of matched elements
	$.fn.value = function(value) {
		// get value
		if (typeof value === 'undefined') {
			return itemValue.call(this);
		}

		// set a single value
		itemValue.call(this, value);
	};

	// get all values of a property as an array
	$.fn.values = function(expanded) {
		return this.map(function() {
			var node = $(this);

			return node.is('[itemscope]') ? microdata.call(node, expanded) : itemValue.call(node);
		}).get();
	};

	// convenience function for manipulating properties of an item
	$.fn.microdata = function(value) {
		switch (typeof value) {
			// get all values of an item
			case 'undefined':
			case 'boolean':
				return this.map(function() {
					return microdata.call($(this), value);
				}).get();

			// get/set a single property
			case 'string':
				if (arguments.length === 1) {
					// get a single property
					return this.property(value).value();
				}

				// set a single property
				this.property(value).value(arguments[1]);

				return this;

			// set the value of multiple properties
			case 'object':
				var nodes = this;

				$.each(value, function(name, value) {
					nodes.property(name).value(value);
				});

				return this;
		}
	};

	// all property nodes, including those in referenced nodes
	var propertyNodes = function() {
		var refs = attrs.call(this, 'itemRef').map(function() {
			return document.getElementById(this);
		});

		var nodes = $.merge($(refs), this);

		return nodes.find('[itemprop]').not(nodes.find('[itemscope] [itemprop]'));
	};

	// get a space-separated attribute as an array
	var attrs = function(attribute) {
		return $(this).map(function() {
			return (this.getAttribute(attribute) || '').split(/\s+/);
		});
	};

	// get or set the value of a node
	var itemValue = function(value) {
		var getting = value == null;

		if (this.is('[itemscope]')) {
			if (!getting) {
				throw 'Not allowed to set the value of an itemscope node';
			}

			return this;
		}

		var node = this.get(0);

		switch (node.nodeName) {
			case 'META':
			return getting ? $.trim(this.attr('content')) : this.attr('content', value);

			case 'DATA':
			return getting ? $.trim(this.attr('value')) : this.attr('value', value);

			case 'METER':
			return getting ? $.trim(this.attr('value')) : this.attr('value', value);

			case 'TIME':
			if (getting) {
				if (this.attr('datetime')) {
					return $.trim(this.attr('datetime'));
				}

				return $.trim(this.text());
			}
			return this.attr('datetime', value);

			case 'AUDIO':
			case 'EMBED':
			case 'IFRAME':
			case 'IMG':
			case 'SOURCE':
			case 'TRACK':
			return getting ? node.src : this.attr('src', value);

			case 'A':
			case 'AREA':
			case 'LINK':
			return getting ? node.href : this.attr('href', value);

			case 'OBJECT':
			return getting ? node.data : this.attr('data', value);

			default:
			return getting ? $.trim(this.text()) : this.text(value);
		}
	};

	// get all properties as a key/value(s) object
	var microdata = function(expanded) {
		if (this.length > 1) {
			return this.map(function() {
				return microdata.call($(this), expanded);
			}).get();
		};

		// the object always includes an itemtype
		var data = {
			type: expanded ? attrs.call(this, 'itemType').get() : attrs.call(this, 'itemType').get(0)
		};

		propertyNodes.call(this).map(function() {
			var node = $(this);
			var property = node.value();

			if (property instanceof jQuery) {
				property = microdata.call(property, expanded);
			}

			attrs.call(this, 'itemProp').each(function(index, name) {
				if (expanded) {
					if (typeof data[name] == 'undefined') {
						data[name] = [];
					}

					data[name].push(property);
				} else {
					if (typeof data[name] == 'undefined') {
						data[name] = property; // first item
					} else if ($.isArray(data[name])) {
						data[name].push(property); // more items
					} else {
						data[name] = [data[name], property];
					}
				}
			});
		});

		return data;
	};
}(jQuery));
<commit_msg>lowercase attributes, allow root override<commit_after>/*
 * jQuery Microdata v1.4
 * https://github.com/hubgit/jquery-microdata
 *
 * Copyright 2014 Alf Eaton
 * Released under the MIT license
 * http://git.macropus.org/mit-license/
 *
 * Date: 2014-01-21
 */
 (function($) {
 	// allow override of the root container, for testing
 	$.microdataRoot = document;

	// get all items of a certain type
	$.fn.items = function(itemtype) {
		return this.find('[itemscope]').filter(function() {
			return attrs.call(this, 'itemtype').get().indexOf(itemtype) !== -1;
		});
	};

	// all nodes with a certain property name
	$.fn.property = function(name) {
		return propertyNodes.apply(this).filter(function(item) {
			return attrs.call(this, 'itemprop').get().indexOf(name) !== -1;
		});
	};

	// get/set the value of matched elements
	$.fn.value = function(value) {
		// get value
		if (typeof value === 'undefined') {
			return itemValue.call(this);
		}

		// set a single value
		itemValue.call(this, value);
	};

	// get all values of a property as an array
	$.fn.values = function(expanded) {
		return this.map(function() {
			var node = $(this);

			return node.is('[itemscope]') ? microdata.call(node, expanded) : itemValue.call(node);
		}).get();
	};

	// convenience function for manipulating properties of an item
	$.fn.microdata = function(value) {
		switch (typeof value) {
			// get all values of an item
			case 'undefined':
			case 'boolean':
				return this.map(function() {
					return microdata.call($(this), value);
				}).get();

			// get/set a single property
			case 'string':
				if (arguments.length === 1) {
					// get a single property
					return this.property(value).value();
				}

				// set a single property
				this.property(value).value(arguments[1]);

				return this;

			// set the value of multiple properties
			case 'object':
				var nodes = this;

				$.each(value, function(name, value) {
					nodes.property(name).value(value);
				});

				return this;
		}
	};

	// all property nodes, including those in referenced nodes
	var propertyNodes = function() {
		var refs = attrs.call(this, 'itemref').map(function(i, id) {
			return $.microdataRoot.find('#' + id).get(0);
		});

		var nodes = $.merge($(refs), this);

		return nodes.find('[itemprop]').not(nodes.find('[itemscope] [itemprop]'));
	};

	// get a space-separated attribute as an array
	var attrs = function(attribute) {
		return $(this).map(function() {
			return (this.getAttribute(attribute) || '').split(/\s+/);
		}).filter(function() {
			return this.length;
		});
	};

	// get or set the value of a node
	var itemValue = function(value) {
		var getting = value == null;

		if (this.is('[itemscope]')) {
			if (!getting) {
				throw 'Not allowed to set the value of an itemscope node';
			}

			return this;
		}

		var node = this.get(0);

		switch (node.nodeName) {
			case 'META':
			return getting ? $.trim(this.attr('content')) : this.attr('content', value);

			case 'DATA':
			return getting ? $.trim(this.attr('value')) : this.attr('value', value);

			case 'METER':
			return getting ? $.trim(this.attr('value')) : this.attr('value', value);

			case 'TIME':
			if (getting) {
				if (this.attr('datetime')) {
					return $.trim(this.attr('datetime'));
				}

				return $.trim(this.text());
			}
			return this.attr('datetime', value);

			case 'AUDIO':
			case 'EMBED':
			case 'IFRAME':
			case 'IMG':
			case 'SOURCE':
			case 'TRACK':
			return getting ? node.src : this.attr('src', value);

			case 'A':
			case 'AREA':
			case 'LINK':
			return getting ? node.href : this.attr('href', value);

			case 'OBJECT':
			return getting ? node.data : this.attr('data', value);

			default:
			return getting ? $.trim(this.text()) : this.text(value);
		}
	};

	// get all properties as a key/value(s) object
	var microdata = function(expanded) {
		if (this.length > 1) {
			return this.map(function() {
				return microdata.call($(this), expanded);
			}).get();
		};

		// the object always includes an itemtype
		var data = {
			type: expanded ? attrs.call(this, 'itemtype').get() : attrs.call(this, 'itemtype').get(0)
		};

		propertyNodes.call(this).map(function() {
			var node = $(this);
			var property = node.value();

			if (property instanceof jQuery) {
				property = microdata.call(property, expanded);
			}

			attrs.call(this, 'itemprop').each(function(index, name) {
				if (expanded) {
					if (typeof data[name] == 'undefined') {
						data[name] = [];
					}

					data[name].push(property);
				} else {
					if (typeof data[name] == 'undefined') {
						data[name] = property; // first item
					} else if ($.isArray(data[name])) {
						data[name].push(property); // more items
					} else {
						data[name] = [data[name], property];
					}
				}
			});
		});

		return data;
	};
}(jQuery));
<|endoftext|>


<commit_before>// Utility for creating objects in older browsers
if ( typeof Object.create !== 'function' )
{
  Object.create = function( obj )
  {
    function F() {}
    F.prototype = obj;
    return new F();
  };
}

/*!
 * jQuery panelSnap
 * Version 0.7.2
 *
 * Requires:
 * - jQuery 1.7.1 or higher (Works with the API changes from 1.9.1 too)
 * - jQuery scrollEvents.js (included in the package)
 *
 * https://github.com/guidobouman/jquery-panelsnap
 *
 * Copyright 2013, Guido Bouman
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * Date: Wed Feb 13 16:05:00 2013 +0100
 */
(function($, window, document, undefined)
{
  var pluginName = 'panelSnap';
  var storageName = 'plugin_' + pluginName;

  var pluginObject = {
    isMouseDown: false,
    isSnapping: false,
    scrollInterval: 0,
    scrollOffset: 0,

    init: function(options, container)
    {
      var self = this;

      self.$window = $(window);
      self.$document = $(document);

      self.container = container;
      self.$container = $(container);

      self.$eventContainer = self.$container;
      if(self.$container.is('body'))
      {
        self.$eventContainer = self.$document;
      }

      self.options = $.extend(true, {}, $.fn.panelSnap.options, options);

      self.bind();

      if(self.options.$menu !== false && $('.active', self.options.$menu).length > 0)
      {
        $('.active', self.options.$menu).click();
      }
      else
      {
        self.activatePanel(self.$container.children(':first'));
      }

      return self;
    },

    bind: function()
    {
      var self = this;

      self.bindProxied(self.$eventContainer, 'scrollstart', self.scrollStart);
      self.bindProxied(self.$eventContainer, 'scrollstop', self.scrollStop);
      self.bindProxied(self.$eventContainer, 'mousewheel', self.mouseWheel);
      self.bindProxied(self.$eventContainer, 'mousedown', self.mouseDown);
      self.bindProxied(self.$eventContainer, 'mouseup', self.mouseUp);

      self.bindProxied(self.$window, 'resize', self.scrollStop);

      if(self.options.$menu !== false)
      {
        self.bindProxied($(self.options.$menu), 'click', self.captureMenuClick, self.options.menuSelector);
      }
    },

    bindProxied: function($element, event, method, selector)
    {
      var self = this;

      selector = typeof selector === 'string' ? selector : null;

      $element.on(event + self.options.namespace, selector, $.proxy(function(e)
      {
        return method.call(self, e);
      }, self));
    },

    destroy: function()
    {
      var self = this;

      // Gotta love namespaced events!
      self.$eventContainer.off(self.options.namespace);

      self.$window.off(self.options.namespace);

      if(self.options.$menu !== false)
      {
        $(self.options.menuSelector, self.options.$menu).off(self.options.namespace);
      }

      self.$container.removeData(storageName);
    },

    captureMenuClick: function(e)
    {
      var self = this;
      var panel = $(e.currentTarget).data('panel');
      var selector = self.options.panelSelector + '[data-panel=' + panel + ']';
      var $target = $(selector, self.$container);

      self.snapToPanel($target);

      return false;
    },

    scrollStart: function(e)
    {
      var self = this;

      // Deprecated, moved storage of scrollOffset to callback of panelSnap
      // self.scrollOffset = self.$container.scrollTop();
    },

    scrollStop: function(e)
    {
      var self = this;

      if(self.isMouseDown)
      {
        self.$eventContainer.one('mouseup' + self.options.namespace, self.processScroll);
        return;
      }

      if(self.isSnapping)
      {
        return;
      }

      var interval = self.$container.height();
      var intervalDifference = interval - self.scrollInterval;
      var offset = self.$container.scrollTop();
      var scrollDifference = offset - self.scrollOffset;
      var maxOffset = self.$container[0].scrollHeight - interval;

      self.scrollInterval = interval;

      if(
        scrollDifference === 0  && intervalDifference === 0 ||
        offset < 0 ||
        offset > maxOffset
      )
      {
        return;
      }

      var child_number;
      if(scrollDifference < -self.options.directionThreshold && scrollDifference > -interval)
      {
        child_number = Math.floor(offset / interval);
      }
      else if(scrollDifference > self.options.directionThreshold && scrollDifference < interval)
      {
        child_number = Math.ceil(offset / interval);
      }
      else
      {
        child_number = Math.round(offset / interval);
      }

      child_number += 1;

      var selector = '> ' + self.options.panelSelector + ':nth-child(' + child_number + ')';
      var $target = $(selector, self.$container);

      self.snapToPanel($target);
    },

    mouseWheel: function(e)
    {
      var self = this;

      // This event only fires when the user actually scrolls with their input device.
      // Be it a trackpad, legacy mouse or anything else.

      self.$container.stop(true);
      self.isSnapping = false;
    },

    mouseDown: function(e)
    {
      var self = this;

      self.isMouseDown = true;
    },

    mouseUp: function(e)
    {
      var self = this;

      self.isMouseDown = false;
    },

    snapToPanel: function($target)
    {
      var self = this;

      self.isSnapping = true;

      self.options.onSnapStart.call(self, $target);
      self.$container.trigger('panelsnap:start', [$target]);

      var scrollTarget = 0;
      if(self.$container.is('body'))
      {
        scrollTarget = $target.offset().top;
      }
      else
      {
        scrollTarget = self.$container.scrollTop() + $target.position().top;
      }

      self.$container.animate(
      {
        scrollTop: scrollTarget
      }, self.options.slideSpeed, function()
      {
        self.scrollOffset = scrollTarget;
        self.isSnapping = false;

        // Call callback
        self.options.onSnapFinish.call(self, $target);
        self.$container.trigger('panelsnap:finish', [$target]);
      });

      self.activatePanel($target);
    },

    activatePanel: function($target)
    {
      var self = this;

      $('> ' + self.options.panelSelector + '.active', self.container).removeClass('active');
      $target.addClass('active');

      if(self.options.$menu !== false)
      {
        $(self.options.menuSelector + '.active', self.options.$menu).removeClass('active');
        var itemSelector = self.options.menuSelector + '[data-panel=' + $target.data('panel') + ']';
        var $activeItem = $(itemSelector, self.options.$menu);
        $activeItem.addClass('active');
      }
    }
  };

  $.fn[pluginName] = function(options)
  {
    return this.each(function()
    {
      var pluginInstance = $.data(this, storageName);
      if(typeof options === 'object' || options === 'init' || ! options)
      {
        if(!pluginInstance)
        {
          if(options === 'init')
          {
            options = Array.prototype.slice.call(arguments, 1);
          }

          pluginInstance = $.data(this, storageName, Object.create(pluginObject).init(options, this));
        }
        else
        {
          $.error('Plugin is already initialized for this object.');
          return;
        }
      }
      else if(!pluginInstance)
      {
        $.error('Plugin is not initialized for this object yet.');
        return;
      }
      else if(pluginInstance[options])
      {
        method = options;
        options = Array.prototype.slice.call(arguments, 1);
        pluginInstance[method](options);
      }
      else
      {
        $.error('Method ' +  options + ' does not exist on jQuery.panelSnap.');
        return;
      }
    });
  };

  $.fn.panelSnap.options = {
    $menu: false,
    menuSelector: 'a',
    panelSelector: 'section',
    namespace: '.panelSnap',
    onSnapStart: function(){},
    onSnapFinish: function(){},
    directionThreshold: 50,
    slideSpeed: 200
  };

})(jQuery, window, document);
<commit_msg>Fixes #1, siblings are now ignored.<commit_after>// Utility for creating objects in older browsers
if ( typeof Object.create !== 'function' )
{
  Object.create = function( obj )
  {
    function F() {}
    F.prototype = obj;
    return new F();
  };
}

/*!
 * jQuery panelSnap
 * Version 0.7.2
 *
 * Requires:
 * - jQuery 1.7.1 or higher (Works with the API changes from 1.9.1 too)
 * - jQuery scrollEvents.js (included in the package)
 *
 * https://github.com/guidobouman/jquery-panelsnap
 *
 * Copyright 2013, Guido Bouman
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * Date: Wed Feb 13 16:05:00 2013 +0100
 */
(function($, window, document, undefined)
{
  var pluginName = 'panelSnap';
  var storageName = 'plugin_' + pluginName;

  var pluginObject = {
    isMouseDown: false,
    isSnapping: false,
    scrollInterval: 0,
    scrollOffset: 0,

    init: function(options, container)
    {
      var self = this;

      self.$window = $(window);
      self.$document = $(document);

      self.container = container;
      self.$container = $(container);

      self.$eventContainer = self.$container;
      if(self.$container.is('body'))
      {
        self.$eventContainer = self.$document;
      }

      self.options = $.extend(true, {}, $.fn.panelSnap.options, options);

      self.bind();

      if(self.options.$menu !== false && $('.active', self.options.$menu).length > 0)
      {
        $('.active', self.options.$menu).click();
      }
      else
      {
        self.activatePanel(self.$container.children(':first'));
      }

      return self;
    },

    bind: function()
    {
      var self = this;

      self.bindProxied(self.$eventContainer, 'scrollstart', self.scrollStart);
      self.bindProxied(self.$eventContainer, 'scrollstop', self.scrollStop);
      self.bindProxied(self.$eventContainer, 'mousewheel', self.mouseWheel);
      self.bindProxied(self.$eventContainer, 'mousedown', self.mouseDown);
      self.bindProxied(self.$eventContainer, 'mouseup', self.mouseUp);

      self.bindProxied(self.$window, 'resize', self.scrollStop);

      if(self.options.$menu !== false)
      {
        self.bindProxied($(self.options.$menu), 'click', self.captureMenuClick, self.options.menuSelector);
      }
    },

    bindProxied: function($element, event, method, selector)
    {
      var self = this;

      selector = typeof selector === 'string' ? selector : null;

      $element.on(event + self.options.namespace, selector, $.proxy(function(e)
      {
        return method.call(self, e);
      }, self));
    },

    destroy: function()
    {
      var self = this;

      // Gotta love namespaced events!
      self.$eventContainer.off(self.options.namespace);

      self.$window.off(self.options.namespace);

      if(self.options.$menu !== false)
      {
        $(self.options.menuSelector, self.options.$menu).off(self.options.namespace);
      }

      self.$container.removeData(storageName);
    },

    captureMenuClick: function(e)
    {
      var self = this;
      var panel = $(e.currentTarget).data('panel');
      var selector = self.options.panelSelector + '[data-panel=' + panel + ']';
      var $target = $(selector, self.$container);

      self.snapToPanel($target);

      return false;
    },

    scrollStart: function(e)
    {
      var self = this;

      // Deprecated, moved storage of scrollOffset to callback of panelSnap
      // self.scrollOffset = self.$container.scrollTop();
    },

    scrollStop: function(e)
    {
      var self = this;

      if(self.isMouseDown)
      {
        self.$eventContainer.one('mouseup' + self.options.namespace, self.processScroll);
        return;
      }

      if(self.isSnapping)
      {
        return;
      }

      var interval = self.$container.height();
      var intervalDifference = interval - self.scrollInterval;
      var offset = self.$container.scrollTop();
      var scrollDifference = offset - self.scrollOffset;
      var maxOffset = self.$container[0].scrollHeight - interval;

      self.scrollInterval = interval;

      if(
        scrollDifference === 0  && intervalDifference === 0 ||
        offset < 0 ||
        offset > maxOffset
      )
      {
        return;
      }

      var child_number;
      if(scrollDifference < -self.options.directionThreshold && scrollDifference > -interval)
      {
        child_number = Math.floor(offset / interval);
      }
      else if(scrollDifference > self.options.directionThreshold && scrollDifference < interval)
      {
        child_number = Math.ceil(offset / interval);
      }
      else
      {
        child_number = Math.round(offset / interval);
      }

      var selector = '> ' + self.options.panelSelector + ':eq(' + child_number + ')';
      var $target = $(selector, self.$container);

      self.snapToPanel($target);
    },

    mouseWheel: function(e)
    {
      var self = this;

      // This event only fires when the user actually scrolls with their input device.
      // Be it a trackpad, legacy mouse or anything else.

      self.$container.stop(true);
      self.isSnapping = false;
    },

    mouseDown: function(e)
    {
      var self = this;

      self.isMouseDown = true;
    },

    mouseUp: function(e)
    {
      var self = this;

      self.isMouseDown = false;
    },

    snapToPanel: function($target)
    {
      var self = this;

      self.isSnapping = true;

      self.options.onSnapStart.call(self, $target);
      self.$container.trigger('panelsnap:start', [$target]);

      var scrollTarget = 0;
      if(self.$container.is('body'))
      {
        scrollTarget = $target.offset().top;
      }
      else
      {
        scrollTarget = self.$container.scrollTop() + $target.position().top;
      }

      self.$container.animate(
      {
        scrollTop: scrollTarget
      }, self.options.slideSpeed, function()
      {
        self.scrollOffset = scrollTarget;
        self.isSnapping = false;

        // Call callback
        self.options.onSnapFinish.call(self, $target);
        self.$container.trigger('panelsnap:finish', [$target]);
      });

      self.activatePanel($target);
    },

    activatePanel: function($target)
    {
      var self = this;

      $('> ' + self.options.panelSelector + '.active', self.container).removeClass('active');
      $target.addClass('active');

      if(self.options.$menu !== false)
      {
        $(self.options.menuSelector + '.active', self.options.$menu).removeClass('active');
        var itemSelector = self.options.menuSelector + '[data-panel=' + $target.data('panel') + ']';
        var $activeItem = $(itemSelector, self.options.$menu);
        $activeItem.addClass('active');
      }
    }
  };

  $.fn[pluginName] = function(options)
  {
    return this.each(function()
    {
      var pluginInstance = $.data(this, storageName);
      if(typeof options === 'object' || options === 'init' || ! options)
      {
        if(!pluginInstance)
        {
          if(options === 'init')
          {
            options = Array.prototype.slice.call(arguments, 1);
          }

          pluginInstance = $.data(this, storageName, Object.create(pluginObject).init(options, this));
        }
        else
        {
          $.error('Plugin is already initialized for this object.');
          return;
        }
      }
      else if(!pluginInstance)
      {
        $.error('Plugin is not initialized for this object yet.');
        return;
      }
      else if(pluginInstance[options])
      {
        method = options;
        options = Array.prototype.slice.call(arguments, 1);
        pluginInstance[method](options);
      }
      else
      {
        $.error('Method ' +  options + ' does not exist on jQuery.panelSnap.');
        return;
      }
    });
  };

  $.fn.panelSnap.options = {
    $menu: false,
    menuSelector: 'a',
    panelSelector: 'section',
    namespace: '.panelSnap',
    onSnapStart: function(){},
    onSnapFinish: function(){},
    directionThreshold: 50,
    slideSpeed: 200
  };

})(jQuery, window, document);
<|endoftext|>


<commit_before>/*!
 * jQuery JavaScript Library v2.2.3
 * https://tech.tiogatours.nl/jquery-speedtest/README.md
 *
 * Copyright Tioga Tours B.V.
 * Released under the MIT license
 * https://tech.tiogatours.nl/jquery-speedtest/LICENSE
 *
 * Date: 2016-04-26
 */
;(function ($) {

	var milliFactor  = 1000,
		kFactor = 1024,

	SpeedTest = function (options)
    {
		var self = this,
			opts,
			i;
		$.extend(true, self.options, options);

		for (i=0; i<2;i++) {
			opts = self.options[['upload', 'download'][i]];

			if (opts.byteSize > 2 * kFactor * kFactor) {
				throw 'Cannot bench with sizes bigger than 2 MB';
			}
			if (opts.byteStep > kFactor * kFactor) {
				throw 'Cannot bench with step sizes bigger than 1 MB';
			}
		}

        // Execute the test twice, the first connection always takes a long time
        // the second connection is much more responsive
        if (self.options.testConnectionTime === true) {
            self.benchType('upload', 1, function () {
            });

            self.benchType('upload', 1, function (speed, duration) {
                self.connectTime = duration;
            });
        }
	};
	SpeedTest.prototype = {
		options: {
			upload: {
				url: '',
				byteSize: 300 * kFactor,
				byteStep: 100 * kFactor,
				iterations: 3,
				timeout: 2, // Seconds
				arbitraryHeaderByteSize: 400 // bytes
			},
			download: {
				url: '',
				iterations: 3,
				byteSize: 300 * kFactor,
				byteStep: 100 * kFactor,
				timeout: 2, // Seconds
				arbitraryHeaderByteSize: 400 // bytes
			},
            // Test the time it takes to do an empty
            // request
            testConnectionTime: true
		},
		startTime: null,
        connectTime: 0,

		randomString: function (byteSize)
		{
			//random data prevents gzip effect
			var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_+`-=[]\{}|;':,./<>?",
				randomString = '',
				i;
			for (i = 0; i < byteSize; i++) {
				randomString += chars.charAt(Math.floor(Math.random() * chars.length));
			}
			return randomString;
		},
		benchmark: function (callback)
        {
			var self = this;
			self.benchUpload(function(uploadSpeed) {
				self.benchDownload(function(downloadSpeed){
					callback(downloadSpeed, uploadSpeed);
				});
			});
		},
		benchUpload: function (callback)
        {
			this.benchIterate('upload', this.options.upload.iterations, callback);
		},
		benchDownload: function (callback)
        {
			this.benchIterate('download', this.options.download.iterations, callback);
		},
		benchIterate: function (type, iterations, callback) {
			var self = this,
				speeds = [],
                durations = [],
				byteSize = this.options[type].byteSize,
			run = function ()
			{
				iterations--;
				self.benchType(type, byteSize, function (speed, duration) {
					if (speed !== -1) {
						speeds.push(speed);
                        durations.push(duration);
						byteSize += self.options[type].byteStep;
					} else {
						byteSize -= self.options[type].byteStep;
					}

					if (iterations > 0) {
						run();
					} else {
						var sumSpeed = 0, i, sumDuration = 0;

						for (i=0;i<speeds.length; i++) {
                            sumSpeed += speeds[i];
                            sumDuration += durations[i];
						}
						if (speeds.length > 0) {
							callback(Math.round(sumSpeed / speeds.length), Math.round(sumDuration / durations.length));
						} else {
							callback(-1, -1);
						}
					}
				});
			};
			run();
		},
		benchType: function (type, byteSize, callback)
        {
			var self = this,
				data = 'size='+byteSize,
				t;

			if (self.startTime !== null) {
				setTimeout(function () {
                    self.benchType(type, byteSize, callback);
                }, 300);
                return;
			}

			if (type === 'upload') {
                data = '';
                var chunkSize = 200;
                for (var i=0; i<byteSize; i+=chunkSize) {
                    data += '&data=' + encodeURIComponent(self.randomString(chunkSize));
                }
                // Correct the size as some extra data was added
                byteSize = data.length;
			}

			self.rq = $.ajax({
				url: self.options[type].url,
				method: type === 'upload' ? 'POST' : 'GET',
				cache: false,
				data: data,
				timeout: self.options[type].timeout * milliFactor,
				success: function (data, txt, xhr) {
					var t = new Date(),
						endTime = t.getSeconds() * milliFactor + t.getMilliseconds(),
						duration = (endTime - self.startTime),
						ot = 0,
						speed,
                        decodeTime = 0,
                        s, e;

                    if (xhr.responseText) {
                        // Benchmark decoding, larger responses require serious decode time
                        s = new Date();
                        JSON.parse(xhr.responseText);
                        e = new Date();

                        decodeTime = e.getSeconds() * milliFactor + e.getMilliseconds() - s.getSeconds() * milliFactor - s.getMilliseconds();
                    }

					if (data && data.ownTime) {
						ot = data.ownTime * milliFactor;
					}

					duration = duration - ot - self.connectTime - decodeTime;

					speed = Math.round((byteSize + self.options[type].arbitraryHeaderByteSize) / (duration/milliFactor));
					self.startTime = null;
					callback(speed, duration);
				},
				complete: function () {
					clearTimeout(self.timeout);
				},
				error: function () {
					self.startTime = null;
					callback(-1);
				}
			});
			// Set start time after ajax, not on beforeSend for more precise testing
			t = new Date();
			self.startTime = t.getSeconds() * milliFactor + t.getMilliseconds();
		}
	};
	window.SpeedTest = SpeedTest;
})(jQuery);<commit_msg>Use promises and added events<commit_after>/*!
 * jQuery JavaScript Library v2.2.3
 * https://tech.tiogatours.nl/jquery-speedtest/README.md
 *
 * Copyright Tioga Tours B.V.
 * Released under the MIT license
 * https://tech.tiogatours.nl/jquery-speedtest/LICENSE
 *
 * Date: 2016-04-26
 */
;(function ($, undef) {

	var milliFactor  = 1000,
		kFactor = 1024,

	SpeedTest = function (options)
    {
		var self = this,
			opts,
			i;
		$.extend(true, self.options, options);

		for (i=0; i<2;i++) {
			opts = self.options[['upload', 'download'][i]];

			if (opts.byteSize > 2 * kFactor * kFactor) {
				throw 'Cannot bench with sizes bigger than 2 MB';
			}
			if (opts.byteStep > kFactor * kFactor) {
				throw 'Cannot bench with step sizes bigger than 1 MB';
			}
		}

        // Execute the test twice, the first connection always takes a long time
        // the second connection is much more responsive
        if (self.options.testConnectionTime === true) {
            self.benchType('upload', 1).then(function () {
            });

            self.benchType('upload', 1).then(function (speed, duration) {
                self.connectTime = duration;
            });
        }
	};
	SpeedTest.prototype = {
		options: {
			upload: {
				url: '',
				byteSize: 300 * kFactor,
				byteStep: 100 * kFactor,
				iterations: 3,
				timeout: 2, // Seconds
				arbitraryHeaderByteSize: 400 // bytes
			},
			download: {
				url: '',
				iterations: 3,
				byteSize: 300 * kFactor,
				byteStep: 100 * kFactor,
				timeout: 2, // Seconds
				arbitraryHeaderByteSize: 400 // bytes
			},
            // Test the time it takes to do an empty
            // request
            testConnectionTime: true
		},
		startTime: null,
        connectTime: 0,

		randomString: function (byteSize)
		{
			//random data prevents gzip effect
			var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~!@#$%^&*()_+`-=[]\{}|;':,./<>?",
				randomString = '',
				i;
			for (i = 0; i < byteSize; i++) {
				randomString += chars.charAt(Math.floor(Math.random() * chars.length));
			}
			return randomString;
		},
		benchmark: function ()
        {
			var self = this,
                deferred = $.Deferred();
			self.benchUpload().then(function(uploadSpeed, uploadDuration) {
				self.benchDownload().then(function(downloadSpeed, downloadDuration){
					deferred.resolve(downloadSpeed, uploadSpeed, uploadDuration, downloadDuration);
				});
			});
            return deferred.promise();
		},
		benchUpload: function ()
        {
            var deferred = $.Deferred();
			this.benchIterate('upload', this.options.upload.iterations).then(function (speed, duration) {
                deferred.resolve(speed, duration);
            });
            return deferred.promise();
		},
		benchDownload: function ()
        {
            var deferred = $.Deferred();
			this.benchIterate('download', this.options.download.iterations).then(function (speed, duration) {
                deferred.resolve(speed, duration);
            });
            return deferred.promise();
		},
		benchIterate: function (type, iterations) {
			var self = this,
				speeds = [],
                durations = [],
				byteSize = this.options[type].byteSize,
                deferred = $.Deferred(),
			run = function ()
			{
				iterations--;
				self.benchType(type, byteSize).then(function (speed, duration) {
					if (speed !== -1) {
						speeds.push(speed);
                        durations.push(duration);
						byteSize += self.options[type].byteStep;
					} else {
						byteSize -= self.options[type].byteStep;
					}

					if (iterations > 0) {
						run();
					} else {
						var sumSpeed = 0, i, sumDuration = 0;

						for (i=0;i<speeds.length; i++) {
                            sumSpeed += speeds[i];
                            sumDuration += durations[i];
						}
						if (speeds.length > 0) {
							deferred.resolve(Math.round(sumSpeed / speeds.length), Math.round(sumDuration / durations.length));
						} else {
                            deferred.resolve(-1, -1);
						}
					}
				});
			};
			run();
            return deferred.promise();
		},
		benchType: function (type, byteSize, deferred)
        {
			var self = this,
				data = 'size='+byteSize,
				t,
                $s = $(self);

            $s.trigger('before-run', [type, byteSize]);

            if (!deferred) {
                deferred = $.Deferred();
            }

			if (self.startTime !== null) {
				setTimeout(function () {
                    $s.trigger('run-wait', [type, byteSize]);
                    self.benchType(type, byteSize, deferred);
                }, 300);
                return deferred.promise();
			}

			if (type === 'upload') {
                data = '';
                var chunkSize = 200;
                for (var i=0; i<byteSize; i+=chunkSize) {
                    data += '&data=' + encodeURIComponent(self.randomString(chunkSize));
                }
                // Correct the size as some extra data was added
                byteSize = data.length;
			}

            $s.trigger('before-start', [type, byteSize]);

			self.rq = $.ajax({
				url: self.options[type].url,
				method: type === 'upload' ? 'POST' : 'GET',
				cache: false,
				data: data,
				timeout: self.options[type].timeout * milliFactor,
				success: function (data, txt, xhr) {
					var t = new Date(),
						endTime = t.getSeconds() * milliFactor + t.getMilliseconds(),
						duration = (endTime - self.startTime),
						ot = 0,
						speed,
                        decodeTime = 0,
                        s, e;

                    if (xhr.responseText) {
                        // Benchmark decoding, larger responses require serious decode time
                        s = new Date();
                        JSON.parse(xhr.responseText);
                        e = new Date();

                        decodeTime = e.getSeconds() * milliFactor + e.getMilliseconds() - s.getSeconds() * milliFactor - s.getMilliseconds();
                    }

					if (data && data.ownTime) {
						ot = data.ownTime * milliFactor;
					}

					duration = duration - ot - self.connectTime - decodeTime;

					speed = Math.round((byteSize + self.options[type].arbitraryHeaderByteSize) / (duration/milliFactor));

                    $s.trigger('run-success', [type, byteSize, speed, duration]);

					self.startTime = null;
					deferred.resolve(speed, duration);
				},
				complete: function () {
                    $s.trigger('run-complete', [type, byteSize]);
				},
				error: function (a,b,c) {
                    $s.trigger('run-error', [a,b,c]);
					self.startTime = null;
                    deferred.resolve(-1, -1);
				}
			});
			// Set start time after ajax, not on beforeSend for more precise testing
			t = new Date();
			self.startTime = t.getSeconds() * milliFactor + t.getMilliseconds();

            return deferred.promise();
		}
	};
	window.SpeedTest = SpeedTest;
})(jQuery);<|endoftext|>