<commit_before>
State.Fase1= function (game) {
	"use strict";
	this.game = game;
	this.tracajet;
	this.star;
	this.plataform;
	this.map;
	this.layer;
	this.jacareLeft;
	this.jacareRight;
	this.jacare1;
	this.jacare2;
	this.jacare3;
	this.jacare4;
	this.speed = 90;
	this.MIN_DISTANCE = 10;
	this.MAX_DISTANCE = 300;
	this.cursors;
	this.enemies;
	this.nameEnemy = 'Enemies';
	this.nameSheets = 'Sheet';
	this.sheets;
	this.txtScore;
	this.txtPause;
};

var folha;
var folhas;

State.Fase1.prototype = {

	preload: function () {
		game.load.tilemap('mapa','assets/1aFase/mapaFase1a.json',null,Phaser.Tilemap.TILED_JSON);
		game.load.spritesheet('tracajet', Config.game.tracajet.dir, Config.game.tracajet.width,Config.game.tracajet.height);
		game.load.spritesheet('folhas', "assets/1aFase/folhas_120-40.png",40,40);
		game.load.spritesheet('jacare', "assets/1aFase/jacare_spritesheet_240-80.png",40,40);
		game.load.image('bg',Config.game.fase1.background);
		game.load.image('tilesetPlataforma','assets/1aFase/assets_1.png');
	},

	create: function () {
		game.world.setBounds(0, 0, 2880, 1200);
		var bg = game.add.tileSprite(0, 0, game.cache.getImage('bg').width,game.cache.getImage('bg').height, 'bg');

		game.physics.startSystem(Phaser.Game.ARCADE);
		this.map = game.add.tilemap('mapa'); //adicionando o map
		this.map.addTilesetImage('assets_1','tilesetPlataforma' );// primeiro vem nome do arquivo, depois o apelido

		this.layer = this.map.createLayer('TileWorld');
		this.layer.resizeWorld(); //seta o mundo com as alterações feitas
		//Colide com esses tilesets
		this.map.setCollision([9,10,11,12,13,14,17,18,19,20,21,22], true,'TileWorld'); // 0 espaco vazio 1 em diante os tiles do tileset
		//Se tocar em algun desses tilesets morre
		this.map.setTileIndexCallback([15,16,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,47,48,55,56],this.gameOver,this);

		//Sprite do tracajet
		this.tracajet = game.add.sprite(20, 20, 'tracajet');
		this.tracajet.animations.add('walk',[0,1,2,1],6,false);
		this.tracajet.animations.add('swim',[5,6,7],6,false);
		this.tracajet.animations.add('startSwim',[3,4],4,true);
		game.physics.enable(this.tracajet, Phaser.Physics.ARCADE); // permite que a sprite tenha um corpo fisico

		this.tracajet.body.acceleration.y = 20;
		this.tracajet.body.collideWorldBounds = true;
	    this.tracajet.body.drag.x = 700;
		this.tracajet.anchor.setTo(.5,.5);
	    this.tracajet.body.gravity.y = 100;
	    game.camera.follow(this.tracajet);

	    //Group jacares
	    this.enemies =  this.game.add.group();
		this.enemies.enableBody = true;
		this.map.createFromObjects(this.nameEnemy, 42, 'jacare', 0, true, false, this.enemies);
		//Configura jacares
		this.enemies.forEach(this.setupEnemies,this);

		//Groups folhas
		this.sheets = this.game.add.group();
		this.sheets.enableBody  = true;
		this.map.createFromObjects(this.nameSheets,2,'folhas',0,true,false,this.sheets);

		//Cursor
		this.cursors = this.game.input.keyboard.createCursorKeys();

		//Score
		var moduloPositionX = Math.abs(this.game.world.position.x);
		var moduloPositionY = Math.abs(this.game.world.position.y);
		this.txtScore = this.game.add.text(moduloPositionX  + this.game.width - 100,moduloPositionY + 20, "", {
			font: "20px Arial",
			fill: "#ff0044",
			align: "left"
		});
		this.txtScore.setText("Score : " + Config.game.score.score);

		this.game.input.keyboard.addCallbacks(this,this.changeGameState);
	},

	update: function () {
		game.physics.arcade.collide(this.tracajet, this.layer)
	    game.physics.arcade.overlap(this.enemies, this.tracajet,this.gameOver, null,this);
	    game.physics.arcade.overlap(this.sheets,this.tracajet,this.increaseScore,null,this);
	    this.updateTracajet();
	    this.updateEnemies();
	    this.updateScorePosition

	},
	updateScorePosition : function(){
		var moduloPositionX = Math.abs(this.game.world.position.x) +  this.game.width -100;
		var moduloPositionY = Math.abs(this.game.world.position.y) + 20;
		this.txtScore.x = moduloPositionX;
		this.txtScore.y = moduloPositionY;
	}
	,
	setupEnemies : function(jacare){
		jacare = game.add.sprite(game.world.randomX, game.world.randomY, 'jacare');
		jacare.animations.add('left',[0,1,2,3,4,5],10,true);
		jacare.animations.add('right',[6,7,8,9,10,11],10,true);
		game.physics.enable(jacare, Phaser.Physics.ARCADE); // permite que a sprite tenha um corpo fisico

		jacare_tween = this.add.tween(jacare);

		jacare_tween.to({x: jacare.body.x+40, y: jacare.body.y}, 1000 /*duration of the tween (in ms)*/,
				Phaser.Easing.Linear.None /*easing type*/, true /*autostart?*/, 100 /*delay*/, false /*yoyo?*/)
				.to({x: jacare.body.x-40, y: jacare.body.y}, 1000 /*duration of the tween (in ms)*/,
				Phaser.Easing.Linear.None /*easing type*/, true /*autostart?*/, 100 /*delay*/, false /*yoyo?*/)
				.loop()
				.start()
				;

		jacare.body.collideWorldBounds = true;
	},
	updateEnemies : function(){
		this.enemies.forEachExists(function(jacare){
			if(this.tracajet.body.y>=300){
				this.followTracajet(jacare);
			}
		},this);
	}
	,
	updateTracajet : function(){
		this.tracajet.body.velocity.x = 0;

		 if ( this.cursors.left.isDown) { // vai para esquerda
	    	this.tracajet.body.velocity.x = -this.speed;
	    	this.tracajet.animations.play('walk');
	    	this.tracajet.scale.x = -1;
	    }
	    else if (this.cursors.right.isDown ) { // vai para direita
	    	this.tracajet.body.velocity.x = this.speed;
	    	this.tracajet.scale.x = +1;  // espelha se antes 1
	    	this.tracajet.animations.play('walk');
	    }
	    else if (this.cursors.up.isDown ) { // vai para cima
	    	this.tracajet.body.velocity.y = -this.speed;
	    	this.tracajet.animations.play('walk');
			this.tracajet.animations.play('jump');
	    }
	    else if (this.cursors.down.isDown ) { // vai para cima
	    	this.tracajet.body.velocity.y = this.speed;
	    	this.tracajet.animations.play('walk');
			this.tracajet.animations.play('jump');
	    }
	    else{
	    	this.tracajet.animations.stop();
	    	this.tracajet.frame = 0;
	    }
	}
	,

	tracajetEatStar: function (dino, star)	{
		this.star.kill();
	},

	gameOver: function(){
		this.tracajet.kill();
		var moduloPositionX = Math.abs(game.world.position.x);
		var moduloPositionY = Math.abs(game.world.position.y);
	    var dieText = this.game.add.text(moduloPositionX  + game.width/3,moduloPositionY +game.height/3, "", {
			font: "48px Arial",
			fill: "#ff0044",
			align: "left"
		});
		dieText.setText("GAME OVER");
	},

	followTracajet: function(jacare){

		var distance = this.game.math.distance(jacare.x, jacare.y, this.tracajet.x, this.tracajet.y);

	    if (distance > this.MIN_DISTANCE && distance < this.MAX_DISTANCE) {

			  if (this.tracajet.body.x < jacare.body.x)
			  {
				jacare.animations.play('left');
			    jacare.body.velocity.x = 45 * -1;

			  }
			  else
			  {
				  jacare.animations.play('right');
				  jacare.body.velocity.x = 45;

			  }
			    if (this.tracajet.body.y < jacare.body.y)
			  {
			    	jacare.body.velocity.y = 45 * -1;
			  }
			  else
			  {
				  jacare.body.velocity.y = 45;
			  }
	    }else{
	    	jacare.animations.stop();
	    }
	},
	increaseScore : function(tracajet,sheet){
		sheet.kill();
		Config.game.score.score += 1;
		this.txtScore.setText("Score : " + Config.game.score.score);
	},
	changeGameState : function(event){
		if(event.keyCode === Phaser.Keyboard.ENTER){
			if(this.game.paused){
				this.resumeGame();
			}else{
				this.pauseGame();
			}
		}else if(event.keyCode === Phaser.Keyboard.P){
			if(this.game.paused){
				this.resumeGame();
			}else{
				this.pauseGame();
			}
		}

	}
	,
	pauseGame : function (){

		this.game.paused = true;
		var moduloPositionX = Math.abs(this.game.world.position.x);
		var moduloPositionY = Math.abs(this.game.world.position.y);
		this.txtPause = this.game.add.text(moduloPositionX  + game.width/3 + 50,moduloPositionY + game.height/3 + 50, "", {
			font: "50px Arial",
			fill: "#ff0044",
			align: "right"
		});
		this.txtPause.setText("Paused");
	},
	resumeGame : function (event){
		if(this.game.paused){
			this.txtPause.destroy();
			this.game.paused = false;
		}
	}

};

<commit_msg>melhorada colidao lateral<commit_after>
State.Fase1= function (game) {
	"use strict";
	this.game = game;
	this.tracajet;
	this.star;
	this.plataform;
	this.map;
	this.layer;
	this.jacareLeft;
	this.jacareRight;
	this.jacare1;
	this.jacare2;
	this.jacare3;
	this.jacare4;
	this.speed = 90;
	this.MIN_DISTANCE = 10;
	this.MAX_DISTANCE = 300;
	this.cursors;
	this.enemies;
	this.nameEnemy = 'Enemies';
	this.nameSheets = 'Sheet';
	this.sheets;
	this.txtScore;
	this.txtPause;
};

var folha;
var folhas;

