<commit_before>// screen Size
var height = window.innerHeight;
var width = window.innerWidth;

// assets
var game;
var amanda;
var background;
var villagers;
var victor;
var ground;
var platforms;
var currentVillager;
var currentVillager2;

// variables
var score = 0;
var scoreText;
var velocity = 200;
var instructions;
var cursors;
var lives = 5;
var livesText;
var centerText;
var started = false;
var instructionPage = 0;
var rawr;
var rawrX = 0.25;
var rawrY = 0.25;
var pauseKey;
var spaceKey;
var enterKey;
var awkwardQuestions = [
	"When is the baby due?", "Are you having a boy or a girl?", "You look like you're ready to pop!", "Can I touch your belly?", "You look so small!", "You look so big!", "Are you pregnant?", "What's the baby doing in there?", "Do you need to sit down?", "Here let me get that for you...", "You must be having a girl because...", "You must be having a boy because...", "Are you sure you aren't having twins??", "Are you old enough to be having a baby?", "Should you be doing this in your condition?", "Are you excited?", "Don't you just LOVE being pregnant?", "How old are you?", "Will you have any more?", "How are you feeling?", "Are you ready?", "Haven't you had that baby yet?", "The secret to raising kids is...", "Remember to sleep when the baby sleeps.", "They grow up so fast...", "You're getting an epidural, right?", "Natural birth is the only way to go.", "Are you married?", "Have you finished the nursery?", "Are you scared?", "I don't have kids, but here's what I think...", "What language are you going to teach him?", "Where is she going to go to college?", "Have you got the preschool picked out yet?", "I knew this one lady who...", "Back in my day...", "Do you think you'll be a good mom?", "Do you have a name picked out yet?", "If you think that's bad, let me tell you...", "If you think pregnancy is bad, wait until the terrible twos!", "This isn't so bad, just wait until she's a teenager!", "It's a good thing you're having a boy, because girl's are the worst!", "It's a good thing you're having a girl, because boys are the worst!", "How many kids do you want?", "Have you read any parenting books?", "What's your parenting style?", "I NEVER did that", "Don't forget to avoid alcohol!", "Make sure you microwave your sandwich meats!", "Don't worry, it gets better."
];
var snarkyAnswers = [
	"NO, you MAY NOT touch my belly!", "NO, I am NOT having twins.", "I do not actually love being pregnant, leave me alone.", "LEAVE ME ALONE!", "You need to be garbage-collected!", "How is this any of your business?", "Can I touch YOUR belly?", "Take that!", "Thank you for your advice,\nperson-I've-never-met-before.", "Pregnant women don't pop -- that's not how this works.", "Why are you asking if I'm scared??\nWhat's wrong with you?", "No, I'm not hungry. Go. Away.", "There isn’t enough Purell to wipe the creepiness off!", "How can I avoid alcohol when I have to talk to you??", "You are causing global warming, because you have me fuming mad!", "I have an app called Decency, and you just broke the build.", "Have you ever even SEEN a child?", "You are lord of the 3-ring-circus", "Who asked you?!", "My baby, my business.", "And who are you? DHS?", "You are being a dark cloud in my array of sunshine.", "Go. Away.", "Oh yeah? How did your kids turn out?", "Maybe you should Google some MANNERS!", "Is it difficult to fit your whole foot into your mouth?"
];

if(isSafari) {
	game = new Phaser.Game(width, height, Phaser.CANVAS, 'midDiv', { preload: preload, create: create, update: update });
} else {
	game = new Phaser.Game(width, height, Phaser.AUTO, 'midDiv', { preload: preload, create: create, update: update });
}

// loads assets
function preload() {

// load my world
game.load.image('background', '/img/kenney_backgroundElements/Samples/colored_talltrees.png');

// load the ground
game.load.image('ground', '/img/ground.png');

// load angry swear words
game.load.image('angry', '/img/angry.png');

// load Amanda
game.load.spritesheet('amanda', '/img/Amanda.png', 64, 64, 260);

// load villain
game.load.spritesheet('victor', '/img/old_man.png', 64, 64, 273);

scoreText = game.add.text(3, 0, 'Score: 0', {fontSize: '2em', fill: '#8B5742'});
livesText = game.add.text(3, 20, 'Patience: 5', {fontSize: '2em', fill: '#8B5742'});

}

function showInstructions() {
	var instructions1 = "Welcome! Press enter to begin.";
	var instructions2 = "Congrats Amanda and Jesse!";
	var instructions3 = "Help Amanda avoid awkward situations!";
	var instructions4 = "In a world where it's culturally appropriate to touch a woman's stomach,\nand ask her awkward questions,\nAmanda needs help stopping these weirdos!";
	var instructions5 = "Run back and forth with your arrow keys to avoid the weirdos.";
	var instructions6 = "If you need a break, you can pause with P.";
	var instructions7 = "Use the down arrow to stop them from coming closer.";
	var instructions8 = "Use the spacebar or up arrow to jump on them for extra points!";
	var instructions9 = "Be careful not to get too close to the weirdos,\nor else you'll have to listen to their unsolicited advice,\nand Amanda will start to lose patience!";
	var instructionList = [instructions1, instructions2, instructions3, instructions4, instructions5, instructions6, instructions7, instructions8, instructions9];

	if (instructionPage < 9) {
		writeCenter(instructionList[instructionPage], 1, null);
		instructionPage++;
		game.paused = true;
	} else {
		centerText.destroy();
		started = true;
	}
}

function create() {
  // load phaser
  game.physics.startSystem(Phaser.Physics.ARCADE);
	game.input.onDown.add(unpause, self);
	pauseKey = game.input.keyboard.addKey(Phaser.Keyboard.P);
	enterKey = game.input.keyboard.addKey(Phaser.Keyboard.ENTER);
	spaceKey = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);

  // platforms (in case of obstacles if I have time)
  platforms = game.add.group();
  platforms.enableBody = true;
  ground = platforms.create(0, game.world.height - 136, 'ground');
	ground.scale.x = width / ground.width;
	ground.body.immovable = true;

  // add the player
  amanda = game.add.sprite((game.world.width * .01), (game.world.height - 200), 'amanda');
  game.physics.arcade.enable(amanda);
  amanda.body.collideWorldBounds = true;
	amanda.body.gravity.y = 900;
	amanda.frame = 26;

	// add angry villagers
	villagers = game.add.group();
	villagers.enableBody = true;
	villagers.setAll('checkWorldBounds', true);
	villagers.setAll('outOfBoundsKill', true);
	victor = villagers.create((game.world.width + (game.world.width * .01)), (game.world.height - 200), 'victor');
	victor.body.velocity.x = -200;

	// set timer for villagers to be created
	game.time.events.loop(Phaser.Timer.SECOND, makeVillagers, this);

  // add in background
  background = game.add.tileSprite(0, 0, game.world.bounds.width, game.cache.getImage('background').height, 'background');
  background.scale.x = (width/background.width);
  background.scale.y = (height/background.height);
  game.world.sendToBack(background);

	// centertext shizz
	centerText = game.add.text(game.world.centerX, game.world.centerY, "");

  // listen for keypresses
  cursors = game.input.keyboard.createCursorKeys();
	amanda.animations.add('left', [118, 119, 120, 121, 122, 123, 124, 125], 10, false);
	amanda.animations.add('right', [144, 145, 146, 147, 148, 149, 150, 151], 10, false);
	amanda.animations.add('hit', [208, 209, 210, 211, 212], 10, false);

	// angry villagers animations 'WE WILL GET YOU'
	victor.animations.add('shuffle', [118, 119, 120, 121, 122, 123, 124, 125], 10, true);
	victor.animations.play('shuffle');

	makeVillagers();

}

// runs the game
function update() {
	game.physics.arcade.collide(platforms, amanda);

	if(currentVillager) {
		currentVillager.destroy();
	}

	if(currentVillager2) {
		currentVillager2.destroy();
	}

	if(!started) {
		showInstructions();
	}

	if (lives > 0) {
		if (!cursors.down.isDown) {
			background.tilePosition.x -= 2;
		}
	}

	if (cursors.left.isDown) {
		amanda.animations.play('left');
		amanda.body.velocity.x = -325;
	} else if (cursors.right.isDown) {
		amanda.animations.play('right');
		amanda.body.velocity.x = 125;
	} else {
		amanda.body.velocity.x = 0;
		amanda.animations.play('right');
	}
	if (cursors.up.isDown) {
		if (amanda.body.touching.down) {
			amanda.body.velocity.y = -600;
		}
	}
	if (!amanda.body.touching.down) {
		game.physics.arcade.overlap(amanda, villagers, jumpOn, null, this);
	} else if (cursors.down.isDown) {
		amanda.frame = 259;
		game.physics.arcade.overlap(amanda, villagers, hit, null, this);
	} else {
		game.physics.arcade.overlap(amanda, villagers, minusOne, null, this);
	}
	pauseKey.onDown.add(pause, this);
	enterKey.onDown.add(unpause, this);
	spaceKey.onDown.add(jumpUp, this);
}

function makeVillagers() {
	if(lives > 0) {
		var num = Math.round(score/500) + 1;
		numVillagers(num);
	}
}

function numVillagers(num) {
	for(var i = 0; i < num; i++) {
		victor = villagers.create(game.world.width + (game.world.width * (Math.random())), (game.world.height - 200), 'victor');
		victor.animations.add('shuffle', [118, 119, 120, 121, 122, 123, 124, 125], 10, true);
		victor.animations.play('shuffle');
		victor.body.velocity.x = -200;
	}
}

function minusOne(amanda, villager) {
	rawr = game.add.sprite(0, 0, 'angry');
	rawr.scale.setTo(rawrX, rawrY);
	rawr.x = (amanda.left + ((amanda.width/1.9) - (rawr.width/1.5)));
	rawr.y = amanda.top - rawr.height;
	amanda.frame = 31;
	villager.frame = 172;
	game.paused = true;
	currentVillager = villager;
	lives -= 1;
	livesText.text = 'Patience: ' + lives;
	var awk = awkwardQuestions[Math.floor(Math.random() * awkwardQuestions.length)];
	writeCenter(awk);
	game.input.onDown.add(unpause, self);
	if(lives == 0) {
		amanda.x = (game.world.width / 2) - (amanda.width / 1.9); // GAME OVER
		rawr.scale.setTo(0.9,0.9);
		rawr.x = (game.world.width / 2) - (rawr.width / 1.5);
		rawr.y = (game.world.height / 2) - (rawr.width / 2);
		villagers.forEachAlive(killEmAll, this);
		writeCenter("GAME OVER\nRefresh to play again!")
	}
}

function jumpOn(amanda, villager) {
	currentVillager2 = villager;
	villager.frame = 265;
	game.paused = true;
	var snark = snarkyAnswers[Math.floor(Math.random() * snarkyAnswers.length)];
	console.log(snark);
	writeCenter(snark);
	score += 10;
	scoreText.text = 'Score: ' + score;
}

function jumpUp() {
	if (amanda.body.touching.down) {
		amanda.body.velocity.y = -600;
	}
}

function hit(amanda, villager) {
	villager.destroy();
	score += 2;
	scoreText.text = 'Score: ' + score;
}

function killEmAll(villager) {
	villager.kill();
}

function writeCenter(text) {
	centerText.destroy();
	centerText = game.add.text(game.world.centerX, 100, text);
	centerText.anchor.set(0.5);
	centerText.align = 'center';

	//	Font style
	centerText.font = 'Arial';
	centerText.fontSize = '3em';
	centerText.fill = '#8B5742';
}

