<commit_before>/*eslint-env browser*/
import React from "react";
import * as globals from "../../util/globals";
import {dataFont, infoPanelStyles} from "../../globalStyles";
import { prettyString } from "./tipSelectedPanel";

const InfoPanel = ({tree, hovered, responsive, viewer}) => {

  /* this is a function - we can bail early */
  if (!(tree && hovered)) {
    return null
  }

  /**
   * This maps tree coordinates to coordinates on the svg.
   * @param  {float} x
   * @param  {float}} y
   * @param  {reactSVGpanZoom} V viewer state
   * @return {[x,y]} point on plane
   */
  const treePosToViewer = (x,y, V) =>{
    const dx = (x*V.a + V.e); //this is the distance form the upper left corner
    const dy = (y*V.d + V.f); //at the current zoome level
    return {x: dx, y: dy};
  }

  /* I have no idea how these should acually be calculated, but apparently
  they are relative to the HTML body */
  const viewerState = viewer.getValue();
  const xOffset = 10;
  const yOffset = 10;

  const width = 200;
  const height = 200;
  const pos = treePosToViewer(hovered.d.xTip, hovered.d.yTip, viewerState);
  const left = pos.x + ((pos.x<viewerState.viewerWidth *0.7)? xOffset : (-width - 3*xOffset));
  const top =  pos.y + ((pos.y<viewerState.viewerHeight*0.7)? 3*yOffset : (-height-yOffset));

  const styles = {
    container: {
      position: "absolute",
      width,
      padding: "10px",
      borderRadius: 10,
      zIndex: 1000,
      pointerEvents: "none",
      fontFamily: infoPanelStyles.panel.fontFamily,
      fontSize: 14,
      lineHeight: 1,
      fontWeight: infoPanelStyles.panel.fontWeight,
      color: infoPanelStyles.panel.color,
      backgroundColor: infoPanelStyles.panel.backgroundColor,
      wordWrap: "break-word",
    }
  };
  if (pos.x<viewerState.viewerWidth*0.7){
    styles.container.left = pos.x + xOffset;
  }else{
    styles.container.right = viewerState.viewerWidth-pos.x + xOffset;
  }
  if (pos.y<viewerState.viewerHeight*0.7){
    styles.container.top = pos.y + 4*yOffset;
  }else{
    styles.container.bottom = viewerState.viewerHeight-pos.y+yOffset;
  }

  /* getX methods return styled JSX */
  const getMutations = (d) => {
    let mutations = "";
    if ((typeof d.muts !== "undefined") && (globals.mutType === "nuc") && (d.muts.length)) {
      const numMutsToShow = 5;
      let tmp_muts = d.muts;
      const nmuts = tmp_muts.length;
      tmp_muts = tmp_muts.slice(0, Math.min(numMutsToShow, nmuts));
      mutations += tmp_muts.join(", ");
      if (nmuts > numMutsToShow) {
        mutations += " + " + (nmuts - numMutsToShow) + " more";
      }
    }
    return (
      mutations !== "" ?
      Mutations at {mutations} :
      No mutations
    );
  };
  const getFrequencies = (d) => {
    if (d.frequency !== undefined) {
      const disp = "Frequency: " + (100 * d.frequency).toFixed(1) + "%";
      return (
{disp}
);
    }
    return null;
  }

  const makeInfoPanel = () => {
    if (hovered.type === ".tip") {
      const tip = hovered.d;
      return (

              {tip.n.attr.strain}

              {prettyString(tip.n.attr.country)}, {prettyString(tip.n.attr.date)}

              Click on tip to display more info

      );
    } else { /* BRANCH */
      const branch = hovered.d;
      return (

              {`Branch with ${branch.n.fullTipCount} children`}

              {getFrequencies(branch.n)}
              {getMutations(branch.n)}

              Click on branch to zoom into this clade

      );
    }
  };

  return (
    makeInfoPanel()
  );
};

export default InfoPanel;
<commit_msg>removed unused lines<commit_after>/*eslint-env browser*/
import React from "react";
import * as globals from "../../util/globals";
import {dataFont, infoPanelStyles} from "../../globalStyles";
import { prettyString } from "./tipSelectedPanel";

const InfoPanel = ({tree, hovered, responsive, viewer}) => {

  /* this is a function - we can bail early */
  if (!(tree && hovered)) {
    return null
  }

  /**
   * This maps tree coordinates to coordinates on the svg.
   * @param  {float} x
   * @param  {float}} y
   * @param  {reactSVGpanZoom} V viewer state
   * @return {[x,y]} point on plane
   */
  const treePosToViewer = (x,y, V) =>{
    const dx = (x*V.a + V.e); //this is the distance form the upper left corner
    const dy = (y*V.d + V.f); //at the current zoome level
    return {x: dx, y: dy};
  }

  /* I have no idea how these should acually be calculated, but apparently
  they are relative to the HTML body */
  const viewerState = viewer.getValue();
  const xOffset = 10;
  const yOffset = 10;

  const width = 200;
  const pos = treePosToViewer(hovered.d.xTip, hovered.d.yTip, viewerState);

  const styles = {
    container: {
      position: "absolute",
      width,
      padding: "10px",
      borderRadius: 10,
      zIndex: 1000,
      pointerEvents: "none",
      fontFamily: infoPanelStyles.panel.fontFamily,
      fontSize: 14,
      lineHeight: 1,
      fontWeight: infoPanelStyles.panel.fontWeight,
      color: infoPanelStyles.panel.color,
      backgroundColor: infoPanelStyles.panel.backgroundColor,
      wordWrap: "break-word",
    }
  };
  if (pos.x<viewerState.viewerWidth*0.7){
    styles.container.left = pos.x + xOffset;
  }else{
    styles.container.right = viewerState.viewerWidth-pos.x + xOffset;
  }
  if (pos.y<viewerState.viewerHeight*0.7){
    styles.container.top = pos.y + 4*yOffset;
  }else{
    styles.container.bottom = viewerState.viewerHeight-pos.y+yOffset;
  }

  /* getX methods return styled JSX */
  const getMutations = (d) => {
    let mutations = "";
    if ((typeof d.muts !== "undefined") && (globals.mutType === "nuc") && (d.muts.length)) {
      const numMutsToShow = 5;
      let tmp_muts = d.muts;
      const nmuts = tmp_muts.length;
      tmp_muts = tmp_muts.slice(0, Math.min(numMutsToShow, nmuts));
      mutations += tmp_muts.join(", ");
      if (nmuts > numMutsToShow) {
        mutations += " + " + (nmuts - numMutsToShow) + " more";
      }
    }
    return (
      mutations !== "" ?
      Mutations at {mutations} :
      No mutations
    );
  };
  const getFrequencies = (d) => {
    if (d.frequency !== undefined) {
      const disp = "Frequency: " + (100 * d.frequency).toFixed(1) + "%";
      return (
{disp}
);
    }
    return null;
  }

  const makeInfoPanel = () => {
    if (hovered.type === ".tip") {
      const tip = hovered.d;
      return (

              {tip.n.attr.strain}

              {prettyString(tip.n.attr.country)}, {prettyString(tip.n.attr.date)}

              Click on tip to display more info

      );
    } else { /* BRANCH */
      const branch = hovered.d;
      return (

              {`Branch with ${branch.n.fullTipCount} children`}

              {getFrequencies(branch.n)}
              {getMutations(branch.n)}

              Click on branch to zoom into this clade

      );
    }
  };

  return (
    makeInfoPanel()
  );
};

export default InfoPanel;
<|endoftext|>


<commit_before>var RPYeti = RPYeti || {};

RPYeti.controls = (function() {
	var self;

	var PI_2 = Math.PI / 2.0,
		TYPE = { DEFAULT: 0, MOUSEOVER: 1, POINTERLOCK: 2, ORIENTATION: 3 },
		ACTION = { FIRE: 'isFiring', MOVEUP: 'isLookUp', MOVEDOWN: 'isLookDown', MOVELEFT: 'isPanLeft', MOVERIGHT: 'isPanRight' };

	return {

		/** Public Properties **/
		isHooked: true,
		state: {},
		keyMap: {},
		controlType: TYPE.DEFAULT,
		publisher: $(document),

		yawGimbal: new THREE.Object3D(),
		pitchGimbal: new THREE.Object3D(),

		/** Constructor **/

		init: function(game) {
			self = this;

			// clear all states
			for( var action in ACTION ) {
				this.state[ ACTION[ action ] ] = false;
			}

			// build keymap from config
			for( var key in RPYeti.config.controls.keys ) {
				var codes = RPYeti.config.controls.keys[ key ];
				for( var code in codes ) {
					this.keyMap[ codes[ code ] ] = key;
				}
			}

			// attach to game object
			this.game = game;
			this.element = this.game.renderer.domElement;
			this.camera = this.game.camera;

			// mount camera on gimbals
			this.pitchGimbal.add( this.camera );
			this.yawGimbal.position.y = RPYeti.config.camera.height;
			this.yawGimbal.rotation.y = RPYeti.config.camera.yaw;
			this.yawGimbal.add( this.pitchGimbal );
			this.game.scene.add( this.yawGimbal );

			// initialize control schemes
			this.initOrientation();
			this.initPointerLock();
			this.initMouseLook();
			this.initMouseFire();
			this.initKeys();
			this.initTouch();

			return this;
		},

		initKeys: function() {
			this.publisher.on('keydown', function(e) {
				if ( e.altKey ) {
					return;
				}
				if( self.keyMap[ e.keyCode ] ) {
					self.state[ ACTION[ self.keyMap[ e.keyCode ] ] ] = true;
				} else  {
					e.preventDefault();
				}
			})
			.on('keyup', function(e) {
				if( self.keyMap[ e.keyCode ] ) {
					self.state[ ACTION[ self.keyMap[ e.keyCode ] ] ] = false;

					if( self.isHooked && self.keyMap[ e.keyCode ] == 'FIRE' ) {
						self.hook();
					}
				} else  {
					e.preventDefault();
				}
			});
		},

		initMouseLook: function() {

		},

		initMouseFire: function() {
			this.publisher.on('mousedown', function(e) {
				self.state.isFiring = true;
				e.preventDefault();
			})
			.on('mouseup', function(e) {
				self.state.isFiring = false;
				e.preventDefault();

				if( self.isHooked ) {
					self.hook();
				}
			})
			.on('contextMenu', function(e) {
				e.preventDefault();
			});
		},

		initTouch: function() {
			this.publisher.on('touchstart', function(e) {
				self.state.isFiring = true;
				e.preventDefault();
			})
			.on('touchmove', function(e) {
				e.preventDefault();
			})
			.on('touchend', function(e) {
				self.state.isFiring = false;
				e.preventDefault();

				if( self.isHooked ) {
					self.hook();
				}
			});
		},

		initPointerLock: function() {
			var pointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
			if( self.controlType == TYPE.ORIENTATION || ! pointerLock ) {
				return;
			}
			var element = document.body,
				prefix = ( document.mozPointerLockElement === null ) ? 'mozpointerlock' : ( ( document.webkitPointerLockElement === null ) ? 'webkitpointerlock' : 'pointerlock' );
			element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock;

			document.addEventListener( prefix + 'change', function( event ) {
				if ( element === ( document.pointerLockElement || document.mozPointerLockElement || document.webkitPointerLockElement ) ) {
					self.controlType = TYPE.POINTERLOCK;
				} else {
					self.controlType = TYPE.DEFAULT;
				}
			});

			document.addEventListener('mousemove', function( event ) {
				if( self.controlType != TYPE.POINTERLOCK ) {
					return;
				}
				var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
				var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
				self.yawGimbal.rotation.y -= movementX * RPYeti.config.controls.mouseSpeed;
				self.pitchGimbal.rotation.x -= movementY * RPYeti.config.controls.mouseSpeed;
				self.pitchGimbal.rotation.x = Math.max( - PI_2, Math.min( PI_2, self.pitchGimbal.rotation.x ) );
			});

			document.addEventListener( prefix + 'error', function( event ) {
				console.log( 'pointerlock error ', event);
			});
			this.publisher.on('dblclick', function() {
				if( self.controlType != TYPE.POINTERLOCK ) {
					element.requestPointerLock();
				}
			});
		},

		initOrientation: function() {
			var setOrientationControls = function(e) {
				if (!e.alpha) {
					return;
				}
				this.controlType = TYPE.ORIENTATION;
				window.removeEventListener('deviceorientation', setOrientationControls, true);

				if( self.controls ) {
					self.controls.dispose();
				}
				// reset camera mount rotation
				self.camera.rotation.set( 0, 0, 0 );
				self.yawGimbal.rotation.set( 0, 0, 0 );
				self.pitchGimbal.rotation.set( 0, 0, 0 );

				self.controls = new THREE.DeviceOrientationControls( self.yawGimbal, true );
				self.controls.connect();
				self.controls.update();

				self.element.addEventListener('click', self.game.fullscreen, false);
			}
			window.addEventListener('deviceorientation', setOrientationControls, true);
		},

		update: function(delta) {
			if( self.controls ) {
				self.controls.update( delta );
			}

			var dx = RPYeti.config.controls.keySpeed.x * delta * ( ( self.state.isLookUp ? 1 : 0 ) + ( self.state.isLookDown ? -1 : 0 ) ),
				dy = RPYeti.config.controls.keySpeed.y * delta * ( ( self.state.isPanLeft ? 1 : 0 ) + ( self.state.isPanRight ? -1 : 0 ) );

			self.yawGimbal.rotation.y += dy;
			self.pitchGimbal.rotation.x += dx;
			self.pitchGimbal.rotation.x = Math.max( - PI_2, Math.min( PI_2, self.pitchGimbal.rotation.x ) );
		},

		getDirection: function() {
			if( self.controlType == TYPE.ORIENTATION ) {
				return self.camera.getWorldDirection();
			}
			var direction = new THREE.Vector3( 0, 0, -1 ),
		    	rotation = new THREE.Euler( 0, 0, 0, 'YXZ' ),
				vector = self.yawGimbal.position.clone();

			rotation.set( self.pitchGimbal.rotation.x, self.yawGimbal.rotation.y, 0 );
		    vector.copy( direction ).applyEuler( rotation )
		    return vector;
		},

		getCamera: function() {
			return self.yawGimbal;
		},

		setHook: function (hook) {
			if (typeof hook === 'function') {
				this.hook = hook;
				this.isHooked = true;
			} else {
				delete this.hook;
				this.isHooked = false;
			}
		},

	};

})();
<commit_msg>Default value of isHooked should not be true, otherwise starting a game at level 1 no longer works<commit_after>var RPYeti = RPYeti || {};