State.Fase1.prototype = {

	preload: function () {
		game.load.tilemap('mapa','assets/1aFase/mapaFase1a.json',null,Phaser.Tilemap.TILED_JSON);
		game.load.spritesheet('tracajet', Config.game.tracajet.dir, Config.game.tracajet.width,Config.game.tracajet.height);
		game.load.spritesheet('folhas', "assets/1aFase/folhas_120-40.png",40,40);
		game.load.spritesheet('jacare', "assets/1aFase/jacare_spritesheet_240-80.png",40,40);
		game.load.image('bg',Config.game.fase1.background);
		game.load.image('tilesetPlataforma','assets/1aFase/assets_1.png');
	},

	create: function () {
		game.world.setBounds(0, 0, 2880, 1200);
		var bg = game.add.tileSprite(0, 0, game.cache.getImage('bg').width,game.cache.getImage('bg').height, 'bg');

		game.physics.startSystem(Phaser.Game.ARCADE);
		this.map = game.add.tilemap('mapa'); //adicionando o map
		this.map.addTilesetImage('assets_1','tilesetPlataforma' );// primeiro vem nome do arquivo, depois o apelido

		this.layer = this.map.createLayer('TileWorld');
		this.layer.resizeWorld(); //seta o mundo com as alterações feitas
		//Colide com esses tilesets
		this.map.setCollision([9,10,11,12,13,14,17,18,19,20,21,22], true,'TileWorld'); // 0 espaco vazio 1 em diante os tiles do tileset
		this.map.setTileSize(36, 40);
		//Se tocar em algun desses tilesets morre
		this.map.setTileIndexCallback([15,16,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,47,48,55,56],this.gameOver,this);

		//Sprite do tracajet
		this.tracajet = game.add.sprite(20, 20, 'tracajet');
		this.tracajet.animations.add('walk',[0,1,2,1],6,false);
		this.tracajet.animations.add('swim',[5,6,7],6,false);
		this.tracajet.animations.add('startSwim',[3,4],4,true);
		game.physics.enable(this.tracajet, Phaser.Physics.ARCADE); // permite que a sprite tenha um corpo fisico

		this.tracajet.body.acceleration.y = 20;
		this.tracajet.body.collideWorldBounds = true;
	    this.tracajet.body.drag.x = 700;
		this.tracajet.anchor.setTo(.5,.5);
	    this.tracajet.body.gravity.y = 100;
		this.tracajet.body.setSize(38, 80);
	    game.camera.follow(this.tracajet);

	    //Group jacares
	    this.enemies =  this.game.add.group();
		this.enemies.enableBody = true;
		this.map.createFromObjects(this.nameEnemy, 42, 'jacare', 0, true, false, this.enemies);
		//Configura jacares
		this.enemies.forEach(this.setupEnemies,this);

		//Groups folhas
		this.sheets = this.game.add.group();
		this.sheets.enableBody  = true;
		this.map.createFromObjects(this.nameSheets,2,'folhas',0,true,false,this.sheets);

		//Cursor
		this.cursors = this.game.input.keyboard.createCursorKeys();

		//Score
		var moduloPositionX = Math.abs(this.game.world.position.x);
		var moduloPositionY = Math.abs(this.game.world.position.y);
		this.txtScore = this.game.add.text(moduloPositionX  + this.game.width - 100,moduloPositionY + 20, "", {
			font: "20px Arial",
			fill: "#ff0044",
			align: "left"
		});
		this.txtScore.setText("Score : " + Config.game.score.score);

		this.game.input.keyboard.addCallbacks(this,this.changeGameState);
	},

	update: function () {
		game.physics.arcade.collide(this.tracajet, this.layer)
	    game.physics.arcade.overlap(this.enemies, this.tracajet,this.gameOver, null,this);
	    game.physics.arcade.overlap(this.sheets,this.tracajet,this.increaseScore,null,this);
	    this.updateTracajet();
	    this.updateEnemies();
	    this.updateScorePosition

	},
	updateScorePosition : function(){
		var moduloPositionX = Math.abs(this.game.world.position.x) +  this.game.width -100;
		var moduloPositionY = Math.abs(this.game.world.position.y) + 20;
		this.txtScore.x = moduloPositionX;
		this.txtScore.y = moduloPositionY;
	}
	,
	setupEnemies : function(jacare){
		jacare = game.add.sprite(game.world.randomX, game.world.randomY, 'jacare');
		jacare.animations.add('left',[0,1,2,3,4,5],10,true);
		jacare.animations.add('right',[6,7,8,9,10,11],10,true);
		game.physics.enable(jacare, Phaser.Physics.ARCADE); // permite que a sprite tenha um corpo fisico

		jacare_tween = this.add.tween(jacare);

		jacare_tween.to({x: jacare.body.x+40, y: jacare.body.y}, 1000 /*duration of the tween (in ms)*/,
				Phaser.Easing.Linear.None /*easing type*/, true /*autostart?*/, 100 /*delay*/, false /*yoyo?*/)
				.to({x: jacare.body.x-40, y: jacare.body.y}, 1000 /*duration of the tween (in ms)*/,
				Phaser.Easing.Linear.None /*easing type*/, true /*autostart?*/, 100 /*delay*/, false /*yoyo?*/)
				.loop()
				.start()
				;

		jacare.body.collideWorldBounds = true;
	},
	updateEnemies : function(){
		this.enemies.forEachExists(function(jacare){
			if(this.tracajet.body.y>=300){
				this.followTracajet(jacare);
			}
		},this);
	}
	,
	updateTracajet : function(){
		this.tracajet.body.velocity.x = 0;

		 if ( this.cursors.left.isDown) { // vai para esquerda
	    	this.tracajet.body.velocity.x = -this.speed;
	    	this.tracajet.animations.play('walk');
	    	this.tracajet.scale.x = -1;
	    }
	    else if (this.cursors.right.isDown ) { // vai para direita
	    	this.tracajet.body.velocity.x = this.speed;
	    	this.tracajet.scale.x = +1;  // espelha se antes 1
	    	this.tracajet.animations.play('walk');
	    }
	    else if (this.cursors.up.isDown ) { // vai para cima
	    	this.tracajet.body.velocity.y = -this.speed;
	    	this.tracajet.animations.play('walk');
			this.tracajet.animations.play('jump');
	    }
	    else if (this.cursors.down.isDown ) { // vai para cima
	    	this.tracajet.body.velocity.y = this.speed;
	    	this.tracajet.animations.play('walk');
			this.tracajet.animations.play('jump');
	    }
	    else{
	    	this.tracajet.animations.stop();
	    	this.tracajet.frame = 0;
	    }
	}
	,

	tracajetEatStar: function (dino, star)	{
		this.star.kill();
	},

	gameOver: function(){
		this.tracajet.kill();
		var moduloPositionX = Math.abs(game.world.position.x);
		var moduloPositionY = Math.abs(game.world.position.y);
	    var dieText = this.game.add.text(moduloPositionX  + game.width/3,moduloPositionY +game.height/3, "", {
			font: "48px Arial",
			fill: "#ff0044",
			align: "left"
		});
		dieText.setText("GAME OVER");
	},

	followTracajet: function(jacare){

		var distance = this.game.math.distance(jacare.x, jacare.y, this.tracajet.x, this.tracajet.y);

	    if (distance > this.MIN_DISTANCE && distance < this.MAX_DISTANCE) {

			  if (this.tracajet.body.x < jacare.body.x)
			  {
				jacare.animations.play('left');
			    jacare.body.velocity.x = 45 * -1;

			  }
			  else
			  {
				  jacare.animations.play('right');
				  jacare.body.velocity.x = 45;

			  }
			    if (this.tracajet.body.y < jacare.body.y)
			  {
			    	jacare.body.velocity.y = 45 * -1;
			  }
			  else
			  {
				  jacare.body.velocity.y = 45;
			  }
	    }else{
	    	jacare.animations.stop();
	    }
	},
	increaseScore : function(tracajet,sheet){
		sheet.kill();
		Config.game.score.score += 1;
		this.txtScore.setText("Score : " + Config.game.score.score);
	},
	changeGameState : function(event){
		if(event.keyCode === Phaser.Keyboard.ENTER){
			if(this.game.paused){
				this.resumeGame();
			}else{
				this.pauseGame();
			}
		}else if(event.keyCode === Phaser.Keyboard.P){
			if(this.game.paused){
				this.resumeGame();
			}else{
				this.pauseGame();
			}
		}

	}
	,
	pauseGame : function (){

		this.game.paused = true;
		var moduloPositionX = Math.abs(this.game.world.position.x);
		var moduloPositionY = Math.abs(this.game.world.position.y);
		this.txtPause = this.game.add.text(moduloPositionX  + game.width/3 + 50,moduloPositionY + game.height/3 + 50, "", {
			font: "50px Arial",
			fill: "#ff0044",
			align: "right"
		});
		this.txtPause.setText("Paused");
	},
	resumeGame : function (event){
		if(this.game.paused){
			this.txtPause.destroy();
			this.game.paused = false;
		}
	}

};

<|endoftext|>


<commit_before>
hippoD.factory('ItemDataService', function($http) {

    var srv = {};

    srv.getRessource = function(itemNo) {
			  if (itemNo.length != 3) {
					return {};
				}
        return $http.get('/api/v1.0/resources', {item: itemNo}
        );
    };

    // Public API
    return {
        getRessource: function(no) {
            return srv.getRessource(no);
        }
    };
});

<commit_msg>factory is not used<commit_after><|endoftext|>


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

