<commit_before>// Player

game.PlayerEntity = me.Entity.extend({
    init: function(x, y, settings) {
        this.setSuper();
        this.setPlayerTimers();
        this.setAttributes();
        this.type = "PlayerEntity";
        this.setFlags();

        me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH);

        this.addAnimtion();

        this.renderable.setCurrentAnimation("idle");
    },

    setSuper: function() {
        this._super(me.Entity, 'init', [x, y, {
                image: "player",
                // the 'width' and 'height' are telling the screen how much space to preserve
                width: 64,
                height: 64,
                // telling us what the size of the image its using is
                spritewidth: "64",
                spriteheight: "64",
                getShape: function() {
                    return(new me.Rect(0, 0, 64, 64)).toPolygon();
                }
            }]);
    },

    setPlayerTimers: function() {
        this.now = new Date().getTime();
        this.lastHit = this.now;
        this.lastAttack = new Date().getTime();
    },

    setAttributes: function() {
        this.health = game.data.playerHealth;
        this.body.setVelocity(5, 20);
        this.attack = game.data.playerAttack;
    },

    setFlags: function() {
        // keeps track of the direction
        this.facing = "right";
        this.dead = false;
        this.attacking  = false;
    },

    addAnimation: function() {
        this.renderable.addAnimation("idle", [78]);
        this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125]);
        this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72], 80);
    },

    update: function(delta) {
        this.now = new Date().getTime();
        this.dead = checkifDead();
        this.checkKeyPressesAndMove();
        this.setAnimation();
        me.collision.check(this, true, this.collideHandler.bind(this), true);
        this.body.update(delta);
        this._super(me.Entity, "update", [delta]);
        return true;
    },

    checkIfDead: function() {
        if (this.health <= 0) {
            return true;
        }
        return false;
    },

    checkKeyPressesAndMove: function() {
        if (me.input.isKeyPressed("right")) {
            this.moveRight();
        } else if (me.input.isKeyPressed("left")) {
            this.moveleft();
        } else {
            this.body.vel.x = 0;
        }

        if (me.input.isKeyPressed("jump") && !this.jumping && !this.body.falling) {
            this.jump();
        }

        this.attacking = me.input.isKeyPressed("attack")
    },

    moveRight: function() {
        // adds to the position of my x by the velocity defined above in
        //setVelocity() and multiplying it by me.timer.tick.
        //me.timer.tick makes the movement look smooth
        this.body.vel.x += this.body.accel.x * me.timer.tick;
        this.facing = "right";
        this.flipX(true);
    },

    moveLeft: function() {
        this.facing = "left";
        this.body.vel.x -= this.body.accel.x * me.timer.tick;
        this.flipX(false);
    },

    jump: function() {
        this.body.jumping = true;
        this.body.vel.y -= this.body.accel.y * me.timer.tick;
    },

    setAnimation: function() {
        if (this.attacking) {
            if (!this.renderable.isCurrentAnimation("attack")) {
                //sets the current animationto attack and one that is over goes
                //back to the idle animation
                this.renderable.setCurrentAnimation("attack", "idle");
                //makes it so next time we start this sequence we begin from the
                //first animation, not wherever we left off when we switched to
                //another animation
                this.renderable.setAnimationFrame();
            }
        }

        else if (this.body.vel.x !== 0 && !this.renderable.isCurrentAnimation("attack")) {
            if (!this.renderable.isCurrentAnimation("walk")) {
                this.renderable.setCurrentAnimation("walk");
            }
        } else if (!this.renderable.isCurrentAnimation("attack")) {
            this.renderable.setCurrentAnimation("idle");
        }
    },

    loseHealth: function(damage) {
        this.health = this.health - damage;
    },

    collideHandler: function(response) {
        if (response.b.type === 'EnemyBaseEntity') {
            var ydif = this.pos.y - response.b.pos.y;
            var xdif = this.pos.x - response.b.pos.x;

            if (ydif < -40 && xdif < 70 && xdif > -35) {
                this.body.falling = false;
                this.body.vel.y = -1;
            }

            // colliding with the base on the right
            else if (xdif < -35 && this.facing === 'right' && xdif < 0 && ydif > -50) {
                this.body.vel.x = 0;
                //this.pos.x = this.pos.x - 1;

                // colliding with the base on the left
            } else if (xdif < 70 && this.facing === 'left' && xdif > 0) {
                this.body.vel.x = 0;
                //this.pos.x = this.pos.x + 1;
            }

            if (this.renderable.isCurrentAnimation("attack") && this.now - this.lastHit >= 600) {
                this.lastHit = this.now;
                response.b.loseHealth();
            }
        } else if (response.b.type === 'EnemyCreep') {
            var xdif = this.pos.x - response.b.pos.x;
            var ydif = this.pos.y - response.b.pos.y;

            if (xdif > 0) {
                this.pos.x = this.pos.x + 1;
                if (this.facing === "left") {
                    this.body.vel.x = 0;
                }
            } else {
                //this.pos.x = this.pos.x - 1;
                if (this.facing === "right") {
                    this.body.vel.x = 0;
                }
            }

            if (this.renderable.isCurrentAnimation("attack") && this.now - this.lastHit >= 1000
                    && (Math.abs(ydif) <= 40) &&
                    (((xdif > 0) && this.facing === "left") || ((xdif < 0) && this.facing === "right"))
                    ) {
                this.lastHit = this.now;
                // if the creeps' health is less than our attack, execute code in if statement
                if (response.b.health <= game.data.playerAttack) {
                    // adds one gold for a creep kill
                    game.data.gold += 1;
                    console.log("Current gold: " + game.data.gold);
                }

                response.b.loseHealth(game.data.playerAttack);
            }
        }
    }
});<commit_msg>no message<commit_after>// Player

game.PlayerEntity = me.Entity.extend({
    init: function(x, y, settings) {
        this.setSuper();
        this.setPlayerTimers();
        this.setAttributes();
        this.type = "PlayerEntity";
        this.setFlags();

        me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH);

        this.addAnimation();

        this.renderable.setCurrentAnimation("idle");
    },

    setSuper: function(x, y) {
        this._super(me.Entity, 'init', [x, y, {
                image: "player",
                // the 'width' and 'height' are telling the screen how much space to preserve
                width: 64,
                height: 64,
                // telling us what the size of the image its using is
                spritewidth: "64",
                spriteheight: "64",
                getShape: function() {
                    return(new me.Rect(0, 0, 64, 64)).toPolygon();
                }
            }]);
    },

    setPlayerTimers: function() {
        this.now = new Date().getTime();
        this.lastHit = this.now;
        this.lastAttack = new Date().getTime();
    },

    setAttributes: function() {
        this.health = game.data.playerHealth;
        this.body.setVelocity(5, 20);
        this.attack = game.data.playerAttack;
    },

    setFlags: function() {
        // keeps track of the direction
        this.facing = "right";
        this.dead = false;
        this.attacking  = false;
    },

    addAnimation: function() {
        this.renderable.addAnimation("idle", [78]);
        this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125]);
        this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72], 80);
    },

    update: function(delta) {
        this.now = new Date().getTime();
        this.dead = this.checkIfDead();
        this.checkKeyPressesAndMove();
        this.addAnimation();
        me.collision.check(this, true, this.collideHandler.bind(this), true);
        this.body.update(delta);
        this._super(me.Entity, "update", [delta]);
        return true;
    },

    checkIfDead: function() {
        if (this.health <= 0) {
            return true;
        }
        return false;
    },

    checkKeyPressesAndMove: function() {
        if (me.input.isKeyPressed("right")) {
            this.moveRight();
        } else if (me.input.isKeyPressed("left")) {
            this.moveleft();
        } else {
            this.body.vel.x = 0;
        }

        if (me.input.isKeyPressed("jump") && !this.jumping && !this.body.falling) {
            this.jump();
        }

        this.attacking = me.input.isKeyPressed("attack")
    },

    moveRight: function() {
        // adds to the position of my x by the velocity defined above in
        //setVelocity() and multiplying it by me.timer.tick.
        //me.timer.tick makes the movement look smooth
        this.body.vel.x += this.body.accel.x * me.timer.tick;
        this.facing = "right";
        this.flipX(true);
    },

    moveLeft: function() {
        this.facing = "left";
        this.body.vel.x -= this.body.accel.x * me.timer.tick;
        this.flipX(false);
    },

    jump: function() {
        this.body.jumping = true;
        this.body.vel.y -= this.body.accel.y * me.timer.tick;
    },

    setAnimation: function() {
        if (this.attacking) {
            if (!this.renderable.isCurrentAnimation("attack")) {
                //sets the current animationto attack and one that is over goes
                //back to the idle animation
                this.renderable.setCurrentAnimation("attack", "idle");
                //makes it so next time we start this sequence we begin from the
                //first animation, not wherever we left off when we switched to
                //another animation
                this.renderable.setAnimationFrame();
            }
        }

        else if (this.body.vel.x !== 0 && !this.renderable.isCurrentAnimation("attack")) {
            if (!this.renderable.isCurrentAnimation("walk")) {
                this.renderable.setCurrentAnimation("walk");
            }
        } else if (!this.renderable.isCurrentAnimation("attack")) {
            this.renderable.setCurrentAnimation("idle");
        }
    },

    loseHealth: function(damage) {
        this.health = this.health - damage;
    },

    collideHandler: function(response) {
        if (response.b.type === 'EnemyBaseEntity') {
            this.collideWithEnemyBase(response);
        } else if (response.b.type === 'EnemyCreep') {
            var xdif = this.pos.x - response.b.pos.x;
            var ydif = this.pos.y - response.b.pos.y;

            if (xdif > 0) {
                this.pos.x = this.pos.x + 1;
                if (this.facing === "left") {
                    this.body.vel.x = 0;
                }
            } else {
                //this.pos.x = this.pos.x - 1;
                if (this.facing === "right") {
                    this.body.vel.x = 0;
                }
            }

            if (this.renderable.isCurrentAnimation("attack") && this.now - this.lastHit >= 1000
                    && (Math.abs(ydif) <= 40) &&
                    (((xdif > 0) && this.facing === "left") || ((xdif < 0) && this.facing === "right"))
                    ) {
                this.lastHit = this.now;
                // if the creeps' health is less than our attack, execute code in if statement
                if (response.b.health <= game.data.playerAttack) {
                    // adds one gold for a creep kill
                    game.data.gold += 1;
                }

                response.b.loseHealth(game.data.playerAttack);
            }
        }
    },
});<|endoftext|>