function unpause(event, villager) {
	game.paused = false;
	centerText.destroy();
	rawr.destroy();
	rawrX += 0.1;
	rawrY += 0.1;
}

function pause(event) {
	if(game.paused == false) {
		game.paused = true;
		console.log(game.paused);
	} else {
		game.paused = false;
	}
}

// in case weirdos use Safari
function isSafari()
{
	var browser = navigator.appVersion;
	var device = navigator.platform;

	if(browser.indexOf("Safari") > -1 && device == "iPad")
	{
		return true;
	}
}
<commit_msg>amanda jumps on villager<commit_after>// screen Size
var height = window.innerHeight;
var width = window.innerWidth;

// assets
var game;
var amanda;
var background;
var villagers;
var victor;
var ground;
var platforms;
var currentVillager;
var currentVillager2;

// variables
var score = 0;
var scoreText;
var velocity = 200;
var instructions;
var cursors;
var lives = 5;
var livesText;
var centerText;
var started = false;
var instructionPage = 0;
var rawr;
var rawrX = 0.25;
var rawrY = 0.25;
var pauseKey;
var spaceKey;
var enterKey;
var awkwardQuestions = [
	"When is the baby due?", "Are you having a boy or a girl?", "You look like you're ready to pop!", "Can I touch your belly?", "You look so small!", "You look so big!", "Are you pregnant?", "What's the baby doing in there?", "Do you need to sit down?", "Here let me get that for you...", "You must be having a girl because...", "You must be having a boy because...", "Are you sure you aren't having twins??", "Are you old enough to be having a baby?", "Should you be doing this in your condition?", "Are you excited?", "Don't you just LOVE being pregnant?", "How old are you?", "Will you have any more?", "How are you feeling?", "Are you ready?", "Haven't you had that baby yet?", "The secret to raising kids is...", "Remember to sleep when the baby sleeps.", "They grow up so fast...", "You're getting an epidural, right?", "Natural birth is the only way to go.", "Are you married?", "Have you finished the nursery?", "Are you scared?", "I don't have kids, but here's what I think...", "What language are you going to teach him?", "Where is she going to go to college?", "Have you got the preschool picked out yet?", "I knew this one lady who...", "Back in my day...", "Do you think you'll be a good mom?", "Do you have a name picked out yet?", "If you think that's bad, let me tell you...", "If you think pregnancy is bad, wait until the terrible twos!", "This isn't so bad, just wait until she's a teenager!", "It's a good thing you're having a boy, because girl's are the worst!", "It's a good thing you're having a girl, because boys are the worst!", "How many kids do you want?", "Have you read any parenting books?", "What's your parenting style?", "I NEVER did that", "Don't forget to avoid alcohol!", "Make sure you microwave your sandwich meats!", "Don't worry, it gets better."
];
var snarkyAnswers = [
	"NO, you MAY NOT touch my belly!", "NO, I am NOT having twins.", "I do not actually love being pregnant, leave me alone.", "LEAVE ME ALONE!", "You need to be garbage-collected!", "How is this any of your business?", "Can I touch YOUR belly?", "Take that!", "Thank you for your advice,\nperson-I've-never-met-before.", "Pregnant women don't pop -- that's not how this works.", "Why are you asking if I'm scared??\nWhat's wrong with you?", "No, I'm not hungry. Go. Away.", "There isn’t enough Purell to wipe the creepiness off!", "How can I avoid alcohol when I have to talk to you??", "You are causing global warming, because you have me fuming mad!", "I have an app called Decency, and you just broke the build.", "Have you ever even SEEN a child?", "You are lord of the 3-ring-circus", "Who asked you?!", "My baby, my business.", "And who are you? DHS?", "You are being a dark cloud in my array of sunshine.", "Go. Away.", "Oh yeah? How did your kids turn out?", "Maybe you should Google some MANNERS!", "Is it difficult to fit your whole foot into your mouth?"
];

if(isSafari) {
	game = new Phaser.Game(width, height, Phaser.CANVAS, 'midDiv', { preload: preload, create: create, update: update });
} else {
	game = new Phaser.Game(width, height, Phaser.AUTO, 'midDiv', { preload: preload, create: create, update: update });
}

// loads assets
function preload() {

// load my world
game.load.image('background', '/img/kenney_backgroundElements/Samples/colored_talltrees.png');

// load the ground
game.load.image('ground', '/img/ground.png');

// load angry swear words
game.load.image('angry', '/img/angry.png');

// load Amanda
game.load.spritesheet('amanda', '/img/Amanda.png', 64, 64, 260);

// load villain
game.load.spritesheet('victor', '/img/old_man.png', 64, 64, 273);

scoreText = game.add.text(3, 0, 'Score: 0', {fontSize: '2em', fill: '#8B5742'});
livesText = game.add.text(3, 20, 'Patience: 5', {fontSize: '2em', fill: '#8B5742'});

}

function showInstructions() {
	var instructions1 = "Welcome! Press enter to begin.";
	var instructions2 = "Congrats Amanda and Jesse!";
	var instructions3 = "Help Amanda avoid awkward situations!";
	var instructions4 = "In a world where it's culturally appropriate to touch a woman's stomach,\nand ask her awkward questions,\nAmanda needs help stopping these weirdos!";
	var instructions5 = "Run back and forth with your arrow keys to avoid the weirdos.";
	var instructions6 = "If you need a break, you can pause with P.";
	var instructions7 = "Use the down arrow to stop them from coming closer.";
	var instructions8 = "Use the spacebar or up arrow to jump on them for extra points!";
	var instructions9 = "Be careful not to get too close to the weirdos,\nor else you'll have to listen to their unsolicited advice,\nand Amanda will start to lose patience!";
	var instructionList = [instructions1, instructions2, instructions3, instructions4, instructions5, instructions6, instructions7, instructions8, instructions9];

	if (instructionPage < 9) {
		writeCenter(instructionList[instructionPage], 1, null);
		instructionPage++;
		game.paused = true;
	} else {
		centerText.destroy();
		started = true;
	}
}

function create() {
  // load phaser
  game.physics.startSystem(Phaser.Physics.ARCADE);
	game.input.onDown.add(unpause, self);
	pauseKey = game.input.keyboard.addKey(Phaser.Keyboard.P);
	enterKey = game.input.keyboard.addKey(Phaser.Keyboard.ENTER);
	spaceKey = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);

  // platforms (in case of obstacles if I have time)
  platforms = game.add.group();
  platforms.enableBody = true;
  ground = platforms.create(0, game.world.height - 136, 'ground');
	ground.scale.x = width / ground.width;
	ground.body.immovable = true;

  // add the player
  amanda = game.add.sprite((game.world.width * .01), (game.world.height - 200), 'amanda');
  game.physics.arcade.enable(amanda);
  amanda.body.collideWorldBounds = true;
	amanda.body.gravity.y = 900;
	amanda.frame = 26;

	// add angry villagers
	villagers = game.add.group();
	villagers.enableBody = true;
	villagers.setAll('checkWorldBounds', true);
	villagers.setAll('outOfBoundsKill', true);
	victor = villagers.create((game.world.width + (game.world.width * .01)), (game.world.height - 200), 'victor');
	victor.body.velocity.x = -200;

	// set timer for villagers to be created
	game.time.events.loop(Phaser.Timer.SECOND, makeVillagers, this);

  // add in background
  background = game.add.tileSprite(0, 0, game.world.bounds.width, game.cache.getImage('background').height, 'background');
  background.scale.x = (width/background.width);
  background.scale.y = (height/background.height);
  game.world.sendToBack(background);

	// centertext shizz
	centerText = game.add.text(game.world.centerX, game.world.centerY, "");

  // listen for keypresses
  cursors = game.input.keyboard.createCursorKeys();
	amanda.animations.add('left', [118, 119, 120, 121, 122, 123, 124, 125], 10, false);
	amanda.animations.add('right', [144, 145, 146, 147, 148, 149, 150, 151], 10, false);
	amanda.animations.add('hit', [208, 209, 210, 211, 212], 10, false);

	// angry villagers animations 'WE WILL GET YOU'
	victor.animations.add('shuffle', [118, 119, 120, 121, 122, 123, 124, 125], 10, true);
	victor.animations.play('shuffle');

	makeVillagers();

}

// runs the game
function update() {
	game.physics.arcade.collide(platforms, amanda);

	if(currentVillager) {
		currentVillager.destroy();
	}

	if(currentVillager2) {
		currentVillager2.destroy();
	}

	if(!started) {
		showInstructions();
	}

	if (lives > 0) {
		if (!cursors.down.isDown) {
			background.tilePosition.x -= 2;
		}
	}

	if (cursors.left.isDown) {
		amanda.animations.play('left');
		amanda.body.velocity.x = -325;
	} else if (cursors.right.isDown) {
		amanda.animations.play('right');
		amanda.body.velocity.x = 125;
	} else {
		amanda.body.velocity.x = 0;
		amanda.animations.play('right');
	}
	if (cursors.up.isDown) {
		if (amanda.body.touching.down) {
			amanda.body.velocity.y = -600;
		}
	}
	if (!amanda.body.touching.down) {
		game.physics.arcade.overlap(amanda, villagers, jumpOn, null, this);
	} else if (cursors.down.isDown) {
		amanda.frame = 259;
		game.physics.arcade.overlap(amanda, villagers, hit, null, this);
	} else {
		game.physics.arcade.overlap(amanda, villagers, minusOne, null, this);
	}
	pauseKey.onDown.add(pause, this);
	enterKey.onDown.add(unpause, this);
	spaceKey.onDown.add(jumpUp, this);
}

function makeVillagers() {
	if(lives > 0) {
		var num = Math.round(score/500) + 1;
		numVillagers(num);
	}
}

function numVillagers(num) {
	for(var i = 0; i < num; i++) {
		victor = villagers.create(game.world.width + (game.world.width * (Math.random())), (game.world.height - 200), 'victor');
		victor.animations.add('shuffle', [118, 119, 120, 121, 122, 123, 124, 125], 10, true);
		victor.animations.play('shuffle');
		victor.body.velocity.x = -200;
	}
}

function minusOne(amanda, villager) {
	rawr = game.add.sprite(0, 0, 'angry');
	rawr.scale.setTo(rawrX, rawrY);
	rawr.x = (amanda.left + ((amanda.width/1.9) - (rawr.width/1.5)));
	rawr.y = amanda.top - rawr.height;
	amanda.frame = 31;
	villager.frame = 172;
	game.paused = true;
	currentVillager = villager;
	lives -= 1;
	livesText.text = 'Patience: ' + lives;
	var awk = awkwardQuestions[Math.floor(Math.random() * awkwardQuestions.length)];
	writeCenter(awk);
	game.input.onDown.add(unpause, self);
	if(lives == 0) {
		amanda.x = (game.world.width / 2) - (amanda.width / 1.9); // GAME OVER
		rawr.scale.setTo(0.9,0.9);
		rawr.x = (game.world.width / 2) - (rawr.width / 1.5);
		rawr.y = (game.world.height / 2) - (rawr.width / 2);
		villagers.forEachAlive(killEmAll, this);
		writeCenter("GAME OVER\nRefresh to play again!")
	}
}

function jumpOn(amanda, villager) {
	currentVillager2 = villager;
	amanda.bottom = villager.top;
	amanda.left = villager.left;
	villager.frame = 265;
	game.paused = true;
	var snark = snarkyAnswers[Math.floor(Math.random() * snarkyAnswers.length)];
	writeCenter(snark);
	score += 10;
	scoreText.text = 'Score: ' + score;
}