Ensembl.Panel.LocationNav = Ensembl.Panel.extend({
  constructor: function (id, params) {
    this.base(id, params);

    Ensembl.EventManager.register('hashChange',  this, this.getContent);
    Ensembl.EventManager.register('changeWidth', this, this.resize);
    Ensembl.EventManager.register('imageResize', this, this.resize);

    if (!window.location.pathname.match(/\/Multi/)) {
      Ensembl.EventManager.register('ajaxComplete', this, function () { this.enabled = true; });
    }
  },

  currentLocations: function() { // extract r's into easy to use format
    var out = {};
    var url = decodeURIComponent(window.location.href).split("?");
    parts = url[1].split(/[;&]/);
    $.each(parts,function(i,part) {
      kv = part.split("=");
      if(!kv[0].match(/^r[0-9]*$/))
        return;
      var r_parts = kv[1].match(/^([^:]*):([^-]*)-([^:]*)(:.*)?/);
      out[kv[0]] = [r_parts[1],parseInt(r_parts[2]),parseInt(r_parts[3]),r_parts[4]||''];
    });
    return out;
  },

  newLocation: function(rs) {
    var url = decodeURIComponent(window.location.href).split("?");
    parts = url[1].split(/[;&]/);
    new_parts = [];
    $.each(parts,function(i,part) {
      kv = part.split("=");
      if(kv[0].match(/^r[0-9]*$/)) {
        new_parts.push(kv[0]+"="+rs[kv[0]][0]+":"+rs[kv[0]][1]+"-"+rs[kv[0]][2]+rs[kv[0]][3]);
      } else {
        new_parts.push(part);
      }
    });
    return url[0]+"?"+new_parts.join(";");
  },

  rescale: function(rs,input) {
    input = Math.round(input);
    var out = {};
    $.each(rs,function(k,v) {
      var r_2centre = Math.round(v[1]+v[2]);
      var r_start = Math.round((r_2centre-input)/2);
      out[k] = [v[0],r_start,r_start+input+1,v[3]];
    });
    return out;
  },

  arrow: function(step) { // href for arrow buttons at cur pos. as string
    var rs = this.currentLocations();
    var out =  {};
    $.each(rs,function(k,v) {
      v[1] += step;
      v[2] += step;
    });
    return this.newLocation(rs);
  },

  zoom: function(factor) { // href for +/- buttons at cur pos. as string
    var rs = this.currentLocations();
    var width = rs['r'][2] - rs['r'][1];
    rs = this.rescale(rs,width*factor);
    if(factor>1) {
      $.each(rs,function(k,v) {
        if(v[1] == v[2]) { v[2]++; }
      });
    }
    return this.newLocation(rs);
  },

  updateButtons: function() { // update button hrefs (and loc) at cur. pos
    var panel = this;

    var rs = this.currentLocations();
    var width = rs['r'][2]-rs['r'][1]+1;
    $('.left_2',panel.el).attr('href',panel.arrow(-1e6));
    $('.left_1',panel.el).attr('href',panel.arrow(-width));
    $('.zoom_in',panel.el).attr('href',panel.zoom(0.5));
    $('.zoom_out',panel.el).attr('href',panel.zoom(2));
    $('.right_1',panel.el).attr('href',panel.arrow(width));
    $('.right_2',panel.el).attr('href',panel.arrow(1e6));
    $('#loc_r',panel.el).val(rs['r'][0]+':'+rs['r'][1]+'-'+rs['r'][2]);
  },

  val2pos: function () { // from 0-100 on UI slider to bp
    var panel = this;

    var rs = this.currentLocations();
    var input = rs['r'][2]-rs['r'][1]+1;
    var sliderConfig = $.parseJSON($('span.ramp', panel.el).text());
    var slide_min = sliderConfig.min;
    var slide_max = sliderConfig.max;
    var slide_mul = ( Math.log(slide_max) - Math.log(slide_min) ) / 100;
    var slide_off = Math.log(slide_min);
    var out = (Math.log(input)-slide_off)/slide_mul;
    if(out < 0) { return 0; }
    if(out > 100) { return 100; }
    return out;
  },

  pos2val: function(pos) { // from bp to 0-100 on UI slider
    var panel = this;

    var sliderConfig = $.parseJSON($('span.ramp', panel.el).text());
    var slide_min = sliderConfig.min;
    var slide_max = sliderConfig.max;
    var slide_mul = ( Math.log(slide_max) - Math.log(slide_min) ) / 100;
    var slide_off = Math.log(slide_min);
    var raw_value = Math.exp(pos * slide_mul + slide_off);
    // To 2sf
    var mag = Math.pow(10,2 - Math.ceil(Math.log(raw_value)/Math.LN10));
    var value = Math.round(Math.round(raw_value*mag)/mag);
    return value;
  },

  init: function () {
    var panel = this;

    this.base();

    this.enabled = this.params.enabled || false;

    this.elLk.locationInput = $('.location_selector', this.el);
    this.elLk.navbar        = $('.navbar', this.el);
    this.elLk.imageNav      = $('.image_nav', this.elLk.navbar);
    this.elLk.forms         = $('form', this.elLk.navbar);

    $('a.go-button', this.elLk.forms).on('click', function () {
      $(this).parents('form').trigger('submit');
      return false;
    });

    this.elLk.navLinks = $('a', this.elLk.imageNav).addClass('constant').on('click', function (e) {
      var newR;

      if (panel.enabled === true) {
        newR = this.href.match(Ensembl.locationMatch)[1];

        if (newR !== Ensembl.coreParams.r) {
          Ensembl.updateLocation(newR);
        }

        return false;
      }
    });

    if(!$('span.ramp', this.el).length) { return; } // No slider here
    $('span.ramp', this.el).hide();
    var sliderConfig = $.parseJSON($('span.ramp', this.el).text());
    var sliderLabel  = $('.slider_label', this.el);

    $('.slider_wrapper', this.el).children().css('display', 'inline-block');
    var slide_min = sliderConfig.min;
    var slide_max = sliderConfig.max;
    var slide_mul = ( Math.log(slide_max) - Math.log(slide_min) ) / 100;
    var slide_off = Math.log(slide_min);
    var rs = panel.currentLocations();
    this.elLk.slider = $('.slider', this.el).slider({
      value: panel.val2pos(),
      step:  1,
      min:   0,
      max:   100,
      force: false,
      slide: function (e, ui) {
        var value = panel.pos2val(ui.value);
        sliderLabel.html(value + ' bp').show();
      },
      change: function (e, ui) {
        if(panel.elLk.slider.slider('option','fake')) { return; }
        var input = panel.pos2val(ui.value);
        rs = panel.rescale(rs,input);
        var url = panel.newLocation(rs);

        if (panel.enabled === false) {
          Ensembl.redirect(url);
          return false;
        } else if (Ensembl.locationURL === 'hash' && !window.location.hash.match(Ensembl.locationMatch) && window.location.search.match(Ensembl.locationMatch)[1] === rs['r']) {
          return false; // when there's no hash, but the current location is the same as the new r
        } else if ((window.location[Ensembl.locationURL].match(Ensembl.locationMatch) || [])[1] === rs['r']) {
          return false;
        }

        Ensembl.updateLocation(rs['r'][0]+":"+rs['r'][1]+"-"+rs['r'][2]);
      },
      stop: function () {
        sliderLabel.hide();
        $('.ui-slider-handle', panel.elLk.slider).trigger('blur'); // Force the blur event to remove the highlighting for the handle
      }
    });
    this.updateButtons();
    this.resize();
  },

  getContent: function () {
    var panel = this;

    if(panel.elLk.slider) {
      panel.elLk.slider.slider('option','fake',true);
      panel.elLk.slider.slider('value',panel.val2pos());
      panel.elLk.slider.slider('option','fake',false);
      panel.updateButtons();
    }
  },

  resize: function () {
    var widths = {
      navbar: this.elLk.navbar.width(),
      slider: this.elLk.imageNav.width(),
      forms:  this.elLk.forms.width()
    };

    if (widths.navbar < widths.forms + widths.slider) {
      this.elLk.navbar.removeClass('narrow1').addClass('narrow2');
    } else if (widths.navbar < (widths.forms * this.elLk.forms.length) + widths.slider) {
      this.elLk.navbar.removeClass('narrow2').addClass('narrow1');
    } else {
      this.elLk.navbar.removeClass('narrow1 narrow2');
    }
    this.updateButtons();
  }
});
<commit_msg>RT#425431, first comment of 6 Oct. Slider bug.<commit_after>/*
 * Copyright [1999-2014] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

Ensembl.Panel.LocationNav = Ensembl.Panel.extend({
  constructor: function (id, params) {
    this.base(id, params);

    Ensembl.EventManager.register('hashChange',  this, this.getContent);
    Ensembl.EventManager.register('changeWidth', this, this.resize);
    Ensembl.EventManager.register('imageResize', this, this.resize);

    if (!window.location.pathname.match(/\/Multi/)) {
      Ensembl.EventManager.register('ajaxComplete', this, function () { this.enabled = true; });
    }
  },

  currentLocations: function() { // extract r's into easy to use format
    var out = {};
    var url = decodeURIComponent(window.location.href).split("?");
    parts = url[1].split(/[;&]/);
    $.each(parts,function(i,part) {
      kv = part.split("=");
      if(!kv[0].match(/^r[0-9]*$/))
        return;
      var r_parts = kv[1].match(/^([^:]*):([^-]*)-([^:]*)(:.*)?/);
      out[kv[0]] = [r_parts[1],parseInt(r_parts[2]),parseInt(r_parts[3]),r_parts[4]||''];
    });
    return out;
  },

  newLocation: function(rs) {
    var url = decodeURIComponent(window.location.href).split("?");
    parts = url[1].split(/[;&]/);
    new_parts = [];
    $.each(parts,function(i,part) {
      kv = part.split("=");
      if(kv[0].match(/^r[0-9]*$/)) {
        new_parts.push(kv[0]+"="+rs[kv[0]][0]+":"+rs[kv[0]][1]+"-"+rs[kv[0]][2]+rs[kv[0]][3]);
      } else {
        new_parts.push(part);
      }
    });
    return url[0]+"?"+new_parts.join(";");
  },

  rescale: function(rs,input) {
    input = Math.round(input);
    var out = {};
    $.each(rs,function(k,v) {
      var r_2centre = Math.round(v[1]+v[2]);
      var r_start = Math.round((r_2centre-input)/2);
      if(r_start<1) { r_start = 1; }
      var r_end = r_start+input+1;
      // TODO: limit end. Means we would need to pass in size from server
      out[k] = [v[0],r_start,r_end,v[3]];
    });
    return out;
  },

  arrow: function(step) { // href for arrow buttons at cur pos. as string
    var rs = this.currentLocations();
    var out =  {};
    $.each(rs,function(k,v) {
      v[1] += step;
      v[2] += step;
    });
    return this.newLocation(rs);
  },

  zoom: function(factor) { // href for +/- buttons at cur pos. as string
    var rs = this.currentLocations();
    var width = rs['r'][2] - rs['r'][1];
    rs = this.rescale(rs,width*factor);
    if(factor>1) {
      $.each(rs,function(k,v) {
        if(v[1] == v[2]) { v[2]++; }
      });
    }
    return this.newLocation(rs);
  },

  updateButtons: function() { // update button hrefs (and loc) at cur. pos
    var panel = this;

    var rs = this.currentLocations();
    var width = rs['r'][2]-rs['r'][1]+1;
    $('.left_2',panel.el).attr('href',panel.arrow(-1e6));
    $('.left_1',panel.el).attr('href',panel.arrow(-width));
    $('.zoom_in',panel.el).attr('href',panel.zoom(0.5));
    $('.zoom_out',panel.el).attr('href',panel.zoom(2));
    $('.right_1',panel.el).attr('href',panel.arrow(width));
    $('.right_2',panel.el).attr('href',panel.arrow(1e6));
    $('#loc_r',panel.el).val(rs['r'][0]+':'+rs['r'][1]+'-'+rs['r'][2]);
  },

  val2pos: function () { // from 0-100 on UI slider to bp
    var panel = this;

    var rs = this.currentLocations();
    var input = rs['r'][2]-rs['r'][1]+1;
    var sliderConfig = $.parseJSON($('span.ramp', panel.el).text());
    var slide_min = sliderConfig.min;
    var slide_max = sliderConfig.max;
    var slide_mul = ( Math.log(slide_max) - Math.log(slide_min) ) / 100;
    var slide_off = Math.log(slide_min);
    var out = (Math.log(input)-slide_off)/slide_mul;
    if(out < 0) { return 0; }
    if(out > 100) { return 100; }
    return out;
  },

  pos2val: function(pos) { // from bp to 0-100 on UI slider
    var panel = this;

    var sliderConfig = $.parseJSON($('span.ramp', panel.el).text());
    var slide_min = sliderConfig.min;
    var slide_max = sliderConfig.max;
    var slide_mul = ( Math.log(slide_max) - Math.log(slide_min) ) / 100;
    var slide_off = Math.log(slide_min);
    var raw_value = Math.exp(pos * slide_mul + slide_off);
    // To 2sf
    var mag = Math.pow(10,2 - Math.ceil(Math.log(raw_value)/Math.LN10));
    var value = Math.round(Math.round(raw_value*mag)/mag);
    return value;
  },

  init: function () {
    var panel = this;

    this.base();

    this.enabled = this.params.enabled || false;

    this.elLk.locationInput = $('.location_selector', this.el);
    this.elLk.navbar        = $('.navbar', this.el);
    this.elLk.imageNav      = $('.image_nav', this.elLk.navbar);
    this.elLk.forms         = $('form', this.elLk.navbar);

    $('a.go-button', this.elLk.forms).on('click', function () {
      $(this).parents('form').trigger('submit');
      return false;
    });

    this.elLk.navLinks = $('a', this.elLk.imageNav).addClass('constant').on('click', function (e) {
      var newR;

      if (panel.enabled === true) {
        newR = this.href.match(Ensembl.locationMatch)[1];

        if (newR !== Ensembl.coreParams.r) {
          Ensembl.updateLocation(newR);
        }

        return false;
      }
    });

    if(!$('span.ramp', this.el).length) { return; } // No slider here
    $('span.ramp', this.el).hide();
    var sliderConfig = $.parseJSON($('span.ramp', this.el).text());
    var sliderLabel  = $('.slider_label', this.el);

    $('.slider_wrapper', this.el).children().css('display', 'inline-block');
    var slide_min = sliderConfig.min;
    var slide_max = sliderConfig.max;
    var slide_mul = ( Math.log(slide_max) - Math.log(slide_min) ) / 100;
    var slide_off = Math.log(slide_min);
    var rs = panel.currentLocations();
    this.elLk.slider = $('.slider', this.el).slider({
      value: panel.val2pos(),
      step:  1,
      min:   0,
      max:   100,
      force: false,
      slide: function (e, ui) {
        var value = panel.pos2val(ui.value);
        sliderLabel.html(value + ' bp').show();
      },
      change: function (e, ui) {
        if(panel.elLk.slider.slider('option','fake')) { return; }
        var input = panel.pos2val(ui.value);
        rs = panel.rescale(rs,input);
        var url = panel.newLocation(rs);

        if (panel.enabled === false) {
          Ensembl.redirect(url);
          return false;
        } else if (Ensembl.locationURL === 'hash' && !window.location.hash.match(Ensembl.locationMatch) && window.location.search.match(Ensembl.locationMatch)[1] === rs['r']) {
          return false; // when there's no hash, but the current location is the same as the new r
        } else if ((window.location[Ensembl.locationURL].match(Ensembl.locationMatch) || [])[1] === rs['r']) {
          return false;
        }

        Ensembl.updateLocation(rs['r'][0]+":"+rs['r'][1]+"-"+rs['r'][2]);
      },
      stop: function () {
        sliderLabel.hide();
        $('.ui-slider-handle', panel.elLk.slider).trigger('blur'); // Force the blur event to remove the highlighting for the handle
      }
    });
    this.updateButtons();
    this.resize();
  },

  getContent: function () {
    var panel = this;

    if(panel.elLk.slider) {
      panel.elLk.slider.slider('option','fake',true);
      panel.elLk.slider.slider('value',panel.val2pos());
      panel.elLk.slider.slider('option','fake',false);
      panel.updateButtons();
    }
  },

  resize: function () {
    var widths = {
      navbar: this.elLk.navbar.width(),
      slider: this.elLk.imageNav.width(),
      forms:  this.elLk.forms.width()
    };

    if (widths.navbar < widths.forms + widths.slider) {
      this.elLk.navbar.removeClass('narrow1').addClass('narrow2');
    } else if (widths.navbar < (widths.forms * this.elLk.forms.length) + widths.slider) {
      this.elLk.navbar.removeClass('narrow2').addClass('narrow1');
    } else {
      this.elLk.navbar.removeClass('narrow1 narrow2');
    }
    this.updateButtons();
  }
});
<|endoftext|>


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