<commit_before>game.PlayerEntity = me.Entity.extend({
	init: function(x, y, settings) { /*constructor function*/
		this._super(me.Entity, 'init', [x, y, {
			image: "player", /*describes what the player entity is, its size shape ect*/
			width: 64,
			height: 64,
			spritewidth: "64",
			spriteheight: "64",
			getShape: function(){
				return(new me.Rect(0, 0, 64, 64)).toPolygon(); /*essentialy sets its hitbox*/
			}
		}]);

		this.body.setVelocity(5, 20); /*20 for the y value is essentially gravity so that the player falls*/
		this.facing = "right"; /*keeps track of direction of character*/

		me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH); /*makes the camerafollow the player*/

		this.renderable.addAnimation("idle", [78]); /*adds the animation for idle*/
		this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125], 80);/*and for walk*/
		this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72], 80); /*as wellas for attack*/

		this.renderable.setCurrentAnimation("idle"); /*by default set the animation for idle*/

	},

	update: function(delta){
		if(me.input.isKeyPressed("right")) { /*if the right arrow is being pushed then.....*/
			/* this adds the position of my x by adding the velocity and multiplying it by me.timer.tick*/
			/*me.timer.tick makes the movement look smooth*/
			this.body.vel.x += this.body.accel.x * me.timer.tick;
			this.facing = "right";
			this.flipX(true);
		}
		else if(me.input.isKeyPressed("left")) { /*if the right arrow is being pushed then.....*/
			/* this adds the position of my x by adding the velocity and multiplying it by me.timer.tick*/
			/*me.timer.tick makes the movement look smooth*/
			this.body.vel.x -= this.body.accel.x * me.timer.tick;
			this.facing ="left";
			this.flipX(false);
		}
		else{ /*if its not being pushed then its not moving*/
			this.body.vel.x = 0;
		}

		if(me.input.isKeyPressed("jump") && !this.body.jumping && !this.body.falling) { /*if jump is pressed, and player isnt jumping or falling*/
			this.body.jumping = true; /*set jumping equal to true*/
			this.body.vel.y -= this.body.accel.y * me.timer.tick; /*formula saying y-velocity= y-accel * time*/
		}

		if(me.input.isKeyPressed("attack")) { /*if attack key (space) is being pressed then*/
			if(!this.renderable.isCurrentAnimation("attack")) { /*check if attack is not being pressed*/
				this.renderable.setCurrentAnimation("attack", "idle") /*if so then set animation to attack and then set it to idle*/
				this.renderable.setAnimationFrame();
				/*makes it so that when the animation plays again it starts from the very beggining*/
			}

		}

		else if(this.body.vel.x !== 0 && !this.renderable.isCurrentAnimation("attack")) { /*if the velocity doesnt equal 0*/
			if(!this.renderable.isCurrentAnimation("walk")) { /*and if the animation is currently not "walk"*/
				this.renderable.setCurrentAnimation("walk"); /* then set it to walk*/
			}
		}
		else if(!this.renderable.isCurrentAnimation("attack")) {
			this.renderable.setCurrentAnimation("idle"); /*otherwise set animation to idle*/
		}

		me.collision.check(this, true, this.collideHandler.bind(this), true); /*passing parameter tha is checking for thecollision and whatever its running in to*/
		this.body.update(delta); /*delta is the change in time*/

		this._super(me.Entity, "update", [delta]);
		return true;
	},

	collideHandler: function(response) {
		if(response.b.type ==='EnemyBaseEntity'){
			var ydif = this.pos.y - response.b.pos.y; /*sets variable equal to y-pos - responce.b.y-pos*/
			var xdif = this.pos.x - response.b.pos.x; /*sets variable equal to x-pos - responce.b.x-pos*/

			if(ydif< -40 && xdif< 70 && xdif >-35 && ydif>-50) { /*if you're in the location of the upper hitbox*/
				this.body.falling = false; /*you're no longer falling*/
				this.body.vel.y = -1; /*and your y velocity is -1*/
			}

			if(xdif > -35 && this.facing === 'right' && (xdif<0)) { /*if you're facing right and xdif>-35*/
				this.body.vel.x = 0; /*set velocity = 0*/
				this.pos.x = this.pos.x - 1; /*set position to itself minus 1*/
			}
			else if(xdif<70 && this.facing === 'left' && (xdif>0)) { /*same thing except inversely for left*/
				this.body.vel.x = 0;
				this.pos.x = this.pos.x + 1;
			}
		}
	}
});
/*Player base*/
game.PlayerBaseEntity = me.Entity.extend({
	init :  function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, { /*specifics for what the playerbase entity is and how big it is and its shape*/
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function() {
				return (new me.Rect(0, 0, 100, 72)).toPolygon();
			}
		}]);
		this.broken = false; /*by default it isnt borken*/
		this.health = 10; /*it has 10 health*/
		this.alwaysUpdate = true; /*always update*/
		this.body.onCollision = this.onCollision.bind(this);

		this.type = "PlayerBaseEntity";

		this.renderable.addAnimation("idle", [0]); /*adds animations for normal and broken towers*/
		this.renderable.addAnimation("broken", [1]);
		this.renderable.setCurrentAnimation("idle"); /*sets the normal animation to idle*/
	},

	update:function(delta) { /*keep checking if*/
		if(this.health<=0) { /*the health<=0 then the tower is broken*/
			this.broken = true; /*if so, then set it to broken*/
			this.renderable.setCurrentAnimation("broken");  /*and use the broken animation*/
		}
		this.body.update(delta); /*time since last update*/

		this._super(me.Entity, "update", [delta]);
		return true;
	},

	onCollision: function() {

	}

});

/*Enemy base*/
game.EnemyBaseEntity = me.Entity.extend({
	init :  function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, {
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function() {
				return (new me.Rect(0, 0, 100,72)).toPolygon();
			}
		}]);
		this.broken = false;
		this.health = 10;
		this.alwaysUpdate = true;
		this.body.onCollision = this.onCollision.bind(this);

		this.type = "EnemyBaseEntity";

		this.renderable.addAnimation("idle", [0]);
		this.renderable.addAnimation("broken", [1]);
		this.renderable.setCurrentAnimation("idle");
	},

	update:function(delta) { /*keep checking if*/
		if(this.health<=0) { /*the health<=0 then the tower is broken*/
			this.broken = true; /*if so, then set it to broken*/
			this.renderable.setCurrentAnimation("broken");  /*and use the broken animation*/
		}
		this.body.update(delta); /*time since last update*/

		this._super(me.Entity, "update", [delta]);
		return true;
	},

	onCollision: function() {

	}

});<commit_msg>I got distracted so i ended up making it so that you cant attack while, moving, or jumping, or falling. just a game design principle.<commit_after>game.PlayerEntity = me.Entity.extend({
	init: function(x, y, settings) { /*constructor function*/
		this._super(me.Entity, 'init', [x, y, {
			image: "player", /*describes what the player entity is, its size shape ect*/
			width: 64,
			height: 64,
			spritewidth: "64",
			spriteheight: "64",
			getShape: function(){
				return(new me.Rect(0, 0, 64, 64)).toPolygon(); /*essentialy sets its hitbox*/
			}
		}]);

		this.body.setVelocity(5, 20); /*20 for the y value is essentially gravity so that the player falls*/
		this.facing = "right"; /*keeps track of direction of character*/

		me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH); /*makes the camerafollow the player*/

		this.renderable.addAnimation("idle", [78]); /*adds the animation for idle*/
		this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125], 80);/*and for walk*/
		this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72], 80); /*as wellas for attack*/

		this.renderable.setCurrentAnimation("idle"); /*by default set the animation for idle*/

	},

	update: function(delta){
		if(me.input.isKeyPressed("right")) { /*if the right arrow is being pushed then.....*/
			/* this adds the position of my x by adding the velocity and multiplying it by me.timer.tick*/
			/*me.timer.tick makes the movement look smooth*/
			this.body.vel.x += this.body.accel.x * me.timer.tick;
			this.facing = "right";
			this.flipX(true);
		}
		else if(me.input.isKeyPressed("left")) { /*if the right arrow is being pushed then.....*/
			/* this adds the position of my x by adding the velocity and multiplying it by me.timer.tick*/
			/*me.timer.tick makes the movement look smooth*/
			this.body.vel.x -= this.body.accel.x * me.timer.tick;
			this.facing ="left";
			this.flipX(false);
		}
		else{ /*if its not being pushed then its not moving*/
			this.body.vel.x = 0;
		}

		if(me.input.isKeyPressed("jump") && !this.body.jumping && !this.body.falling) { /*if jump is pressed, and player isnt jumping or falling*/
			this.body.jumping = true; /*set jumping equal to true*/
			this.body.vel.y -= this.body.accel.y * me.timer.tick; /*formula saying y-velocity= y-accel * time*/
		}

		/*I made it so you cant attack while in the air*/
		if(me.input.isKeyPressed("attack") && !this.body.jumping && !this.body.falling){ /*if attack key (space) is being pressed then*/
			if(!this.renderable.isCurrentAnimation("attack")) { /*check if attack is not being pressed*/
				this.renderable.setCurrentAnimation("attack", "idle") /*if so then set animation to attack and then set it to idle*/
				this.renderable.setAnimationFrame();
				/*makes it so that when the animation plays again it starts from the very beggining*/
			}

		}

		else if(this.body.vel.x !== 0 && !this.renderable.isCurrentAnimation("attack")) { /*if the velocity doesnt equal 0*/
			if(!this.renderable.isCurrentAnimation("walk")) { /*and if the animation is currently not "walk"*/
				this.renderable.setCurrentAnimation("walk"); /* then set it to walk*/
			}
		}
		else if(!this.renderable.isCurrentAnimation("attack")) {
			this.renderable.setCurrentAnimation("idle"); /*otherwise set animation to idle*/
		}

		if(this.renderable.isCurrentAnimation("attack"))  { /*I made it so that you cant move while attacking*/
			this.body.vel.x = 0; /*if you're attacking your x velocity is 0*/
		}

		me.collision.check(this, true, this.collideHandler.bind(this), true); /*passing parameter tha is checking for thecollision and whatever its running in to*/
		this.body.update(delta); /*delta is the change in time*/

		this._super(me.Entity, "update", [delta]);
		return true;
	},

	collideHandler: function(response) {
		if(response.b.type ==='EnemyBaseEntity'){
			var ydif = this.pos.y - response.b.pos.y; /*sets variable equal to y-pos - responce.b.y-pos*/
			var xdif = this.pos.x - response.b.pos.x; /*sets variable equal to x-pos - responce.b.x-pos*/

			if(ydif< -40 && xdif< 70 && xdif >-35 && ydif>-50) { /*if you're in the location of the upper hitbox*/
				this.body.falling = false; /*you're no longer falling*/
				this.body.vel.y = -1; /*and your y velocity is -1*/
			}

			if(xdif > -35 && this.facing === 'right' && (xdif<0)) { /*if you're facing right and xdif>-35*/
				this.body.vel.x = 0; /*set velocity = 0*/
				this.pos.x = this.pos.x - 1; /*set position to itself minus 1*/
			}
			else if(xdif<70 && this.facing === 'left' && (xdif>0)) { /*same thing except inversely for left*/
				this.body.vel.x = 0;
				this.pos.x = this.pos.x + 1;
			}
		}
	}
});
/*Player base*/
game.PlayerBaseEntity = me.Entity.extend({
	init :  function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, { /*specifics for what the playerbase entity is and how big it is and its shape*/
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function() {
				return (new me.Rect(0, 0, 100, 72)).toPolygon();
			}
		}]);
		this.broken = false; /*by default it isnt borken*/
		this.health = 10; /*it has 10 health*/
		this.alwaysUpdate = true; /*always update*/
		this.body.onCollision = this.onCollision.bind(this);

		this.type = "PlayerBaseEntity";

		this.renderable.addAnimation("idle", [0]); /*adds animations for normal and broken towers*/
		this.renderable.addAnimation("broken", [1]);
		this.renderable.setCurrentAnimation("idle"); /*sets the normal animation to idle*/
	},

	update:function(delta) { /*keep checking if*/
		if(this.health<=0) { /*the health<=0 then the tower is broken*/
			this.broken = true; /*if so, then set it to broken*/
			this.renderable.setCurrentAnimation("broken");  /*and use the broken animation*/
		}
		this.body.update(delta); /*time since last update*/

		this._super(me.Entity, "update", [delta]);
		return true;
	},

	onCollision: function() {

	}

});