function jumpUp() {
	if (amanda.body.touching.down) {
		amanda.body.velocity.y = -600;
	}
}

function hit(amanda, villager) {
	villager.destroy();
	score += 2;
	scoreText.text = 'Score: ' + score;
}

function killEmAll(villager) {
	villager.kill();
}

function writeCenter(text) {
	centerText.destroy();
	centerText = game.add.text(game.world.centerX, 100, text);
	centerText.anchor.set(0.5);
	centerText.align = 'center';

	//	Font style
	centerText.font = 'Arial';
	centerText.fontSize = '3em';
	centerText.fill = '#8B5742';
}

function unpause(event, villager) {
	game.paused = false;
	centerText.destroy();
	rawr.destroy();
	rawrX += 0.1;
	rawrY += 0.1;
}

function pause(event) {
	if(game.paused == false) {
		game.paused = true;
		console.log(game.paused);
	} else {
		game.paused = false;
	}
}

// in case weirdos use Safari
function isSafari()
{
	var browser = navigator.appVersion;
	var device = navigator.platform;

	if(browser.indexOf("Safari") > -1 && device == "iPad")
	{
		return true;
	}
}
<|endoftext|>


<commit_before>var isCursor = function (c) {
  return c && c._publishCursor;
};

var deepCopy = function(value) {
  return EJSON.clone(value);
}

Meteor.smartPublish = function(name, callback) {
  Meteor.publish(name, function() {
    var self = this;
    var collections = {};
    var relations = {};
    var dependencies = {};

    var updateFromData = function(name, id, fields) {
      var res = {};
      var merged = collections[name][id].mergedData;
      _.each(fields, function(flag, key) {
        var cur = undefined;
        _.each(collections[name][id].data[key], (function(value) {
          cur = _.extend(deepCopy(value), cur);
        }));
        res[key] = cur;
        if (_.isUndefined(cur)) {
          delete merged[key];
        } else {
          merged[key] = cur;
        }
      });
      self.changed(name, id, res);
    }

    var counter = 0; // this is global counter for index for publishCursor(), all indices should be different
    var updateChildren = function(name, id, fields, removeAll) {
      if (!relations[name]) return;
      var update = {};
      _.each(fields, function(flag, key) {
        if (!relations[name][key]) return;
        _.each(relations[name][key], function(id) {
          update[id] = true;
        });
      });
      _.each(update, function(flag, depId) {
        var dep = dependencies[name][depId];
        var toRemove = [];
        if (depId in collections[name][id].children) {
          collections[name][id].children[depId].forEach(function(x, i) {
            _.each(x.activeItems, function(flag, subid) {
              toRemove.push([x.name, x.index, subid]);
            });
            x.observer.stop();
          });
        }

        if (!removeAll) {
          var cursors = dep(collections[name][id].mergedData);
          if (isCursor(cursors)) cursors = [cursors];
          if (!_.isArray(cursors))
            throw new Meteor.Error("Dependency function can only return a Cursor or an array of Cursors");

          var observers = collections[name][id].children[depId] = [];
          for (var i = 0; i < cursors.length; i++) {
            var c = cursors[i];
            if (!isCursor(c))
              throw new Meteor.Error("Dependency function returned an array of non-Cursors");

            if (!c._cursorDescription) throw new Meteor.Error("Unable to get cursor's collection name");
            var subname = c._cursorDescription.collectionName;
            if (!subname) throw new Meteor.Error("Unable to get cursor's collection name");

            observers.push(publishCursor(c, subname, '_' + counter));
            counter++;
          }
        }
        toRemove.forEach(function(args) {
          smartRemoved.apply(this, args);
        });
      });
    }
    var smartAdded = function(name, index, id, fields) {
      if (!name)
        throw new Meteor.Error("Trying to add element to anonymous collection");

      collections[name] = collections[name] || {};

      if (!collections[name][id]) {
        self.added(name, id, fields);
        collections[name][id] = { count: 1, data: {}, mergedData: deepCopy(fields), children: {} };
        _.each(fields, function(val, key) {
          collections[name][id].data[key] = collections[name][id].data[key] || {};
          collections[name][id].data[key][index] = deepCopy(val);
        });
        updateChildren(name, id, relations[name]);
      } else {
        _.each(fields, function(val, key) {
          collections[name][id].data[key] = collections[name][id].data[key] || {};
          collections[name][id].data[key][index] = deepCopy(val);
        });
        collections[name][id].count++;
        updateFromData(name, id, fields);
        updateChildren(name, id, fields);
      }
    }
    var smartChanged = function(name, index, id, fields) {
      _.each(fields, function(val, key) {
        if (val === undefined) {
          delete collections[name][id].data[key][index];
        } else {
          collections[name][id].data[key][index] = deepCopy(val);
        }
      });
      updateFromData(name, id, fields);
      updateChildren(name, id, fields);
    }
    var smartRemoved = function(name, index, id) {
      if (!name                 ) throw new Meteor.Error("Trying to remove element from anonymous collection");
      if (!collections[name]    ) throw new Meteor.Error("Removing element from non-existing collection '" + name + "'");
      if (!collections[name][id]) throw new Meteor.Error("Removing unexisting element '" + id + "' from collection '" + name + "'");

      if (!--collections[name][id].count) { // If reference counter was decremented to zero
        updateChildren(name, id, relations[name], true);
        delete collections[name][id];
        self.removed(name, id);
      } else {
        var fields = {};
        _.each(collections[name][id].data, function(vals, key) {
          if (index in vals) {
            fields[key] = 1;
            delete vals[index];
          }
        });
        updateFromData(name, id, fields);
        updateChildren(name, id, fields);
      }
    }

    self.addDependency = function(name, fields, callback) {
      if (!_.isArray(fields)) fields = [fields];
      relations[name] = relations[name] || {};
      dependencies[name] = dependencies[name] || [];
      fields.forEach(function(field) {
        relations[name][field] = relations[name][field] || [];
        relations[name][field].push(dependencies[name].length);
      });
      dependencies[name].push(callback);
    }

    var cursors = callback.apply(self, arguments);
    if (isCursor(cursors)) cursors = [cursors];

    if (!cursors) return;
    if (!_.isArray(cursors))
      throw new Meteor.Error("Publish function can only return a Cursor or an array of Cursors");

    for (var i = 0; i < cursors.length; i++)
      if (!isCursor(cursors[i]))
        throw new Meteor.Error("Publish function returned an array of non-Cursors");

    var observers = [];
    for (var i = 0; i < cursors.length; i++) {
      var c = cursors[i];

      if (!c._cursorDescription) throw new Meteor.Error("Unable to get cursor's collection name");

      function publishCursor(c, name, index) {
        var activeItems = {};
        return {
          observer: c.observeChanges({
            added:   function(id, fields) {
              activeItems[id] = 1;
              fields['_id'] = id;
              smartAdded  (name, index, id, fields);
            },
            changed: function(id, fields) {
              smartChanged(name, index, id, fields);
            },
            removed: function(id) {
              delete activeItems[id];
              smartRemoved(name, index, id);
            },
          }),
          activeItems: activeItems,
          name: name,
          index: index
        }
      };

      var name = c._cursorDescription.collectionName;
      if (!name) throw new Meteor.Error("Unable to get cursor's collection name");
      observers.push(publishCursor(c, name, i).observer);
    }
    this.ready();
    this.onStop(function() {
      _.forEach(observers, function(x) { x.stop(); });
    });
  });
}
<commit_msg>Fixes #4: now smartChanged correctly handles updates on non-existing fields<commit_after>var isCursor = function (c) {
  return c && c._publishCursor;
};

var deepCopy = function(value) {
  return EJSON.clone(value);
}

Meteor.smartPublish = function(name, callback) {
  Meteor.publish(name, function() {
    var self = this;
    var collections = {};
    var relations = {};
    var dependencies = {};

    var updateFromData = function(name, id, fields) {
      var res = {};
      var merged = collections[name][id].mergedData;
      _.each(fields, function(flag, key) {
        var cur = undefined;
        _.each(collections[name][id].data[key], (function(value) {
          cur = _.extend(deepCopy(value), cur);
        }));
        res[key] = cur;
        if (_.isUndefined(cur)) {
          delete merged[key];
        } else {
          merged[key] = cur;
        }
      });
      self.changed(name, id, res);
    }

    var counter = 0; // this is global counter for index for publishCursor(), all indices should be different
    var updateChildren = function(name, id, fields, removeAll) {
      if (!relations[name]) return;
      var update = {};
      _.each(fields, function(flag, key) {
        if (!relations[name][key]) return;
        _.each(relations[name][key], function(id) {
          update[id] = true;
        });
      });
      _.each(update, function(flag, depId) {
        var dep = dependencies[name][depId];
        var toRemove = [];
        if (depId in collections[name][id].children) {
          collections[name][id].children[depId].forEach(function(x, i) {
            _.each(x.activeItems, function(flag, subid) {
              toRemove.push([x.name, x.index, subid]);
            });
            x.observer.stop();
          });
        }

        if (!removeAll) {
          var cursors = dep(collections[name][id].mergedData);
          if (isCursor(cursors)) cursors = [cursors];
          if (!_.isArray(cursors))
            throw new Meteor.Error("Dependency function can only return a Cursor or an array of Cursors");

          var observers = collections[name][id].children[depId] = [];
          for (var i = 0; i < cursors.length; i++) {
            var c = cursors[i];
            if (!isCursor(c))
              throw new Meteor.Error("Dependency function returned an array of non-Cursors");

            if (!c._cursorDescription) throw new Meteor.Error("Unable to get cursor's collection name");
            var subname = c._cursorDescription.collectionName;
            if (!subname) throw new Meteor.Error("Unable to get cursor's collection name");

            observers.push(publishCursor(c, subname, '_' + counter));
            counter++;
          }
        }
        toRemove.forEach(function(args) {
          smartRemoved.apply(this, args);
        });
      });
    }
    var smartAdded = function(name, index, id, fields) {
      if (!name)
        throw new Meteor.Error("Trying to add element to anonymous collection");

      collections[name] = collections[name] || {};

      if (!collections[name][id]) {
        self.added(name, id, fields);
        collections[name][id] = { count: 1, data: {}, mergedData: deepCopy(fields), children: {} };
        _.each(fields, function(val, key) {
          collections[name][id].data[key] = collections[name][id].data[key] || {};
          collections[name][id].data[key][index] = deepCopy(val);
        });
        updateChildren(name, id, relations[name]);
      } else {
        _.each(fields, function(val, key) {
          collections[name][id].data[key] = collections[name][id].data[key] || {};
          collections[name][id].data[key][index] = deepCopy(val);
        });
        collections[name][id].count++;
        updateFromData(name, id, fields);
        updateChildren(name, id, fields);
      }
    }
    var smartChanged = function(name, index, id, fields) {
      var data = collections[name][id].data;
      _.each(fields, function(val, key) {
        if (!data[key]) data[key] = {};
        if (val === undefined) {
          delete data[key][index];
        } else {
          data[key][index] = deepCopy(val);
        }
      });
      updateFromData(name, id, fields);
      updateChildren(name, id, fields);
    }
    var smartRemoved = function(name, index, id) {
      if (!name                 ) throw new Meteor.Error("Trying to remove element from anonymous collection");
      if (!collections[name]    ) throw new Meteor.Error("Removing element from non-existing collection '" + name + "'");
      if (!collections[name][id]) throw new Meteor.Error("Removing unexisting element '" + id + "' from collection '" + name + "'");

      if (!--collections[name][id].count) { // If reference counter was decremented to zero
        updateChildren(name, id, relations[name], true);
        delete collections[name][id];
        self.removed(name, id);
      } else {
        var fields = {};
        _.each(collections[name][id].data, function(vals, key) {
          if (index in vals) {
            fields[key] = 1;
            delete vals[index];
          }
        });
        updateFromData(name, id, fields);
        updateChildren(name, id, fields);
      }
    }

    self.addDependency = function(name, fields, callback) {
      if (!_.isArray(fields)) fields = [fields];
      relations[name] = relations[name] || {};
      dependencies[name] = dependencies[name] || [];
      fields.forEach(function(field) {
        relations[name][field] = relations[name][field] || [];
        relations[name][field].push(dependencies[name].length);
      });
      dependencies[name].push(callback);
    }

    var cursors = callback.apply(self, arguments);
    if (isCursor(cursors)) cursors = [cursors];

    if (!cursors) return;
    if (!_.isArray(cursors))
      throw new Meteor.Error("Publish function can only return a Cursor or an array of Cursors");

    for (var i = 0; i < cursors.length; i++)
      if (!isCursor(cursors[i]))
        throw new Meteor.Error("Publish function returned an array of non-Cursors");

    var observers = [];
    for (var i = 0; i < cursors.length; i++) {
      var c = cursors[i];

      if (!c._cursorDescription) throw new Meteor.Error("Unable to get cursor's collection name");

      function publishCursor(c, name, index) {
        var activeItems = {};
        return {
          observer: c.observeChanges({
            added:   function(id, fields) {
              activeItems[id] = 1;
              fields['_id'] = id;
              smartAdded  (name, index, id, fields);
            },
            changed: function(id, fields) {
              smartChanged(name, index, id, fields);
            },
            removed: function(id) {
              delete activeItems[id];
              smartRemoved(name, index, id);
            },
          }),
          activeItems: activeItems,
          name: name,
          index: index
        }
      };

      var name = c._cursorDescription.collectionName;
      if (!name) throw new Meteor.Error("Unable to get cursor's collection name");
      observers.push(publishCursor(c, name, i).observer);
    }
    this.ready();
    this.onStop(function() {
      _.forEach(observers, function(x) { x.stop(); });
    });
  });
}
<|endoftext|>