RPYeti.controls = (function() {
	var self;

	var PI_2 = Math.PI / 2.0,
		TYPE = { DEFAULT: 0, MOUSEOVER: 1, POINTERLOCK: 2, ORIENTATION: 3 },
		ACTION = { FIRE: 'isFiring', MOVEUP: 'isLookUp', MOVEDOWN: 'isLookDown', MOVELEFT: 'isPanLeft', MOVERIGHT: 'isPanRight' };

	return {

		/** Public Properties **/
		isHooked: false,
		state: {},
		keyMap: {},
		controlType: TYPE.DEFAULT,
		publisher: $(document),

		yawGimbal: new THREE.Object3D(),
		pitchGimbal: new THREE.Object3D(),

		/** Constructor **/

		init: function(game) {
			self = this;

			// clear all states
			for( var action in ACTION ) {
				this.state[ ACTION[ action ] ] = false;
			}

			// build keymap from config
			for( var key in RPYeti.config.controls.keys ) {
				var codes = RPYeti.config.controls.keys[ key ];
				for( var code in codes ) {
					this.keyMap[ codes[ code ] ] = key;
				}
			}

			// attach to game object
			this.game = game;
			this.element = this.game.renderer.domElement;
			this.camera = this.game.camera;

			// mount camera on gimbals
			this.pitchGimbal.add( this.camera );
			this.yawGimbal.position.y = RPYeti.config.camera.height;
			this.yawGimbal.rotation.y = RPYeti.config.camera.yaw;
			this.yawGimbal.add( this.pitchGimbal );
			this.game.scene.add( this.yawGimbal );

			// initialize control schemes
			this.initOrientation();
			this.initPointerLock();
			this.initMouseLook();
			this.initMouseFire();
			this.initKeys();
			this.initTouch();

			return this;
		},

		initKeys: function() {
			this.publisher.on('keydown', function(e) {
				if ( e.altKey ) {
					return;
				}
				if( self.keyMap[ e.keyCode ] ) {
					self.state[ ACTION[ self.keyMap[ e.keyCode ] ] ] = true;
				} else  {
					e.preventDefault();
				}
			})
			.on('keyup', function(e) {
				if( self.keyMap[ e.keyCode ] ) {
					self.state[ ACTION[ self.keyMap[ e.keyCode ] ] ] = false;

					if( self.isHooked && self.keyMap[ e.keyCode ] == 'FIRE' ) {
						self.hook();
					}
				} else  {
					e.preventDefault();
				}
			});
		},

		initMouseLook: function() {

		},

		initMouseFire: function() {
			this.publisher.on('mousedown', function(e) {
				self.state.isFiring = true;
				e.preventDefault();
			})
			.on('mouseup', function(e) {
				self.state.isFiring = false;
				e.preventDefault();

				if( self.isHooked ) {
					self.hook();
				}
			})
			.on('contextMenu', function(e) {
				e.preventDefault();
			});
		},

		initTouch: function() {
			this.publisher.on('touchstart', function(e) {
				self.state.isFiring = true;
				e.preventDefault();
			})
			.on('touchmove', function(e) {
				e.preventDefault();
			})
			.on('touchend', function(e) {
				self.state.isFiring = false;
				e.preventDefault();

				if( self.isHooked ) {
					self.hook();
				}
			});
		},

		initPointerLock: function() {
			var pointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
			if( self.controlType == TYPE.ORIENTATION || ! pointerLock ) {
				return;
			}
			var element = document.body,
				prefix = ( document.mozPointerLockElement === null ) ? 'mozpointerlock' : ( ( document.webkitPointerLockElement === null ) ? 'webkitpointerlock' : 'pointerlock' );
			element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock;

			document.addEventListener( prefix + 'change', function( event ) {
				if ( element === ( document.pointerLockElement || document.mozPointerLockElement || document.webkitPointerLockElement ) ) {
					self.controlType = TYPE.POINTERLOCK;
				} else {
					self.controlType = TYPE.DEFAULT;
				}
			});

			document.addEventListener('mousemove', function( event ) {
				if( self.controlType != TYPE.POINTERLOCK ) {
					return;
				}
				var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
				var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
				self.yawGimbal.rotation.y -= movementX * RPYeti.config.controls.mouseSpeed;
				self.pitchGimbal.rotation.x -= movementY * RPYeti.config.controls.mouseSpeed;
				self.pitchGimbal.rotation.x = Math.max( - PI_2, Math.min( PI_2, self.pitchGimbal.rotation.x ) );
			});

			document.addEventListener( prefix + 'error', function( event ) {
				console.log( 'pointerlock error ', event);
			});
			this.publisher.on('dblclick', function() {
				if( self.controlType != TYPE.POINTERLOCK ) {
					element.requestPointerLock();
				}
			});
		},

		initOrientation: function() {
			var setOrientationControls = function(e) {
				if (!e.alpha) {
					return;
				}
				this.controlType = TYPE.ORIENTATION;
				window.removeEventListener('deviceorientation', setOrientationControls, true);

				if( self.controls ) {
					self.controls.dispose();
				}
				// reset camera mount rotation
				self.camera.rotation.set( 0, 0, 0 );
				self.yawGimbal.rotation.set( 0, 0, 0 );
				self.pitchGimbal.rotation.set( 0, 0, 0 );

				self.controls = new THREE.DeviceOrientationControls( self.yawGimbal, true );
				self.controls.connect();
				self.controls.update();

				self.element.addEventListener('click', self.game.fullscreen, false);
			}
			window.addEventListener('deviceorientation', setOrientationControls, true);
		},

		update: function(delta) {
			if( self.controls ) {
				self.controls.update( delta );
			}

			var dx = RPYeti.config.controls.keySpeed.x * delta * ( ( self.state.isLookUp ? 1 : 0 ) + ( self.state.isLookDown ? -1 : 0 ) ),
				dy = RPYeti.config.controls.keySpeed.y * delta * ( ( self.state.isPanLeft ? 1 : 0 ) + ( self.state.isPanRight ? -1 : 0 ) );

			self.yawGimbal.rotation.y += dy;
			self.pitchGimbal.rotation.x += dx;
			self.pitchGimbal.rotation.x = Math.max( - PI_2, Math.min( PI_2, self.pitchGimbal.rotation.x ) );
		},

		getDirection: function() {
			if( self.controlType == TYPE.ORIENTATION ) {
				return self.camera.getWorldDirection();
			}
			var direction = new THREE.Vector3( 0, 0, -1 ),
		    	rotation = new THREE.Euler( 0, 0, 0, 'YXZ' ),
				vector = self.yawGimbal.position.clone();

			rotation.set( self.pitchGimbal.rotation.x, self.yawGimbal.rotation.y, 0 );
		    vector.copy( direction ).applyEuler( rotation )
		    return vector;
		},

		getCamera: function() {
			return self.yawGimbal;
		},

		setHook: function (hook) {
			if (typeof hook === 'function') {
				this.hook = hook;
				this.isHooked = true;
			} else {
				delete this.hook;
				this.isHooked = false;
			}
		},

	};

})();
<|endoftext|>


<commit_before>import React from 'react';

import SpellLink from 'common/SpellLink';
import Icon from 'common/Icon';
import { formatNumber } from 'common/format';

import SmallStatisticBox, { STATISTIC_ORDER } from 'Main/SmallStatisticBox';

import Analyzer from 'Parser/Core/Analyzer';
import HealingDone from 'Parser/Core/Modules/HealingDone';
import DamageDone from 'Parser/Core/Modules/DamageDone';
import DamageTaken from 'Parser/Core/Modules/DamageTaken';