/*Enemy base*/
game.EnemyBaseEntity = me.Entity.extend({
	init :  function(x, y, settings) {
		this._super(me.Entity, 'init', [x, y, {
			image: "tower",
			width: 100,
			height: 100,
			spritewidth: "100",
			spriteheight: "100",
			getShape: function() {
				return (new me.Rect(0, 0, 100,72)).toPolygon();
			}
		}]);
		this.broken = false;
		this.health = 10;
		this.alwaysUpdate = true;
		this.body.onCollision = this.onCollision.bind(this);

		this.type = "EnemyBaseEntity";

		this.renderable.addAnimation("idle", [0]);
		this.renderable.addAnimation("broken", [1]);
		this.renderable.setCurrentAnimation("idle");
	},

	update:function(delta) { /*keep checking if*/
		if(this.health<=0) { /*the health<=0 then the tower is broken*/
			this.broken = true; /*if so, then set it to broken*/
			this.renderable.setCurrentAnimation("broken");  /*and use the broken animation*/
		}
		this.body.update(delta); /*time since last update*/

		this._super(me.Entity, "update", [delta]);
		return true;
	},

	onCollision: function() {

	}

});<|endoftext|>


<commit_before>game.PlayerEntity = me.Entity.extend({
    init: function(x, y, settings){
        this._super(me.Entity, 'init', [x, y, {
            image: "player",
            width: 64,
            height: 64,
            spritewidth: "64",
            spriteheight: "64",
            getShape: function(){
                return(new me.Rect(0, 0, 64, 64)).toPolygon();
            }
        }]);
       this.body.setVelocity(5, 20);
       //keeps track of which direction your character is going
       this.facing = "right";
       me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH);

       this.renderable.addAnimation("idle", [78]);
       this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125], 80);
       this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72], 80);

       this.renderable.setCurrentAnimation("idle");
    },

    update: function(delta){
        if(me.input.isKeyPressed("right")){
            //adds the position of my x by the velocity defined above in
            //setVelocity and multiplying it by me.timer.tick
            //me.timer.tick makes movement look smooth
            this.body.vel.x += this.body.accel.x * me.timer.tick;
            this.facing = "right";
            this.flipX(true);
        }else if(me.input.isKeyPressed("left")){
            this.facing = "left";
            this.body.vel.x -=this.body.accel.x * me.timer.tick;
            this.flipX(false);
        }else{
            this.body.vel.x = 0;
        }
        //i made the character go left when the left key is pressed
        if(me.input.isKeyPressed("jump") && !this.jumping && !this.falling){
            this.jumping = true;
            this.body.vel.y -= this.body.accel.y * me.timer.tick;
        }
        //i am making the character jump when i press the space button
        if(me.input.isKeyPressed("attack")){
            if(!this.renderable.isCurrentAnimation("attack")){
                console.log(this.renderable.isCurrentAnimation("attack"));
                //sets the current animation to attack and once that is over
                //goes back to the idle animation
                this.renderable.setCurrentAnimation("attack", "idle");
                //makes it so the next time we start this sequence we begin
                //from the first animation, not from wherever we left off when we
                //switched to another animation
                this.renderable.setAnimationFrame();
            }
        }

        else if(this.body.vel.x !== 0) {
             if(!this.renderable.isCurrentAnimation("walk")){
                 this.renderable.setCurrentAnimation("walk");
        }
        }else{
           this.renderable.setCurrentAnimation("idle");
        }

        if(me.input.isKeyPressed("attack")){
            if(!this.renderable.isCurrentAnimation("attack")){
                console.log(this.renderable.isCurrentAnimation("attack"));
                //sets the current animation to attack and once that is over
                //goes back to the idle animation
                this.renderable.setCurrentAnimation("attack", "idle");
                //makes it so the next time we start this sequence we begin
                //from the first animation, not from wherever we left off when we
                //switched to another animation
                this.renderable.setAnimationFrame();
            }
        }

        me.collision.check(this, true, this.collideHandler.bind(this), true);
        this.body.update(delta);

        this._super(me.Entity, "update", [delta]);
        return true;
    },

    collideHandler: function(response){
        if(response.b.type==='EnemyBaseEntity'){
            var ydif = this.pos.y - response.b.pos.y;
            var xdif = this.pos.x - response.b.pos.x;

            console.log("xdif " + xdif + " ydif " + ydif);

            if(xdif>-35 && this.facing==='right'){
                this.body.vel.x = 0;
                this.pos.x = this.pos.x -1;
            }
        }
    }
});

game.PlayerBaseEntity = me.Entity.extend({
    init : function(x, y, settings){
        this._super(me.Entity, 'init', [x, y, {
            image: "tower",
            width: 100,
            height: 100,
            spritewidth: "100",
            spriteheight: "100",
            getShape: function(){
                return (new me.Rect(0, 0, 100, 70)).toPolygon();
            }
        }]);
        this.broken = false;
        this.health = 10;
        this.alwaysUpdate = true;
        this.body.onCollision = this.onCollision.bind(this);
        console.log("init");
        this.type = "PlayerBaseEntity";

        this.renderable.addAnimation("idle", [0]);
        this.renderable.addAnimation("broken", [1]);
        this.renderable.setCurrentAnimation("idle");
    },

    update:function(delta){
        if(this.health<=0){
            this.broken = true;
            this.renderable.setCurrentAnimation("broken");
        }
        this.body.update(delta);

        this._super(me.Entity, "update", [delta]);
        return true;
    },

    onCollision: function(){

    }

});

game.EnemyBaseEntity = me.Entity.extend({
    init : function(x, y, settings){
        this._super(me.Entity, 'init', [x, y, {
            image: "tower",
            width: 100,
            height: 100,
            spritewidth: "100",
            spriteheight: "100",
            getShape: function(){
                return (new me.Rect(0, 0, 100, 70)).toPolygon();
            }
        }]);
        this.broken = false;
        this.health = 10;
        this.alwaysUpdate = true;
        this.body.onCollision = this.onCollision.bind(this);
        console.log("init");
        this.type = "EnemyBaseEntity";

        this.renderable.addAnimation("idle", [0]);
        this.renderable.addAnimation("broken", [1]);
        this.renderable.setCurrentAnimation("idle");
    },

    update:function(delta){
        if(this.health<=0){
            this.broken = true;
            this.renderable.setCurrentAnimation("broken");
        }
        this.body.update(delta);

        this._super(me.Entity, "update", [delta]);
        return true;
    },

    onCollision: function(){

    }

});<commit_msg>done with video 16 making collision from the top<commit_after>game.PlayerEntity = me.Entity.extend({
    init: function(x, y, settings){
        this._super(me.Entity, 'init', [x, y, {
            image: "player",
            width: 64,
            height: 64,
            spritewidth: "64",
            spriteheight: "64",
            getShape: function(){
                return(new me.Rect(0, 0, 64, 64)).toPolygon();
            }
        }]);
       this.body.setVelocity(5, 20);
       //keeps track of which direction your character is going
       this.facing = "right";
       me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH);

       this.renderable.addAnimation("idle", [78]);
       this.renderable.addAnimation("walk", [117, 118, 119, 120, 121, 122, 123, 124, 125], 80);
       this.renderable.addAnimation("attack", [65, 66, 67, 68, 69, 70, 71, 72], 80);

       this.renderable.setCurrentAnimation("idle");
    },

    update: function(delta){
        if(me.input.isKeyPressed("right")){
            //adds the position of my x by the velocity defined above in
            //setVelocity and multiplying it by me.timer.tick
            //me.timer.tick makes movement look smooth
            this.body.vel.x += this.body.accel.x * me.timer.tick;
            this.facing = "right";
            this.flipX(true);
        }else if(me.input.isKeyPressed("left")){
            this.facing = "left";
            this.body.vel.x -=this.body.accel.x * me.timer.tick;
            this.flipX(false);
        }else{
            this.body.vel.x = 0;
        }
        //i made the character go left when the left key is pressed
        if(me.input.isKeyPressed("jump") && !this.body.jumping && !this.body.falling){
            this.jumping = true;
            this.body.vel.y -= this.body.accel.y * me.timer.tick;
        }
        //i am making the character jump when i press the space button
        if(me.input.isKeyPressed("attack")){
            if(!this.renderable.isCurrentAnimation("attack")){
                console.log(this.renderable.isCurrentAnimation("attack"));
                //sets the current animation to attack and once that is over
                //goes back to the idle animation
                this.renderable.setCurrentAnimation("attack", "idle");
                //makes it so the next time we start this sequence we begin
                //from the first animation, not from wherever we left off when we
                //switched to another animation
                this.renderable.setAnimationFrame();
            }
        }

        else if(this.body.vel.x !== 0) {
             if(!this.renderable.isCurrentAnimation("walk")){
                 this.renderable.setCurrentAnimation("walk");
        }
        }else{
           this.renderable.setCurrentAnimation("idle");
        }

        if(me.input.isKeyPressed("attack")){
            if(!this.renderable.isCurrentAnimation("attack")){
                console.log(this.renderable.isCurrentAnimation("attack"));
                //sets the current animation to attack and once that is over
                //goes back to the idle animation
                this.renderable.setCurrentAnimation("attack", "idle");
                //makes it so the next time we start this sequence we begin
                //from the first animation, not from wherever we left off when we
                //switched to another animation
                this.renderable.setAnimationFrame();
            }
        }

        me.collision.check(this, true, this.collideHandler.bind(this), true);
        this.body.update(delta);

        this._super(me.Entity, "update", [delta]);
        return true;
    },

    collideHandler: function(response){
        if(response.b.type==='EnemyBaseEntity'){
            var ydif = this.pos.y - response.b.pos.y;
            var xdif = this.pos.x - response.b.pos.x;

            if(ydif<-40 && xdif< 70 && xdif>-35){
                this.body.falling = false;
                this.body.vel.y = -1;
            }
            else if(xdif>-35 && this.facing==='right' && (xdif<0)){
                this.body.vel.x = 0;
                this.pos.x = this.pos.x -1;
            }else if(xdif<70 && this.facing==='left' && (xdif>0)){
                this.body.vel.x = 0;
                this.pos.x = this.pos.x +1;
            }
        }
    }
});