Ensembl.Panel.SpeciesList = Ensembl.Panel.extend({
  init: function () {
    this.base();

    var reorder    = $('.reorder_species', this.el);
    var full       = $('.full_species', this.el);
    var favourites = $('.favourites', this.el);
    var container  = $('.species_list_container', this.el);
    var dropdown   = $('.dropdown_redirect',this.el);

    if (!reorder.length || !full.length || !favourites.length) {
      return;
    }

    $('.toggle_link', this.el).on('click', function () {
      reorder.toggle();
      full.toggle();
    });

    $('.favourites, .species', this.el).sortable({
      connectWith: '.list',
      containment: this.el,
      stop: function () {
        $.ajax({
          url: '/Account/Favourites/Save',
          data: { favourites: favourites.sortable('toArray').join(',').replace(/(favourite|species)-/g, '') },
          dataType: 'json',
          success: function (data) {
            container.html(data.list);
            dropdown.html(data.dropdown);
          }
        });
      }
    });

    $('select.dropdown_redirect', this.el).on('change', function () {
      Ensembl.redirect(this.value);
    });
  }
});
<commit_msg>Modified Species List JavaScript to work with dropdown in different div to favourite species panel<commit_after>/*
 * Copyright [1999-2014] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

Ensembl.Panel.SpeciesList = Ensembl.Panel.extend({
  init: function () {
    this.base();

    var reorder    = $('.reorder_species');
    var full       = $('.full_species');
    var favourites = $('.favourites');
    var container  = $('.species_list_container');
    var dropdown   = $('.dropdown_redirect',this.el);

    if (!reorder.length || !full.length || !favourites.length) {
      return;
    }

    $('.toggle_link', this.el).on('click', function () {
      reorder.toggle();
      full.toggle();
    });

    $('.favourites, .species', this.el).sortable({
      connectWith: '.list',
      containment: this.el,
      stop: function () {
        $.ajax({
          url: '/Account/Favourites/Save',
          data: { favourites: favourites.sortable('toArray').join(',').replace(/(favourite|species)-/g, '') },
          dataType: 'json',
          success: function (data) {
            container.html(data.list);
            dropdown.html(data.dropdown);
          }
        });
      }
    });

    $('select.dropdown_redirect', this.el).on('change', function () {
      Ensembl.redirect(this.value);
    });
  }
});
<|endoftext|>


<commit_before>/* -*- mode: espresso; espresso-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim: set softtabstop=2 shiftwidth=2 tabstop=2 expandtab: */

var ConnectorTable = new function()
{
  /** Pointer to the existing instance of table. */
  this.connectorTable = null;

  var self = this;
  var asInitValsSyn = new Array();

  this.init = function (pid) {
    var tableid = '#connectortable';
    var skeletonID = SkeletonAnnotations.getActiveSkeletonId();

    self.connectorTable = $(tableid).dataTable(
      {
        // http://www.datatables.net/usage/options
        "bDestroy": true,
        "sDom": '<"H"lr>t<"F"ip>',
        // default: <"H"lfr>t<"F"ip>
        "bProcessing": true,
        "bServerSide": true,
        "bAutoWidth": false,
        "sAjaxSource": 'model/connector.list.php',
        "fnServerData": function (sSource, aoData, fnCallback) {

          if (!skeletonID) {
            $('#growl-alert').growlAlert({
              autoShow: true,
              content: 'You need to activate a treenode to display the connector table of its skeleton.',
              title: 'BEWARE',
              position: 'top-right',
              delayTime: 2500,
              onComplete: function() {
                g.remove();
              }
            });
            skeletonID = 0;
          }

          aoData.push({
            "name": "relation_type",
            "value" : $('#connector_relation_type :selected').attr("value")
          });
          aoData.push({
            "name" : "pid",
            "value" : pid
          });
          aoData.push({
            "name" : "skeleton_id",
            "value" : skeletonID
          });
          $.ajax({
            "dataType": 'json',
            "type": "POST",
            "url": sSource,
            "data": aoData,
            "success": fnCallback
          });

        },
        "aLengthMenu": [
          [10, 25, 50, -1],
          [10, 25, 50, "All"]
        ],
        "bJQueryUI": true,
        "aoColumns": [
          {
            "bSearchable": false,
            "bSortable": true
          },
          // connector id
          {
            "sClass": "center",
            "bSearchable": false
          },
          // x
          {
            "sClass": "center",
            "bSearchable": false
          },
          // y
          {
            "sClass": "center",
            "bSearchable": false
          },
          // z
          {
            "bSearchable": false,
            "bSortable": true
          },
          // connectortags
          {
            "bSearchable": false,
            "bSortable": true
          },
          // number of nodes
          {
            "bVisible": true,
            "bSortable": true
          },
          // username
          {
            "bSearchable": false,
            "bSortable": true,
            "bVisible": false
          } // treenodes
        ]
      });

    $(tableid + " tfoot input").keyup(function () { /* Filter on the column (the index) of this element */
      self.connectorTable.fnFilter(this.value, $("tfoot input").index(this));
    });

    /*
     * Support functions to provide a little bit of 'user friendlyness' to the textboxes in
     * the footer
     */
    $(tableid + " tfoot input").each(function (i) {
      asInitValsSyn[i] = this.value;
    });

    $(tableid + " tfoot input").focus(function () {
      if (this.className == "search_init") {
        this.className = "";
        this.value = "";
      }
    });

    $(tableid + " tfoot input").blur(function (i) {
      if (this.value == "") {
        this.className = "search_init";
        this.value = asInitValsSyn[$("tfoot input").index(this)];
      }
    });

    $(tableid + " tbody tr").live('dblclick', function () {

      var aData = self.connectorTable.fnGetData(this);
      // retrieve coordinates and moveTo
      var x = parseFloat(aData[1]);
      var y = parseFloat(aData[2]);
      var z = parseFloat(aData[3]);
      project.moveTo(z, y, x);

      // activate the treenode with a delay
      var id = parseInt(aData[7], 10);
      window.setTimeout("SkeletonAnnotations.staticSelectNode(" + id + ")", 1000);

    });

    $('#connector_relation_type').change(function() {
      self.connectorTable.fnDraw();
      if ($('#connector_relation_type :selected').attr("value")) {
        $("#connector_nr_nodes_top").text("# nodes for source(s)");
      } else {
        $("#connector_nr_nodes_top").text("# nodes for target(s)");
      }

    });

  }
}<commit_msg>Correct target/source column name in connector table<commit_after>/* -*- mode: espresso; espresso-indent-level: 2; indent-tabs-mode: nil -*- */
/* vim: set softtabstop=2 shiftwidth=2 tabstop=2 expandtab: */

var ConnectorTable = new function()
{
  /** Pointer to the existing instance of table. */
  this.connectorTable = null;

  var self = this;
  var asInitValsSyn = new Array();

  this.init = function (pid) {
    var tableid = '#connectortable';
    var skeletonID = SkeletonAnnotations.getActiveSkeletonId();

    self.connectorTable = $(tableid).dataTable(
      {
        // http://www.datatables.net/usage/options
        "bDestroy": true,
        "sDom": '<"H"lr>t<"F"ip>',
        // default: <"H"lfr>t<"F"ip>
        "bProcessing": true,
        "bServerSide": true,
        "bAutoWidth": false,
        "sAjaxSource": 'model/connector.list.php',
        "fnServerData": function (sSource, aoData, fnCallback) {

          if (!skeletonID) {
            $('#growl-alert').growlAlert({
              autoShow: true,
              content: 'You need to activate a treenode to display the connector table of its skeleton.',
              title: 'BEWARE',
              position: 'top-right',
              delayTime: 2500,
              onComplete: function() {
                g.remove();
              }
            });
            skeletonID = 0;
          }

          aoData.push({
            "name": "relation_type",
            "value" : $('#connector_relation_type :selected').attr("value")
          });
          aoData.push({
            "name" : "pid",
            "value" : pid
          });
          aoData.push({
            "name" : "skeleton_id",
            "value" : skeletonID
          });
          $.ajax({
            "dataType": 'json',
            "type": "POST",
            "url": sSource,
            "data": aoData,
            "success": fnCallback
          });

        },
        "aLengthMenu": [
          [10, 25, 50, -1],
          [10, 25, 50, "All"]
        ],
        "bJQueryUI": true,
        "aoColumns": [
          {
            "bSearchable": false,
            "bSortable": true
          },
          // connector id
          {
            "sClass": "center",
            "bSearchable": false
          },
          // x
          {
            "sClass": "center",
            "bSearchable": false
          },
          // y
          {
            "sClass": "center",
            "bSearchable": false
          },
          // z
          {
            "bSearchable": false,
            "bSortable": true
          },
          // connectortags
          {
            "bSearchable": false,
            "bSortable": true
          },
          // number of nodes
          {
            "bVisible": true,
            "bSortable": true
          },
          // username
          {
            "bSearchable": false,
            "bSortable": true,
            "bVisible": false
          } // treenodes
        ]
      });

    $(tableid + " tfoot input").keyup(function () { /* Filter on the column (the index) of this element */
      self.connectorTable.fnFilter(this.value, $("tfoot input").index(this));
    });

    /*
     * Support functions to provide a little bit of 'user friendlyness' to the textboxes in
     * the footer
     */
    $(tableid + " tfoot input").each(function (i) {
      asInitValsSyn[i] = this.value;
    });

    $(tableid + " tfoot input").focus(function () {
      if (this.className == "search_init") {
        this.className = "";
        this.value = "";
      }
    });

    $(tableid + " tfoot input").blur(function (i) {
      if (this.value == "") {
        this.className = "search_init";
        this.value = asInitValsSyn[$("tfoot input").index(this)];
      }
    });

    $(tableid + " tbody tr").live('dblclick', function () {

      var aData = self.connectorTable.fnGetData(this);
      // retrieve coordinates and moveTo
      var x = parseFloat(aData[1]);
      var y = parseFloat(aData[2]);
      var z = parseFloat(aData[3]);
      project.moveTo(z, y, x);

      // activate the treenode with a delay
      var id = parseInt(aData[7], 10);
      window.setTimeout("SkeletonAnnotations.staticSelectNode(" + id + ")", 1000);

    });

    $('#connector_relation_type').change(function() {
      self.connectorTable.fnDraw();
      if ($('#connector_relation_type :selected').attr("value") === "0") {
        $("#connector_nr_nodes_top").text("# nodes for source(s)");
        $("#connector_nr_nodes_bottom").text("# nodes for source(s)");
      } else {
        $("#connector_nr_nodes_top").text("# nodes for target(s)");
        $("#connector_nr_nodes_bottom").text("# nodes for target(s)");
      }

    });

  }
}<|endoftext|>