// http://www.wowhead.com/uncategorized-spells/name:Vantus+Rune:?filter=29;42;0 $.makeArray($('.listview-cleartext[href^="/spell="]')).map(item => `${item.href.replace(/^.*spell=([0-9]+)$/, '$1')}, // ${item.innerText}`).join("\n")
// buff id: boss id
// TODO: Make files for the old bosses below in the Raids folder, adding back their Vantus Rune ids. Or don't since nobody cares about them anymore. In that case remove this code when BfA is released.
// const VANTUS_RUNE_SPELL_IDS = {
//   192761: bosses.EmeraldNightmare.NYTHENDRA, // Vantus Rune: Nythendra
//   192765: bosses.EmeraldNightmare.ELERETHE_RENFERAL, // Vantus Rune: Elerethe Renferal
//   192762: bosses.EmeraldNightmare.ILGYNOTH_THE_HEART_OF_CORRUPTION, // Vantus Rune: Il'gynoth, The Heart of Corruption
//   191464: bosses.EmeraldNightmare.URSOC, // Vantus Rune: Ursoc
//   192763: bosses.EmeraldNightmare.DRAGONS_OF_NIGHTMARE, // Vantus Rune: Dragons of Nightmare
//   192766: bosses.EmeraldNightmare.CENARIUS, // Vantus Rune: Cenarius
//   192764: bosses.EmeraldNightmare.XAVIUS, // Vantus Rune: Xavius
//   // Trial of Valor
//   229174: bosses.TrialOfValor.ODYN, // Vantus Rune: Odyn
//   229175: bosses.TrialOfValor.GUARM, // Vantus Rune: Guarm
//   229176: bosses.TrialOfValor.HELYA, // Vantus Rune: Helya
//   // The Nighthold
//   192767: bosses.TheNighthold.SKORPYRON, // Vantus Rune: Skorpyron
//   192768: bosses.TheNighthold.CHRONOMATIC_ANOMALY, // Vantus Rune: Chronomatic Anomaly
//   192769: bosses.TheNighthold.TRILLIAX, // Vantus Rune: Trilliax
//   192770: bosses.TheNighthold.SPELLBLADE_ALURIEL, // Vantus Rune: Spellblade Aluriel
//   192771: bosses.TheNighthold.TICHONDRIUS, // Vantus Rune: Tichondrius
//   192773: bosses.TheNighthold.KROSUS, // Vantus Rune: Krosus
//   192772: bosses.TheNighthold.HIGH_BOTANIST_TELARN, // Vantus Rune: High Botanist Tel'arn
//   192774: bosses.TheNighthold.STAR_AUGUR_ETRAEUS, // Vantus Rune: Star Augur Etraeus
//   192775: bosses.TheNighthold.GRAND_MAGISTRIX_ELISANDE, // Vantus Rune: Grand Magistrix Elisande
//   192776: bosses.TheNighthold.GULDAN, // Vantus Rune: Gul'dan
//   // Tomb of Sargeras
//   237821: bosses.TombOfSargeras.GOROTH, // Vantus Rune: Goroth
//   237828: bosses.TombOfSargeras.DEMONIC_INQUISITION, // Vantus Rune: Demonic Inquisition
//   237824: bosses.TombOfSargeras.HARJATAN, // Vantus Rune: Harjatan
//   237826: bosses.TombOfSargeras.MISTRESS_SASSZINE, // Vantus Rune: Mistress Sassz'ine
//   237822: bosses.TombOfSargeras.SISTERS_OF_THE_MOON, // Vantus Rune: Sisters of the Moon
//   237827: bosses.TombOfSargeras.THE_DESOLATE_HOST, // Vantus Rune: The Desolate Host
//   237820: bosses.TombOfSargeras.FALLEN_AVATAR, // Vantus Rune: Fallen Avatar
//   237825: bosses.TombOfSargeras.KILJAEDEN, // Vantus Rune: Kil'jaeden
// };
const VANTUS_RUNE_VERSATILITY = 20.80; //85 at level 120
const VERSATILITY_PER_PERCENT_THROUGHPUT = 2080; //8500 at level 120
const VERSATILITY_PER_PERCENT_DAMAGE_REDUCTION = VERSATILITY_PER_PERCENT_THROUGHPUT * 2;
const VANTUS_RUNE_PERCENTAGE_THROUGHPUT = VANTUS_RUNE_VERSATILITY / VERSATILITY_PER_PERCENT_THROUGHPUT;
const VANTUS_RUNE_PERCENTAGE_DAMAGE_REDUCTION = VANTUS_RUNE_VERSATILITY / VERSATILITY_PER_PERCENT_DAMAGE_REDUCTION;

class VantusRune extends Analyzer {
  static dependencies = {
    healingDone: HealingDone,
    damageDone: DamageDone,
    damageTaken: DamageTaken,
  };

  activeRune = null;
  constructor(...args) {
    super(...args);
    const boss = this.owner.boss;

    /** @var {number|null} */
    const vantusRuneBuffId = boss ? boss.fight.vantusRuneBuffId : null;
    if (vantusRuneBuffId) {
      const match = this.selectedCombatant.getBuff(vantusRuneBuffId);
      if (match !== undefined) {
        this.activeRune = match;
      }
    }
    this.active = this.activeRune !== null;
  }

  statistic() {
    const fightDuration = this.owner.fightDuration;

    const damageDone = this.damageDone.total.effective - (this.damageDone.total.effective / (1 + VANTUS_RUNE_PERCENTAGE_THROUGHPUT));
    const healingDone = this.healingDone.total.effective - (this.healingDone.total.effective / (1 + VANTUS_RUNE_PERCENTAGE_THROUGHPUT));
    const damageReduced = (this.damageTaken.total.effective / (1 - VANTUS_RUNE_PERCENTAGE_DAMAGE_REDUCTION)) - this.damageTaken.total.effective;

    return (
      <SmallStatisticBox
        icon={(
          <SpellLink id={this.activeRune.ability.guid} icon={false}>
            <Icon icon={this.activeRune.ability.abilityIcon} />
          </SpellLink>
        )}
        value={damageDone > healingDone ? `${formatNumber(damageDone / fightDuration * 1000)} DPS` : `${formatNumber(healingDone / fightDuration * 1000)} HPS`}
        label="Vantus Rune gain"
        tooltip={`The throughput gain from using a Vantus Rune. You gained ${formatNumber(damageDone / fightDuration * 1000)} damage per second (DPS) and ${formatNumber(healingDone / fightDuration * 1000)} healing per second (HPS), and reduced your damage taken by ${formatNumber(damageReduced / fightDuration * 1000)} per second (DRPS).`}
      />
    );
  }
  statisticOrder = STATISTIC_ORDER.UNIMPORTANT();
}

export default VantusRune;
<commit_msg>updated vantus rune versatility<commit_after>import React from 'react';

import SpellLink from 'common/SpellLink';
import Icon from 'common/Icon';
import { formatNumber } from 'common/format';

import SmallStatisticBox, { STATISTIC_ORDER } from 'Main/SmallStatisticBox';

import Analyzer from 'Parser/Core/Analyzer';
import HealingDone from 'Parser/Core/Modules/HealingDone';
import DamageDone from 'Parser/Core/Modules/DamageDone';
import DamageTaken from 'Parser/Core/Modules/DamageTaken';

// http://www.wowhead.com/uncategorized-spells/name:Vantus+Rune:?filter=29;42;0 $.makeArray($('.listview-cleartext[href^="/spell="]')).map(item => `${item.href.replace(/^.*spell=([0-9]+)$/, '$1')}, // ${item.innerText}`).join("\n")
// buff id: boss id
// TODO: Make files for the old bosses below in the Raids folder, adding back their Vantus Rune ids. Or don't since nobody cares about them anymore. In that case remove this code when BfA is released.
// const VANTUS_RUNE_SPELL_IDS = {
//   192761: bosses.EmeraldNightmare.NYTHENDRA, // Vantus Rune: Nythendra
//   192765: bosses.EmeraldNightmare.ELERETHE_RENFERAL, // Vantus Rune: Elerethe Renferal
//   192762: bosses.EmeraldNightmare.ILGYNOTH_THE_HEART_OF_CORRUPTION, // Vantus Rune: Il'gynoth, The Heart of Corruption
//   191464: bosses.EmeraldNightmare.URSOC, // Vantus Rune: Ursoc
//   192763: bosses.EmeraldNightmare.DRAGONS_OF_NIGHTMARE, // Vantus Rune: Dragons of Nightmare
//   192766: bosses.EmeraldNightmare.CENARIUS, // Vantus Rune: Cenarius
//   192764: bosses.EmeraldNightmare.XAVIUS, // Vantus Rune: Xavius
//   // Trial of Valor
//   229174: bosses.TrialOfValor.ODYN, // Vantus Rune: Odyn
//   229175: bosses.TrialOfValor.GUARM, // Vantus Rune: Guarm
//   229176: bosses.TrialOfValor.HELYA, // Vantus Rune: Helya
//   // The Nighthold
//   192767: bosses.TheNighthold.SKORPYRON, // Vantus Rune: Skorpyron
//   192768: bosses.TheNighthold.CHRONOMATIC_ANOMALY, // Vantus Rune: Chronomatic Anomaly
//   192769: bosses.TheNighthold.TRILLIAX, // Vantus Rune: Trilliax
//   192770: bosses.TheNighthold.SPELLBLADE_ALURIEL, // Vantus Rune: Spellblade Aluriel
//   192771: bosses.TheNighthold.TICHONDRIUS, // Vantus Rune: Tichondrius
//   192773: bosses.TheNighthold.KROSUS, // Vantus Rune: Krosus
//   192772: bosses.TheNighthold.HIGH_BOTANIST_TELARN, // Vantus Rune: High Botanist Tel'arn
//   192774: bosses.TheNighthold.STAR_AUGUR_ETRAEUS, // Vantus Rune: Star Augur Etraeus
//   192775: bosses.TheNighthold.GRAND_MAGISTRIX_ELISANDE, // Vantus Rune: Grand Magistrix Elisande
//   192776: bosses.TheNighthold.GULDAN, // Vantus Rune: Gul'dan
//   // Tomb of Sargeras
//   237821: bosses.TombOfSargeras.GOROTH, // Vantus Rune: Goroth
//   237828: bosses.TombOfSargeras.DEMONIC_INQUISITION, // Vantus Rune: Demonic Inquisition
//   237824: bosses.TombOfSargeras.HARJATAN, // Vantus Rune: Harjatan
//   237826: bosses.TombOfSargeras.MISTRESS_SASSZINE, // Vantus Rune: Mistress Sassz'ine
//   237822: bosses.TombOfSargeras.SISTERS_OF_THE_MOON, // Vantus Rune: Sisters of the Moon
//   237827: bosses.TombOfSargeras.THE_DESOLATE_HOST, // Vantus Rune: The Desolate Host
//   237820: bosses.TombOfSargeras.FALLEN_AVATAR, // Vantus Rune: Fallen Avatar
//   237825: bosses.TombOfSargeras.KILJAEDEN, // Vantus Rune: Kil'jaeden
// };
const VANTUS_RUNE_VERSATILITY = 68;
const VERSATILITY_PER_PERCENT_THROUGHPUT = 2080;
const VERSATILITY_PER_PERCENT_DAMAGE_REDUCTION = VERSATILITY_PER_PERCENT_THROUGHPUT * 2;
const VANTUS_RUNE_PERCENTAGE_THROUGHPUT = VANTUS_RUNE_VERSATILITY / VERSATILITY_PER_PERCENT_THROUGHPUT;
const VANTUS_RUNE_PERCENTAGE_DAMAGE_REDUCTION = VANTUS_RUNE_VERSATILITY / VERSATILITY_PER_PERCENT_DAMAGE_REDUCTION;

class VantusRune extends Analyzer {
  static dependencies = {
    healingDone: HealingDone,
    damageDone: DamageDone,
    damageTaken: DamageTaken,
  };

  activeRune = null;
  constructor(...args) {
    super(...args);
    const boss = this.owner.boss;

    /** @var {number|null} */
    const vantusRuneBuffId = boss ? boss.fight.vantusRuneBuffId : null;
    if (vantusRuneBuffId) {
      const match = this.selectedCombatant.getBuff(vantusRuneBuffId);
      if (match !== undefined) {
        this.activeRune = match;
      }
    }
    this.active = this.activeRune !== null;
  }

  statistic() {
    const fightDuration = this.owner.fightDuration;

    const damageDone = this.damageDone.total.effective - (this.damageDone.total.effective / (1 + VANTUS_RUNE_PERCENTAGE_THROUGHPUT));
    const healingDone = this.healingDone.total.effective - (this.healingDone.total.effective / (1 + VANTUS_RUNE_PERCENTAGE_THROUGHPUT));
    const damageReduced = (this.damageTaken.total.effective / (1 - VANTUS_RUNE_PERCENTAGE_DAMAGE_REDUCTION)) - this.damageTaken.total.effective;

    return (
      <SmallStatisticBox
        icon={(
          <SpellLink id={this.activeRune.ability.guid} icon={false}>
            <Icon icon={this.activeRune.ability.abilityIcon} />
          </SpellLink>
        )}
        value={damageDone > healingDone ? `${formatNumber(damageDone / fightDuration * 1000)} DPS` : `${formatNumber(healingDone / fightDuration * 1000)} HPS`}
        label="Vantus Rune gain"
        tooltip={`The throughput gain from using a Vantus Rune. You gained ${formatNumber(damageDone / fightDuration * 1000)} damage per second (DPS) and ${formatNumber(healingDone / fightDuration * 1000)} healing per second (HPS), and reduced your damage taken by ${formatNumber(damageReduced / fightDuration * 1000)} per second (DRPS).`}
      />
    );
  }
  statisticOrder = STATISTIC_ORDER.UNIMPORTANT();
}

export default VantusRune;
<|endoftext|>