<commit_before>goog.provide('test.anim1');

goog.require('lime');
goog.require('lime.Button');
goog.require('lime.Circle');
goog.require('lime.CoverNode');
goog.require('lime.Director');
goog.require('lime.Label');

goog.require('lime.Layer');
goog.require('lime.Scene');
goog.require('lime.Sprite');
goog.require('lime.animation.Loop');
goog.require('lime.animation.MoveBy');
goog.require('lime.animation.RotateBy');
goog.require('lime.animation.ScaleBy');
goog.require('lime.animation.Sequence');
goog.require('lime.animation.Spawn');
goog.require('lime.animation.ColorTo');

test.WIDTH = 600;
test.HEIGHT = 400;

test.start = function() {

	//director
	test.director = new lime.Director(document.body, test.WIDTH, test.HEIGHT);
	test.director.makeMobileWebAppCapable();

	var menuscene = new lime.Scene;

	var layer = (new lime.Layer).setPosition(200, 200);
	menuscene.appendChild(layer);

	var sprite = new lime.Sprite().setFill(100,0,0).setSize(100, 100).setRenderer(lime.Renderer.CANVAS);
	layer.appendChild(sprite);

	var anim = new lime.animation.Sequence(new lime.animation.Spawn(
	        new lime.animation.MoveBy(400, 0).setDuration(3),
	        new lime.animation.ScaleBy(2),
            new lime.animation.ColorTo(0,100,0)

	    ),    new lime.animation.Spawn(
        	        new lime.animation.MoveBy(-200, 0).setDuration(1.5),
        	        new lime.animation.ScaleBy(.5),
                    new lime.animation.ColorTo(200,0,0)

        	    ));
	sprite.runAction(new lime.animation.Loop(anim).setLimit(5));

	var sprite = new lime.Sprite().setFill('#0c0').setSize(50, 50).setPosition(0, 100).setRenderer(lime.Renderer.CANVAS);
	layer.appendChild(sprite);

	var anim = new lime.animation.Spawn(
	    new lime.animation.RotateBy(-90).setDuration(3).enableOptimizations(),
	    new lime.animation.MoveBy(300, 0).setDuration(3).enableOptimizations()
    );
    var a2 = new lime.animation.Sequence(anim, anim.reverse());
    sprite.runAction(new lime.animation.Loop(a2).setLimit(5));

	// set active scene
	test.director.replaceScene(menuscene);

};

goog.exportSymbol('test.start', test.start);
<commit_msg>Update anim1.js<commit_after>goog.provide('test.anim1');

goog.require('lime');
goog.require('lime.Button');
goog.require('lime.Circle');
goog.require('lime.CoverNode');
goog.require('lime.Director');
goog.require('lime.Label');

goog.require('lime.Layer');
goog.require('lime.Scene');
goog.require('lime.Sprite');
goog.require('lime.animation.Loop');
goog.require('lime.animation.MoveBy');
goog.require('lime.animation.RotateBy');
goog.require('lime.animation.ScaleBy');
goog.require('lime.animation.Sequence');
goog.require('lime.animation.Spawn');
goog.require('lime.animation.ColorTo');

test.WIDTH = 600;
test.HEIGHT = 400;

test.start = function() {

	//director
	test.director = new lime.Director(document.body, test.WIDTH, test.HEIGHT);
	test.director.makeMobileWebAppCapable();

	var menuscene = new lime.Scene;

	var layer = (new lime.Layer).setPosition(200, 200);
	menuscene.appendChild(layer);

	var sprite = new lime.Sprite().setFill(100,0,0).setSize(100, 100).setRenderer(lime.Renderer.CANVAS);
	layer.appendChild(sprite);

	var anim = new lime.animation.Sequence(new lime.animation.Spawn(
	        new lime.animation.MoveBy(400, 0).setDuration(3),
	        new lime.animation.ScaleBy(2),
            new lime.animation.ColorTo(0,100,0)

	    ),    new lime.animation.Spawn(
        	        new lime.animation.MoveBy(-200, 0).setDuration(1.5),
        	        new lime.animation.ScaleBy(.5),
                    new lime.animation.ColorTo(200,0,0)

        	    ));
	sprite.runAction(new lime.animation.Loop(anim).setLimit(5));

	var sprite = new lime.Sprite().setFill('#0c0').setSize(50, 50).setPosition(0, 100).setRenderer(lime.Renderer.CANVAS);
	//layer.appendChild(sprite);

	var anim = new lime.animation.Spawn(
	    new lime.animation.RotateBy(-90).setDuration(3).enableOptimizations(),
	    new lime.animation.MoveBy(300, 0).setDuration(3).enableOptimizations()
    );
    var a2 = new lime.animation.Sequence(anim, anim.reverse());
    sprite.runAction(new lime.animation.Loop(a2).setLimit(5));

	// set active scene
	test.director.replaceScene(menuscene);

};

goog.exportSymbol('test.start', test.start);
<|endoftext|>


<commit_before>Package.describe({
  summary: "Meteor's latency-compensated distributed data server",
  version: '2.2.0',
  documentation: null
});

Npm.depends({
  "permessage-deflate": "0.1.6",
  sockjs: "0.3.19"
});

Package.onUse(function (api) {
  api.use(['check', 'random', 'ejson', 'underscore',
           'retry', 'mongo-id', 'diff-sequence', 'ecmascript'],
          'server');

  // common functionality
  api.use('ddp-common', 'server'); // heartbeat
  api.use('ddp-rate-limiter', 'server', {weak: true});
  // Transport
  api.use('ddp-client', 'server');
  api.imply('ddp-client');

  api.use(['webapp', 'routepolicy'], 'server');

  // Detect whether or not the user wants us to audit argument checks.
  api.use(['audit-argument-checks'], 'server', {weak: true});

  // Allow us to detect 'autopublish', so we can print a warning if the user
  // runs Meteor.publish while it's loaded.
  api.use('autopublish', 'server', {weak: true});

  // If the facts package is loaded, publish some statistics.
  api.use('facts-base', 'server', {weak: true});

  api.use('callback-hook', 'server');

  // we depend on LocalCollection._diffObjects, _applyChanges,
  // _idParse, _idStringify.
  api.use('minimongo', 'server');

  api.export('DDPServer', 'server');

  api.addFiles('stream_server.js', 'server');

  api.addFiles('livedata_server.js', 'server');
  api.addFiles('writefence.js', 'server');
  api.addFiles('crossbar.js', 'server');

  api.addFiles('server_convenience.js', 'server');
});

Package.onTest(function (api) {
  api.use('ecmascript', ['client', 'server']);
  api.use('livedata', ['client', 'server']);
  api.use('mongo', ['client', 'server']);
  api.use('test-helpers', ['client', 'server']);
  api.use(['underscore', 'tinytest', 'random', 'tracker', 'minimongo', 'reactive-var']);

  api.addFiles('livedata_server_tests.js', 'server');
  api.addFiles('session_view_tests.js', ['server']);
  api.addFiles('crossbar_tests.js', ['server']);
});
<commit_msg>Remove `minimongo` dependency from `ddp-server`<commit_after>Package.describe({
  summary: "Meteor's latency-compensated distributed data server",
  version: '2.2.0',
  documentation: null
});

Npm.depends({
  "permessage-deflate": "0.1.6",
  sockjs: "0.3.19"
});

Package.onUse(function (api) {
  api.use(['check', 'random', 'ejson', 'underscore',
           'retry', 'mongo-id', 'diff-sequence', 'ecmascript'],
          'server');

  // common functionality
  api.use('ddp-common', 'server'); // heartbeat
  api.use('ddp-rate-limiter', 'server', {weak: true});
  // Transport
  api.use('ddp-client', 'server');
  api.imply('ddp-client');

  api.use(['webapp', 'routepolicy'], 'server');

  // Detect whether or not the user wants us to audit argument checks.
  api.use(['audit-argument-checks'], 'server', {weak: true});

  // Allow us to detect 'autopublish', so we can print a warning if the user
  // runs Meteor.publish while it's loaded.
  api.use('autopublish', 'server', {weak: true});

  // If the facts package is loaded, publish some statistics.
  api.use('facts-base', 'server', {weak: true});

  api.use('callback-hook', 'server');
  api.export('DDPServer', 'server');

  api.addFiles('stream_server.js', 'server');

  api.addFiles('livedata_server.js', 'server');
  api.addFiles('writefence.js', 'server');
  api.addFiles('crossbar.js', 'server');

  api.addFiles('server_convenience.js', 'server');
});

Package.onTest(function (api) {
  api.use('ecmascript', ['client', 'server']);
  api.use('livedata', ['client', 'server']);
  api.use('mongo', ['client', 'server']);
  api.use('test-helpers', ['client', 'server']);
  api.use(['underscore', 'tinytest', 'random', 'tracker', 'minimongo', 'reactive-var']);

  api.addFiles('livedata_server_tests.js', 'server');
  api.addFiles('session_view_tests.js', ['server']);
  api.addFiles('crossbar_tests.js', ['server']);
});
<|endoftext|>


<commit_before>// ==UserScript==
// @name        Smart QR
// @namespace   http://tampermonkey.net/
// @description Detects phone numbers and locations and displays their value as a QR code on mouseover. Needs doubleclick somewhere on the page to get triggered.
// @copyright   2017, Georg Jähnig
// @include     http://*
// @include     https://*
// @version     0.1
// ==/UserScript==
//
// ==OpenUserJS==
// @author jorges
// ==/OpenUserJS==