<commit_before>import { check } from 'meteor/check'
import { ProfileImages, UserData, Wallet, ProblemComments, Features, Redflags, Summaries } from '/imports/api/indexDB.js'
import { creditUserWith } from '/imports/api/utilities.js'

Meteor.methods({
  // stubbed method for deposits, has no checks
    addOthers: (currency, amount) => {
      UserData.update({
        _id: Meteor.userId()
      }, {
        $inc: {
          [`others.${currency}`]: amount
        }
      })

      Wallet.insert({
              time: new Date().getTime(),
              owner: Meteor.userId(),
              type: 'transaction',
                from: 'Blockrazor',
                message: `${currency} has been deposited to your account.`,
                amount: amount,
              read: false,
              currency: currency,
              rewardType: 'deposit'
            })
    },
    generateInviteCode: () => { // for backwards compability
      Meteor.users.find({
        inviteCode: {
          $exists: false
        }
      }).fetch().forEach(i => {
        Meteor.users.update({
          _id: i._id
        }, {
          $set: {
            inviteCode: Random.id(20)
          }
        })
      })
    },
    setReferral: (inviteCode) => {
      let invitedBy = Meteor.users.findOne({
        inviteCode: inviteCode
      })

      if (invitedBy && invitedBy._id !== Meteor.userId()) { // you can't invite yourself, duh
        Meteor.users.update({
          _id: Meteor.userId(),
          invitedBy: {
            $exists: false // can't update if user already has a referral
          }
        }, {
          $set: {
            referral: {
              invitedBy: invitedBy._id
            }
          }
        })
      }
    },
    rewardReferral: () => {
      Meteor.users.find({}).fetch().forEach(i => {
        let invited = Meteor.users.find({
          'referral.invitedBy': i._id
        }).fetch()

        if (invited.length) {
          let last24h = new Date().getTime() - 86400000 // last 24 hours

          let earnedToday = invited.reduce((i1, i2) => { // sum everything referrals have earned in the last 24hours
            let val = Wallet.find({
              rewardType: {
                $ne: 'referral'
              },
              owner: i2._id,
              time: {
                $gt: last24h
              }
            }).fetch().reduce((j1, j2) => j1 + j2.amount, 0)

            return i1 + val
          }, 0)

          creditUserWith(earnedToday * 0.05, i._id, 'inviting other users to Blockrazor.', 'referral') // reward with 5% of all
        }
      })
    },
    userStrike: (userId, type, token) => {
      if (token === 's3rv3r-only') {
        let user = UserData.findOne({
          _id: userId
        })

        if (user) {
          // add a strike to user's date
          UserData.update({
            _id: user._id
          }, {
            $push: {
              strikes: {
                time: new Date().getTime(),
                type: type
              }
            }
          })

          let lastWeek = new Date().getTime() - 24*60*60*1000*7 // one week
          let strikesWeek = user.strikes ? user.strikes.reduce((i1, i2) => {
            let val = i2.time > lastWeek ? 1 : 0

            return i1 + val
          }, 0) + 1 : 0

          let lastMonth = new Date().getTime() - 24*60*60*1000*30 // one month (30 days average)
          let strikesMonth = user.strikes ? user.strikes.reduce((i1, i2) => {
            let val = i2.time > lastMonth ? 1 : 0

            return i1 + val
          }, 0) + 1 : 0

          if (strikesWeek > 3 || strikesMonth > 6) {
            Meteor.users.update({
              _id: Meteor.userId()
            }, {
              $set: {
                suspended: true
              }
            })
          }
        } else {
          throw new Meteor.Error('Error.', 'Invalid user.')
        }
      } else {
        throw new Meteor.Error('Error.', 'This method is server only.')
      }
    },
    applyForPardon: (reason) => {
      if (Meteor.userId()) {
        UserData.update({
          _id: Meteor.userId()
        }, {
          $set: {
            pardon: {
              reason: reason,
              status: 'new'
            }
          }
        })
      } else {
        throw new Meteor.Error('Error.', 'You need to be logged in.')
      }
    },
    pardonVote: function(userId, type) {
      if (!Meteor.userId()) {
        throw new Meteor.Error('Error.', 'Please log in first')
      }

      let mod = UserData.findOne({
        _id: this.userId
      }, {
        fields: {
          moderator: true
        }
      })

      if (!mod || !mod.moderator) {
          throw new Meteor.Error('Error.', 'mod-only')
      }

      let u = UserData.findOne({
        _id: userId
      })

      if (!(u.pardon.votes || []).filter(i => i.userId === this.userId).length) { // user hasn't voted yet
        UserData.update({
          _id: u._id
        }, {
          $inc: {
            'pardon.score': type === 'voteUp' ? 1 : -1, // increase or decrease the current score
            [`pardon.${type === 'voteUp' ? 'upvotes' : 'downvotes'}`]: 1 // increase upvotes or downvotes
          },
          $push: {
            'pardon.votes': {
              userId: this.userId,
              type: type,
              loggedIP: this.connection.clientAddress,
              time: new Date().getTime()
            }
          }
        })
      }

      let approveChange = UserData.find({
        _id: u._id
      }, {
        fields: {
          pardon: 1
        }
      }).fetch()[0]

      // pardon user if he/she receives more than 3 positive votes
      if (approveChange.pardon.score >= 3) {
        UserData.update({
          _id: u._id
        }, {
          $set: {
            pardon: {
              status: 'granted'
            }
          }
        })

        Meteor.users.update({
          _id: u._id
        }, {
          $set: {
            strikes: [], // clear his sins
            suspended: false
          }
        })

        return 'ok'
      }

      // If the user has 3 or more negative votes, deny his/her pardon request
      if (approveChange.pardon.score <= -3) {
        if (u) {
          UserData.update({
            _id: u._id
          }, {
            $set: {
              pardon: {
                status: 'denied'
              }
            }
          })
        } else {
          throw new Meteor.Error('Error.', 'Wrong id.')
        }

        return 'not-ok'
      }
    },
    userInputRanking: () => {
      Meteor.users.find({}).fetch().forEach(i => {
        let features = Features.find({
          createdBy: i._id
        }).fetch()

        let redflags = Redflags.find({
          createdBy: i._id
        }).fetch()

        let problems = ProblemComments.find({
          createdBy: i._id
        }).fetch()

        let summaries = Summaries.find({
          createdBy: i._id
        }).fetch()

        let all = _.union(features, redflags, problems, summaries)

        let total = 0
        let up = 0

        all.forEach(j => {
          total += j.appealNumber // total number of votes on an item
          up += (j.appealNumber + j.appeal) / 2 // total number of upvotes (10 . 6 = 8)
        })

        /*
        if (up > 10) {
          // we could add user badges here
        }
        */

        UserData.update({
          _id: i._id
        }, {
          $set: {
            inputRanking: total ? (up / total) : 0 // avoid division by zero
          }
        })
      })
    },
    initializeUser: function() {
        if (_.size(UserData.findOne({_id: this.userId})) == 0) {
          let u = UserData.find({
            'sessionData.loggedIP': this.connection.clientAddress
          }).count()

          let user = Meteor.users.findOne({
            _id: this.userId
          })

          const validate = address => {
            address = address.split('@').pop()

              const disposable = require('disposable-email')
              const ourList = ['mvrht.net'] // disposable emails currently not on the list

              return !~ourList.indexOf(address) && disposable.validate(address)
          }

          UserData.insert({
            _id: this.userId,
            moderator: 0,
            developer: false,
            balance: 0,
            others: {
              'USD': 0,
              'ETH': 0,
              'XMR': 0
            },
            approvedCurrencies: 0,
            createdTime: new Date().getTime(),
            sessionData: [{
              loggedIP: this.connection.clientAddress,
              headerData: this.connection.httpHeaders,
              time: new Date().getTime()
            }],
            flags: {
              duplicate: {
                createdIP: !!u,
                accessIP: false,
                disposableEmail: !validate(user.email)
              }
            }
          })
        } else {
          UserData.upsert({
            _id: this.userId
          }, {
            $push: {
              sessionData: {
                loggedIP: this.connection.clientAddress,
                headerData: this.connection.httpHeaders, // this could be a problem in the future, it's quite a big object
                time: new Date().getTime()
              }
            }
          })
        }
      },
    getUserConnectionInfo: function() {
      return this.connection;
    },
    'editProfile': function(data) {
        if (!this.userId) { throw new Meteor.Error('error', 'please log in') };

        //only update profile if data is true
        if (data) {
            //validate json objects are strings
            check(data.email, String)
            check(data.bio, String)
            check(data.username, String)

            Meteor.users.update({ _id: this.userId }, {
                    $set: {
                        email: data.email,
                        username: data.username,
                        bio: data.bio
                    }
                },
                function(error) {
                    console.log('editProfile method failed', error)
                });
        }

    },
    uploadProfilePicture: (fileName, binaryData, md5) => {
        let md5validate = CryptoJS.MD5(CryptoJS.enc.Latin1.parse(binaryData)).toString()
        if (md5validate !== md5) {
            throw new Meteor.Error('Error.', 'Failed to validate md5 hash.')
            return false
        }
        if (!Meteor.userId()) {
            throw new Meteor.Error('Error.', 'You must be logged in to do this.');
            return false
        }

        const fs = require('fs')

        let mime = require('mime-types')
        let mimetype = mime.lookup(fileName)
        let validFile = _supportedFileTypes.includes(mimetype)
        let fileExtension = mime.extension(mimetype)
        let filename_thumbnail = `${_profilePictureUploadDirectory}${md5}_thumbnail.${fileExtension}`
        let filename = `${_profilePictureUploadDirectory}${md5}.${fileExtension}`

        let insert = false

        if (!validFile) {
            throw new Meteor.Error('Error.', 'File type not supported, png, gif and jpeg supported');
            return false
        }

        Meteor.users.update({ _id: Meteor.userId() }, {
                $set: {
                    profilePicture: {
                        small: `${md5}_thumbnail.${fileExtension}`,
                        large: `${md5}.${fileExtension}`
                    }
                }
            },
            function(error) {
                console.log('editProfile method failed', error)
            });

        fs.writeFileSync(filename, binaryData, {
            encoding: 'binary'
        }, Meteor.bindEnvironment((error) => {
            if (error) {
                log.error('Error in uploadProfilePicture', error)
            }
        }))

          var size = { width: 200, height: 200 };
  gm(filename)
      .resize(size.width, size.height + ">")
      .gravity('Center')
      .write(filename_thumbnail, function(error) {
          if (error) console.log('Error - ', error);
      });

    },
});<commit_msg>problem: demo moderator account keeps getting suspended #954<commit_after>import { check } from 'meteor/check'
import { ProfileImages, UserData, Wallet, ProblemComments, Features, Redflags, Summaries } from '/imports/api/indexDB.js'
import { creditUserWith } from '/imports/api/utilities.js'