<commit_before>// Uses javascript from there : http://code.stephenmorley.org/javascript/collapsible-lists/#usage but modified.

jQuery(document).ready(function () {
    jQuery.noConflict();
    jQuery('.term-relational-tree').injectRelationalTree();

});

var element_to_inject;
var json_path;
var label;
var ontology_name;

//make it a jquery plugin that can be attached to any element.
(function ($) {

    //function getDataAndInject(){
    $.fn.injectRelationalTree = function () {

        element_to_inject = this;

        //Get the <term-relational-tree> tag label attribute
        //var label = $(".term-relational-tree").attr("data-label");
        var label = this.attr("data-label");
        //Get the <term-relational-tree> tag ontology-name attribute
        //var ontology_name= $(".term-relational-tree").attr("data-ontology-name");
        ontology_name = this.attr("data-ontology-name");

        //Get the <term-relational-tree> tag json-path attribute
        // The json_path the url pointing to the solr server, or the server which given a label parameter returns the expected json.
        // The label part of the url should contain the following string "LABEL_TO_REPLACE" so that the widget can easily replace
        // this with the given label.

        // If the json_path was not given use the ebi default url.
        //var json_path = $(".term-relational-tree").attr("data-json-path")
        json_path = this.attr("data-json-path");
        if (typeof json_path == 'undefined' || json_path.indexOf("LABEL_TO_REPLACE") == -1) {
            json_path = "http://localhost:8983/solr/ontology/select?q=label%3ALABEL_TO_REPLACE&rows=1&wt=json&indent=true";
        }
        //If the json_path does not contain a LABEL_TO_REPLACE string then send an error message.
        else if (json_path.indexOf("LABEL_TO_REPLACE") == -1) {
            html_to_inject = '
BAD USE OF THE <term-relational-tree> tag, you should provide a json_path parameter which is a url' +
            'pointing to your solr server with a LABEL_TO_REPLACE string where the widget need to replace with the given label
' +
            'ex : <term-relational-tree  label="lung" ontology-name="EFO" json-path="http://localhost:8983/solr/ontology/select?q=label%3ALABEL_TO_REPLACE+AND+ontology_name%3AONTOLOGY_NAME_TO_REPLACE&rows=1&wt=json&indent=true"></term-relational-tree>
';

            //$('.term-relational-tree').append(html_to_inject);
            this.append(html_to_inject);
        }
        //If the json_path does not contain a LABEL_TO_REPLACE string then send an error message.
        else if (json_path.indexOf("ONTOLOGY_NAME_TO_REPLACE") == -1) {
            html_to_inject = '
BAD USE OF THE <term-relational-tree> tag, you should provide a json_path parameter which is a url' +
            'pointing to your solr server with a ONTOLOGY_NAME_TO_REPLACE string where the widget need to replace with the given ontology-name
' +
            'ex : <term-relational-tree  label="lung" ontology-name="EFO" json-path="http://localhost:8983/solr/ontology/select?q=label%3ALABEL_TO_REPLACE+AND+ontology_name%3AONTOLOGY_NAME_TO_REPLACE&rows=1&wt=json&indent=true"></term-relational-tree>
';

            //$('.term-relational-tree').append(html_to_inject);
            this.append(html_to_inject);
        }
        //If the user didn't provide the label parameter then send an error message.
        else if (typeof label == 'undefined') {
            html_to_inject = '
BAD USE OF THE <term-relational-tree> tag, you should at least provide a label parameter
' +
            'ex : <term-relational-tree label="lung"></term-relational-tree>
';
            //$('.term-relational-tree').append(html_to_inject);
            this.append(html_to_inject);
        }
        else if (typeof ontology_name == 'undefined') {
            html_to_inject = '
BAD USE OF THE <term-relational-tree> tag, you should at least provide an ontology-name parameter
' +
            'ex : <term-relational-tree label="lung" ontology-name="EFO"></term-relational-tree>
';
            //$('.term-relational-tree').append(html_to_inject);
            this.append(html_to_inject);
        }

        //Finally if the user has provided everything then parse the json, build the term overview and inject it in the <term-relational-tree> tag.
        else {

            var full_path = json_path.replace("LABEL_TO_REPLACE", label);
            full_path = full_path.replace("ONTOLOGY_NAME_TO_REPLACE", ontology_name);
            //because the url contains the string json.wrf=on_data, then javascript knows that when
            // $.getJSON(full_path);
            // is called it should build the json object from the given full_path parameter and send it to the on_data function.
            full_path = full_path + "&wt=json&json.wrf=on_data&callback=?"

            $.getJSON(full_path);//,function(json){
        }
    }

}(jQuery));

function on_data(json) {

    var bbop_sibling_graph_json_string = json.response.docs[0].bbop_sibling_graph_json;

    var bbop_sibling_graph_json = JSON.parse(bbop_sibling_graph_json_string);

    var requestedTermLabel = json.response.docs[0].label;

    var treeData = new Object();

    var all_children;
    var all_parent = [];

    var iri2label = [];
    for (var i = 0; i<bbop_sibling_graph_json.nodes.length; i++){
        var iri =bbop_sibling_graph_json.nodes[i].IRI;
        var label = bbop_sibling_graph_json.nodes[i].LABEL;
        console.log(iri + " = " + label + "\n");
        iri2label[iri2label.length] = iri + "\t" + label;
    }

    console.log("iri2label.length = " + iri2label.length + "\n");

    for (var i = 0; i < bbop_sibling_graph_json.edges.length; i++) {

        var obj = bbop_sibling_graph_json.edges[i].obj;
        var sub = bbop_sibling_graph_json.edges[i].sub;

        all_children = all_children + "\t" + obj;
        all_parent[all_parent.length] = sub;

        var children_array = treeData[sub];
        if (typeof children_array == 'undefined') {
            children_array = [];
        }
        children_array[children_array.length] = obj;
        treeData[sub] = children_array;

    }

    //Search for the tree root (i.e. : the one element which has no parent).
    var root;
    for (var i = 0; i < all_parent.length; i++) {
        var parent = all_parent[i];
        if (all_children.indexOf(parent) == -1) {
            root = parent;
        }

    }

    //Get the html description of the tree
    var collapsibleHtml =  "
"
        + readTreeData(treeData, root, iri2label, requestedTermLabel,"")
        +"
";

    //Inject the html description of the tree in the element with id "myid"
    var element = document.getElementById("myid");
    element.innerHTML = collapsibleHtml ;

    // make ul element with class="collapsibleList" collapsible
    CollapsibleLists.apply();
}

//Returns true if the iri term has children, false if it doesn't.
//treeData : an object which associates parents with and array of direct children
//          ex : { http://www.ebi.ac.uk/efo/EFO_0000001 : ["http://www.ifomis.org/bfo/1.1/snap#SpecificallyDependentContinuant","http://www.ifomis.org/bfo/1.1/snap#MaterialEntity","http://www.ifomis.org/bfo/1.1/snap#Site","http://purl.obolibrary.org/obo/IAO_0000030", "http://www.ifomis.org/bfo/1.1/span#ProcessualEntity"],
//                 http://www.ifomis.org/bfo/1.1/snap#SpecificallyDependentContinuant : ["http://www.ifomis.org/bfo/1.1/snap#Disposition", "http://www.ifomis.org/bfo/1.1/snap#Function", "http://www.ifomis.org/bfo/1.1/snap#Role", "http://www.ifomis.org/bfo/1.1/snap#Quality"]
//               }
//
function hasChildren(treeData, iri){
    var rootChildren = treeData[iri];
    if(typeof  rootChildren !== 'undefined' ) {

        if(rootChildren.length !== 0) {
            return true;
        }else{
            return false;
        }
    }else{
        return false;
    }

}

//
// Recursive function which build the tree.
// treeData : an object which associates parents with and array of direct children
//          ex : { http://www.ebi.ac.uk/efo/EFO_0000001 : ["http://www.ifomis.org/bfo/1.1/snap#SpecificallyDependentContinuant","http://www.ifomis.org/bfo/1.1/snap#MaterialEntity","http://www.ifomis.org/bfo/1.1/snap#Site","http://purl.obolibrary.org/obo/IAO_0000030", "http://www.ifomis.org/bfo/1.1/span#ProcessualEntity"],
//                 http://www.ifomis.org/bfo/1.1/snap#SpecificallyDependentContinuant : ["http://www.ifomis.org/bfo/1.1/snap#Disposition", "http://www.ifomis.org/bfo/1.1/snap#Function", "http://www.ifomis.org/bfo/1.1/snap#Role", "http://www.ifomis.org/bfo/1.1/snap#Quality"]
//               }
// root : the root of the tree
//       ex :http://www.ebi.ac.uk/efo/EFO_0000001
// iri2label : an array of cells containing the iri of a term followed by its label
//            ex : http://www.ebi.ac.uk/efo/EFO_0000001 experimental factor
// requestedTermLabel : the term for which we're building the tree ( this is so that it can be highlighted when displayed (if not given, nothing will be highlighted).
//
// Return : an html string representing the tree.
//          ex :

//
 experimental factor
//

//
 material property
//

//
 disposition
//

//
 disease
//

//
 brain disease
//

//
 insomnia

 Genetic neurodegenerative disease

//
 narcolepsy with cataplexy

 mental retardation

//
 Genetic dementia

//
 memory impairment

//
 Pick disease

//
 central nervous system cyst

//
 dementia

//

//

//
 mode of inheritance

//
 normal

//
 mental health

//

//

//
 function

//
 role

//
 quality

//

//

//
 material entity

//
 site

//
 information entity

//
 process

//

//

//

//
function readTreeData(treeData, root, iri2label, requestedTermLabel){

    var string = "";

    var label;
    for(var k=0;k<iri2label.length; k++){
        var value = iri2label[k];
        if(value.indexOf(root) != -1){
            var splitValue = value.split("\t");
            label = splitValue[1];
        }
    }

    var color = "#4D4D4D";
    console.log(requestedTermLabel + ", " + root + ", " + label + "\n");
    if(requestedTermLabel == label){
        color = "#FFC36E";
    }

    string = string + "
";
    string = string + " " + label + "";
    if(hasChildren(treeData, root)) {
        string = string +  "
";
    }

    var rootChildren = treeData[root];
    if(typeof  rootChildren !== 'undefined' ) {

        if(rootChildren.length !== 0) {

            for (var i = 0; i < rootChildren.length; i++) {

                string = string + readTreeData(treeData, rootChildren[i], iri2label,requestedTermLabel);

            }

        }
    }
    if(hasChildren(treeData, root)) {
        string = string +  "
";
    }
    string = string + "
";

    return string;

}

<commit_msg>Documentation<commit_after>// Uses javascript from there : http://code.stephenmorley.org/javascript/collapsible-lists/#usage but modified.

jQuery(document).ready(function () {
    jQuery.noConflict();
    jQuery('.term-relational-tree').injectRelationalTree();

});

var element_to_inject;
var json_path;
var label;
var ontology_name;