(function () {

  "use strict";

  function addQR(value) {
    //console.log(value);
    if (value == '') {
      return;
    }
    img.src = 'https://chart.apis.google.com/chart?cht=qr&chs=100x100&chld=L|0&chl=' + encodeURIComponent(value);
    img.style.visibility = "visible";
  };

  function removeQR() {
    img.style.visibility = "hidden";
  };

  function addListeners(element, value) {
    element.addEventListener('mouseover', function() { addQR(value); } );
    element.addEventListener('mouseout', function() { removeQR(); });
  }

  function handleTextSelect(event) {
    var selection = document.getSelection();
    var text = selection.toString();
    if (text == '') {
      removeQR();
    }
    // Geo coordinates.
    // Match selections like "12.34 , 56.789".
    var re = new RegExp('^\\s*([0-9]\+\.[0-9]\+)\\s*(,\|;)\\s*([0-9]\+\.[0-9]\+)\\s*$');
    var matches = text.match(re);
    if (matches) {
      var value = 'geo:' + matches[1] + ',' + matches[3];
      addQR(value);
      return;
    }
    // Phone number.
    var re = new RegExp('^[^a-zA-Z]*$');
    var matches = text.match(re);
    if (matches) {
      var number = matches[0].replace(/[^0-9\+]/g, '');
      if (number == '') {
        return;
      }
      number = 'tel:' + number;
      addQR(number);
      return;
    }
  }

  function parseAndAddListeners() {
    var elements = document.getElementsByTagName('a');
    for(var i=0, len=elements.length; i < len; i++){
      var element = elements[i];
      if (element.href) {
        // elements with href="tel:..."
        var re = new RegExp('^tel:(.*)$');
        var matches = element.href.match(re);
        if (matches) {
          addListeners(element, element.href);
        }
        // elements with href="maps.google.com/?.*q=12,34"
        var re = new RegExp('maps.google.com.*q=([0-9\.]*),([0-9\.]*)');
        var matches = element.href.match(re);
        if (matches) {
          var value = 'geo:' + matches[1] + ',' + matches[2];
          addListeners(element, value);
        }
        // elements with href="@12.34,56.78"
        var re = new RegExp('google.*@([0-9]\+\.[0-9]\+),([0-9]\+\.[0-9]\+)');
        var matches = element.href.match(re);
        if (matches) {
          var value = 'geo:' + matches[1] + ',' + matches[2];
          addListeners(element, value);
        }
        // Wikipedia location elements.
        if (currentURL.hostname.match(/wikipedia\.org/)) {
          var re = new RegExp('tools.wmflabs.org/geohack/geohack\.php.*params=([0-9\.]*)_._([0-9\.]*)');
          var matches = element.href.match(re);
          if (matches) {
            var value = 'geo:' + matches[1] + ',' + matches[2];
            addListeners(element, value);
          }
        }
        // Openstreetmap coordinate link.
        if (currentURL.hostname.match(/openstreetmap\.org/)) {
          var re = new RegExp('/#map=[0-9]+/([0-9\.]+)/([0-9\.]+)');
          var matches = element.href.match(re);
          if (matches) {
            var value = 'geo:' + matches[1] + ',' + matches[2];
            addListeners(element, value);
          }
        }
        // Any "geo:" link.
        var re = new RegExp('geo:([0-9\.]+),([0-9\.]+)');
        var matches = element.href.match(re);
        if (matches) {
          var value = 'geo:' + matches[1] + ',' + matches[2];
          addListeners(element, value);
        }
      }
      // elements with data-number.
      if (element.dataset) {
        if (element.dataset.number) {
          var value = 'tel:' + element.dataset.number;
          addListeners(element, value);
        }
      }
    }
    // Facebook events, location.
    if (currentURL.hostname.match(/facebook\.com/)) {
      var elements = document.getElementsByTagName('img');
      for(var i=0, len=elements.length; i < len; i++){
        var element = elements[i];
        if (element.src) {
          var re = new RegExp('markers=([0-9\.]+)%2C([0-9\.]+)');
          var matches = element.src.match(re);
          if (matches) {
            var value = 'geo:' + matches[1] + ',' + matches[2];
            addListeners(element, value);
          }
        }
      }
    }
    // Google maps, info sidebar, phone numbers
    if (currentURL.hostname.match(/google/)) {
      var elements = document.getElementsByTagName('button');
      for(var i=0, len=elements.length; i < len; i++){
        var element = elements[i];
        if (element.dataset) {
          if (element.dataset.href) {
            addListeners(element, element.dataset.href);
          }
        }
      }
    }
    // Text selections.
    document.addEventListener('mouseup', handleTextSelect);
  }

  function manualTriggerWithDblClick() {
    document.body.appendChild(img);
    window.addEventListener('dblclick', parseAndAddListeners, true);
  }

  function parseURL(url) {
    var parser = document.createElement('a');
    parser.href = url;
    return parser;
  }

  var currentURL = parseURL(window.location.href);

  // Create code and add to body.
  var img = document.createElement("img");
  img.style.width = "100px";
  img.style.height = "100px";
  img.style.position = "fixed";
  img.style.left = "10px";
  img.style.bottom = "30px";
  img.style.zIndex = "999";
  img.style.visibility = "hidden";
  img.alt = "QR Code";

  img.addEventListener('mouseover', removeQR, true);

  manualTriggerWithDblClick();

}());

<commit_msg>Don't remove on mouseout.<commit_after>// ==UserScript==
// @name        Smart QR
// @namespace   http://tampermonkey.net/
// @description Detects phone numbers and locations and displays their value as a QR code on mouseover. Needs doubleclick somewhere on the page to get triggered.
// @copyright   2017, Georg Jähnig
// @include     http://*
// @include     https://*
// @version     0.1
// ==/UserScript==
//
// ==OpenUserJS==
// @author jorges
// ==/OpenUserJS==

(function () {

  "use strict";

  function addQR(value) {
    //console.log(value);
    if (value == '') {
      return;
    }
    img.src = 'https://chart.apis.google.com/chart?cht=qr&chs=100x100&chld=L|0&chl=' + encodeURIComponent(value);
    img.style.visibility = "visible";
  };

  function removeQR() {
    img.style.visibility = "hidden";
  };

  function addListeners(element, value) {
    element.addEventListener('mouseover', function() { addQR(value); } );
    //element.addEventListener('mouseout', function() { removeQR(); });
  }

  function handleTextSelect(event) {
    var selection = document.getSelection();
    var text = selection.toString();
    if (text == '') {
      removeQR();
    }
    // Geo coordinates.
    // Match selections like "12.34 , 56.789".
    var re = new RegExp('^\\s*([0-9]\+\.[0-9]\+)\\s*(,\|;)\\s*([0-9]\+\.[0-9]\+)\\s*$');
    var matches = text.match(re);
    if (matches) {
      var value = 'geo:' + matches[1] + ',' + matches[3];
      addQR(value);
      return;
    }
    // Phone number.
    var re = new RegExp('^[^a-zA-Z]*$');
    var matches = text.match(re);
    if (matches) {
      var number = matches[0].replace(/[^0-9\+]/g, '');
      if (number == '') {
        return;
      }
      number = 'tel:' + number;
      addQR(number);
      return;
    }
  }

  function parseAndAddListeners() {
    var elements = document.getElementsByTagName('a');
    for(var i=0, len=elements.length; i < len; i++){
      var element = elements[i];
      if (element.href) {
        // elements with href="tel:..."
        var re = new RegExp('^tel:(.*)$');
        var matches = element.href.match(re);
        if (matches) {
          addListeners(element, element.href);
        }
        // elements with href="maps.google.com/?.*q=12,34"
        var re = new RegExp('maps.google.com.*q=([0-9\.]*),([0-9\.]*)');
        var matches = element.href.match(re);
        if (matches) {
          var value = 'geo:' + matches[1] + ',' + matches[2];
          addListeners(element, value);
        }
        // elements with href="@12.34,56.78"
        var re = new RegExp('google.*@([0-9]\+\.[0-9]\+),([0-9]\+\.[0-9]\+)');
        var matches = element.href.match(re);
        if (matches) {
          var value = 'geo:' + matches[1] + ',' + matches[2];
          addListeners(element, value);
        }
        // Wikipedia location elements.
        if (currentURL.hostname.match(/wikipedia\.org/)) {
          var re = new RegExp('tools.wmflabs.org/geohack/geohack\.php.*params=([0-9\.]*)_._([0-9\.]*)');
          var matches = element.href.match(re);
          if (matches) {
            var value = 'geo:' + matches[1] + ',' + matches[2];
            addListeners(element, value);
          }
        }
        // Openstreetmap coordinate link.
        if (currentURL.hostname.match(/openstreetmap\.org/)) {
          var re = new RegExp('/#map=[0-9]+/([0-9\.]+)/([0-9\.]+)');
          var matches = element.href.match(re);
          if (matches) {
            var value = 'geo:' + matches[1] + ',' + matches[2];
            addListeners(element, value);
          }
        }
        // Any "geo:" link.
        var re = new RegExp('geo:([0-9\.]+),([0-9\.]+)');
        var matches = element.href.match(re);
        if (matches) {
          var value = 'geo:' + matches[1] + ',' + matches[2];
          addListeners(element, value);
        }
      }
      // elements with data-number.
      if (element.dataset) {
        if (element.dataset.number) {
          var value = 'tel:' + element.dataset.number;
          addListeners(element, value);
        }
      }
    }
    // Facebook events, location.
    if (currentURL.hostname.match(/facebook\.com/)) {
      var elements = document.getElementsByTagName('img');
      for(var i=0, len=elements.length; i < len; i++){
        var element = elements[i];
        if (element.src) {
          var re = new RegExp('markers=([0-9\.]+)%2C([0-9\.]+)');
          var matches = element.src.match(re);
          if (matches) {
            var value = 'geo:' + matches[1] + ',' + matches[2];
            addListeners(element, value);
          }
        }
      }
    }
    // Google maps, info sidebar, phone numbers
    if (currentURL.hostname.match(/google/)) {
      var elements = document.getElementsByTagName('button');
      for(var i=0, len=elements.length; i < len; i++){
        var element = elements[i];
        if (element.dataset) {
          if (element.dataset.href) {
            addListeners(element, element.dataset.href);
          }
        }
      }
    }
    // Text selections.
    document.addEventListener('mouseup', handleTextSelect);
  }

  function manualTriggerWithDblClick() {
    document.body.appendChild(img);
    window.addEventListener('dblclick', parseAndAddListeners, true);
  }

  function parseURL(url) {
    var parser = document.createElement('a');
    parser.href = url;
    return parser;
  }

  var currentURL = parseURL(window.location.href);

  // Create code and add to body.
  var img = document.createElement("img");
  img.style.width = "100px";
  img.style.height = "100px";
  img.style.position = "fixed";
  img.style.left = "10px";
  img.style.bottom = "30px";
  img.style.zIndex = "999";
  img.style.visibility = "hidden";
  img.alt = "QR Code";

  img.addEventListener('mouseover', removeQR, true);

  manualTriggerWithDblClick();

}());

<|endoftext|>


<commit_before>const fs = require('fs')
const request = require('request')
const FileCookieStore = require('tough-cookie-filestore')
const logger = require('log4js').getLogger()
const Promise = require('bluebird')

const handler = require('./handler')

const { promisify, parseForm, decodeURIForm, encodeURIForm } = handler

/**
 * Request Constructor
 * @param {string} cookiePath cookieJar file path. If undefined, the request won't take any cookie.
 * @param {object} config request config.
 */