Meteor.methods({
  // stubbed method for deposits, has no checks
    addOthers: (currency, amount) => {
      UserData.update({
        _id: Meteor.userId()
      }, {
        $inc: {
          [`others.${currency}`]: amount
        }
      })

      Wallet.insert({
              time: new Date().getTime(),
              owner: Meteor.userId(),
              type: 'transaction',
                from: 'Blockrazor',
                message: `${currency} has been deposited to your account.`,
                amount: amount,
              read: false,
              currency: currency,
              rewardType: 'deposit'
            })
    },
    generateInviteCode: () => { // for backwards compability
      Meteor.users.find({
        inviteCode: {
          $exists: false
        }
      }).fetch().forEach(i => {
        Meteor.users.update({
          _id: i._id
        }, {
          $set: {
            inviteCode: Random.id(20)
          }
        })
      })
    },
    setReferral: (inviteCode) => {
      let invitedBy = Meteor.users.findOne({
        inviteCode: inviteCode
      })

      if (invitedBy && invitedBy._id !== Meteor.userId()) { // you can't invite yourself, duh
        Meteor.users.update({
          _id: Meteor.userId(),
          invitedBy: {
            $exists: false // can't update if user already has a referral
          }
        }, {
          $set: {
            referral: {
              invitedBy: invitedBy._id
            }
          }
        })
      }
    },
    rewardReferral: () => {
      Meteor.users.find({}).fetch().forEach(i => {
        let invited = Meteor.users.find({
          'referral.invitedBy': i._id
        }).fetch()

        if (invited.length) {
          let last24h = new Date().getTime() - 86400000 // last 24 hours

          let earnedToday = invited.reduce((i1, i2) => { // sum everything referrals have earned in the last 24hours
            let val = Wallet.find({
              rewardType: {
                $ne: 'referral'
              },
              owner: i2._id,
              time: {
                $gt: last24h
              }
            }).fetch().reduce((j1, j2) => j1 + j2.amount, 0)

            return i1 + val
          }, 0)

          creditUserWith(earnedToday * 0.05, i._id, 'inviting other users to Blockrazor.', 'referral') // reward with 5% of all
        }
      })
    },
    userStrike: (userId, type, token) => {
      if (token === 's3rv3r-only') {
        let user = UserData.findOne({
          _id: userId
        })

        if (user && !user.moderator) {
          // add a strike to user's date
          UserData.update({
            _id: user._id
          }, {
            $push: {
              strikes: {
                time: new Date().getTime(),
                type: type
              }
            }
          })

          let lastWeek = new Date().getTime() - 24*60*60*1000*7 // one week
          let strikesWeek = user.strikes ? user.strikes.reduce((i1, i2) => {
            let val = i2.time > lastWeek ? 1 : 0

            return i1 + val
          }, 0) + 1 : 0

          let lastMonth = new Date().getTime() - 24*60*60*1000*30 // one month (30 days average)
          let strikesMonth = user.strikes ? user.strikes.reduce((i1, i2) => {
            let val = i2.time > lastMonth ? 1 : 0

            return i1 + val
          }, 0) + 1 : 0

          if (strikesWeek > 3 || strikesMonth > 6) {
            Meteor.users.update({
              _id: Meteor.userId()
            }, {
              $set: {
                suspended: true
              }
            })
          }
        } else {
          throw new Meteor.Error('Error.', 'Invalid user.')
        }
      } else {
        throw new Meteor.Error('Error.', 'This method is server only.')
      }
    },
    applyForPardon: (reason) => {
      if (Meteor.userId()) {
        UserData.update({
          _id: Meteor.userId()
        }, {
          $set: {
            pardon: {
              reason: reason,
              status: 'new'
            }
          }
        })
      } else {
        throw new Meteor.Error('Error.', 'You need to be logged in.')
      }
    },
    pardonVote: function(userId, type) {
      if (!Meteor.userId()) {
        throw new Meteor.Error('Error.', 'Please log in first')
      }

      let mod = UserData.findOne({
        _id: this.userId
      }, {
        fields: {
          moderator: true
        }
      })

      if (!mod || !mod.moderator) {
          throw new Meteor.Error('Error.', 'mod-only')
      }

      let u = UserData.findOne({
        _id: userId
      })

      if (!(u.pardon.votes || []).filter(i => i.userId === this.userId).length) { // user hasn't voted yet
        UserData.update({
          _id: u._id
        }, {
          $inc: {
            'pardon.score': type === 'voteUp' ? 1 : -1, // increase or decrease the current score
            [`pardon.${type === 'voteUp' ? 'upvotes' : 'downvotes'}`]: 1 // increase upvotes or downvotes
          },
          $push: {
            'pardon.votes': {
              userId: this.userId,
              type: type,
              loggedIP: this.connection.clientAddress,
              time: new Date().getTime()
            }
          }
        })
      }

      let approveChange = UserData.find({
        _id: u._id
      }, {
        fields: {
          pardon: 1
        }
      }).fetch()[0]

      // pardon user if he/she receives more than 3 positive votes
      if (approveChange.pardon.score >= 3) {
        UserData.update({
          _id: u._id
        }, {
          $set: {
            pardon: {
              status: 'granted'
            }
          }
        })

        Meteor.users.update({
          _id: u._id
        }, {
          $set: {
            strikes: [], // clear his sins
            suspended: false
          }
        })

        return 'ok'
      }

      // If the user has 3 or more negative votes, deny his/her pardon request
      if (approveChange.pardon.score <= -3) {
        if (u) {
          UserData.update({
            _id: u._id
          }, {
            $set: {
              pardon: {
                status: 'denied'
              }
            }
          })
        } else {
          throw new Meteor.Error('Error.', 'Wrong id.')
        }

        return 'not-ok'
      }
    },
    userInputRanking: () => {
      Meteor.users.find({}).fetch().forEach(i => {
        let features = Features.find({
          createdBy: i._id
        }).fetch()

        let redflags = Redflags.find({
          createdBy: i._id
        }).fetch()

        let problems = ProblemComments.find({
          createdBy: i._id
        }).fetch()

        let summaries = Summaries.find({
          createdBy: i._id
        }).fetch()

        let all = _.union(features, redflags, problems, summaries)

        let total = 0
        let up = 0

        all.forEach(j => {
          total += j.appealNumber // total number of votes on an item
          up += (j.appealNumber + j.appeal) / 2 // total number of upvotes (10 . 6 = 8)
        })

        /*
        if (up > 10) {
          // we could add user badges here
        }
        */

        UserData.update({
          _id: i._id
        }, {
          $set: {
            inputRanking: total ? (up / total) : 0 // avoid division by zero
          }
        })
      })
    },
    initializeUser: function() {
        if (_.size(UserData.findOne({_id: this.userId})) == 0) {
          let u = UserData.find({
            'sessionData.loggedIP': this.connection.clientAddress
          }).count()

          let user = Meteor.users.findOne({
            _id: this.userId
          })

          const validate = address => {
            address = address.split('@').pop()

              const disposable = require('disposable-email')
              const ourList = ['mvrht.net'] // disposable emails currently not on the list

              return !~ourList.indexOf(address) && disposable.validate(address)
          }

          UserData.insert({
            _id: this.userId,
            moderator: 0,
            developer: false,
            balance: 0,
            others: {
              'USD': 0,
              'ETH': 0,
              'XMR': 0
            },
            approvedCurrencies: 0,
            createdTime: new Date().getTime(),
            sessionData: [{
              loggedIP: this.connection.clientAddress,
              headerData: this.connection.httpHeaders,
              time: new Date().getTime()
            }],
            flags: {
              duplicate: {
                createdIP: !!u,
                accessIP: false,
                disposableEmail: !validate(user.email)
              }
            }
          })
        } else {
          UserData.upsert({
            _id: this.userId
          }, {
            $push: {
              sessionData: {
                loggedIP: this.connection.clientAddress,
                headerData: this.connection.httpHeaders, // this could be a problem in the future, it's quite a big object
                time: new Date().getTime()
              }
            }
          })
        }
      },
    getUserConnectionInfo: function() {
      return this.connection;
    },
    'editProfile': function(data) {
        if (!this.userId) { throw new Meteor.Error('error', 'please log in') };

        //only update profile if data is true
        if (data) {
            //validate json objects are strings
            check(data.email, String)
            check(data.bio, String)
            check(data.username, String)

            Meteor.users.update({ _id: this.userId }, {
                    $set: {
                        email: data.email,
                        username: data.username,
                        bio: data.bio
                    }
                },
                function(error) {
                    console.log('editProfile method failed', error)
                });
        }

    },
    uploadProfilePicture: (fileName, binaryData, md5) => {
        let md5validate = CryptoJS.MD5(CryptoJS.enc.Latin1.parse(binaryData)).toString()
        if (md5validate !== md5) {
            throw new Meteor.Error('Error.', 'Failed to validate md5 hash.')
            return false
        }
        if (!Meteor.userId()) {
            throw new Meteor.Error('Error.', 'You must be logged in to do this.');
            return false
        }

        const fs = require('fs')

        let mime = require('mime-types')
        let mimetype = mime.lookup(fileName)
        let validFile = _supportedFileTypes.includes(mimetype)
        let fileExtension = mime.extension(mimetype)
        let filename_thumbnail = `${_profilePictureUploadDirectory}${md5}_thumbnail.${fileExtension}`
        let filename = `${_profilePictureUploadDirectory}${md5}.${fileExtension}`

        let insert = false

        if (!validFile) {
            throw new Meteor.Error('Error.', 'File type not supported, png, gif and jpeg supported');
            return false
        }

        Meteor.users.update({ _id: Meteor.userId() }, {
                $set: {
                    profilePicture: {
                        small: `${md5}_thumbnail.${fileExtension}`,
                        large: `${md5}.${fileExtension}`
                    }
                }
            },
            function(error) {
                console.log('editProfile method failed', error)
            });

        fs.writeFileSync(filename, binaryData, {
            encoding: 'binary'
        }, Meteor.bindEnvironment((error) => {
            if (error) {
                log.error('Error in uploadProfilePicture', error)
            }
        }))

          var size = { width: 200, height: 200 };
  gm(filename)
      .resize(size.width, size.height + ">")
      .gravity('Center')
      .write(filename_thumbnail, function(error) {
          if (error) console.log('Error - ', error);
      });

    },
});<|endoftext|>


<commit_before>import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';

import { Graphs } from '/imports/api/graphs.js';

import './app-graph-maker.css';
import './app-graph-maker.html';
import '/public/input/sampleGraph.js';

Template.App_graphMaker.onCreated(function appGraphMakerOnCreated() {
    var self = this;
    self.autorun(function() {
      self.subscribe('allGraphs');
    })
    // const graph_data = Graphs.find();
    // // const graph_data = Graphs.example();
    // // const graph_data = Graphs.findOne({id: 'example-graph'});
    // console.log("LOOK AT ME! LOOK HERE! HEY HEY! I'm the CLIENT!!!");
    // console.log(graph_data);
    // if (graph_data.count() === 0) {
    //     console.log("No data. Sorry.");
    // }
    // else {
    //     console.log("Pa-ching! Data found!")
    // }
});