//make it a jquery plugin that can be attached to any element.
(function ($) {

    //function getDataAndInject(){
    $.fn.injectRelationalTree = function () {

        element_to_inject = this;

        //Get the <term-relational-tree> tag label attribute
        //var label = $(".term-relational-tree").attr("data-label");
        var label = this.attr("data-label");
        //Get the <term-relational-tree> tag ontology-name attribute
        //var ontology_name= $(".term-relational-tree").attr("data-ontology-name");
        ontology_name = this.attr("data-ontology-name");

        //Get the <term-relational-tree> tag json-path attribute
        // The json_path the url pointing to the solr server, or the server which given a label parameter returns the expected json.
        // The label part of the url should contain the following string "LABEL_TO_REPLACE" so that the widget can easily replace
        // this with the given label.

        // If the json_path was not given use the ebi default url.
        //var json_path = $(".term-relational-tree").attr("data-json-path")
        json_path = this.attr("data-json-path");
        if (typeof json_path == 'undefined' || json_path.indexOf("LABEL_TO_REPLACE") == -1) {
            json_path = "http://localhost:8983/solr/ontology/select?q=label%3ALABEL_TO_REPLACE&rows=1&wt=json&indent=true";
        }
        //If the json_path does not contain a LABEL_TO_REPLACE string then send an error message.
        else if (json_path.indexOf("LABEL_TO_REPLACE") == -1) {
            html_to_inject = '
BAD USE OF THE <term-relational-tree> tag, you should provide a json_path parameter which is a url' +
            'pointing to your solr server with a LABEL_TO_REPLACE string where the widget need to replace with the given label
' +
            'ex : <term-relational-tree  label="lung" ontology-name="EFO" json-path="http://localhost:8983/solr/ontology/select?q=label%3ALABEL_TO_REPLACE+AND+ontology_name%3AONTOLOGY_NAME_TO_REPLACE&rows=1&wt=json&indent=true"></term-relational-tree>
';

            //$('.term-relational-tree').append(html_to_inject);
            this.append(html_to_inject);
        }
        //If the json_path does not contain a LABEL_TO_REPLACE string then send an error message.
        else if (json_path.indexOf("ONTOLOGY_NAME_TO_REPLACE") == -1) {
            html_to_inject = '
BAD USE OF THE <term-relational-tree> tag, you should provide a json_path parameter which is a url' +
            'pointing to your solr server with a ONTOLOGY_NAME_TO_REPLACE string where the widget need to replace with the given ontology-name
' +
            'ex : <term-relational-tree  label="lung" ontology-name="EFO" json-path="http://localhost:8983/solr/ontology/select?q=label%3ALABEL_TO_REPLACE+AND+ontology_name%3AONTOLOGY_NAME_TO_REPLACE&rows=1&wt=json&indent=true"></term-relational-tree>
';

            //$('.term-relational-tree').append(html_to_inject);
            this.append(html_to_inject);
        }
        //If the user didn't provide the label parameter then send an error message.
        else if (typeof label == 'undefined') {
            html_to_inject = '
BAD USE OF THE <term-relational-tree> tag, you should at least provide a label parameter
' +
            'ex : <term-relational-tree label="lung"></term-relational-tree>
';
            //$('.term-relational-tree').append(html_to_inject);
            this.append(html_to_inject);
        }
        else if (typeof ontology_name == 'undefined') {
            html_to_inject = '
BAD USE OF THE <term-relational-tree> tag, you should at least provide an ontology-name parameter
' +
            'ex : <term-relational-tree label="lung" ontology-name="EFO"></term-relational-tree>
';
            //$('.term-relational-tree').append(html_to_inject);
            this.append(html_to_inject);
        }

        //Finally if the user has provided everything then parse the json, build the term overview and inject it in the <term-relational-tree> tag.
        else {

            var full_path = json_path.replace("LABEL_TO_REPLACE", label);
            full_path = full_path.replace("ONTOLOGY_NAME_TO_REPLACE", ontology_name);
            //because the url contains the string json.wrf=on_data, then javascript knows that when
            // $.getJSON(full_path);
            // is called it should build the json object from the given full_path parameter and send it to the on_data function.
            full_path = full_path + "&wt=json&json.wrf=on_data&callback=?"

            $.getJSON(full_path);//,function(json){
        }
    }

}(jQuery));

function on_data(json) {

    var bbop_sibling_graph_json_string = json.response.docs[0].bbop_sibling_graph_json;

    var bbop_sibling_graph_json = JSON.parse(bbop_sibling_graph_json_string);

    var requestedTermLabel = json.response.docs[0].label;

    var treeData = new Object();

    var all_children;
    var all_parent = [];

    // The bbop_sibling_graph_json which is stored in the solR index is composed of 2 part :
    //   the node part where all the node composing the tree are described
    //   the edge part where the tree is described
    // From the node part we get all the term IRI and label and build and iri2label array associating
    // the iri with their label as follow :
    //      IRI[\t]label
    // This array will be used later on when building the tree to display the the node label in the nodes rather then
    // the node IRI.
    var iri2label = [];
    for (var i = 0; i<bbop_sibling_graph_json.nodes.length; i++){
        var iri =bbop_sibling_graph_json.nodes[i].IRI;
        var label = bbop_sibling_graph_json.nodes[i].LABEL;
        console.log(iri + " = " + label + "\n");
        iri2label[iri2label.length] = iri + "\t" + label;
    }

    //Walking through the bbob_sibling_graph_json.edges description of the tree to build the treeData object.
    //There I have used the javascript object treeData as a 'dictionnary', 'hash' or 'map' to associate a nodes with
    // an array of their children.
    // treeData[http://ebi.ac.uk/efo/EFO_000001] woulr return and array containing the IRI of the direct children of that
    // node.
    for (var i = 0; i < bbop_sibling_graph_json.edges.length; i++) {

        var obj = bbop_sibling_graph_json.edges[i].obj;
        var sub = bbop_sibling_graph_json.edges[i].sub;

        all_children = all_children + "\t" + obj;
        all_parent[all_parent.length] = sub;

        var children_array = treeData[sub];
        if (typeof children_array == 'undefined') {
            children_array = [];
        }
        children_array[children_array.length] = obj;
        treeData[sub] = children_array;

    }

    //Search for the tree root (i.e. : the one element which has no parent).
    var root;
    for (var i = 0; i < all_parent.length; i++) {
        var parent = all_parent[i];
        if (all_children.indexOf(parent) == -1) {
            root = parent;
        }
    }

    //Get the html description of the tree
    var collapsibleHtml =  "
"
        + readTreeData(treeData, root, iri2label, requestedTermLabel,"")
        +"
";

    //Inject the html description of the tree in the element with id "myid"
    var element = document.getElementById("myid");
    element.innerHTML = collapsibleHtml ;

    // make ul element with class="collapsibleList" collapsible
    CollapsibleLists.apply();
}

//Returns true if the iri term has children, false if it doesn't.
//treeData : an object which associates parents with and array of direct children
//          ex : { http://www.ebi.ac.uk/efo/EFO_0000001 : ["http://www.ifomis.org/bfo/1.1/snap#SpecificallyDependentContinuant","http://www.ifomis.org/bfo/1.1/snap#MaterialEntity","http://www.ifomis.org/bfo/1.1/snap#Site","http://purl.obolibrary.org/obo/IAO_0000030", "http://www.ifomis.org/bfo/1.1/span#ProcessualEntity"],
//                 http://www.ifomis.org/bfo/1.1/snap#SpecificallyDependentContinuant : ["http://www.ifomis.org/bfo/1.1/snap#Disposition", "http://www.ifomis.org/bfo/1.1/snap#Function", "http://www.ifomis.org/bfo/1.1/snap#Role", "http://www.ifomis.org/bfo/1.1/snap#Quality"]
//               }
//
function hasChildren(treeData, iri){
    var rootChildren = treeData[iri];
    if(typeof  rootChildren !== 'undefined' ) {

        if(rootChildren.length !== 0) {
            return true;
        }else{
            return false;
        }
    }else{
        return false;
    }

}

//
// Recursive function which build the tree.
// treeData : an object which associates parents with and array of direct children
//          ex : { http://www.ebi.ac.uk/efo/EFO_0000001 : ["http://www.ifomis.org/bfo/1.1/snap#SpecificallyDependentContinuant","http://www.ifomis.org/bfo/1.1/snap#MaterialEntity","http://www.ifomis.org/bfo/1.1/snap#Site","http://purl.obolibrary.org/obo/IAO_0000030", "http://www.ifomis.org/bfo/1.1/span#ProcessualEntity"],
//                 http://www.ifomis.org/bfo/1.1/snap#SpecificallyDependentContinuant : ["http://www.ifomis.org/bfo/1.1/snap#Disposition", "http://www.ifomis.org/bfo/1.1/snap#Function", "http://www.ifomis.org/bfo/1.1/snap#Role", "http://www.ifomis.org/bfo/1.1/snap#Quality"]
//               }
// root : the root of the tree
//       ex :http://www.ebi.ac.uk/efo/EFO_0000001
// iri2label : an array of cells containing the iri of a term followed by its label
//            ex : http://www.ebi.ac.uk/efo/EFO_0000001 experimental factor
// requestedTermLabel : the term for which we're building the tree ( this is so that it can be highlighted when displayed (if not given, nothing will be highlighted).
//
// Return : an html string representing the tree.
//          ex :

//
 experimental factor
//

//
 material property
//

//
 disposition
//

//
 disease
//

//
 brain disease
//

//
 insomnia

 Genetic neurodegenerative disease

//
 narcolepsy with cataplexy

 mental retardation

//
 Genetic dementia

//
 memory impairment

//
 Pick disease

//
 central nervous system cyst

//
 dementia

//

//

//
 mode of inheritance

//
 normal

//
 mental health

//

//

//
 function

//
 role

//
 quality

//

//

//
 material entity

//
 site

//
 information entity

//
 process

//

//

//

//
function readTreeData(treeData, root, iri2label, requestedTermLabel){

    var string = "";

    var label;
    for(var k=0;k<iri2label.length; k++){
        var value = iri2label[k];
        if(value.indexOf(root) != -1){
            var splitValue = value.split("\t");
            label = splitValue[1];
        }
    }

    //Right the node label in orange if the node is the node for which the user requested the tree or in  dark grey
    // otherwise.
    var color = "#4D4D4D"; //dark grey
    console.log(requestedTermLabel + ", " + root + ", " + label + "\n");
    if(requestedTermLabel == label){
        color = "#FFC36E";//orange
    }

    string = string + "
";
    string = string + " " + label + "";
    if(hasChildren(treeData, root)) {
        string = string +  "
";
    }

    var rootChildren = treeData[root];
    if(typeof  rootChildren !== 'undefined' ) {

        if(rootChildren.length !== 0) {

            for (var i = 0; i < rootChildren.length; i++) {

                string = string + readTreeData(treeData, rootChildren[i], iri2label,requestedTermLabel);

            }

        }
    }
    if(hasChildren(treeData, root)) {
        string = string +  "
";
    }
    string = string + "
";

    return string;

}

<|endoftext|>


<commit_before>import React from 'react';
import {shallow} from 'enzyme';

import CommentDecorationsController from '../../lib/controllers/comment-decorations-controller';
<commit_msg>add tests for CommentDecorationsController<commit_after>import React from 'react';
import {mount} from 'enzyme';
import path from 'path';

import {BareCommentDecorationsController} from '../../lib/controllers/comment-decorations-controller';
import RelayNetworkLayerManager from '../../lib/relay-network-layer-manager';
import {aggregatedReviewsBuilder} from '../builder/graphql/aggregated-reviews-builder';
import {getEndpoint} from '../../lib/models/endpoint';
import pullRequestsQuery from '../../lib/controllers/__generated__/commentDecorationsController_pullRequests.graphql';
import {pullRequestBuilder} from '../builder/graphql/pr';
import Branch from '../../lib/models/branch';
import BranchSet from '../../lib/models/branch-set';
import Remote from '../../lib/models/remote';
import RemoteSet from '../../lib/models/remote-set';