game.PlayerBaseEntity = me.Entity.extend({
    init : function(x, y, settings){
        this._super(me.Entity, 'init', [x, y, {
            image: "tower",
            width: 100,
            height: 100,
            spritewidth: "100",
            spriteheight: "100",
            getShape: function(){
                return (new me.Rect(0, 0, 100, 70)).toPolygon();
            }
        }]);
        this.broken = false;
        this.health = 10;
        this.alwaysUpdate = true;
        this.body.onCollision = this.onCollision.bind(this);
        console.log("init");
        this.type = "PlayerBaseEntity";

        this.renderable.addAnimation("idle", [0]);
        this.renderable.addAnimation("broken", [1]);
        this.renderable.setCurrentAnimation("idle");
    },

    update:function(delta){
        if(this.health<=0){
            this.broken = true;
            this.renderable.setCurrentAnimation("broken");
        }
        this.body.update(delta);

        this._super(me.Entity, "update", [delta]);
        return true;
    },

    onCollision: function(){

    }

});

game.EnemyBaseEntity = me.Entity.extend({
    init : function(x, y, settings){
        this._super(me.Entity, 'init', [x, y, {
            image: "tower",
            width: 100,
            height: 100,
            spritewidth: "100",
            spriteheight: "100",
            getShape: function(){
                return (new me.Rect(0, 0, 100, 70)).toPolygon();
            }
        }]);
        this.broken = false;
        this.health = 10;
        this.alwaysUpdate = true;
        this.body.onCollision = this.onCollision.bind(this);
        console.log("init");
        this.type = "EnemyBaseEntity";

        this.renderable.addAnimation("idle", [0]);
        this.renderable.addAnimation("broken", [1]);
        this.renderable.setCurrentAnimation("idle");
    },

    update:function(delta){
        if(this.health<=0){
            this.broken = true;
            this.renderable.setCurrentAnimation("broken");
        }
        this.body.update(delta);

        this._super(me.Entity, "update", [delta]);
        return true;
    },

    onCollision: function(){

    }

});<|endoftext|>