Template.App_graphMaker.rendered = function() {

  console.log("Rendering graphmaker");
  // var initial_nodes = [];
  let currentGraph = Session.get("currentGraph");
  let initial_nodes = [];
  if (currentGraph.graphData === "EMPTY") {
      initial_nodes = sampleGraph;
  }
  // get initial data
  // $.ajax({
  //     type: "GET",
  //     url: "input/nodes.json",
  //     dataType: "json",
  //     async: false,
  //     success: function (data) {
  //         initial_nodes = data;
  //     }})
  //     .fail(function(xhr, status, error) {
  //         var err = status + ", " + error;
  //         console.log("Request failed: " + err)
  // });
  var row_count = Math.floor(Math.sqrt(initial_nodes.length)) + 1;

  // initialize the graph
  cy = cytoscape({

      container: document.getElementById('cy'),

      ready: function(){
        console.log("Graph is ready!")
      },

      //RB 11/15/16: This should be recalculated dynamically based on the nodes.
      layout: {
          name: 'grid',
          //cols: column_count,
          rows: row_count
      },

      wheelSensitivity: 0.3,

      style: [
          {
              selector: 'node',
              css: {
                  'content': 'data(name)',
                  'height': 100,
                  'width': 100,
                  'text-valign': 'center',
                  'text-halign': 'center',
                  'text-align': 'justify',
                  'background-color': '#eee',
                  'text-wrap': 'wrap',
                  'text-max-width': 200,
                  'text-outline-color': '#eee',
                  'text-outline-width': 3,
                  'border-width': 1,
                  'border-color': '#ccc'
              }
          },
          {
            selector: 'node:selected',
            css: {
              'content': 'data(name)',
              'height': 100,
              'width': 100,
              'text-valign': 'center',
              'text-halign': 'center',
              'text-align': 'justify',
              'background-color': '#eee',
              'text-wrap': 'wrap',
              'text-max-width': 200,
              'text-outline-color': '#eee',
              'text-outline-width': 3,
              'border-width': 4,
              'border-color': 'blue'
            }
          },
          {
              selector: 'node.why-hard',
              css: {
                  'shape': 'triangle',
                  'background-color': '#ffb3b3'
              }
          },

          {
              selector: 'edge',
              css: {
                  'curve-style': 'bezier',
                  'target-arrow-shape': 'triangle',
                  //'line-color': '#eee',
                  'width': 8
              }
          },

          // some style for the ext

          {
              selector: '.edgehandles-hover',
              css: {
                  //'background-color': 'green'
              }
          },

          {
              selector: '.edgehandles-source',
              css: {
                  'border-width': 2,
                  'border-color': 'maroon'
              }
          },

          {
              selector: '.edgehandles-target',
              css: {
                  'border-width': 2,
                  'border-color': 'maroon'
              }
          },

          {
              selector: '.edgehandles-preview, .edgehandles-ghost-edge',
              css: {
                  'line-color': 'maroon',
                  'target-arrow-color': 'maroon',
                  'source-arrow-color': 'maroon'
              }
          }
      ],

      elements: {
          nodes: initial_nodes,
          edges: []
      },
  });

  // remove an edge when it's clicked on
  // cy.on('click', 'edge', function(evnt) {
  //     var target = evnt.cyTarget;
  //     console.log(target.json());
  //     target.remove();
  // });
  // cy.on('keydown', 'nodes', function(evnt) {
  //     // Key codes for backspace and delete
  //     delete_keys = [8,46];
  //     console.log(evnt);
  //     if (delete_keys.indexOf(evnt.keyCode) > -1) {
  //         //cy.selected().remove();
  //         console.log("DELETE!");
  //         cy.$(':selected').remove();
  //     }
  // });

  window.addEventListener('keydown', function(event) {
      // Key codes for backspace and delete
      delete_keys = [8,46];
      console.log(event);
      if (delete_keys.indexOf(event.keyCode) > -1) {
          //cy.selected().remove();
          console.log("DELETE!");
          cy.$(':selected').remove();
      }
  });

  // Add node on "canvas" double click
  document.getElementById('cy').addEventListener('dblclick', function(event) {
      console.log("Double click event.");
      var data = {
          group: 'nodes',
          name: 'new node'
      };

      cy.add({
          data: data,
          position: {
              x: event.pageX,
              y: event.pageY
          }
      });
  });

  let toAdd = currentGraph.graphData
  if (toAdd != "EMPTY") {
    toAdd.elements.nodes.forEach(function(node) {
      cy.add(node);
    });
    toAdd.elements.edges.forEach(function(edge) {
      cy.add(edge);
    });
  }

  cy.edgehandles({
      toggleOffOnLeave: true,
      handleNodes: "node",
      handleSize: 10,
      handleColor: 'maroon',
      handleIcon: false,
      edgeType: function(){ return 'flat'; }
  });

  var selectAllOfTheSameType = function(ele) {
      cy.elements().unselect();
      if(ele.isNode()) {
          cy.nodes().select();
      }
      else if(ele.isEdge()) {
          cy.edges().select();
      }
  };

  // controllers for context menus
  cy.contextMenus({
      menuItems: [
        {
          id: 'remove',
          title: 'remove',
          selector: 'node, edge',
          onClickFunction: function (event) {
            var ok = confirm("Are you sure? You cannot undo this action.");
            if (ok) {
              event.cyTarget.remove();
            }
          },
          // hasTrailingDivider: true
        },
        {
          id: 'edit-label',
          title: 'edit label',
          selector: 'node',
          onClickFunction: function (event) {
            // get the current name of the node
            var currentName = event.cyTarget.data('name');
            // prompt the user for a new name
            // (provide current name as default)
            var newName = prompt("Edit node label", currentName);
            if (!newName) {
                // use the old name if the user cancels
                event.cyTarget.data('name', currentName);
            } else {
                // put in the new name
                event.cyTarget.data('name', newName);
            }

          }
        },
        {
          id: 'change-type',
          title: 'change type',
          selector: 'node',
          onClickFunction: function (event) {
            event.cyTarget.toggleClass("why-hard");
          }
        },
        // {
        //   id: 'hide',
        //   title: 'hide',
        //   selector: '*',
        //   onClickFunction: function (event) {
        //     event.cyTarget.hide();
        //   },
        //   disabled: false
        // },
        {
          id: 'add-action',
          title: 'add node',
          coreAsWell: true,
          onClickFunction: function (event) {
            var newName = prompt("Name this node");
            var data = {
                group: 'nodes',
                name: newName
            };

            cy.add({
                data: data,
                position: {
                    x: event.cyPosition.x,
                    y: event.cyPosition.y
                }
            });
          }
        },
        {
          id: 'add-why-hard',
          title: 'add why-hard',
          coreAsWell: true,
          onClickFunction: function (event) {
            var newName = prompt("Name this node");
            var data = {
                group: 'nodes',
                name: newName
            };

            cy.add({
                data: data,
                position: {
                    x: event.cyPosition.x,
                    y: event.cyPosition.y
                },
                classes: "why-hard"
            });
          }
        },
        {
          id: 'remove-selected',
          title: 'remove selected',
          coreAsWell: true,
          onClickFunction: function (event) {
            var ok = confirm("Are you sure? You cannot undo this action.");
            if (ok) {
              cy.$(':selected').remove();
            }
          }
        },
        {
          id: 'select-all-nodes',
          title: 'select all nodes',
          selector: 'node',
          onClickFunction: function (event) {
            selectAllOfTheSameType(event.cyTarget);
          }
        },
        {
          id: 'select-all-edges',
          title: 'select all edges',
          selector: 'edge',
          onClickFunction: function (event) {
            selectAllOfTheSameType(event.cyTarget);
          }
        }
    ]
  });

  // initiate "draw mode" for drawing edges
  document.querySelector('#draw-mode').addEventListener('click', function(e) {
      var draw_button = e.target;
      var draw_mode = draw_button.getAttribute("data-draw-mode");
      console.log(draw_mode);
      if (draw_mode === "drawon") {
          draw_mode = "drawoff";
          draw_button_switch = "OFF";
      }
      else {
          draw_mode = "drawon";
          draw_button_switch = "ON";
      }
      cy.edgehandles(draw_mode);
      draw_button.setAttribute("data-draw-mode", draw_mode);
      draw_button.innerHTML = "Draw mode: " + draw_button_switch;
  });

  // print the current state of the graph to console
  // when user clicks on the "record" button
  document.getElementById('record-json').addEventListener('click', function(){
      //this is an object, not an iterable
      var nodes = cy.nodes();
      var nodes_arr = [];
      for (var i = 0; i < nodes.length; i++) {
        nodes_arr.push(nodes[i].data());
      }
      var edges = cy.edges();
            var edges_arr = [];
      for (var i = 0; i < edges.length; i++) {
        edges_arr.push(edges[i].data());
      }

      //console.log(edges.json());
      console.log(JSON.stringify(nodes_arr));
      console.log(JSON.stringify(edges_arr));
      //export the graph in a JSON format comparable to that
      //when initialized
      console.log(JSON.stringify(cy.json()));
      var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(cy.json(), null, 3));
      var dlAnchorElem = document.getElementById('export-json');
      dlAnchorElem.setAttribute("href", dataStr);
      dlAnchorElem.setAttribute("download", "my-graph.json");
      dlAnchorElem.click();
      // document.getElementById("export-json").setAttribute("href", cy.json());
      // document.getElementById("export-json").click();
  });

  // document.getElementById('record-png').addEventListener('click', function(){
  //   document.getElementById("export-png").setAttribute("href", cy.png());
  //   document.getElementById("export-png").click();
  // });

}

Template.App_graphMaker.helpers({
  graph: function() {
    console.log(Graphs.findOne());
    return Graphs.find().count();
  }
});

Template.App_graphMaker.events({
  'click #record-png': function() {
     document.getElementById("export-png").setAttribute("href", cy.png());
    document.getElementById("export-png").click();
  },
  'click #record-json': function() {
    var nodes = cy.nodes();
    var nodes_arr = [];
    for (var i = 0; i < nodes.length; i++) {
      nodes_arr.push(nodes[i].data());
    }
    var edges = cy.edges();
          var edges_arr = [];
    for (var i = 0; i < edges.length; i++) {
      edges_arr.push(edges[i].data());
    }

    //console.log(edges.json());
    console.log(JSON.stringify(nodes_arr));
    console.log(JSON.stringify(edges_arr));
    //export the graph in a JSON format comparable to that
    //when initialized
    console.log(JSON.stringify(cy.json()));
    var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(cy.json(), null, 3));
    var dlAnchorElem = document.getElementById('export-json');
    dlAnchorElem.setAttribute("href", dataStr);
    dlAnchorElem.setAttribute("download", "my-graph.json");
    dlAnchorElem.click();
  },
  'click #save-changes': function() {
    let newName = prompt("(Optional) name this graph", "Untitled graph");
    Graphs.update({_id: Session.get("currentGraph")._id},{$set: {graphData: cy.json()}});
    alert("Successfully saved!");
  }
});
<commit_msg>Fix position of added node from double click<commit_after>import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';

import { Graphs } from '/imports/api/graphs.js';

import './app-graph-maker.css';
import './app-graph-maker.html';
import '/public/input/sampleGraph.js';