describe.only('CommentDecorationsController', function() {
  let atomEnv, relayEnv;

  beforeEach(function() {
    atomEnv = global.buildAtomEnvironment();
    relayEnv = RelayNetworkLayerManager.getEnvironmentForHost(getEndpoint('github.com'), '1234');
  });

  afterEach(function() {
    atomEnv.destroy();
  });

  function buildApp(override = {}) {
    const origin = new Remote('origin', 'git@github.com:owner/repo.git');
    const upstreamBranch = Branch.createRemoteTracking('refs/remotes/origin/master', 'origin', 'refs/heads/master');
    const branch = new Branch('master', upstreamBranch, upstreamBranch, true);
    const {commentThreads} = aggregatedReviewsBuilder()
      .addReviewThread(t => {
        t.addComment(c => c.id(0).path('file0.txt').position(2).bodyHTML('one'));
      })
      .addReviewThread(t => {
        t.addComment(c => c.id(1).path('file1.txt').position(15).bodyHTML('two'));
      })
      .addReviewThread(t => {
        t.addComment(c => c.id(2).path('file2.txt').position(7).bodyHTML('three'));
      })
      .build();

    const pr = pullRequestBuilder(pullRequestsQuery)
      .headRefName('master')
      .headRepository(r => {
        r.owner(o => o.login('owner'));
        r.name('repo');
      }).build();

    const props = {
      relay: {environment: relayEnv},
      pullRequests: [pr],
      repository: {},
      endpoint: getEndpoint('github.com'),
      owner: 'owner',
      repo: 'repo',
      workspace: atomEnv.workspace,
      repoData: {
        branches: new BranchSet([branch]),
        remotes: new RemoteSet([origin]),
        currentRemote: origin,
        workingDirectoryPath: __dirname,
      },
      commentThreads,
      commentTranslations: {
        get: () => {},
      },
      ...override,
    };

    return <BareCommentDecorationsController {...props} />;
  }

  describe('renders EditorCommentDecorationsController and Gutter', function() {
    let editor0, editor1, editor2, wrapper;

    beforeEach(async function() {
      editor0 = await atomEnv.workspace.open(path.join(__dirname, 'file0.txt'));
      editor1 = await atomEnv.workspace.open(path.join(__dirname, 'another-unrelated-file.txt'));
      editor2 = await atomEnv.workspace.open(path.join(__dirname, 'file1.txt'));
      wrapper = mount(buildApp());
    });

    it('a pair per matching opened editor', function() {
      assert.strictEqual(wrapper.find('EditorCommentDecorationsController').length, 2);
      assert.isNotNull(editor0.gutterWithName('github-comment-icon'));
      assert.isNotNull(editor2.gutterWithName('github-comment-icon'));
      assert.isNull(editor1.gutterWithName('github-comment-icon'));
    });

    it('updates its EditorCommentDecorationsController and Gutter children as editor panes get created', async function() {
      editor2 = await atomEnv.workspace.open(path.join(__dirname, 'file2.txt'));
      wrapper.update();

      assert.strictEqual(wrapper.find('EditorCommentDecorationsController').length, 3);
      assert.isNotNull(editor2.gutterWithName('github-comment-icon'));
    });

    it('updates its EditorCommentDecorationsController and Gutter children as editor panes get destroyed', async function() {
      assert.strictEqual(wrapper.find('EditorCommentDecorationsController').length, 2);
      await atomEnv.workspace.getActivePaneItem().destroy();
      wrapper.update();

      assert.strictEqual(wrapper.find('EditorCommentDecorationsController').length, 1);
    });
  });

});
<|endoftext|>