<commit_before>define(['exports'],
function(exports) {

  // Base64 implementations:
  // https://github.com/ForbesLindesay/base64-decode
  // https://github.com/ForbesLindesay/base64-encode
  // https://github.com/mshang/base64-js
  // https://github.com/dankogai/js-base64
  //
  // http://rumkin.com/tools/cipher/base64.php
  // http://rumkin.com/tools/cipher/js/base64.js

  var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

  function encode(input) {
    var output = '';
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    while (i < input.length) {
      chr1 = input.charCodeAt(i++);
      chr2 = input.charCodeAt(i++);
      chr3 = input.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
        enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
        enc4 = 64;
      }

      output = output +
        keyStr.charAt(enc1) + keyStr.charAt(enc2) +
        keyStr.charAt(enc3) + keyStr.charAt(enc4);
    };

    return output;
  }

  function decode(input) {
    var output = '';
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    while (i < input.length) {
      enc1 = keyStr.indexOf(input.charAt(i++));
      enc2 = keyStr.indexOf(input.charAt(i++));
      enc3 = keyStr.indexOf(input.charAt(i++));
      enc4 = keyStr.indexOf(input.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64) {
        output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
        output = output + String.fromCharCode(chr3);
      }
    }

    return output;
  }

  exports.encode = encode;
  exports.decode = decode;
});
<commit_msg>Add reference to atob and btoa.<commit_after>define(['exports'],
function(exports) {

  // Base64 implementations:
  // https://github.com/ForbesLindesay/base64-decode
  // https://github.com/ForbesLindesay/base64-encode
  // https://github.com/mshang/base64-js
  // https://github.com/dankogai/js-base64
  //
  // http://rumkin.com/tools/cipher/base64.php
  // http://rumkin.com/tools/cipher/js/base64.js

  // https://developer.mozilla.org/en-US/docs/DOM/window.atob
  // https://developer.mozilla.org/en-US/docs/DOM/window.btoa

  var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

  function encode(input) {
    var output = '';
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    while (i < input.length) {
      chr1 = input.charCodeAt(i++);
      chr2 = input.charCodeAt(i++);
      chr3 = input.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
        enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
        enc4 = 64;
      }

      output = output +
        keyStr.charAt(enc1) + keyStr.charAt(enc2) +
        keyStr.charAt(enc3) + keyStr.charAt(enc4);
    };

    return output;
  }

  function decode(input) {
    var output = '';
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    while (i < input.length) {
      enc1 = keyStr.indexOf(input.charAt(i++));
      enc2 = keyStr.indexOf(input.charAt(i++));
      enc3 = keyStr.indexOf(input.charAt(i++));
      enc4 = keyStr.indexOf(input.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64) {
        output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
        output = output + String.fromCharCode(chr3);
      }
    }

    return output;
  }

  exports.encode = encode;
  exports.decode = decode;
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 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.
 */

CLASS({
  package: 'foam.u2',
  name: 'TableView',
  extends: 'foam.u2.View',

  requires: [
    'SimpleValue',
    'foam.u2.ScrollView',
    'foam.u2.TableRowView'
  ],

  imports: [
    'document',
    'hardSelection$',
    'setTimeout',
    'softSelection$',
    'sortOrder$',
    'window'
  ],

  exports: [
    'as tableView'
  ],

  documentation: 'A view that renders a table. Note that it does not use real HTML <tt>
</tt> tags. Features draggable columns and click-to-sort.',

  properties: [
    ['nodeName', 'flex-table'],
    ['ascIcon', '▲'],
    ['descIcon', '▼'],
    {
      name: 'data',
      postSet: function(_, data) {
        var model = this.data && this.data.model;
        if ( this.model !== model ) this.model = model;
      }
    },
    {
      name: 'model',
      defaultValueFn: function() {
        return this.X.model;
      },
      postSet: function(_, model) {
        if ( ! this.columnProperties )
          this.columnProperties_ = this.getColumnProperties_();

        var allProps = [];
        var columnProps = {};
        for (var i = 0; i < this.columnProperties_.length; i++) {
          columnProps[this.columnProperties_[i].name] = true;
          allProps.push(this.columnProperties_[i]);
        }

        var props = model.getRuntimeProperties();

        for (var i = 0; i < props.length; i++) {
          if (props[i].hidden || columnProps[props[i].name]) continue;
          allProps.push(props[i]);
        }

        this.allProperties_ = allProps;
      }
    },
    {
      type: 'Array',
      name: 'allProperties_',
      documentation: 'All the (non-hidden) properties on the model.',
    },
    {
      type: 'Array',
      name: 'columnProperties',
      documentation: 'An array of Property objects for all selected ' +
          'properties. If this is set, this is exactly the set of properties ' +
          'that will be displayed. Otherwise the model\'s tableProperties, ' +
          'if defined, will be displayed. Finally, all non-hidden properties ' +
          'will be displayed.',
      factory: function() { return null; },
      postSet: function(_, ps) {
        this.columnProperties_ = ps;
      }
    },
    {
      type: 'Array',
      name: 'columnProperties_',
      postSet: function(old, nu) {
        this.scrollView.invalidate();
      }
    },
    ['sortOrder', undefined],
    ['sortProp', undefined],
    {
      type: 'Int',
      name: 'minColWidth',
      defaultValue: 50
    },
    'hardSelection',
    'softSelection',
    'headE',
    'bodyE',
    {
      model_: 'foam.core.types.DAOProperty',
      name: 'filteredDAO',
      dynamicValue: [function() {
        this.data; this.sortOrder;
      }, function() {
        return this.data && this.data.orderBy(this.sortOrder);
      }]
    },
    {
      type: 'ViewFactory',
      name: 'rowView',
      defaultValue: 'foam.u2.TableRowView',
      documentation: 'Set this to override the row view. It should be a ' +
          'subclass of $$DOC{ref:"foam.u2.TableRowView"} unless you ' +
          'really know what you\'re doing.',
      adapt: function(old, nu) {
        return nu ? nu : 'foam.u2.TableRowView';
      }
    },
    {
      name: 'rowHeight',
      documentation: 'Set this to override the height of a table row.',
      defaultValue: 48
    },
    {
      name: 'scrollView',
      factory: function() {
        return this.ScrollView.create({
          data:      this.filteredDAO$Proxy,
          rowHeight: this.rowHeight,
          rowView:   this.makeRow
        });
      }
    },
    {
      type: 'Array',
      name: 'colWidths_'
    },
    {
      type: 'Boolean',
      name: 'isResizing',
      defaultValue: false
    }
  ],

  methods: [
    function load() {
      this.SUPER();
      this.window.addEventListener('resize', this.onResize);
      this.onResize();
    },

    function unload() {
      this.SUPER();
      this.window.removeEventListener('resize', this.onResize);
    },

    function getColumnProperties_() {
      if ( ! this.model ) return [];

      if ( this.model.tableProperties && this.model.tableProperties.length > 0 ) {
          return this.model.tableProperties.map(function(name) {
            return this.model.getProperty(name);
          }.bind(this));
      }

      return this.model.getRuntimeProperties().filter(function(p) {
        return ! p.hidden;
      });
    },

    function computeColWidths() {
      /* Call this to populate the colWidths_ array with the actual values. */
      if ( ! this.headE ||  ! this.headRowE ) return;

      var cells = this.headRowE.children;
      var columnProperties = this.columnProperties_;

      for ( var i = 0 ; i < cells.length ; i++ ) {
        if ( columnProperties[i].tableWidth ) {
          cells[i].style({
            width: columnProperties[i].tableWidth + 'px',
            'flex-grow': null
          });
        } else {
          cells[i].style({
            width: 'initial',
            'flex-grow': '1'
          });
        }
      }
      this.measureColWidths(cells);
      for ( var i = 0 ; i < cells.length ; i++ ) {
        cells[i].style({
          width: null,
          'flex-grow': null
        });
      }
    },
    function measureColWidths(cells) {
      for ( var i = 0 ; i < cells.length ; i++ ) {
        if ( ! this.colWidths_[i] )
          this.colWidths_[i] = this.makeColWidthValue(i);
        this.colWidths_[i].set(cells[i].el().offsetWidth);
      }
    },
    function onSortOrder(prop) {
      this.sortProp = prop;
      this.sortOrder = this.sortOrder === prop ? DESC(prop) : prop;
    },

    function makeResizeHandle(i) {
      /*
        Returns a new resize handler element, with event bindings, that follows
        column i.
       */
      var handle = this.E('flex-col-resize-handle').cls(this.myCls('resize-handle'));
      handle.on('click', function(e) { e.stopPropagation(); });
      handle.on('mousedown', function(e) {
        var self = this;
        var startX = e.x;
        var col1 = handle.el().parentElement;
        var col2 = col1.nextElementSibling;
        var row = col1.parentElement;
        var w1 = col1.offsetWidth;
        var w2 = col2? col2.offsetWidth : 0;

        e.preventDefault();
        this.isResizing = true;

        function onMouseMove(e) {
          var delta = e.x - startX;
          var minWidth = self.minColWidth;
          var newW1 = w1 + ( col2 ? Math.min(w2, delta) : delta );
          var newW2 = w2 + Math.min(-delta, w1);

          if ( newW1 < minWidth ) {
            newW1 = minWidth;
            newW2 = w1 + w2 - minWidth;
          } else if ( w2 && newW2 < minWidth ) {
            newW1 = w1 + w2 - minWidth;
            newW2 = minWidth;
          }

          self.colWidths_[i].set(newW1);
          if ( w2 )
            self.colWidths_[i + 1].set(newW2);
        }

        var onMouseUp = function(e) {
          e.preventDefault();
          self.isResizing = false;
          self.document.removeEventListener('mousemove', onMouseMove);
          self.document.removeEventListener('mouseup', onMouseUp);
        };

        self.document.addEventListener('mousemove', onMouseMove);
        self.document.addEventListener('mouseup', onMouseUp);
      }.bind(this));

      return handle;
    },

    function initE() {
      // Need to make sure to bind in the flex-table-view-col-resize class, to
      // the resize boolean.
      // Need to add/remove (or show/hide) ascending and descending icons for
      // each column based on the current sort order property.

      this.cls(this.myCls());
      this.headE = this.start('flex-table-head').cls(this.myCls('head'));
      this.headE.end();
      this.bodyE = this.start('flex-table-body').cls(this.myCls('body'));
      this.bodyE.end();

      // Populate the header. The whole header is wrapped in a dynamic().
      // It would be slightly better if only the children were, but dynamically
      // producing an array of elements is not supported right now.
      this.headE.add(this.dynamic(function(dao, props) {
        if ( ! dao ) return 'set dao';

        // TODO(braden): Find a way to remove the old listeners, or confirm that
        // it's already happening properly.
        this.headRowE = this.E('flex-table-row').cls(this.myCls('row')).add(
            props.map(this.makeHeadCell.bind(this)));

        this.onResize();
        return this.headRowE;
      }.bind(this), this.data$, this.columnProperties_$, this.sortOrder$));

      // Attach a dynamic class to the head that reveals the column resizers
      // when one of them is being dragged.
      this.headE.enableCls(this.myCls('col-resize'), this.isResizing$);

      // Populate the body.
      this.bodyE.add(this.scrollView);
    },

    function makeHeadCell(prop, i) {
      // Returns an array of Elements, suitable for add().
      var cell = this.E('flex-table-cell');
      // These can get away with not being dynamic, because the whole header
      // will be rebuilt on a column change.
      cell.cls(this.myCls('col-' + i)).cls(this.myCls('cell'));
      cell.on('click', this.onSortOrder.bind(this, prop));

      if (this.isPropNumeric(prop)) cell.cls(this.myCls('numeric'));
      var sorted = this.isSortedByProp(prop);
      if (sorted) cell.cls(this.myCls('sort'));

      var colLabel = cell.start('flex-col-label').cls(this.myCls('col-label'))
          .start('label').add(prop.tableLabel).end();
      if (sorted) {
        var icon = this.sortOrder === prop ? this.ascIcon : this.descIcon;
        colLabel.start('span').cls(this.myCls('sort-indicator')).add(icon).end();
      }
      colLabel.end();

      cell.add(this.makeResizeHandle(i));

      if (!this.colWidths_[i])
        this.colWidths_[i] = this.makeColWidthValue(i);

      return cell;
    },

    function isPropNumeric(prop) {
      return IntProperty.isInstance(prop) || FloatProperty.isInstance(prop);
    },

    function isSortedByProp(prop) {
      return this.sortProp === prop;
    },

    function makeColWidthValue(i) {
      var styleE = this.E('style');
      var value = this.SimpleValue.create();
      value.addListener(function(obj, prop, old, nu) {
        styleE.el().innerHTML = '#' + this.id + ' .' + this.myCls('col-' + i) +
            '{ width: ' + nu + 'px; }';
      }.bind(this));
      this.headE.add(styleE);
      return value;
    }
  ],

  listeners: [
    function makeRow(map, Y) {
      map = map || {};
      map.properties$ = this.columnProperties_$;
      return this.rowView(map, Y);
    },
    function onResize() {
      if (this.headRowE && this.headRowE.state === this.headRowE.LOADED) {
        this.computeColWidths();
      } else {
        this.headRowE.on('load', this.computeColWidths.bind(this));
      }
    }
  ],

  templates: [
    function CSS() {/*
      ^col-resize * {
        cursor: ew-resize !important;
      }

      ^ {
        display: flex;
        flex-direction: column;
        flex-grow: 1;
        flex-shrink: 1;
        overflow-x: hidden;
        overflow-y: auto;
        width: 100%;
      }

      ^head {
        display: flex;
        flex-direction: column;
        flex-grow: 0;
        flex-shrink: 0;
      }

      ^body {
        display: flex;
        flex-direction: column;
        flex-grow: 1
        flex-shrink: 1;
        overflow-x: hidden;
        overflow-y: auto;
        position: relative;
      }

      ^row {
        align-items: center;
        display: flex;
        flex-shrink: 0;
        flex-grow: 0;
        height: 100%;
      }

      ^col-label {
        display: flex;
        flex-shrink: 1;
        flex-grow: 1;
      }

      ^cell {
        align-items: center;
        display: flex;
        flex-grow: 0;
        flex-shrink: 0;
        padding: 8px;
        position: relative;
      }
      ^cell^numeric {
        justify-content: flex-end;
      }

      ^cell, ^cell * {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      ^cell img {
        flex-grow: 0;
        flex-shrink: 0;
      }

      ^head ^cell ^resize-handle {
        background-color: #ccc;
        display: block;
        position: absolute;
        top: 0;
        right: 0px;
        width: 1px;
        bottom: 0;
        z-index: 9;
        cursor: ew-resize;
      }

      ^cell:last-child ^resize-handle {
        display: none;
      }

      ^head ^row {
        align-items: center;
        border-bottom: 1px solid #ccc;
        height: 36px;
      }

      ^head ^cell {
        height: 100%;
        margin: 0;
        padding: 0 8px;
      }

      ^numeric {
        text-align: right;
      }
      ^numeric ^col-label {
        flex-direction: row-reverse;
      }

      ^sort {
        font-weight: bold;
      }

      ^col-label label {
        font-weight: bold;
        flex-grow: 0;
      }
      ^col-label span {
        flex-grow: 0;
        flex-shrink: 0;
      }
    */}
  ]
});
<commit_msg>U2 TableView: Fix CSS typo that was breaking some flex layout<commit_after>/**
 * @license
 * Copyright 2016 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.
 */

CLASS({
  package: 'foam.u2',
  name: 'TableView',
  extends: 'foam.u2.View',

  requires: [
    'SimpleValue',
    'foam.u2.ScrollView',
    'foam.u2.TableRowView'
  ],

  imports: [
    'document',
    'hardSelection$',
    'setTimeout',
    'softSelection$',
    'sortOrder$',
    'window'
  ],

  exports: [
    'as tableView'
  ],

  documentation: 'A view that renders a table. Note that it does not use real HTML <tt>
</tt> tags. Features draggable columns and click-to-sort.',

  properties: [
    ['nodeName', 'flex-table'],
    ['ascIcon', '▲'],
    ['descIcon', '▼'],
    {
      name: 'data',
      postSet: function(_, data) {
        var model = this.data && this.data.model;
        if ( this.model !== model ) this.model = model;
      }
    },
    {
      name: 'model',
      defaultValueFn: function() {
        return this.X.model;
      },
      postSet: function(_, model) {
        if ( ! this.columnProperties )
          this.columnProperties_ = this.getColumnProperties_();

        var allProps = [];
        var columnProps = {};
        for (var i = 0; i < this.columnProperties_.length; i++) {
          columnProps[this.columnProperties_[i].name] = true;
          allProps.push(this.columnProperties_[i]);
        }

        var props = model.getRuntimeProperties();

        for (var i = 0; i < props.length; i++) {
          if (props[i].hidden || columnProps[props[i].name]) continue;
          allProps.push(props[i]);
        }

        this.allProperties_ = allProps;
      }
    },
    {
      type: 'Array',
      name: 'allProperties_',
      documentation: 'All the (non-hidden) properties on the model.',
    },
    {
      type: 'Array',
      name: 'columnProperties',
      documentation: 'An array of Property objects for all selected ' +
          'properties. If this is set, this is exactly the set of properties ' +
          'that will be displayed. Otherwise the model\'s tableProperties, ' +
          'if defined, will be displayed. Finally, all non-hidden properties ' +
          'will be displayed.',
      factory: function() { return null; },
      postSet: function(_, ps) {
        this.columnProperties_ = ps;
      }
    },
    {
      type: 'Array',
      name: 'columnProperties_',
      postSet: function(old, nu) {
        this.scrollView.invalidate();
      }
    },
    ['sortOrder', undefined],
    ['sortProp', undefined],
    {
      type: 'Int',
      name: 'minColWidth',
      defaultValue: 50
    },
    'hardSelection',
    'softSelection',
    'headE',
    'bodyE',
    {
      model_: 'foam.core.types.DAOProperty',
      name: 'filteredDAO',
      dynamicValue: [function() {
        this.data; this.sortOrder;
      }, function() {
        return this.data && this.data.orderBy(this.sortOrder);
      }]
    },
    {
      type: 'ViewFactory',
      name: 'rowView',
      defaultValue: 'foam.u2.TableRowView',
      documentation: 'Set this to override the row view. It should be a ' +
          'subclass of $$DOC{ref:"foam.u2.TableRowView"} unless you ' +
          'really know what you\'re doing.',
      adapt: function(old, nu) {
        return nu ? nu : 'foam.u2.TableRowView';
      }
    },
    {
      name: 'rowHeight',
      documentation: 'Set this to override the height of a table row.',
      defaultValue: 48
    },
    {
      name: 'scrollView',
      factory: function() {
        return this.ScrollView.create({
          data:      this.filteredDAO$Proxy,
          rowHeight: this.rowHeight,
          rowView:   this.makeRow
        });
      }
    },
    {
      type: 'Array',
      name: 'colWidths_'
    },
    {
      type: 'Boolean',
      name: 'isResizing',
      defaultValue: false
    }
  ],

  methods: [
    function load() {
      this.SUPER();
      this.window.addEventListener('resize', this.onResize);
      this.onResize();
    },

    function unload() {
      this.SUPER();
      this.window.removeEventListener('resize', this.onResize);
    },

    function getColumnProperties_() {
      if ( ! this.model ) return [];

      if ( this.model.tableProperties && this.model.tableProperties.length > 0 ) {
          return this.model.tableProperties.map(function(name) {
            return this.model.getProperty(name);
          }.bind(this));
      }

      return this.model.getRuntimeProperties().filter(function(p) {
        return ! p.hidden;
      });
    },

    function computeColWidths() {
      /* Call this to populate the colWidths_ array with the actual values. */
      if ( ! this.headE ||  ! this.headRowE ) return;

      var cells = this.headRowE.children;
      var columnProperties = this.columnProperties_;

      for ( var i = 0 ; i < cells.length ; i++ ) {
        if ( columnProperties[i].tableWidth ) {
          cells[i].style({
            width: columnProperties[i].tableWidth + 'px',
            'flex-grow': null
          });
        } else {
          cells[i].style({
            width: 'initial',
            'flex-grow': '1'
          });
        }
      }
      this.measureColWidths(cells);
      for ( var i = 0 ; i < cells.length ; i++ ) {
        cells[i].style({
          width: null,
          'flex-grow': null
        });
      }
    },
    function measureColWidths(cells) {
      for ( var i = 0 ; i < cells.length ; i++ ) {
        if ( ! this.colWidths_[i] )
          this.colWidths_[i] = this.makeColWidthValue(i);
        this.colWidths_[i].set(cells[i].el().offsetWidth);
      }
    },
    function onSortOrder(prop) {
      this.sortProp = prop;
      this.sortOrder = this.sortOrder === prop ? DESC(prop) : prop;
    },

    function makeResizeHandle(i) {
      /*
        Returns a new resize handler element, with event bindings, that follows
        column i.
       */
      var handle = this.E('flex-col-resize-handle').cls(this.myCls('resize-handle'));
      handle.on('click', function(e) { e.stopPropagation(); });
      handle.on('mousedown', function(e) {
        var self = this;
        var startX = e.x;
        var col1 = handle.el().parentElement;
        var col2 = col1.nextElementSibling;
        var row = col1.parentElement;
        var w1 = col1.offsetWidth;
        var w2 = col2? col2.offsetWidth : 0;

        e.preventDefault();
        this.isResizing = true;

        function onMouseMove(e) {
          var delta = e.x - startX;
          var minWidth = self.minColWidth;
          var newW1 = w1 + ( col2 ? Math.min(w2, delta) : delta );
          var newW2 = w2 + Math.min(-delta, w1);

          if ( newW1 < minWidth ) {
            newW1 = minWidth;
            newW2 = w1 + w2 - minWidth;
          } else if ( w2 && newW2 < minWidth ) {
            newW1 = w1 + w2 - minWidth;
            newW2 = minWidth;
          }

          self.colWidths_[i].set(newW1);
          if ( w2 )
            self.colWidths_[i + 1].set(newW2);
        }

        var onMouseUp = function(e) {
          e.preventDefault();
          self.isResizing = false;
          self.document.removeEventListener('mousemove', onMouseMove);
          self.document.removeEventListener('mouseup', onMouseUp);
        };

        self.document.addEventListener('mousemove', onMouseMove);
        self.document.addEventListener('mouseup', onMouseUp);
      }.bind(this));

      return handle;
    },

    function initE() {
      // Need to make sure to bind in the flex-table-view-col-resize class, to
      // the resize boolean.
      // Need to add/remove (or show/hide) ascending and descending icons for
      // each column based on the current sort order property.

      this.cls(this.myCls());
      this.headE = this.start('flex-table-head').cls(this.myCls('head'));
      this.headE.end();
      this.bodyE = this.start('flex-table-body').cls(this.myCls('body'));
      this.bodyE.end();

      // Populate the header. The whole header is wrapped in a dynamic().
      // It would be slightly better if only the children were, but dynamically
      // producing an array of elements is not supported right now.
      this.headE.add(this.dynamic(function(dao, props) {
        if ( ! dao ) return 'set dao';

        // TODO(braden): Find a way to remove the old listeners, or confirm that
        // it's already happening properly.
        this.headRowE = this.E('flex-table-row').cls(this.myCls('row')).add(
            props.map(this.makeHeadCell.bind(this)));

        this.onResize();
        return this.headRowE;
      }.bind(this), this.data$, this.columnProperties_$, this.sortOrder$));

      // Attach a dynamic class to the head that reveals the column resizers
      // when one of them is being dragged.
      this.headE.enableCls(this.myCls('col-resize'), this.isResizing$);

      // Populate the body.
      this.bodyE.add(this.scrollView);
    },

    function makeHeadCell(prop, i) {
      // Returns an array of Elements, suitable for add().
      var cell = this.E('flex-table-cell');
      // These can get away with not being dynamic, because the whole header
      // will be rebuilt on a column change.
      cell.cls(this.myCls('col-' + i)).cls(this.myCls('cell'));
      cell.on('click', this.onSortOrder.bind(this, prop));

      if (this.isPropNumeric(prop)) cell.cls(this.myCls('numeric'));
      var sorted = this.isSortedByProp(prop);
      if (sorted) cell.cls(this.myCls('sort'));

      var colLabel = cell.start('flex-col-label').cls(this.myCls('col-label'))
          .start('label').add(prop.tableLabel).end();
      if (sorted) {
        var icon = this.sortOrder === prop ? this.ascIcon : this.descIcon;
        colLabel.start('span').cls(this.myCls('sort-indicator')).add(icon).end();
      }
      colLabel.end();

      cell.add(this.makeResizeHandle(i));

      if (!this.colWidths_[i])
        this.colWidths_[i] = this.makeColWidthValue(i);

      return cell;
    },

    function isPropNumeric(prop) {
      return IntProperty.isInstance(prop) || FloatProperty.isInstance(prop);
    },

    function isSortedByProp(prop) {
      return this.sortProp === prop;
    },

    function makeColWidthValue(i) {
      var styleE = this.E('style');
      var value = this.SimpleValue.create();
      value.addListener(function(obj, prop, old, nu) {
        styleE.el().innerHTML = '#' + this.id + ' .' + this.myCls('col-' + i) +
            '{ width: ' + nu + 'px; }';
      }.bind(this));
      this.headE.add(styleE);
      return value;
    }
  ],

  listeners: [
    function makeRow(map, Y) {
      map = map || {};
      map.properties$ = this.columnProperties_$;
      return this.rowView(map, Y);
    },
    function onResize() {
      if (this.headRowE && this.headRowE.state === this.headRowE.LOADED) {
        this.computeColWidths();
      } else {
        this.headRowE.on('load', this.computeColWidths.bind(this));
      }
    }
  ],

  templates: [
    function CSS() {/*
      ^col-resize * {
        cursor: ew-resize !important;
      }

      ^ {
        display: flex;
        flex-direction: column;
        flex-grow: 1;
        flex-shrink: 1;
        overflow-x: hidden;
        overflow-y: auto;
        width: 100%;
      }

      ^head {
        display: flex;
        flex-direction: column;
        flex-grow: 0;
        flex-shrink: 0;
      }

      ^body {
        display: flex;
        flex-direction: column;
        flex-grow: 1;
        flex-shrink: 1;
        overflow-x: hidden;
        overflow-y: auto;
        position: relative;
      }

      ^row {
        align-items: center;
        display: flex;
        flex-shrink: 0;
        flex-grow: 0;
        height: 100%;
      }

      ^col-label {
        display: flex;
        flex-shrink: 1;
        flex-grow: 1;
      }

      ^cell {
        align-items: center;
        display: flex;
        flex-grow: 0;
        flex-shrink: 0;
        padding: 8px;
        position: relative;
      }
      ^cell^numeric {
        justify-content: flex-end;
      }

      ^cell, ^cell * {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      ^cell img {
        flex-grow: 0;
        flex-shrink: 0;
      }

      ^head ^cell ^resize-handle {
        background-color: #ccc;
        display: block;
        position: absolute;
        top: 0;
        right: 0px;
        width: 1px;
        bottom: 0;
        z-index: 9;
        cursor: ew-resize;
      }

      ^cell:last-child ^resize-handle {
        display: none;
      }

      ^head ^row {
        align-items: center;
        border-bottom: 1px solid #ccc;
        height: 36px;
      }

      ^head ^cell {
        height: 100%;
        margin: 0;
        padding: 0 8px;
      }

      ^numeric {
        text-align: right;
      }
      ^numeric ^col-label {
        flex-direction: row-reverse;
      }

      ^sort {
        font-weight: bold;
      }

      ^col-label label {
        font-weight: bold;
        flex-grow: 0;
      }
      ^col-label span {
        flex-grow: 0;
        flex-shrink: 0;
      }
    */}
  ]
});
<|endoftext|>


<commit_before>/*
 * $Id: base64.js,v 2.12 2013/05/06 07:54:20 dankogai Exp dankogai $
 *
 *  Licensed under the MIT license.
 *    http://opensource.org/licenses/mit-license
 *
 *  References:
 *    http://en.wikipedia.org/wiki/Base64
 */

(function(global) {
    'use strict';
    if (global.Base64) return;
    var version = "2.1.2";
    // if node.js, we use Buffer
    var buffer;
    if (typeof module !== 'undefined' && module.exports) {
        buffer = require('buffer').Buffer;
    }
    // constants
    var b64chars
        = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    var b64tab = function(bin) {
        var t = {};
        for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
        return t;
    }(b64chars);
    var fromCharCode = String.fromCharCode;
    // encoder stuff
    var cb_utob = function(c) {
        if (c.length < 2) {
            var cc = c.charCodeAt(0);
            return cc < 0x80 ? c
                : cc < 0x800 ? (fromCharCode(0xc0 | (cc >>> 6))
                                + fromCharCode(0x80 | (cc & 0x3f)))
                : (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f))
                   + fromCharCode(0x80 | ((cc >>>  6) & 0x3f))
                   + fromCharCode(0x80 | ( cc         & 0x3f)));
        } else {
            var cc = 0x10000
                + (c.charCodeAt(0) - 0xD800) * 0x400
                + (c.charCodeAt(1) - 0xDC00);
            return (fromCharCode(0xf0 | ((cc >>> 18) & 0x07))
                    + fromCharCode(0x80 | ((cc >>> 12) & 0x3f))
                    + fromCharCode(0x80 | ((cc >>>  6) & 0x3f))
                    + fromCharCode(0x80 | ( cc         & 0x3f)));
        }
    };
    var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
    var utob = function(u) {
        return u.replace(re_utob, cb_utob);
    };
    var cb_encode = function(ccc) {
        var padlen = [0, 2, 1][ccc.length % 3],
        ord = ccc.charCodeAt(0) << 16
            | ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8)
            | ((ccc.length > 2 ? ccc.charCodeAt(2) : 0)),
        chars = [
            b64chars.charAt( ord >>> 18),
            b64chars.charAt((ord >>> 12) & 63),
            padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63),
            padlen >= 1 ? '=' : b64chars.charAt(ord & 63)
        ];
        return chars.join('');
    };
    var btoa = global.btoa ? function(b) {
        return global.btoa(b);
    } : function(b) {
        return b.replace(/[\s\S]{1,3}/g, cb_encode);
    };
    var _encode = buffer
        ? function (u) { return (new buffer(u)).toString('base64') }
    : function (u) { return btoa(utob(u)) }
    ;
    var encode = function(u, urisafe) {
        return !urisafe
            ? _encode(u)
            : _encode(u).replace(/[+\/]/g, function(m0) {
                return m0 == '+' ? '-' : '_';
            }).replace(/=/g, '');
    };
    var encodeURI = function(u) { return encode(u, true) };
    // decoder stuff
    var re_btou = new RegExp([
        '[\xC0-\xDF][\x80-\xBF]',
        '[\xE0-\xEF][\x80-\xBF]{2}',
        '[\xF0-\xF7][\x80-\xBF]{3}'
    ].join('|'), 'g');
    var cb_btou = function(cccc) {
        switch(cccc.length) {
        case 4:
            var cp = ((0x07 & cccc.charCodeAt(0)) << 18)
                |    ((0x3f & cccc.charCodeAt(1)) << 12)
                |    ((0x3f & cccc.charCodeAt(2)) <<  6)
                |     (0x3f & cccc.charCodeAt(3)),
            offset = cp - 0x10000;
            return (fromCharCode((offset  >>> 10) + 0xD800)
                    + fromCharCode((offset & 0x3FF) + 0xDC00));
        case 3:
            return fromCharCode(
                ((0x0f & cccc.charCodeAt(0)) << 12)
                    | ((0x3f & cccc.charCodeAt(1)) << 6)
                    |  (0x3f & cccc.charCodeAt(2))
            );
        default:
            return  fromCharCode(
                ((0x1f & cccc.charCodeAt(0)) << 6)
                    |  (0x3f & cccc.charCodeAt(1))
            );
        }
    };
    var btou = function(b) {
        return b.replace(re_btou, cb_btou);
    };
    var cb_decode = function(cccc) {
        var len = cccc.length,
        padlen = len % 4,
        n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0)
            | (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0)
            | (len > 2 ? b64tab[cccc.charAt(2)] <<  6 : 0)
            | (len > 3 ? b64tab[cccc.charAt(3)]       : 0),
        chars = [
            fromCharCode( n >>> 16),
            fromCharCode((n >>>  8) & 0xff),
            fromCharCode( n         & 0xff)
        ];
        chars.length -= [0, 0, 2, 1][padlen];
        return chars.join('');
    };
    var atob = global.atob ? function(a) {
        return global.atob(a);
    } : function(a){
        return a.replace(/[\s\S]{1,4}/g, cb_decode);
    };
    var _decode = buffer
        ? function(a) { return (new buffer(a, 'base64')).toString() }
    : function(a) { return btou(atob(a)) };
    var decode = function(a){
        return _decode(
            a.replace(/[-_]/g, function(m0) { return m0 == '-' ? '+' : '/' })
                .replace(/[^A-Za-z0-9\+\/]/g, '')
        );
    };
    // export Base64
    global.Base64 = {
        VERSION: version,
        atob: atob,
        btoa: btoa,
        fromBase64: decode,
        toBase64: encode,
        utob: utob,
        encode: encode,
        encodeURI: encodeURI,
        btou: btou,
        decode: decode
    };
    // if ES5 is available, make Base64.extendString() available
    if (typeof Object.defineProperty === 'function') {
        var noEnum = function(v){
            return {value:v,enumerable:false,writable:true,configurable:true};
        };
        global.Base64.extendString = function () {
            Object.defineProperty(
                String.prototype, 'fromBase64', noEnum(function () {
                    return decode(this)
                }));
            Object.defineProperty(
                String.prototype, 'toBase64', noEnum(function (urisafe) {
                    return encode(this, urisafe)
                }));
            Object.defineProperty(
                String.prototype, 'toBase64URI', noEnum(function () {
                    return encode(this, true)
                }));
        };
    }
    // that's it!
})(this);
<commit_msg>Added noConflict() so multiple versions can be included in the same context safely.<commit_after>/*
 * $Id: base64.js,v 2.12 2013/05/06 07:54:20 dankogai Exp dankogai $
 *
 *  Licensed under the MIT license.
 *    http://opensource.org/licenses/mit-license
 *
 *  References:
 *    http://en.wikipedia.org/wiki/Base64
 */