Template.App_graphMaker.onCreated(function appGraphMakerOnCreated() {
    var self = this;
    self.autorun(function() {
      self.subscribe('allGraphs');
    })
    // const graph_data = Graphs.find();
    // // const graph_data = Graphs.example();
    // // const graph_data = Graphs.findOne({id: 'example-graph'});
    // console.log("LOOK AT ME! LOOK HERE! HEY HEY! I'm the CLIENT!!!");
    // console.log(graph_data);
    // if (graph_data.count() === 0) {
    //     console.log("No data. Sorry.");
    // }
    // else {
    //     console.log("Pa-ching! Data found!")
    // }
});

Template.App_graphMaker.rendered = function() {

  console.log("Rendering graphmaker");
  // var initial_nodes = [];
  let currentGraph = Session.get("currentGraph");
  let initial_nodes = [];
  if (currentGraph.graphData === "EMPTY") {
      initial_nodes = sampleGraph;
  }
  // get initial data
  // $.ajax({
  //     type: "GET",
  //     url: "input/nodes.json",
  //     dataType: "json",
  //     async: false,
  //     success: function (data) {
  //         initial_nodes = data;
  //     }})
  //     .fail(function(xhr, status, error) {
  //         var err = status + ", " + error;
  //         console.log("Request failed: " + err)
  // });
  var row_count = Math.floor(Math.sqrt(initial_nodes.length)) + 1;

  // initialize the graph
  cy = cytoscape({

      container: document.getElementById('cy'),

      ready: function(){
        console.log("Graph is ready!")
      },

      //RB 11/15/16: This should be recalculated dynamically based on the nodes.
      layout: {
          name: 'grid',
          //cols: column_count,
          rows: row_count
      },

      wheelSensitivity: 0.3,

      style: [
          {
              selector: 'node',
              css: {
                  'content': 'data(name)',
                  'height': 100,
                  'width': 100,
                  'text-valign': 'center',
                  'text-halign': 'center',
                  'text-align': 'justify',
                  'background-color': '#eee',
                  'text-wrap': 'wrap',
                  'text-max-width': 200,
                  'text-outline-color': '#eee',
                  'text-outline-width': 3,
                  'border-width': 1,
                  'border-color': '#ccc'
              }
          },
          {
            selector: 'node:selected',
            css: {
              'content': 'data(name)',
              'height': 100,
              'width': 100,
              'text-valign': 'center',
              'text-halign': 'center',
              'text-align': 'justify',
              'background-color': '#eee',
              'text-wrap': 'wrap',
              'text-max-width': 200,
              'text-outline-color': '#eee',
              'text-outline-width': 3,
              'border-width': 4,
              'border-color': 'blue'
            }
          },
          {
              selector: 'node.why-hard',
              css: {
                  'shape': 'triangle',
                  'background-color': '#ffb3b3'
              }
          },

          {
              selector: 'edge',
              css: {
                  'curve-style': 'bezier',
                  'target-arrow-shape': 'triangle',
                  //'line-color': '#eee',
                  'width': 8
              }
          },

          // some style for the ext

          {
              selector: '.edgehandles-hover',
              css: {
                  //'background-color': 'green'
              }
          },

          {
              selector: '.edgehandles-source',
              css: {
                  'border-width': 2,
                  'border-color': 'maroon'
              }
          },

          {
              selector: '.edgehandles-target',
              css: {
                  'border-width': 2,
                  'border-color': 'maroon'
              }
          },

          {
              selector: '.edgehandles-preview, .edgehandles-ghost-edge',
              css: {
                  'line-color': 'maroon',
                  'target-arrow-color': 'maroon',
                  'source-arrow-color': 'maroon'
              }
          }
      ],

      elements: {
          nodes: initial_nodes,
          edges: []
      },
  });

  // remove an edge when it's clicked on
  // cy.on('click', 'edge', function(evnt) {
  //     var target = evnt.cyTarget;
  //     console.log(target.json());
  //     target.remove();
  // });
  // cy.on('keydown', 'nodes', function(evnt) {
  //     // Key codes for backspace and delete
  //     delete_keys = [8,46];
  //     console.log(evnt);
  //     if (delete_keys.indexOf(evnt.keyCode) > -1) {
  //         //cy.selected().remove();
  //         console.log("DELETE!");
  //         cy.$(':selected').remove();
  //     }
  // });

  // Track the position of the last click
  var clickPosition;
  cy.on('click', function(event) {
    clickPosition = event.cyPosition;
  });

  // Add node on double click
  document.getElementById('cy').addEventListener('dblclick', function(event) {
      console.log("Double click event.");
      var data = {
          group: 'nodes',
          name: 'new node'
      };

      cy.add({
          data: data,
          position: clickPosition
      });
  });

  window.addEventListener('keydown', function(event) {
      // Key codes for backspace and delete
      delete_keys = [8,46];

      // Check if node or edge has focus
      if (delete_keys.indexOf(event.keyCode) > -1) {
          //cy.selected().remove();
          console.log("DELETE!");
          cy.$(':selected').remove();
      }
  });

  let toAdd = currentGraph.graphData
  if (toAdd != "EMPTY") {
    toAdd.elements.nodes.forEach(function(node) {
      cy.add(node);
    });
    toAdd.elements.edges.forEach(function(edge) {
      cy.add(edge);
    });
  }

  cy.edgehandles({
      toggleOffOnLeave: true,
      handleNodes: "node",
      handleSize: 10,
      handleColor: 'maroon',
      handleIcon: false,
      edgeType: function(){ return 'flat'; }
  });

  var selectAllOfTheSameType = function(ele) {
      cy.elements().unselect();
      if(ele.isNode()) {
          cy.nodes().select();
      }
      else if(ele.isEdge()) {
          cy.edges().select();
      }
  };

  // controllers for context menus
  cy.contextMenus({
      menuItems: [
        {
          id: 'remove',
          title: 'remove',
          selector: 'node, edge',
          onClickFunction: function (event) {
            var ok = confirm("Are you sure? You cannot undo this action.");
            if (ok) {
              event.cyTarget.remove();
            }
          },
          // hasTrailingDivider: true
        },
        {
          id: 'edit-label',
          title: 'edit label',
          selector: 'node',
          onClickFunction: function (event) {
            // get the current name of the node
            var currentName = event.cyTarget.data('name');
            // prompt the user for a new name
            // (provide current name as default)
            var newName = prompt("Edit node label", currentName);
            if (!newName) {
                // use the old name if the user cancels
                event.cyTarget.data('name', currentName);
            } else {
                // put in the new name
                event.cyTarget.data('name', newName);
            }

          }
        },
        {
          id: 'change-type',
          title: 'change type',
          selector: 'node',
          onClickFunction: function (event) {
            event.cyTarget.toggleClass("why-hard");
          }
        },
        // {
        //   id: 'hide',
        //   title: 'hide',
        //   selector: '*',
        //   onClickFunction: function (event) {
        //     event.cyTarget.hide();
        //   },
        //   disabled: false
        // },
        {
          id: 'add-action',
          title: 'add node',
          coreAsWell: true,
          onClickFunction: function (event) {
            var newName = prompt("Name this node");
            var data = {
                group: 'nodes',
                name: newName
            };

            cy.add({
                data: data,
                position: {
                    x: event.cyPosition.x,
                    y: event.cyPosition.y
                }
            });
          }
        },
        {
          id: 'add-why-hard',
          title: 'add why-hard',
          coreAsWell: true,
          onClickFunction: function (event) {
            var newName = prompt("Name this node");
            var data = {
                group: 'nodes',
                name: newName
            };

            cy.add({
                data: data,
                position: {
                    x: event.cyPosition.x,
                    y: event.cyPosition.y
                },
                classes: "why-hard"
            });
          }
        },
        {
          id: 'remove-selected',
          title: 'remove selected',
          coreAsWell: true,
          onClickFunction: function (event) {
            var ok = confirm("Are you sure? You cannot undo this action.");
            if (ok) {
              cy.$(':selected').remove();
            }
          }
        },
        {
          id: 'select-all-nodes',
          title: 'select all nodes',
          selector: 'node',
          onClickFunction: function (event) {
            selectAllOfTheSameType(event.cyTarget);
          }
        },
        {
          id: 'select-all-edges',
          title: 'select all edges',
          selector: 'edge',
          onClickFunction: function (event) {
            selectAllOfTheSameType(event.cyTarget);
          }
        }
    ]
  });

  // initiate "draw mode" for drawing edges
  document.querySelector('#draw-mode').addEventListener('click', function(e) {
      var draw_button = e.target;
      var draw_mode = draw_button.getAttribute("data-draw-mode");
      console.log(draw_mode);
      if (draw_mode === "drawon") {
          draw_mode = "drawoff";
          draw_button_switch = "OFF";
      }
      else {
          draw_mode = "drawon";
          draw_button_switch = "ON";
      }
      cy.edgehandles(draw_mode);
      draw_button.setAttribute("data-draw-mode", draw_mode);
      draw_button.innerHTML = "Draw mode: " + draw_button_switch;
  });

  // print the current state of the graph to console
  // when user clicks on the "record" button
  document.getElementById('record-json').addEventListener('click', function(){
      //this is an object, not an iterable
      var nodes = cy.nodes();
      var nodes_arr = [];
      for (var i = 0; i < nodes.length; i++) {
        nodes_arr.push(nodes[i].data());
      }
      var edges = cy.edges();
            var edges_arr = [];
      for (var i = 0; i < edges.length; i++) {
        edges_arr.push(edges[i].data());
      }

      //console.log(edges.json());
      console.log(JSON.stringify(nodes_arr));
      console.log(JSON.stringify(edges_arr));
      //export the graph in a JSON format comparable to that
      //when initialized
      console.log(JSON.stringify(cy.json()));
      var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(cy.json(), null, 3));
      var dlAnchorElem = document.getElementById('export-json');
      dlAnchorElem.setAttribute("href", dataStr);
      dlAnchorElem.setAttribute("download", "my-graph.json");
      dlAnchorElem.click();
      // document.getElementById("export-json").setAttribute("href", cy.json());
      // document.getElementById("export-json").click();
  });

  // document.getElementById('record-png').addEventListener('click', function(){
  //   document.getElementById("export-png").setAttribute("href", cy.png());
  //   document.getElementById("export-png").click();
  // });

}

Template.App_graphMaker.helpers({
  graph: function() {
    console.log(Graphs.findOne());
    return Graphs.find().count();
  }
});

Template.App_graphMaker.events({
  'click #record-png': function() {
     document.getElementById("export-png").setAttribute("href", cy.png());
    document.getElementById("export-png").click();
  },
  'click #record-json': function() {
    var nodes = cy.nodes();
    var nodes_arr = [];
    for (var i = 0; i < nodes.length; i++) {
      nodes_arr.push(nodes[i].data());
    }
    var edges = cy.edges();
          var edges_arr = [];
    for (var i = 0; i < edges.length; i++) {
      edges_arr.push(edges[i].data());
    }

    //console.log(edges.json());
    console.log(JSON.stringify(nodes_arr));
    console.log(JSON.stringify(edges_arr));
    //export the graph in a JSON format comparable to that
    //when initialized
    console.log(JSON.stringify(cy.json()));
    var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(cy.json(), null, 3));
    var dlAnchorElem = document.getElementById('export-json');
    dlAnchorElem.setAttribute("href", dataStr);
    dlAnchorElem.setAttribute("download", "my-graph.json");
    dlAnchorElem.click();
  },
  'click #save-changes': function() {
    let newName = prompt("(Optional) name this graph", "Untitled graph");
    Graphs.update({_id: Session.get("currentGraph")._id},{$set: {graphData: cy.json()}});
    alert("Successfully saved!");
  }
});
<|endoftext|>