function Request(cookiePath, config) {
  const defaultConfig = {
    headers: {
      'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
    },
    gzip: true,
    timeout: 20000,
  }

  const appendConfig = config || {}

  if (cookiePath) {
    const jar = request.jar(new FileCookieStore(cookiePath))
    appendConfig.jar = jar
  }

  this.request = request.defaults(Object.assign(appendConfig, defaultConfig))
  // avoid redirct cycle
  this.maxRedirects = 10
  this.redirects = 0
}

/**
 * Request server with GET method.
 * @param {string} url Request URL.
 * @param {object} params QueryString dictionary object. Axer will automaticlly encode all params value for request.
 * @return {Object} Axer will combine request object and response object and return to developer.
 */
Request.prototype.get = async function(url, params) {
  let _url = url
  if (typeof params === 'object') {
    const qs = encodeURIForm(params)
    _url = `${_url}?${qs}`
  }

  logger.info('GET', _url)
  const res = await promisify(this.request, _url)
  const response = await this.followRedirect(res)
  return response
}

/**
 * Request server with POST method.
 * @param {string} url Request URL.
 * @param {object} form post form. Axer will convert this object to x-www-form-urlencoded formart string.
 * @return {Object} Axer will combine request object and response object and return to developer.
 */
Request.prototype.post = async function(url, form) {
  if (typeof form === 'object') {
    form = decodeURIForm(form)
  }

  if (typeof form === 'string') {
    form = parseForm(form)
  }

  logger.info('POST ', url)
  logger.info('Body:', form)
  const res = await promisify(this.request.post, { url, form })
  const response = await this.followRedirect(res)
  return response
}

/**
 * Download file from server.
 * @param {string} url download url.
 * @param {string} filePath the file's save path.
 * @return {promise} return promise object for conveniently use aync/await.
 */
Request.prototype.download = function(url, filePath) {
  return new Promise((resolve, reject) => {
    this.request.get(url)
      .on('response', res => {
        logger.info(`Status: ${res.statusCode}`)
        logger.info(`Content-Type: ${res.headers['content-type']}`)
        logger.info(`Content-Length: ${res.headers['content-length']}`)
      })
      .on('end', () => {
        logger.info(`Download success`)
        resolve(url)
      })
      .on('error', err => {
        logger.error(`Download failed: ${err}`)
        reject(err)
      })
      .pipe(fs.createWriteStream(filePath))
  })
}

/**
 * Upload file to server.
 * @param {string} url download url.
 * @param {string} formData the request formData.
 * @return {promise} return promise object for conveniently use aync/await.
 */
Request.prototype.upload = function(url, formData) {
  logger.info('POST FormData', url)
  logger.info('Body:', formData)
  const response = promisify(this.request.post, { url, formData })
  return response
}

/**
 * Creae a binary stream pipe.
 * @param {string} url download url.
 * @return {promise} return promise object for conveniently use aync/await.
 */
Request.prototype.pipe = function (url) {
  return new Promise((resolve, reject) => {
    const res = this.request.get(url)
      .on('response', res => {
        logger.info(`Status: ${res.statusCode}`)
        logger.info(`Content-Type: ${res.headers['content-type']}`)
        logger.info(`Content-Length: ${res.headers['content-length']}`)
      })
      .on('end', () => {
        logger.info(`Download success`)
        resolve(url)
      })
      .on('error', err => {
        logger.error(`Download failed: ${err}`)
        reject(err)
      })

    resolve(res)
  })
}

Request.prototype.followRedirect = async function (response) {
  if (response.statusCode >= 300 && response.statusCode < 400) {
    if (this.redirects >= this.maxRedirects) {
      throw new Error('Too many redircts, the default max redircts is:' + this.maxRedirects)
    } else {
      this.redirects++
      const url = response.headers.location
      logger.info('Auto Follow:', url)
      const res = await promisify(this.request, url)
      return await this.followRedirect(res)
    }
  } else {
    this.redirects = 0
    return response
  }
}

module.exports = Request
<commit_msg>bug fixed<commit_after>const fs = require('fs')
const request = require('request')
const FileCookieStore = require('tough-cookie-filestore-bugfixed')
const logger = require('log4js').getLogger()
const Promise = require('bluebird')

const handler = require('./handler')

const { promisify, parseForm, decodeURIForm, encodeURIForm } = handler

/**
 * Request Constructor
 * @param {string} cookiePath cookieJar file path. If undefined, the request won't take any cookie.
 * @param {object} config request config.
 */
function Request(cookiePath, config) {
  const defaultConfig = {
    headers: {
      'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
    },
    gzip: true,
    timeout: 20000,
  }

  const appendConfig = config || {}

  if (cookiePath) {
    const jar = request.jar(new FileCookieStore(cookiePath))
    appendConfig.jar = jar
  }

  this.request = request.defaults(Object.assign(appendConfig, defaultConfig))
  // avoid redirct cycle
  this.maxRedirects = 10
  this.redirects = 0
}

/**
 * Request server with GET method.
 * @param {string} url Request URL.
 * @param {object} params QueryString dictionary object. Axer will automaticlly encode all params value for request.
 * @return {Object} Axer will combine request object and response object and return to developer.
 */
Request.prototype.get = async function(url, params) {
  let _url = url
  if (typeof params === 'object') {
    const qs = encodeURIForm(params)
    _url = `${_url}?${qs}`
  }

  logger.info('GET', _url)
  const res = await promisify(this.request, _url)
  const response = await this.followRedirect(res)
  return response
}

/**
 * Request server with POST method.
 * @param {string} url Request URL.
 * @param {object} form post form. Axer will convert this object to x-www-form-urlencoded formart string.
 * @return {Object} Axer will combine request object and response object and return to developer.
 */
Request.prototype.post = async function(url, form) {
  if (typeof form === 'object') {
    form = decodeURIForm(form)
  }

  if (typeof form === 'string') {
    form = parseForm(form)
  }

  logger.info('POST ', url)
  logger.info('Body:', form)
  const res = await promisify(this.request.post, { url, form })
  const response = await this.followRedirect(res)
  return response
}

/**
 * Download file from server.
 * @param {string} url download url.
 * @param {string} filePath the file's save path.
 * @return {promise} return promise object for conveniently use aync/await.
 */
Request.prototype.download = function(url, filePath) {
  return new Promise((resolve, reject) => {
    this.request.get(url)
      .on('response', res => {
        logger.info(`Status: ${res.statusCode}`)
        logger.info(`Content-Type: ${res.headers['content-type']}`)
        logger.info(`Content-Length: ${res.headers['content-length']}`)
      })
      .on('end', () => {
        logger.info(`Download success`)
        resolve(url)
      })
      .on('error', err => {
        logger.error(`Download failed: ${err}`)
        reject(err)
      })
      .pipe(fs.createWriteStream(filePath))
  })
}

/**
 * Upload file to server.
 * @param {string} url download url.
 * @param {string} formData the request formData.
 * @return {promise} return promise object for conveniently use aync/await.
 */
Request.prototype.upload = function(url, formData) {
  logger.info('POST FormData', url)
  logger.info('Body:', formData)
  const response = promisify(this.request.post, { url, formData })
  return response
}

/**
 * Creae a binary stream pipe.
 * @param {string} url download url.
 * @return {promise} return promise object for conveniently use aync/await.
 */
Request.prototype.pipe = function (url) {
  return new Promise((resolve, reject) => {
    const res = this.request.get(url)
      .on('response', res => {
        logger.info(`Status: ${res.statusCode}`)
        logger.info(`Content-Type: ${res.headers['content-type']}`)
        logger.info(`Content-Length: ${res.headers['content-length']}`)
      })
      .on('end', () => {
        logger.info(`Download success`)
        resolve(url)
      })
      .on('error', err => {
        logger.error(`Download failed: ${err}`)
        reject(err)
      })

    resolve(res)
  })
}

Request.prototype.followRedirect = async function (response) {
  if (response.statusCode >= 300 && response.statusCode < 400) {
    if (this.redirects >= this.maxRedirects) {
      throw new Error('Too many redircts, the default max redircts is:' + this.maxRedirects)
    } else {
      this.redirects++
      const url = response.headers.location
      logger.info('Auto Follow:', url)
      const res = await promisify(this.request, url)
      return await this.followRedirect(res)
    }
  } else {
    this.redirects = 0
    return response
  }
}

module.exports = Request
<|endoftext|>


<commit_before>var PLUGIN_INFO =
<KeySnailPlugin>
    <name>Navigate Relations</name>
    <description>Easily move via next/prev tags/links</description>
    <version>0.1</version>
    <updateURL>http://github.com/kidd/keysnail-navigate-relations/raw/master/navigate-relations.ks.js</updateURL>
    <author mail="raimonster@gmail.com" homepage="https://puntoblogspot.blogspot.com/">Raimon Grau</author>
    <license>The MIT License</license>
    <minVersion>1.0</minVersion>
    <include>main</include>
    <provides>
    <ext>navi-next</ext>
    <ext>navi-prev</ext>
    <ext>navi-up</ext>
    </provides>
    <detail><![CDATA[
=== Usage ===
            Use \]\] to go to logical 'next' page, and \[\[ to the 'previous' one.
            '^' moves upper in the url structure

    ]]></detail>
</KeySnailPlugin>;

function matching_text(aTags, searchText){
    var found;
    for (var i = 0; i < aTags.length; i++) {
        if (aTags[i].textContent == searchText) {
            found = aTags[i];
            return found;
        }
    }
}

function navi_dir(words){
    var aTags = window.content.document.getElementsByTagName("a");
    var found;
    for (var i in words){
        found = matching_text(aTags, words[i]);
        if (found) { found.click(); return found}
    }
}

function rel_dir(dir){
    function all(tag){
        return window.content.document.getElementsByTagName(tag)
    }
    function rel(elems, dir){
        for (var i in elems) {
            if((new RegExp("^"+dir, 'i')).test(elems[i].rel)) {
                window.content.document.location = elems[i].href;
                return true;
            }
        }
    }
    return rel(all('link'), dir) || rel(all('a'), dir)
}

function navi_prev(){
    rel_dir('prev') || navi_dir(['prev','<']);
}

function navi_next(){
    rel_dir('next') || navi_dir(['next', '>']);
}

function navi_up(){
    var url = window.content.document.location.href.toString();
    rel_dir('up') || (window.content.document.location = url.replace(/[^/]*\/?$/,''))
}

var navi_next_doc =   'Navigates to next page';
var navi_prev_doc =   'Navigates to previous page';
var navi_up_doc =   'Navigates to upper in the url structure';

ext.add("navi-next", navi_next , M({en: navi_next_doc}));
ext.add("navi-prev", navi_prev , M({en: navi_prev_doc}));
ext.add("navi-up", navi_up , M({en: navi_up_doc}));

key.setViewKey(["]", "]"], function (ev) {
    navi_next();
}, navi_next_doc, true);

key.setViewKey(["[", "["], function (ev) {
    navi_prev();
},  navi_prev_doc, true);

key.setViewKey(["^"], function (ev) {
    navi_up();
}, navi_up_doc, true);
<commit_msg>Add 'previous' to prev keywords<commit_after>var PLUGIN_INFO =
<KeySnailPlugin>
    <name>Navigate Relations</name>
    <description>Easily move via next/prev tags/links</description>
    <version>0.1</version>
    <updateURL>http://github.com/kidd/keysnail-navigate-relations/raw/master/navigate-relations.ks.js</updateURL>
    <author mail="raimonster@gmail.com" homepage="https://puntoblogspot.blogspot.com/">Raimon Grau</author>
    <license>The MIT License</license>
    <minVersion>1.0</minVersion>
    <include>main</include>
    <provides>
    <ext>navi-next</ext>
    <ext>navi-prev</ext>
    <ext>navi-up</ext>
    </provides>
    <detail><![CDATA[
=== Usage ===
            Use \]\] to go to logical 'next' page, and \[\[ to the 'previous' one.
            '^' moves upper in the url structure

    ]]></detail>