(function(global) {
    'use strict';
    // existing version for noConflict()
    var _Base64 = global.Base64;
    var version = "2.1.2";
    // if node.js, we use Buffer
    var buffer;
    if (typeof module !== 'undefined' && module.exports) {
        buffer = require('buffer').Buffer;
    }
    // constants
    var b64chars
        = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    var b64tab = function(bin) {
        var t = {};
        for (var i = 0, l = bin.length; i < l; i++) t[bin.charAt(i)] = i;
        return t;
    }(b64chars);
    var fromCharCode = String.fromCharCode;
    // encoder stuff
    var cb_utob = function(c) {
        if (c.length < 2) {
            var cc = c.charCodeAt(0);
            return cc < 0x80 ? c
                : cc < 0x800 ? (fromCharCode(0xc0 | (cc >>> 6))
                                + fromCharCode(0x80 | (cc & 0x3f)))
                : (fromCharCode(0xe0 | ((cc >>> 12) & 0x0f))
                   + fromCharCode(0x80 | ((cc >>>  6) & 0x3f))
                   + fromCharCode(0x80 | ( cc         & 0x3f)));
        } else {
            var cc = 0x10000
                + (c.charCodeAt(0) - 0xD800) * 0x400
                + (c.charCodeAt(1) - 0xDC00);
            return (fromCharCode(0xf0 | ((cc >>> 18) & 0x07))
                    + fromCharCode(0x80 | ((cc >>> 12) & 0x3f))
                    + fromCharCode(0x80 | ((cc >>>  6) & 0x3f))
                    + fromCharCode(0x80 | ( cc         & 0x3f)));
        }
    };
    var re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
    var utob = function(u) {
        return u.replace(re_utob, cb_utob);
    };
    var cb_encode = function(ccc) {
        var padlen = [0, 2, 1][ccc.length % 3],
        ord = ccc.charCodeAt(0) << 16
            | ((ccc.length > 1 ? ccc.charCodeAt(1) : 0) << 8)
            | ((ccc.length > 2 ? ccc.charCodeAt(2) : 0)),
        chars = [
            b64chars.charAt( ord >>> 18),
            b64chars.charAt((ord >>> 12) & 63),
            padlen >= 2 ? '=' : b64chars.charAt((ord >>> 6) & 63),
            padlen >= 1 ? '=' : b64chars.charAt(ord & 63)
        ];
        return chars.join('');
    };
    var btoa = global.btoa ? function(b) {
        return global.btoa(b);
    } : function(b) {
        return b.replace(/[\s\S]{1,3}/g, cb_encode);
    };
    var _encode = buffer
        ? function (u) { return (new buffer(u)).toString('base64') }
    : function (u) { return btoa(utob(u)) }
    ;
    var encode = function(u, urisafe) {
        return !urisafe
            ? _encode(u)
            : _encode(u).replace(/[+\/]/g, function(m0) {
                return m0 == '+' ? '-' : '_';
            }).replace(/=/g, '');
    };
    var encodeURI = function(u) { return encode(u, true) };
    // decoder stuff
    var re_btou = new RegExp([
        '[\xC0-\xDF][\x80-\xBF]',
        '[\xE0-\xEF][\x80-\xBF]{2}',
        '[\xF0-\xF7][\x80-\xBF]{3}'
    ].join('|'), 'g');
    var cb_btou = function(cccc) {
        switch(cccc.length) {
        case 4:
            var cp = ((0x07 & cccc.charCodeAt(0)) << 18)
                |    ((0x3f & cccc.charCodeAt(1)) << 12)
                |    ((0x3f & cccc.charCodeAt(2)) <<  6)
                |     (0x3f & cccc.charCodeAt(3)),
            offset = cp - 0x10000;
            return (fromCharCode((offset  >>> 10) + 0xD800)
                    + fromCharCode((offset & 0x3FF) + 0xDC00));
        case 3:
            return fromCharCode(
                ((0x0f & cccc.charCodeAt(0)) << 12)
                    | ((0x3f & cccc.charCodeAt(1)) << 6)
                    |  (0x3f & cccc.charCodeAt(2))
            );
        default:
            return  fromCharCode(
                ((0x1f & cccc.charCodeAt(0)) << 6)
                    |  (0x3f & cccc.charCodeAt(1))
            );
        }
    };
    var btou = function(b) {
        return b.replace(re_btou, cb_btou);
    };
    var cb_decode = function(cccc) {
        var len = cccc.length,
        padlen = len % 4,
        n = (len > 0 ? b64tab[cccc.charAt(0)] << 18 : 0)
            | (len > 1 ? b64tab[cccc.charAt(1)] << 12 : 0)
            | (len > 2 ? b64tab[cccc.charAt(2)] <<  6 : 0)
            | (len > 3 ? b64tab[cccc.charAt(3)]       : 0),
        chars = [
            fromCharCode( n >>> 16),
            fromCharCode((n >>>  8) & 0xff),
            fromCharCode( n         & 0xff)
        ];
        chars.length -= [0, 0, 2, 1][padlen];
        return chars.join('');
    };
    var atob = global.atob ? function(a) {
        return global.atob(a);
    } : function(a){
        return a.replace(/[\s\S]{1,4}/g, cb_decode);
    };
    var _decode = buffer
        ? function(a) { return (new buffer(a, 'base64')).toString() }
    : function(a) { return btou(atob(a)) };
    var decode = function(a){
        return _decode(
            a.replace(/[-_]/g, function(m0) { return m0 == '-' ? '+' : '/' })
                .replace(/[^A-Za-z0-9\+\/]/g, '')
        );
    };
    var noConflict = function() {
        var Base64 = global.Base64;
        global.Base64 = _Base64;
        return Base64;
    };
    // export Base64
    global.Base64 = {
        VERSION: version,
        atob: atob,
        btoa: btoa,
        fromBase64: decode,
        toBase64: encode,
        utob: utob,
        encode: encode,
        encodeURI: encodeURI,
        btou: btou,
        decode: decode,
        noConflict: noConflict
    };
    // if ES5 is available, make Base64.extendString() available
    if (typeof Object.defineProperty === 'function') {
        var noEnum = function(v){
            return {value:v,enumerable:false,writable:true,configurable:true};
        };
        global.Base64.extendString = function () {
            Object.defineProperty(
                String.prototype, 'fromBase64', noEnum(function () {
                    return decode(this)
                }));
            Object.defineProperty(
                String.prototype, 'toBase64', noEnum(function (urisafe) {
                    return encode(this, urisafe)
                }));
            Object.defineProperty(
                String.prototype, 'toBase64URI', noEnum(function () {
                    return encode(this, true)
                }));
        };
    }
    // that's it!
})(this);
<|endoftext|>