<commit_before>define(["Tone/core/Tone"], function (Tone) {

	/**
	 *  @class Tone.EventEmitter gives classes which extend it
	 *         the ability to listen for and trigger events.
	 *         Inspiration and reference from Jerome Etienne's [MicroEvent](https://github.com/jeromeetienne/microevent.js).
	 *         MIT (c) 2011 Jerome Etienne.
	 *
	 *  @extends {Tone}
	 */
	Tone.EventEmitter = function(){
		/**
		 *  Contains all of the events.
		 *  @private
		 *  @type  {Object}
		 */
		this._events = {};
	};

	Tone.extend(Tone.EventEmitter);

	/**
	 *  Bind a callback to a specific event.
	 *  @param  {String}    event     The name of the event to listen for.
	 *  @param  {Function}  callback  The callback to invoke when the
	 *                                event is triggered
	 *  @return  {Tone.EventEmitter}    this
	 */
	Tone.EventEmitter.prototype.on = function(event, callback){
		//split the event
		var events = event.split(/\W+/);
		for (var i = 0; i < events.length; i++){
			var eventName = events[i];
			if (!this._events.hasOwnProperty(eventName)){
				this._events[eventName] = [];
			}
			this._events[eventName].push(callback);
		}
		return this;
	};

	/**
	 *  Remove the event listener.
	 *  @param  {String}    event     The event to stop listening to.
	 *  @param  {Function}  callback  The callback which was bound to
	 *                                the event with Tone.EventEmitter.on.
	 *  @return  {Tone.EventEmitter}    this
	 */
	Tone.EventEmitter.prototype.off = function(event, callback){
		var events = event.split(/\W+/);
		for (var ev = 0; ev < events.length; ev++){
			event = events[ev];
			if (this._events.hasOwnProperty(event)){
				var eventList = this._events[event];
				for (var i = 0; i < eventList.length; i++){
					if (eventList[i] === callback){
						eventList.splice(i, 1);
						break;
					}
				}
			}
		}
		return this;
	};

	/**
	 *  Invoke all of the callbacks bound to the event
	 *  with any arguments passed in.
	 *  @param  {String}  event  The name of the event.
	 *  @param {*...} args The arguments to pass to the functions listening.
	 *  @return  {Tone.EventEmitter}  this
	 */
	Tone.EventEmitter.prototype.trigger = function(event){
		if (this._events){
			var args = Array.prototype.slice.call(arguments, 1);
			if (this._events.hasOwnProperty(event)){
				var eventList = this._events[event];
				for (var i = 0, len = eventList.length; i < len; i++){
					eventList[i].apply(this, args);
				}
			}
		}
		return this;
	};

	/**
	 *  Add EventEmitter functions (on/off/trigger) to the object
	 *  @param  {Object|Function}  object  The object or class to extend.
	 */
	Tone.EventEmitter.mixin = function(object){
		var functions = ["on", "off", "trigger"];
		object._events = {};
		for (var i = 0; i < functions.length; i++){
			var func = functions[i];
			var emitterFunc = Tone.EventEmitter.prototype[func];
			object[func] = emitterFunc;
		}
	};

	/**
	 *  Clean up
	 *  @return  {Tone.EventEmitter}  this
	 */
	Tone.EventEmitter.prototype.dispose = function(){
		Tone.prototype.dispose.call(this);
		this._events = null;
		return this;
	};

	return Tone.EventEmitter;
});<commit_msg>Removes all events when no callback with `off``<commit_after>define(["Tone/core/Tone"], function (Tone) {

	/**
	 *  @class Tone.EventEmitter gives classes which extend it
	 *         the ability to listen for and trigger events.
	 *         Inspiration and reference from Jerome Etienne's [MicroEvent](https://github.com/jeromeetienne/microevent.js).
	 *         MIT (c) 2011 Jerome Etienne.
	 *
	 *  @extends {Tone}
	 */
	Tone.EventEmitter = function(){
		/**
		 *  Contains all of the events.
		 *  @private
		 *  @type  {Object}
		 */
		this._events = {};
	};

	Tone.extend(Tone.EventEmitter);

	/**
	 *  Bind a callback to a specific event.
	 *  @param  {String}    event     The name of the event to listen for.
	 *  @param  {Function}  callback  The callback to invoke when the
	 *                                event is triggered
	 *  @return  {Tone.EventEmitter}    this
	 */
	Tone.EventEmitter.prototype.on = function(event, callback){
		//split the event
		var events = event.split(/\W+/);
		for (var i = 0; i < events.length; i++){
			var eventName = events[i];
			if (!this._events.hasOwnProperty(eventName)){
				this._events[eventName] = [];
			}
			this._events[eventName].push(callback);
		}
		return this;
	};

	/**
	 *  Remove the event listener.
	 *  @param  {String}    event     The event to stop listening to.
	 *  @param  {Function=}  callback  The callback which was bound to
	 *                                the event with Tone.EventEmitter.on.
	 *                                If no callback is given, all callbacks
	 *                                events are removed.
	 *  @return  {Tone.EventEmitter}    this
	 */
	Tone.EventEmitter.prototype.off = function(event, callback){
		var events = event.split(/\W+/);
		for (var ev = 0; ev < events.length; ev++){
			event = events[ev];
			if (this._events.hasOwnProperty(event)){
				if (this.isUndef(callback)){
					this._events[event] = [];
				} else {
					var eventList = this._events[event];
					for (var i = 0; i < eventList.length; i++){
						if (eventList[i] === callback){
							eventList.splice(i, 1);
						}
					}
				}
			}
		}
		return this;
	};

	/**
	 *  Invoke all of the callbacks bound to the event
	 *  with any arguments passed in.
	 *  @param  {String}  event  The name of the event.
	 *  @param {*...} args The arguments to pass to the functions listening.
	 *  @return  {Tone.EventEmitter}  this
	 */
	Tone.EventEmitter.prototype.trigger = function(event){
		if (this._events){
			var args = Array.prototype.slice.call(arguments, 1);
			if (this._events.hasOwnProperty(event)){
				var eventList = this._events[event];
				for (var i = 0, len = eventList.length; i < len; i++){
					eventList[i].apply(this, args);
				}
			}
		}
		return this;
	};

	/**
	 *  Add EventEmitter functions (on/off/trigger) to the object
	 *  @param  {Object|Function}  object  The object or class to extend.
	 */
	Tone.EventEmitter.mixin = function(object){
		var functions = ["on", "off", "trigger"];
		object._events = {};
		for (var i = 0; i < functions.length; i++){
			var func = functions[i];
			var emitterFunc = Tone.EventEmitter.prototype[func];
			object[func] = emitterFunc;
		}
	};

	/**
	 *  Clean up
	 *  @return  {Tone.EventEmitter}  this
	 */
	Tone.EventEmitter.prototype.dispose = function(){
		Tone.prototype.dispose.call(this);
		this._events = null;
		return this;
	};

	return Tone.EventEmitter;
});<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { PowerSelectMultiple } from 'src';
import { countries } from '../constants';

const CustomOptionComponnet = ({ option }) => (

    {option.name} ({option.code})

);

const CustomSelectedOptionComponent = ({ option, optionLabelPath, onCloseClick, select }) => (

      {option[optionLabelPath]}

     {
        event.stopPropagation();
        onCloseClick({ option, select });
      }}
    >
      ×

);

export default class ArrayOfObjectsDemo extends Component {
  state = {
    selectedCountries: [countries[2], countries[4]],
  };

  handleChange = ({ options }) => {
    this.setState({ selectedCountries: options });
  };

  render() {
    return (

Custom Selected Options

        <PowerSelectMultiple
          options={countries}
          selected={this.state.selectedCountries}
          optionLabelPath="name"
          optionComponent={<CustomOptionComponnet />}
          selectedOptionComponent={<CustomSelectedOptionComponent />}
          onChange={this.handleChange}
          placeholder="Select your favourite countries"
        />

    );
  }
}
<commit_msg>Fix the example in docs<commit_after>import React, { Component } from 'react';
import { PowerSelectMultiple } from 'src';
import { countries } from '../constants';

const CustomOptionComponnet = ({ option }) => (

    {option.name} ({option.code})

);

const CustomSelectedOptionComponent = ({ option }) => (

    {option.name}

);

export default class ArrayOfObjectsDemo extends Component {
  state = {
    selectedCountries: [countries[2], countries[4]],
  };

  handleChange = ({ options }) => {
    this.setState({ selectedCountries: options });
  };

  render() {
    return (

Custom Selected Options

        <PowerSelectMultiple
          options={countries}
          selected={this.state.selectedCountries}
          optionLabelPath="name"
          optionComponent={<CustomOptionComponnet />}
          selectedOptionComponent={<CustomSelectedOptionComponent />}
          onChange={this.handleChange}
          placeholder="Select your favourite countries"
        />

    );
  }
}
<|endoftext|>


<commit_before>/* jshint multistr: true */

/* relies on:
    - jquery-ui.js
    - dropzone.js
*/
(function ($) {

    $(document).on('click', '.closeModal', function(event){
        event.preventDefault();
        $('#openModal').remove();
    });

    var modalPreview = function(url){
        var modal = '
\

\
                        X\
                        <video src="'+ url +'" width="500px" controls></video>\

\

';
        return modal;
    };

    var singleMedia = function(file, index){
        var single_media = '';
        if (file.file_src.indexOf('.mp4') > 0){
            single_media = '
<video data-id="'+ file.sha1 + '" id="image_'+ index + '" class="image  clickable-menu image_media" src="'+ file.file_src +'" style="max-height:80%;max-width:80%;"></video>
';
        }else{
            single_media = '

';
        }
        return single_media;
    };

    var sidebar = '\

\

\

Media
\
                <input placeholder="Search..." id="gallery-filter" type="text" class="form-control">\

\

Drag and drop or click to upload Media
\

\

\

Click on an item to view more options
\

\

';

    var sidebar_size = 200;
    var loaded = false;
    var initialized = false;
    var id= null;
    var toggle_button = null;
    var count = 0;

    var modal = '
\

\

\

\
                <button type="button" class="close" data-dismiss="modal">×Close</button>\

Modal title
\

\

\
                <video src="" id="modal-video" controls style="width:100%" preload="auto"></video>\

\

\
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>\
                <button type="button" class="btn btn-primary">Save changes</button>\

\

\

\

';

    function SidebarGallery(options){
        this.options = options;
        this._init();
        Dropzone.autoDiscover = false;
    }

    function notify_user(descr, level){
        $('body').prepend('
'+ descr + '
');
        setTimeout(function(){
            $('.notify-user-label').remove();
        }, 5000);
    }

    function update_progress_info(url) {
        $.getJSON(url, {'X-Progress-ID': id}, function(data, status){
            if(data){
                $('#progress-span').text((data.uploaded /data.lenght)*100);
            }
            else{
                $('#progress-span').text(100);
                return false;
            }
            setTimeout(update_progress_info(url), 100);
        });
    }

    SidebarGallery.prototype = {

        _init: function(){
            _this = this;
            $('body').append(_this.options.toggle).append(sidebar);
            $(document).on('click','#btn-toggle', _this._toggle_sidebar);
            $(document).on('keyup', '#gallery-filter', _this.filterImage);
            if (_this.options.url_progress){
                $(document).on('start_upload', function(){
                    setTimeout(update_progress_info(_this.options.url_progress), 20);
                });
            }
            $(document).on('click', '#delete_media', _this.deleteMedia);
            $(document).on('click', '#tag_media', _this.tagMedia);
            $(document).on('click', '#preview_media', _this.previewMedia);

            $(document).on('editInputVisible', function(){
                $('#input_editor').droppable({
                    drop: function(event, ui){
                        var droppable = $(this);
                        var draggable = ui.draggable;
                        droppable.focus();
                        droppable.selection('insert',{text:'![Alt text]('+ draggable.attr('src') +')' ,mode:'before'});
                        $(ui.helper).remove();
                        $('#input_editor').trigger('autosize.resize');
                    }
                });
            });

            $('.droppable-image').droppable({
                drop: function( event, ui ) {
                    var droppable = $(this);
                    if (droppable.prop("tagName") == 'IMG'){
                        if (ui.draggable.attr('src').indexOf(".png") > 0 || ui.draggable.attr('src').indexOf(".jpg") > 0){
                            droppable.attr('src', ui.draggable.attr('src'));
                            $(ui.helper).remove();
                            _this.saveImage(droppable);
                        }else{
                            notify_user("You can't put other file than image in this place", 'error');
                        }
                    }else if (droppable.prop("tagName") == 'VIDEO'){
                        if (ui.draggable.attr('src').indexOf(".mp4") > 0){
                            droppable.attr('src', ui.draggable.attr('src'));
                            $(ui.helper).remove();
                            _this.saveImage(droppable);
                        }else{
                            notify_user("You can't put other file than video in this place", 'error');
                        }
                    }
              }
            });

            var DocDropzone = new Dropzone('#media-container', { // Make the whole body a dropzone
                paramName: 'file',
                url: _this.options.base_media_url,
                maxFilesize: 50,
                parallelUploads: 2,
                clickable: true,
                createImageThumbnails:false,
            });

            DocDropzone.on("processing", function(file){
                id = (new Date()).getTime();
                if (_this.options.url_progress){
                    this.options.url = _this.options.base_media_url + '?X-Progress-ID=' +id;
                }
            });

            DocDropzone.on("cancel", function(file){
                $('.progress-text').remove();
            });

            DocDropzone.on("sending", function(file, xhr, formData){
                formData.append('csrfmiddlewaretoken', _this.options.csrf_token);
                $('#media-container').append('
Upload in progress

0%
Please wait...
');
                $.event.trigger({
                  type:    "start_upload",
                  message: "myTrigger fired.",
                  time:    new Date()
                });
            });

            DocDropzone.on("dragover", function(event){
                if (count !== 0){
                    $('body').prepend('
Release your file to upload it
');
                    count = 1;
                }
            });

            DocDropzone.on("drop", function(event){
                if ($('.url_info').length){
                    $('.url_info').remove();
                }
                $('.notify-user-label').remove();
                count = 0;
            });

            DocDropzone.on("dragleave", function(event){
                $('.notify-user-label').remove();
                count = 0;
            });

            DocDropzone.on("error", function(data, response){
                $('#media-container').append('
' + response.message + '
');
                setTimeout(function() {
                    $('.alert').remove();
                }, 3000);
            });

            DocDropzone.on("success", function(file, response){
                var status = file.xhr.status;
                $('.progress-text').remove();
                $('.dz-preview').remove();
                var last_index = $('#list-media').children().last().children().attr('id');
                if (last_index){
                    last_index = parseInt(last_index.split('image_')[1]) + 1;
                }else{
                    last_index = 0;
                }
                if (status == 201){
                    $('#list-media').prepend(singleMedia(response, last_index));

                    $('#image_' + last_index).draggable({
                        helper: 'clone',
                        revert: true,
                        appendTo: "body",
                        start: function() {
                            $(".ui-draggable").not(this).css({
                                width: 50
                            });
                        },
                    });
                    _this.makemenu();
                    var descr = "We're processing your uploaded file. You can start use it by using the sample in your gallery.";
                    notify_user(descr, 'info');
                }else{
                    notify_user(response.message, 'error');
                }
                if (!$('#sidebar-gallery').hasClass('active')){
                    _this._open_sidebar();
                }
            });
        },

        deleteMedia: function(event){
            event.preventDefault();
            var $this_element = $(this);
            $.ajax({
                method: 'delete',
                url: _this.options.base_media_url + $this_element.attr('media') +'/',
                success: function(){
                    $('img[data-id="' + $this_element.attr('media') + '"], video[data-id="' + $this_element.attr('media') + '"]').parent('.media-single-container').remove();
                }
            });
            $('#media-info').empty();
        },

        tagMedia: function(event){
            event.preventDefault();
            var $this_element = $(this);
            var orginal_tags = null;
            $.ajax({
                method: 'get',
                async:false,
                url:_this.options.base_media_url + $this_element.attr('media') +'/',
                success: function(response){
                    orginal_tags = response.tags;
                }
            });
            var tags = prompt('Please enter tags', orginal_tags);
            if (tags !== null){
                $.ajax({
                    method: 'patch',
                    url:_this.options.base_media_url + $this_element.attr('media') + '/',
                    data:{'tags': tags},
                    success: function(){
                        console.log('updated');
                    }
                });
            }
        },

        previewMedia: function(event){
            event.preventDefault();
            var $this_element = $(this);
            $('body').append(modalPreview($this_element.attr('src')));
        },

        saveImage: function(element){
            id_element = element.attr('id');
            data = {text: element.attr('src')};
            $.ajax({
                method:'PUT',
                async:false,
                url: _this.options.base_save_url + id_element +'/',
                data:data,
                success: function(data){
                    console.log('saved');
                }
            });
        },

        _initMediaInfo: function(){
            $('#media-info').addClass('placeholder').text('Click on an item to view more options');
        },

        _toggle_sidebar: function(){
            if ($('#sidebar-container').hasClass('active')){
                _this._close_sidebar();
            }else{
                _this._open_sidebar();
            }
        },

        _draggableButton: function(){
            $('#btn-toggle').draggable({
                axis: "x",
                cursor: "move",
                drag: function(event, ui){
                    var view_width = $(window).width();
                    if (view_width - ui.position.left - $(ui.helper).outerWidth() >= 300){
                        $('#sidebar-container').css("right", "0px").css("width", view_width - ui.position.left - $(ui.helper).outerWidth());
                    }else{
                        $('#btn-toggle').css("left", view_width - 300 - $(ui.helper).outerWidth());
                        return false;
                    }
                },
                stop : function(event, ui){
                    var view_width = $(window).width();
                    if (view_width - ui.position.left - $(ui.helper).outerWidth() >= 300){
                        $('#sidebar-container').css("right", "0px").css("width", view_width - ui.position.left - $(ui.helper).outerWidth());
                    }else{
                        $('#sidebar-container').css("right", "0px").css("width", 300);
                    }

                    $( event.toElement ).one('click', function(e){ e.stopImmediatePropagation(); } );

                }
            });
        },

        _open_sidebar: function(){
            $('#btn-toggle').addClass('active');
            _this._draggableButton();
            $('#sidebar-container').addClass('active');
            _this.loadImage();
        },

        _close_sidebar: function(){
            $('#sidebar-container').removeClass('active').attr("style", "");
            $('#btn-toggle').removeClass('active').attr("style", "");
            $('#btn-toggle').draggable('destroy');
            $('.image-gallery').remove();
        },

        filterImage: function(){
            var search_string = $(this).val();
            _this.loadImage(search_string);
        },

        loadImage: function(search){
            if (!search){
                search = "";
            }

            $.ajax({
                method:'GET',
                url:_this.options.base_media_url + '?q='+search,
                success: function(data){
                    $('#list-media').empty();
                    $.each(data, function(index,file){
                        $('#list-media').append(singleMedia(file, index));
                        $('#image_' + index).draggable({
                            helper: 'clone',
                            revert: true,
                            appendTo: "body",
                            start: function() {
                                $(".ui-draggable").not(this).css({
                                    // height: 50,
                                    width: 50
                                });
                            },
                        });
                    });
                }
            });
            _this.makemenu();
        },

        makemenu: function(){

            $(document).on('click', '.clickable-menu', function(){
                _this._initMediaInfo();
                $('.clickable-menu').not($(this)).removeClass('active-media');
                $('.media-single-container').css("border-color","transparent");
                if (!$(this).hasClass('active-media')){
                    $('#media-info').removeClass('placeholder').text('');
                    $(this).addClass('active-media');
                    $(this).parent('.media-single-container').css("border-color", "#000");
                    $.ajax({
                        method: 'get',
                        async:false,
                        url:_this.options.base_media_url + $(this).data('id') + '/',
                        success: function(response){
                            $('#media-info').append('
<textarea style="width:98%" rows="4" readonly>'+response.file_src +'</textarea>
');
                        }
                    });
                    $('#media-info').append(_this.menuMedia($(this).data('id'), $(this).prop("tagName") == 'VIDEO', $(this).attr('src')));
                }else{
                    $(this).removeClass('active-media');
                }
            });
        },

        menuMedia : function(sha, video, src){
            var menu = '\
                <button id="tag_media" media="' + sha + '" class="' + _this.options.button_class + '">Add tag</button>\
                <button id="delete_media" media="' + sha + '" class="' + _this.options.button_class + '">Delete</button>';
            if (video){
                menu += '<button id="preview_media" image="' + sha + '" src="'+ src +'" class="' + _this.options.button_class + '">Preview</button>';
            }
            return menu;
        }
    };

    $.sidebargallery = function(options) {
        var opts = $.extend( {}, $.sidebargallery.defaults, options );
        gallery = new SidebarGallery(opts);
    };

    $.sidebargallery.defaults = {
        base_save_url: null, // Url to send request to server
        csrf_token:'',
        base_media_url:'',
        url_progress:null,
        toggle: '<button class="btn btn-default" id="btn-toggle">Gallery</button>',
        button_class: ''
    };
})(jQuery);
<commit_msg>Add containment to toggle draggable<commit_after>/* jshint multistr: true */

/* relies on:
    - jquery-ui.js
    - dropzone.js
*/
(function ($) {

    $(document).on('click', '.closeModal', function(event){
        event.preventDefault();
        $('#openModal').remove();
    });

    var modalPreview = function(url){
        var modal = '
\

\
                        X\
                        <video src="'+ url +'" width="500px" controls></video>\

\

';
        return modal;
    };

    var singleMedia = function(file, index){
        var single_media = '';
        if (file.file_src.indexOf('.mp4') > 0){
            single_media = '
<video data-id="'+ file.sha1 + '" id="image_'+ index + '" class="image  clickable-menu image_media" src="'+ file.file_src +'" style="max-height:80%;max-width:80%;"></video>
';
        }else{
            single_media = '

';
        }
        return single_media;
    };

    var sidebar = '\

\

\

Media
\
                <input placeholder="Search..." id="gallery-filter" type="text" class="form-control">\

\

Drag and drop or click to upload Media
\

\

\

Click on an item to view more options
\

\

';

    var sidebar_size = 200;
    var loaded = false;
    var initialized = false;
    var id= null;
    var toggle_button = null;
    var count = 0;

    var modal = '
\

\

\

\
                <button type="button" class="close" data-dismiss="modal">×Close</button>\

Modal title
\

\

\
                <video src="" id="modal-video" controls style="width:100%" preload="auto"></video>\

\

\
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>\
                <button type="button" class="btn btn-primary">Save changes</button>\

\

\

\

';

    function SidebarGallery(options){
        this.options = options;
        this._init();
        Dropzone.autoDiscover = false;
    }

    function notify_user(descr, level){
        $('body').prepend('
'+ descr + '
');
        setTimeout(function(){
            $('.notify-user-label').remove();
        }, 5000);
    }

    function update_progress_info(url) {
        $.getJSON(url, {'X-Progress-ID': id}, function(data, status){
            if(data){
                $('#progress-span').text((data.uploaded /data.lenght)*100);
            }
            else{
                $('#progress-span').text(100);
                return false;
            }
            setTimeout(update_progress_info(url), 100);
        });
    }

    SidebarGallery.prototype = {

        _init: function(){
            _this = this;
            $('body').append(_this.options.toggle).append(sidebar);
            $(document).on('click','#btn-toggle', _this._toggle_sidebar);
            $(document).on('keyup', '#gallery-filter', _this.filterImage);
            if (_this.options.url_progress){
                $(document).on('start_upload', function(){
                    setTimeout(update_progress_info(_this.options.url_progress), 20);
                });
            }
            $(document).on('click', '#delete_media', _this.deleteMedia);
            $(document).on('click', '#tag_media', _this.tagMedia);
            $(document).on('click', '#preview_media', _this.previewMedia);

            $(document).on('editInputVisible', function(){
                $('#input_editor').droppable({
                    drop: function(event, ui){
                        var droppable = $(this);
                        var draggable = ui.draggable;
                        droppable.focus();
                        droppable.selection('insert',{text:'![Alt text]('+ draggable.attr('src') +')' ,mode:'before'});
                        $(ui.helper).remove();
                        $('#input_editor').trigger('autosize.resize');
                    }
                });
            });

            $('.droppable-image').droppable({
                drop: function( event, ui ) {
                    var droppable = $(this);
                    if (droppable.prop("tagName") == 'IMG'){
                        if (ui.draggable.attr('src').indexOf(".png") > 0 || ui.draggable.attr('src').indexOf(".jpg") > 0){
                            droppable.attr('src', ui.draggable.attr('src'));
                            $(ui.helper).remove();
                            _this.saveImage(droppable);
                        }else{
                            notify_user("You can't put other file than image in this place", 'error');
                        }
                    }else if (droppable.prop("tagName") == 'VIDEO'){
                        if (ui.draggable.attr('src').indexOf(".mp4") > 0){
                            droppable.attr('src', ui.draggable.attr('src'));
                            $(ui.helper).remove();
                            _this.saveImage(droppable);
                        }else{
                            notify_user("You can't put other file than video in this place", 'error');
                        }
                    }
              }
            });

            var DocDropzone = new Dropzone('#media-container', { // Make the whole body a dropzone
                paramName: 'file',
                url: _this.options.base_media_url,
                maxFilesize: 50,
                parallelUploads: 2,
                clickable: true,
                createImageThumbnails:false,
            });

            DocDropzone.on("processing", function(file){
                id = (new Date()).getTime();
                if (_this.options.url_progress){
                    this.options.url = _this.options.base_media_url + '?X-Progress-ID=' +id;
                }
            });

            DocDropzone.on("cancel", function(file){
                $('.progress-text').remove();
            });

            DocDropzone.on("sending", function(file, xhr, formData){
                formData.append('csrfmiddlewaretoken', _this.options.csrf_token);
                $('#media-container').append('
Upload in progress

0%
Please wait...
');
                $.event.trigger({
                  type:    "start_upload",
                  message: "myTrigger fired.",
                  time:    new Date()
                });
            });

            DocDropzone.on("dragover", function(event){
                if (count !== 0){
                    $('body').prepend('
Release your file to upload it
');
                    count = 1;
                }
            });

            DocDropzone.on("drop", function(event){
                if ($('.url_info').length){
                    $('.url_info').remove();
                }
                $('.notify-user-label').remove();
                count = 0;
            });

            DocDropzone.on("dragleave", function(event){
                $('.notify-user-label').remove();
                count = 0;
            });

            DocDropzone.on("error", function(data, response){
                $('#media-container').append('
' + response.message + '
');
                setTimeout(function() {
                    $('.alert').remove();
                }, 3000);
            });

            DocDropzone.on("success", function(file, response){
                var status = file.xhr.status;
                $('.progress-text').remove();
                $('.dz-preview').remove();
                var last_index = $('#list-media').children().last().children().attr('id');
                if (last_index){
                    last_index = parseInt(last_index.split('image_')[1]) + 1;
                }else{
                    last_index = 0;
                }
                if (status == 201){
                    $('#list-media').prepend(singleMedia(response, last_index));

                    $('#image_' + last_index).draggable({
                        helper: 'clone',
                        revert: true,
                        appendTo: "body",
                        start: function() {
                            $(".ui-draggable").not(this).css({
                                width: 50
                            });
                        },
                    });
                    _this.makemenu();
                    var descr = "We're processing your uploaded file. You can start use it by using the sample in your gallery.";
                    notify_user(descr, 'info');
                }else{
                    notify_user(response.message, 'error');
                }
                if (!$('#sidebar-gallery').hasClass('active')){
                    _this._open_sidebar();
                }
            });
        },

        deleteMedia: function(event){
            event.preventDefault();
            var $this_element = $(this);
            $.ajax({
                method: 'delete',
                url: _this.options.base_media_url + $this_element.attr('media') +'/',
                success: function(){
                    $('img[data-id="' + $this_element.attr('media') + '"], video[data-id="' + $this_element.attr('media') + '"]').parent('.media-single-container').remove();
                }
            });
            $('#media-info').empty();
        },

        tagMedia: function(event){
            event.preventDefault();
            var $this_element = $(this);
            var orginal_tags = null;
            $.ajax({
                method: 'get',
                async:false,
                url:_this.options.base_media_url + $this_element.attr('media') +'/',
                success: function(response){
                    orginal_tags = response.tags;
                }
            });
            var tags = prompt('Please enter tags', orginal_tags);
            if (tags !== null){
                $.ajax({
                    method: 'patch',
                    url:_this.options.base_media_url + $this_element.attr('media') + '/',
                    data:{'tags': tags},
                    success: function(){
                        console.log('updated');
                    }
                });
            }
        },

        previewMedia: function(event){
            event.preventDefault();
            var $this_element = $(this);
            $('body').append(modalPreview($this_element.attr('src')));
        },

        saveImage: function(element){
            id_element = element.attr('id');
            data = {text: element.attr('src')};
            $.ajax({
                method:'PUT',
                async:false,
                url: _this.options.base_save_url + id_element +'/',
                data:data,
                success: function(data){
                    console.log('saved');
                }
            });
        },

        _initMediaInfo: function(){
            $('#media-info').addClass('placeholder').text('Click on an item to view more options');
        },

        _toggle_sidebar: function(){
            if ($('#sidebar-container').hasClass('active')){
                _this._close_sidebar();
            }else{
                _this._open_sidebar();
            }
        },

        _draggableButton: function(){
            $('#btn-toggle').draggable({
                axis: "x",
                cursor: "move",
                containment: "window",
                drag: function(event, ui){
                    var view_width = $(window).width();
                    if (view_width - ui.position.left - $(ui.helper).outerWidth() >= 300){
                        $('#sidebar-container').css("right", "0px").css("width", view_width - ui.position.left - $(ui.helper).outerWidth());
                    }else{
                        $('#btn-toggle').css("left", view_width - 300 - $(ui.helper).outerWidth());
                        return false;
                    }
                },
                stop : function(event, ui){
                    var view_width = $(window).width();
                    if (view_width - ui.position.left - $(ui.helper).outerWidth() >= 300){
                        $('#sidebar-container').css("right", "0px").css("width", view_width - ui.position.left - $(ui.helper).outerWidth());
                    }else{
                        $('#sidebar-container').css("right", "0px").css("width", 300);
                    }

                    $( event.toElement ).one('click', function(e){ e.stopImmediatePropagation(); } );
                }
            });
        },

        _open_sidebar: function(){
            $('#btn-toggle').addClass('active');
            _this._draggableButton();
            $('#sidebar-container').addClass('active');
            _this.loadImage();
        },

        _close_sidebar: function(){
            $('#sidebar-container').removeClass('active').attr("style", "");
            $('#btn-toggle').removeClass('active').attr("style", "");
            $('#btn-toggle').draggable('destroy');
            $('.image-gallery').remove();
        },

        filterImage: function(){
            var search_string = $(this).val();
            _this.loadImage(search_string);
        },

        loadImage: function(search){
            if (!search){
                search = "";
            }

            $.ajax({
                method:'GET',
                url:_this.options.base_media_url + '?q='+search,
                success: function(data){
                    $('#list-media').empty();
                    $.each(data, function(index,file){
                        $('#list-media').append(singleMedia(file, index));
                        $('#image_' + index).draggable({
                            helper: 'clone',
                            revert: true,
                            appendTo: "body",
                            start: function() {
                                $(".ui-draggable").not(this).css({
                                    // height: 50,
                                    width: 50
                                });
                            },
                        });
                    });
                }
            });
            _this.makemenu();
        },

        makemenu: function(){

            $(document).on('click', '.clickable-menu', function(){
                _this._initMediaInfo();
                $('.clickable-menu').not($(this)).removeClass('active-media');
                $('.media-single-container').css("border-color","transparent");
                if (!$(this).hasClass('active-media')){
                    $('#media-info').removeClass('placeholder').text('');
                    $(this).addClass('active-media');
                    $(this).parent('.media-single-container').css("border-color", "#000");
                    $.ajax({
                        method: 'get',
                        async:false,
                        url:_this.options.base_media_url + $(this).data('id') + '/',
                        success: function(response){
                            $('#media-info').append('
<textarea style="width:98%" rows="4" readonly>'+response.file_src +'</textarea>
');
                        }
                    });
                    $('#media-info').append(_this.menuMedia($(this).data('id'), $(this).prop("tagName") == 'VIDEO', $(this).attr('src')));
                }else{
                    $(this).removeClass('active-media');
                }
            });
        },

        menuMedia : function(sha, video, src){
            var menu = '\
                <button id="tag_media" media="' + sha + '" class="' + _this.options.button_class + '">Add tag</button>\
                <button id="delete_media" media="' + sha + '" class="' + _this.options.button_class + '">Delete</button>';
            if (video){
                menu += '<button id="preview_media" image="' + sha + '" src="'+ src +'" class="' + _this.options.button_class + '">Preview</button>';
            }
            return menu;
        }
    };

    $.sidebargallery = function(options) {
        var opts = $.extend( {}, $.sidebargallery.defaults, options );
        gallery = new SidebarGallery(opts);
    };

    $.sidebargallery.defaults = {
        base_save_url: null, // Url to send request to server
        csrf_token:'',
        base_media_url:'',
        url_progress:null,
        toggle: '<button class="btn btn-default" id="btn-toggle">Gallery</button>',
        button_class: ''
    };
})(jQuery);
<|endoftext|>