</KeySnailPlugin>;

function matching_text(aTags, searchText){
    var found;
    for (var i = 0; i < aTags.length; i++) {
        if (aTags[i].textContent == searchText) {
            found = aTags[i];
            return found;
        }
    }
}

function navi_dir(words){
    var aTags = window.content.document.getElementsByTagName("a");
    var found;
    for (var i in words){
        found = matching_text(aTags, words[i]);
        if (found) { found.click(); return found}
    }
}

function rel_dir(dir){
    function all(tag){
        return window.content.document.getElementsByTagName(tag)
    }
    function rel(elems, dir){
        for (var i in elems) {
            if((new RegExp("^"+dir, 'i')).test(elems[i].rel)) {
                window.content.document.location = elems[i].href;
                return true;
            }
        }
    }
    return rel(all('link'), dir) || rel(all('a'), dir)
}

function navi_prev(){
    rel_dir('prev') || navi_dir(['prev', 'previous', '<']);
}

function navi_next(){
    rel_dir('next') || navi_dir(['next', '>']);
}

function navi_up(){
    var url = window.content.document.location.href.toString();
    rel_dir('up') || (window.content.document.location = url.replace(/[^/]*\/?$/,''))
}

var navi_next_doc =   'Navigates to next page';
var navi_prev_doc =   'Navigates to previous page';
var navi_up_doc =   'Navigates to upper in the url structure';

ext.add("navi-next", navi_next , M({en: navi_next_doc}));
ext.add("navi-prev", navi_prev , M({en: navi_prev_doc}));
ext.add("navi-up", navi_up , M({en: navi_up_doc}));

key.setViewKey(["]", "]"], function (ev) {
    navi_next();
}, navi_next_doc, true);

key.setViewKey(["[", "["], function (ev) {
    navi_prev();
},  navi_prev_doc, true);

key.setViewKey(["^"], function (ev) {
    navi_up();
}, navi_up_doc, true);
<|endoftext|>