<commit_before>angular.module("umbraco")
    .controller("Umbraco.Editors.ListViewController",
        function ($rootScope, $scope, $routeParams, contentResource, contentTypeResource, editorContextService) {

        $scope.selected = [];

        $scope.options = {
            pageSize: 10,
            pageNumber: 1,
            filter: '',
            orderBy: 'Id',
            orderDirection: "desc"
        };

        $scope.next = function(){
            if ($scope.options.pageNumber < $scope.listViewResultSet.totalPages) {
                $scope.options.pageNumber++;
                $scope.reloadView($scope.content.id);
            }
        };

        $scope.goToPage = function (pageNumber) {
            $scope.options.pageNumber = pageNumber + 1;
            $scope.reloadView($scope.content.id);
        };

        $scope.sort = function (field) {

            $scope.options.orderBy = field;

            if ($scope.options.orderDirection === "desc") {
                $scope.options.orderDirection = "asc";
            }else{
                $scope.options.orderDirection = "desc";
            }

            $scope.reloadView($scope.content.id);
        };

        $scope.prev = function(){
            if ($scope.options.pageNumber > 1) {
                $scope.options.pageNumber--;
                $scope.reloadView($scope.content.id);
            }
        };

        /*Loads the search results, based on parameters set in prev,next,sort and so on*/
        /*Pagination is done by an array of objects, due angularJS's funky way of monitoring state
        with simple values */

        $scope.reloadView = function(id) {
            contentResource.getChildren(id, $scope.options).then(function(data) {

                $scope.listViewResultSet = data;
                $scope.pagination = [];

                for (var i = $scope.listViewResultSet.totalPages - 1; i >= 0; i--) {
                    $scope.pagination[i] = { index: i, name: i + 1 };
                }

                if ($scope.options.pageNumber > $scope.listViewResultSet.totalPages) {
                    $scope.options.pageNumber = $scope.listViewResultSet.totalPages;
                }

            });
        };

        var updateSelected = function (action, id) {
            if (action === 'add' && $scope.selected.indexOf(id) === -1) {
                $scope.selected.push(id);
            }
            if (action === 'remove' && $scope.selected.indexOf(id) !== -1) {
                $scope.selected.splice($scope.selected.indexOf(id), 1);
            }
        };

        $scope.updateSelection = function ($event, id) {
            var checkbox = $event.target;
            var action = (checkbox.checked ? 'add' : 'remove');
            updateSelected(action, id);
        };

        $scope.selectAll = function ($event) {
            var checkbox = $event.target;
            var action = (checkbox.checked ? 'add' : 'remove');
            for (var i = 0; i < $scope.listViewResultSet.items.length; i++) {
                var entity = $scope.listViewResultSet.items[i];
                updateSelected(action, entity.id);
            }
        };

        $scope.getSelectedClass = function (entity) {
            return $scope.isSelected(entity.id) ? 'selected' : '';
        };

        $scope.isSelected = function (id) {
            return $scope.selected.indexOf(id) >= 0;
        };

        $scope.isSelectedAll = function () {
            if ($scope.listViewResultSet != null)
                return $scope.selected.length === $scope.listViewResultSet.items.length;
            else
                return false;
        };

        $scope.isAnythingSelected = function() {
            return $scope.selected.length > 0;
        };

        $scope.delete = function () {
            $scope.bulkStatus = "Starting with delete";
            var current = 1;
            var total = $scope.selected.length;
            for (var i = 0; i < $scope.selected.length; i++) {
                contentResource.deleteById($scope.selected[i]).then(function (data) {
                    $scope.bulkStatus = "Deleted doc" + i + " out of "+ total +"documents";
                    if (current == total) {
                        $scope.bulkStatus = "Deleting done";
                        $scope.selected = [];
                        $scope.reloadView($scope.content.id);
                    }
                    current++;
                });
            }

        };

        $scope.publish = function () {
            $scope.bulkStatus = "Starting with publish";
            var current = 1;
            var total = $scope.selected.length;
            for (var i = 0; i < $scope.selected.length; i++) {
                contentResource.getById($scope.selected[i]).then(function(content) {
                    contentResource.publish(content, false)
                        .then(function(content){
                            $scope.bulkStatus = "Publishing doc" + i + " out of " + total + "documents";
                            if (current == total) {
                                $scope.bulkStatus = "Publish done";
                                $scope.reloadView($scope.content.id);
                            }
                            current++;
                        });
                });
            }
        };

        $scope.unpublish = function () {

        };

        if($routeParams.id){
            $scope.pagination = new Array(100);
            $scope.listViewAllowedTypes = contentTypeResource.getAllowedTypes($routeParams.id);
            $scope.reloadView($routeParams.id);

            $scope.content = editorContextService.getContext();

        }

});
<commit_msg>List view editor: hooks in notification service<commit_after>angular.module("umbraco")
    .controller("Umbraco.Editors.ListViewController",
        function ($rootScope, $scope, $routeParams, contentResource, contentTypeResource, editorContextService, notificationsService) {

        $scope.selected = [];

        $scope.options = {
            pageSize: 10,
            pageNumber: 1,
            filter: '',
            orderBy: 'Id',
            orderDirection: "desc"
        };

        $scope.next = function(){
            if ($scope.options.pageNumber < $scope.listViewResultSet.totalPages) {
                $scope.options.pageNumber++;
                $scope.reloadView($scope.content.id);
            }
        };

        $scope.goToPage = function (pageNumber) {
            $scope.options.pageNumber = pageNumber + 1;
            $scope.reloadView($scope.content.id);
        };

        $scope.sort = function (field) {

            $scope.options.orderBy = field;

            if ($scope.options.orderDirection === "desc") {
                $scope.options.orderDirection = "asc";
            }else{
                $scope.options.orderDirection = "desc";
            }

            $scope.reloadView($scope.content.id);
        };

        $scope.prev = function(){
            if ($scope.options.pageNumber > 1) {
                $scope.options.pageNumber--;
                $scope.reloadView($scope.content.id);
            }
        };

        /*Loads the search results, based on parameters set in prev,next,sort and so on*/
        /*Pagination is done by an array of objects, due angularJS's funky way of monitoring state
        with simple values */

        $scope.reloadView = function(id) {
            contentResource.getChildren(id, $scope.options).then(function(data) {

                $scope.listViewResultSet = data;
                $scope.pagination = [];

                for (var i = $scope.listViewResultSet.totalPages - 1; i >= 0; i--) {
                    $scope.pagination[i] = { index: i, name: i + 1 };
                }

                if ($scope.options.pageNumber > $scope.listViewResultSet.totalPages) {
                    $scope.options.pageNumber = $scope.listViewResultSet.totalPages;
                }

            });
        };

        var updateSelected = function (action, id) {
            if (action === 'add' && $scope.selected.indexOf(id) === -1) {
                $scope.selected.push(id);
            }
            if (action === 'remove' && $scope.selected.indexOf(id) !== -1) {
                $scope.selected.splice($scope.selected.indexOf(id), 1);
            }
        };

        $scope.updateSelection = function ($event, id) {
            var checkbox = $event.target;
            var action = (checkbox.checked ? 'add' : 'remove');
            updateSelected(action, id);
        };

        $scope.selectAll = function ($event) {
            var checkbox = $event.target;
            var action = (checkbox.checked ? 'add' : 'remove');
            for (var i = 0; i < $scope.listViewResultSet.items.length; i++) {
                var entity = $scope.listViewResultSet.items[i];
                updateSelected(action, entity.id);
            }
        };

        $scope.getSelectedClass = function (entity) {
            return $scope.isSelected(entity.id) ? 'selected' : '';
        };

        $scope.isSelected = function (id) {
            return $scope.selected.indexOf(id) >= 0;
        };

        $scope.isSelectedAll = function () {
            if ($scope.listViewResultSet != null)
                return $scope.selected.length === $scope.listViewResultSet.items.length;
            else
                return false;
        };

        $scope.isAnythingSelected = function() {
            return $scope.selected.length > 0;
        };

        $scope.delete = function () {
            $scope.bulkStatus = "Starting with delete";
            var current = 1;
            var total = $scope.selected.length;
            for (var i = 0; i < $scope.selected.length; i++) {
                contentResource.deleteById($scope.selected[i]).then(function (data) {
                    $scope.bulkStatus = "Deleted doc" + i + " out of "+ total +"documents";
                    if (current == total) {
                        notificationsService.success("Bulk action", "Deleted " + total + "documents");
                        $scope.bulkStatus = "";
                        $scope.selected = [];
                        $scope.reloadView($scope.content.id);
                    }
                    current++;
                });
            }

        };

        $scope.publish = function () {
            $scope.bulkStatus = "Starting with publish";
            var current = 1;
            var total = $scope.selected.length;
            for (var i = 0; i < $scope.selected.length; i++) {
                contentResource.getById($scope.selected[i]).then(function(content) {
                    contentResource.publish(content, false)
                        .then(function(content){
                            $scope.bulkStatus = "Publishing doc" + i + " out of " + total + "documents";
                            if (current == total) {
                                notificationsService.success("Bulk action", "Published " + total + "documents");
                                $scope.bulkStatus = "";
                                $scope.reloadView($scope.content.id);
                            }
                            current++;
                        });
                });
            }
        };

        $scope.unpublish = function () {

        };

        if($routeParams.id){
            $scope.pagination = new Array(100);
            $scope.listViewAllowedTypes = contentTypeResource.getAllowedTypes($routeParams.id);
            $scope.reloadView($routeParams.id);

            $scope.content = editorContextService.getContext();

        }

});
<|endoftext|>