<commit_before>String.prototype.linkify = function()
{
    var str = this.toString();

    str = str.replace(/(https?:\/\/[^\s]+)/gim, '$1', str);
    str = str.replace(/([#|@][^\s]+)/gim, '$1', str);

    return str;
}

$(function()
{
    function getBlogFeed()
    {
        $.getJSON('https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://feeds.feedburner.com/ahmednuaman&callback=?', function(data)
        {
            var entries = data.responseData.feed.entries;
            var ul = $('#blog-feed').find('ul').empty();
            var entry;

            for (var i = 0; i < entries.length; i++)
            {
                entry = entries[i];

                ul.append('
' + entry.title + '
');
            }
        });
    }

    function getTweets()
    {
        $.getJSON('https://api.twitter.com/1/statuses/user_timeline.json?screen_name=ahmednuaman&count=5&exclude_replies=true&callback=?', function(data)
        {
            var ul = $('#twitter-feed').find('ul').empty();
            var tweet;

            for (var i = 0; i < data.length; i++)
            {
                tweet = data[i];

                ul.append('
' + tweet.text.linkify() + '
');
            }
        });
    }

    getBlogFeed();
    getTweets();
});<commit_msg>added github feed<commit_after>$(function()
{
    String.prototype.linkify = function()
    {
        var str = this.toString();

        str = str.replace(/(https?:\/\/[^\s]+)/gim, '$1', str);
        str = str.replace(/([#|@][^\s]+)/gim, '$1', str);

        return str;
    }

    var GitEntry = function(data)
    {
        var str = '';

        switch (data.type)
        {
            case 'CreateEvent':
            case 'DeleteEvent':
            case 'ForkEvent':
            case 'WatchEvent':
                var action = data.type.replace('Event', '');

                if (action.length < 6)
                {
                    action += 'e';
                }

                str = action + 'd ';

            break;

            case 'GistEvent':
                str = data.payload.action + 'd a gist called \'' + data.payload.desc + '\'';

            break;

            case 'PullRequestEvent':
                str = 'Added a pull request for '

            break;

            case 'PushEvent':
                str = 'Pushed to ';

            break;
        }

        if (data['repository'])
        {
            str += '' + data.repository.owner + '\
                /\
                ' + data.repository.name + ' repo';
        }

        return {
            toString: function()
            {
                return str;
            }
        };
    }

    function getBlogFeed()
    {
        $.getJSON('https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=http://feeds.feedburner.com/ahmednuaman&callback=?', function(data)
        {
            var entries = data.responseData.feed.entries;
            var ul = $('#blog-feed').find('ul').empty();
            var entry;

            for (var i = 0; i < entries.length; i++)
            {
                entry = entries[i];

                ul.append('
' + entry.title + '
');
            }
        });
    }

    function getGithubFeed()
    {
        $.getJSON('https://github.com/ahmednuaman.json?callback=?', function(data)
        {
            var ul = $('#github-feed').find('ul').empty();
            var entry;

            for (var i = 0; i < 5; i++)
            {
                entry = new GitEntry(data[i]);

                ul.append('
' + entry.toString() + '
');
            }
        });
    }

    function getTweets()
    {
        $.getJSON('https://api.twitter.com/1/statuses/user_timeline.json?screen_name=ahmednuaman&count=10&exclude_replies=true&callback=?', function(data)
        {
            var ul = $('#twitter-feed').find('ul').empty();
            var tweet;

            for (var i = 0; i < 5; i++)
            {
                tweet = data[i];

                ul.append('
' + tweet.text.linkify() + '
');
            }
        });
    }

    getBlogFeed();
    getGithubFeed();
    getTweets();
});<|endoftext|>


<commit_before>
// global variable
var servers = {
    proxy: "http://ipolcore.ipol.im/:9003/",
};
<commit_msg>[static/clientApp/ipol.servers.js] Changed to prod address<commit_after>
// global variable
var servers = {
    proxy: "http://ipolcore.ipol.im/:9003/"
};
<|endoftext|>


<commit_before>import hashsum from 'hash-sum'
import ee from 'event-emitter'
import React from 'react'
import raf from 'raf'
import ReactDOM from 'react-dom'
import clone from 'clone'
import Bluebird, { Promise } from 'bluebird'

import 'reapp-object-assign'
import './shim/root'
import './shim/flintMap'
import './shim/on'
import './shim/partial'
import './lib/bluebirdErrorHandle'
import createComponent from './createComponent'
import range from './lib/range'
import iff from './lib/iff'
import router from './lib/router'
import assignToGlobal from './lib/assignToGlobal'
import safeRun from './lib/safeRun'
import reportError from './lib/reportError'
import arrayDiff from './lib/arrayDiff'
import createElement from './tag/createElement'
import ErrorDefinedTwice from './views/ErrorDefinedTwice'
import NotFound from './views/NotFound'
import Main from './views/Main'

/*

  Welcome to Flint!

    This file deals mostly with setting up Flint,
    loading views and files, rendering,
    and exposing the public Flint functions

*/

Promise.longStackTraces()

// GLOBALS
root._history = history // for imported modules to use
root._bluebird = Bluebird // for imported modules to use
root.Promise = Promise // for modules to use
root.ReactDOM = ReactDOM
root.on = on
root.module = {}
root.fetch.json = (...args) => fetch(...args).then(res => res.json())

const uuid = () => Math.floor(Math.random() * 1000000)

export default function run(browserNode, userOpts, afterRenderCb) {
  const opts = Object.assign({
    namespace: {},
    entry: 'Main'
  }, userOpts)

  const isDevTools = opts.app == 'devTools'

  // error handling
  const flintOnError = (...args) => {
    reportError(...args)

    // restore last working views
    Object.keys(Flint.views).forEach(name => {
      Flint.views[name] = Internal.lastWorkingViews[name]
    })
  }

  root.onerror = flintOnError

  const Internal = root._Flint = {
    isRendering: 0,
    firstRender: true,

    viewCache: {}, // map of views in various files
    viewsInFile: {}, // current build up of running hot insertion
    currentFileViews: null, // tracks views as file loads, for hot reloading
    currentHotFile: null, // current file that is running
    getCache: {}, // stores { path: { name: val } } for use in view.get()
    getCacheInit: {}, // stores the vars after a view is first run
    propsHashes: {},

    changedViews: [],
    mountedViews: {},
    lastWorkingViews: {},
    lastWorkingRenders: {},
    preloaders: [], // async functions needed before loading app

    // devtools
    inspector: {},
    viewsAtPath: {},

    setCache(path, name, val) {
      Internal.getCache[path][name] = val
      // when devtools inspecting
      setInspector(path)
    }
  }

  function pathToName(path) {
    let p = path.split(',')
    return p[p.length - 1].split('.')[0]
  }

  // devtools edit
  function writeBack(path, writePath) {
    // update getCache
    writePath.reduce((acc, key) => {
      if (key == 'root') return acc
      if (Array.isArray(key))
        acc[key[0]] = key[1] // final index is arr: [key, val]
      else
        return acc[key]
    }, Internal.getCache[path])

    // update view
    const name = pathToName(path)
    Flint.render()
  }

  function setInspector(path) {
    if (Internal.inspector.path && Internal.inspector.path == path) {
      const name = pathToName(path)
      let props = Internal.viewsAtPath[path].props
      const state = Internal.getCache[path]
      Internal.inspector.cb(name, props, state, writeBack)
    }
  }

  const emitter = ee({})

  let Flint = {
    router,
    range,
    iff,

    views: {},
    removeView(key) { delete Flint.views[key] },

    render() {
      if (Internal.preloaders.length)
        Promise.all(Internal.preloaders.map(loader => loader())).then(run)
      else
        run()

      function run() {
        Internal.isRendering++
        log(`render(), Internal.isRendering(${Internal.isRendering})`)
        if (Internal.isRendering > 3) return

        const MainComponent = (
            Flint.views.Main.component || Internal.lastWorkingViews.Main.component
        )

        if (!browserNode) {
          Flint.renderedToString = React.renderToString(<MainComponent />)
          afterRenderCb && afterRenderCb(Flint.renderedToString)
        }
        else {
          if (window.__isDevingDevTools)
            browserNode = '_flintdevtools'

          ReactDOM.render(<MainComponent />, document.getElementById(browserNode))
        }

        // computing internal paths is expensive,
        // lets compute them after first render,
        if (Internal.firstRender && !isDevTools)
          setTimeout(Flint.render, 5)

        Internal.firstRender = false
        emitter.emit('afterRender')
        Internal.isRendering = 0
      }
    },

    // internal events
    on(name, cb) { emitter.on(name, cb) },

    // for use in jsx
    debug: () => { debugger },

    // load a file
    file(file, run) {
      if (!process.env.production) {
        Internal.viewsInFile[file] = []
        Internal.changedViews = []
        Internal.currentHotFile = file
      }

      // capture exports
      let fileExports = {}

      // run file
      run(fileExports)

      Flint.setExports(fileExports)

      if (!process.env.production) {
        const cached = Internal.viewCache[file] || []
        const _views = Internal.viewsInFile[file]

        // remove Internal.viewsInFile that werent made
        const removed = arrayDiff(cached, _views)
        removed.map(Flint.removeView)

        Internal.currentHotFile = null
        Internal.viewCache[file] = Internal.viewsInFile[file]

        if (Internal.firstRender)
          return

        raf(() => {
          Internal.changedViews.forEach(name => {
            Internal.mountedViews[name] = Internal.mountedViews[name].map(view => {
              if (view.isMounted()) {
                view.forceUpdate()
                return view
              }
            }).filter(x => !!x)
          })
        })
      }
    },

    view(name, body) {
      const comp = createComponent.partial(Flint, Internal, name, body)

      function setView(name, component) {
        Flint.views[name] = { hash, component }
      }

      if (process.env.production)
        setView(name, comp())

      const hash = hashsum(body)

      // if new
      if (!Flint.views[name]) {
        setView(name, comp({ hash, changed: true }))
        Internal.changedViews.push(name)
        return
      }

      // hot reloaded
      if (!process.env.production) {
        if (!Internal.mountedViews[name])
          Internal.mountedViews[name] = []

        Internal.viewsInFile[Internal.currentHotFile].push(name)

        // not new
        // if defined twice during first run
        if (Internal.firstRender) {
          Flint.views[name] = ErrorDefinedTwice(name)
          throw new Error(`Defined a view twice: ${name}`)
        }

        // if unchanged
        if (Flint.views[name].hash == hash) {
          setView(name, comp({ hash, unchanged: true }))
          return
        }

        // changed
        setView(name, comp({ hash, changed: true }))
        Internal.changedViews.push(name)

        // this resets tool errors
        window.onViewLoaded()
      }
    },

    deleteFile(name) {
      const weirdName = `/${name}`
      Internal.viewsInFile[weirdName].map(Flint.removeView)
      delete Internal.viewsInFile[weirdName]
      delete Internal.viewCache[weirdName]
      Flint.render()
    },

    getView(name, parentName) {
      let result

      // View.SubView
      const subName = `${parentName}.${name}`
      if (Flint.views[subName]) {
        result = Flint.views[subName].component
      }
      // regular view
      else if (Flint.views[name]) {
        result = Flint.views[name].component
      }
      else {
        result = NotFound(name)
      }

      return result
    },

    routeMatch(path) {
      router.add(path)
      return router.isActive(path)
    },

    routeParams(path) {
      return router.params(path)
    },

    // export globals
    setExports(_exports) {
      if (!_exports) return
      Object.freeze(_exports)
      const names = Object.keys(_exports)

      if (names.length) {
        names.forEach(name => {
          if (name === 'default') {
            Object.keys(_exports.default).forEach(key => {
              assignToGlobal(key, _exports.default[key])
            })
          }

          assignToGlobal(name, _exports[name])
        })
      }
    },

    inspect(path, cb) {
      Internal.inspector = { path, cb }
      setInspector(path)
    }
  };

  router.init(Flint.render)

  // shim root view
  opts.namespace.view = {
    update: () => {},
    el: createElement('_'),
    Flint
  }
  opts.namespace.Flint = Flint

  // prevent overwriting
  Object.freeze(Flint)

  return Flint
}

function log(...args) {
  if (window.location.search == '?debug') console.log(...args)
}<commit_msg>fix adding and removing views hot reloads<commit_after>import hashsum from 'hash-sum'
import ee from 'event-emitter'
import React from 'react'
import raf from 'raf'
import ReactDOM from 'react-dom'
import clone from 'clone'
import Bluebird, { Promise } from 'bluebird'

import 'reapp-object-assign'
import './shim/root'
import './shim/flintMap'
import './shim/on'
import './shim/partial'
import './lib/bluebirdErrorHandle'
import createComponent from './createComponent'
import range from './lib/range'
import iff from './lib/iff'
import router from './lib/router'
import assignToGlobal from './lib/assignToGlobal'
import safeRun from './lib/safeRun'
import reportError from './lib/reportError'
import arrayDiff from './lib/arrayDiff'
import createElement from './tag/createElement'
import ErrorDefinedTwice from './views/ErrorDefinedTwice'
import NotFound from './views/NotFound'
import Main from './views/Main'

/*

  Welcome to Flint!

    This file deals mostly with setting up Flint,
    loading views and files, rendering,
    and exposing the public Flint functions

*/

Promise.longStackTraces()

// GLOBALS
root._history = history // for imported modules to use
root._bluebird = Bluebird // for imported modules to use
root.Promise = Promise // for modules to use
root.ReactDOM = ReactDOM
root.on = on
root.module = {}
root.fetch.json = (...args) => fetch(...args).then(res => res.json())

const uuid = () => Math.floor(Math.random() * 1000000)

export default function run(browserNode, userOpts, afterRenderCb) {
  const opts = Object.assign({
    namespace: {},
    entry: 'Main'
  }, userOpts)

  const isDevTools = opts.app == 'devTools'

  // error handling
  const flintOnError = (...args) => {
    reportError(...args)

    // restore last working views
    Object.keys(Flint.views).forEach(name => {
      Flint.views[name] = Internal.lastWorkingViews[name]
    })
  }

  root.onerror = flintOnError

  const Internal = root._Flint = {
    isRendering: 0,
    firstRender: true,

    viewCache: {}, // map of views in various files
    viewsInFile: {}, // current build up of running hot insertion
    currentFileViews: null, // tracks views as file loads, for hot reloading
    currentHotFile: null, // current file that is running
    getCache: {}, // stores { path: { name: val } } for use in view.get()
    getCacheInit: {}, // stores the vars after a view is first run
    propsHashes: {},

    changedViews: [],
    mountedViews: {},
    lastWorkingViews: {},
    lastWorkingRenders: {},
    preloaders: [], // async functions needed before loading app

    // devtools
    inspector: {},
    viewsAtPath: {},

    setCache(path, name, val) {
      Internal.getCache[path][name] = val
      // when devtools inspecting
      setInspector(path)
    }
  }

  function pathToName(path) {
    let p = path.split(',')
    return p[p.length - 1].split('.')[0]
  }

  // devtools edit
  function writeBack(path, writePath) {
    // update getCache
    writePath.reduce((acc, key) => {
      if (key == 'root') return acc
      if (Array.isArray(key))
        acc[key[0]] = key[1] // final index is arr: [key, val]
      else
        return acc[key]
    }, Internal.getCache[path])

    // update view
    const name = pathToName(path)
    Flint.render()
  }

  function setInspector(path) {
    if (Internal.inspector.path && Internal.inspector.path == path) {
      const name = pathToName(path)
      let props = Internal.viewsAtPath[path].props
      const state = Internal.getCache[path]
      Internal.inspector.cb(name, props, state, writeBack)
    }
  }

  const emitter = ee({})

  let Flint = {
    router,
    range,
    iff,

    views: {},
    removeView(key) {
      console.log('remove view', key)
      delete Flint.views[key]
    },

    render() {
      if (Internal.preloaders.length)
        Promise.all(Internal.preloaders.map(loader => loader())).then(run)
      else
        run()

      function run() {
        Internal.isRendering++
        log(`render(), Internal.isRendering(${Internal.isRendering})`)
        if (Internal.isRendering > 3) return

        const MainComponent = (
            Flint.views.Main.component || Internal.lastWorkingViews.Main.component
        )

        if (!browserNode) {
          Flint.renderedToString = React.renderToString(<MainComponent />)
          afterRenderCb && afterRenderCb(Flint.renderedToString)
        }
        else {
          if (window.__isDevingDevTools)
            browserNode = '_flintdevtools'

          ReactDOM.render(<MainComponent />, document.getElementById(browserNode))
        }

        // computing internal paths is expensive,
        // lets compute them after first render,
        if (Internal.firstRender && !isDevTools)
          setTimeout(Flint.render, 5)

        Internal.firstRender = false
        emitter.emit('afterRender')
        Internal.isRendering = 0
      }
    },

    // internal events
    on(name, cb) { emitter.on(name, cb) },

    // for use in jsx
    debug: () => { debugger },

    // load a file
    file(file, run) {
      if (!process.env.production) {
        Internal.viewsInFile[file] = []
        Internal.changedViews = []
        Internal.currentHotFile = file
      }

      // capture exports
      let fileExports = {}

      // run file
      run(fileExports)

      Flint.setExports(fileExports)

      if (!process.env.production) {
        const cached = Internal.viewCache[file] || Internal.viewsInFile[file]
        const views = Internal.viewsInFile[file]

        // remove Internal.viewsInFile that werent made
        const removed = arrayDiff(cached, views)
        removed.map(Flint.removeView)

        Internal.currentHotFile = null
        Internal.viewCache[file] = Internal.viewsInFile[file]

        if (Internal.firstRender)
          return

        raf(() => {
          const added = arrayDiff(views, cached)

          // if removed, just root
          if (removed.length || added.length)
            return Flint.render()

          Internal.changedViews.forEach(name => {
            Internal.mountedViews[name] = Internal.mountedViews[name].map(view => {
              if (view.isMounted()) {
                view.forceUpdate()
                return view
              }
            }).filter(x => !!x)
          })
        })
      }
    },

    view(name, body) {
      const comp = createComponent.partial(Flint, Internal, name, body)

      if (process.env.production)
        return setView(name, comp())

      function setView(name, component) {
        Flint.views[name] = { hash, component }
      }

      // set view in cache
      Internal.viewsInFile[Internal.currentHotFile].push(name)

      const hash = hashsum(body)

      // if new
      if (!Flint.views[name]) {
        setView(name, comp({ hash, changed: true }))
        Internal.changedViews.push(name)
        return
      }

      // hot reloaded
      if (!process.env.production) {
        if (!Internal.mountedViews[name])
          Internal.mountedViews[name] = []

        // not new
        // if defined twice during first run
        if (Internal.firstRender) {
          Flint.views[name] = ErrorDefinedTwice(name)
          throw new Error(`Defined a view twice: ${name}`)
        }

        // if unchanged
        if (Flint.views[name].hash == hash) {
          setView(name, comp({ hash, unchanged: true }))
          return
        }

        // changed
        setView(name, comp({ hash, changed: true }))
        Internal.changedViews.push(name)

        // this resets tool errors
        window.onViewLoaded()
      }
    },

    deleteFile(name) {
      const weirdName = `/${name}`
      Internal.viewsInFile[weirdName].map(Flint.removeView)
      delete Internal.viewsInFile[weirdName]
      delete Internal.viewCache[weirdName]
      Flint.render()
    },

    getView(name, parentName) {
      let result

      // View.SubView
      const subName = `${parentName}.${name}`
      if (Flint.views[subName]) {
        result = Flint.views[subName].component
      }
      // regular view
      else if (Flint.views[name]) {
        result = Flint.views[name].component
      }
      else {
        result = NotFound(name)
      }

      return result
    },

    routeMatch(path) {
      router.add(path)
      return router.isActive(path)
    },

    routeParams(path) {
      return router.params(path)
    },

    // export globals
    setExports(_exports) {
      if (!_exports) return
      Object.freeze(_exports)
      const names = Object.keys(_exports)

      if (names.length) {
        names.forEach(name => {
          if (name === 'default') {
            Object.keys(_exports.default).forEach(key => {
              assignToGlobal(key, _exports.default[key])
            })
          }

          assignToGlobal(name, _exports[name])
        })
      }
    },

    inspect(path, cb) {
      Internal.inspector = { path, cb }
      setInspector(path)
    }
  };

  router.init(Flint.render)

  // shim root view
  opts.namespace.view = {
    update: () => {},
    el: createElement('_'),
    Flint
  }
  opts.namespace.Flint = Flint

  // prevent overwriting
  Object.freeze(Flint)

  return Flint
}

function log(...args) {
  if (window.location.search == '?debug') console.log(...args)
}<|endoftext|>