Skip to content
Snippets Groups Projects
panther2d.js 53.1 KiB
Newer Older
Lucio Zambon's avatar
Lucio Zambon committed
// jshint esversion: 6 
	let gui = new lil.GUI();
	let hideTimeout = false;
	let svg;
	let zoom = 1;
	let oldZoom = 1;
	let panZoomPanther;
	let foundAnimate = 1;
	let foundScale = 1.05;
	let myPanZoomTimer = null;
	let historytime = + new Date();
	let fel1 = false;
	let fel2 = false;
	const panZoomTime = 500;
	const facilities = [''];
	const names = [];
Lucio Zambon's avatar
Lucio Zambon committed
	const shrinkedNames = [];
Lucio Zambon's avatar
Lucio Zambon committed
	const serviceareanames = [];
	const alias = [];
	let maxZoom = 230;
	const status = [];
Lucio Zambon's avatar
Lucio Zambon committed
	const compData = {};
Lucio Zambon's avatar
Lucio Zambon committed
	const point = {x: 0, y: 0};
	const pa = document.location.search.replace('?','').split('&');
	const parameters = {};
	const state = document.location.search.indexOf('ps')>-1;
	const vlv = document.location.search.indexOf('vlv')>-1;
	const vlvs = [];
Lucio Zambon's avatar
Lucio Zambon committed
	const speechToken = Math.floor(Math.random() * 1000000000000);
Lucio Zambon's avatar
Lucio Zambon committed
	for (let i=0; i<pa.length; i++) {const p = pa[i].split('='); parameters[p[0]] = p[1];}
	const machineCaseSensitive = document.location.search.indexOf('machine=')>-1? document.location.search.split('machine=')[1].split('&')[0]: 'elettra';
	const machine = machineCaseSensitive.toLowerCase();
Lucio Zambon's avatar
Lucio Zambon committed
	let measurementStart = false;
Lucio Zambon's avatar
Lucio Zambon committed
	let cx, cy;
Lucio Zambon's avatar
Lucio Zambon committed
	let measurementType = document.location.search.indexOf('measurement=')>-1? document.location.search.split('measurement=')[1].split('&')[0].split(','): document.location.search.indexOf('measurement')>-1;
	let measurementEvent = 'contextmenu';
	if (typeof measurementType == "object") {
		const index = measurementType.indexOf('left'); 
Lucio Zambon's avatar
Lucio Zambon committed
		if (index>-1) {
Lucio Zambon's avatar
Lucio Zambon committed
			measurementEvent = 'mousedown';
			measurementType.splice(index, 1);
Lucio Zambon's avatar
Lucio Zambon committed
		}
Lucio Zambon's avatar
Lucio Zambon committed
		if (measurementType.length==0) $('#bm').hide();
Lucio Zambon's avatar
Lucio Zambon committed
	}
	else $('#bm').hide();
Lucio Zambon's avatar
Lucio Zambon committed
	let measurement = typeof measurementType == "object" || measurementType;
Lucio Zambon's avatar
Lucio Zambon committed

Lucio Zambon's avatar
Lucio Zambon committed
	function setTick(x, y, cx, cy, dist, distPixel, n, pow10=1000) {
		const tx1 = cx + (x - cx) / dist * pow10 * n;
		const ty1 = cy + (y - cy) / dist * pow10 * n;
		const tx2 = tx1 - (y - cy) / distPixel * 10;
		const ty2 = ty1 + (x - cx) / distPixel * 10;
		$('#tick'+n).attr('x1', tx1);
		$('#tick'+n).attr('y1', ty1);
		$('#tick'+n).attr('x2', tx2);
		$('#tick'+n).attr('y2', ty2);
Lucio Zambon's avatar
Lucio Zambon committed
		$('#tickLabel'+n).attr('x', 2*tx2-tx1);
		$('#tickLabel'+n).attr('y', 2*ty2-ty1);
		$('#tickLabel'+n).html(x==cx || distPixel<220? '': pow10 * n / 1000);
Lucio Zambon's avatar
Lucio Zambon committed
	}
	// https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
	function pDistance(x, y, x1, y1, x2, y2) {
		var A = x - x1;
		var B = y - y1;
		var C = x2 - x1;
		var D = y2 - y1;
		var dot = A * C + B * D;
		var len_sq = C * C + D * D;
		var param = -1;
		if (len_sq != 0) param = dot / len_sq; //in case of 0 length line
		var xx, yy;
		if (param < 0) {
			xx = x1;
			yy = y1;
		}
		else if (param > 1) {
			xx = x2;
			yy = y2;
		}
		else {
			xx = x1 + param * C;
			yy = y1 + param * D;
		}
		var dx = x - xx;
		var dy = y - yy;
		return {dist: Math.sqrt(dx * dx + dy * dy), x: xx, y: yy};
	}
Lucio Zambon's avatar
Lucio Zambon committed
	function getCursorPosition(main, event) {
		const rect = main.getBoundingClientRect();
		const x = event.clientX - rect.left;
		const y = event.clientY - rect.top;
		const distPixel = Math.sqrt(Math.pow(x - cx, 2) + Math.pow(y - cy, 2));
Lucio Zambon's avatar
Lucio Zambon committed
		const dist = distPixel / panZoomPanther.getSizes().realZoom;
Lucio Zambon's avatar
Lucio Zambon committed
		if (measurementStart) $('#stright').val(Math.round(dist)/1000);
Lucio Zambon's avatar
Lucio Zambon committed
		// const alpha = (Math.atan2(y-cy, x-cx) * 180) / Math.PI;
		$('#pos').val(Math.round((x - panZoomPanther.getPan().x)/panZoomPanther.getSizes().realZoom)/1000+' '+(-Math.round((y - panZoomPanther.getPan().y)/panZoomPanther.getSizes().realZoom)/1000));
Lucio Zambon's avatar
Lucio Zambon committed
		if (measurementStart) {
			// stright measurement
Lucio Zambon's avatar
Lucio Zambon committed
			const pow10 = Math.pow(10, Math.round(Math.log10(dist))-1);
Lucio Zambon's avatar
Lucio Zambon committed
			$('#measurementLine').attr('x2', x); 
			$('#measurementLine').attr('y2', y);
Lucio Zambon's avatar
Lucio Zambon committed
			$('#measurementLineStroke').attr('x2', x); 
			$('#measurementLineStroke').attr('y2', y);
Lucio Zambon's avatar
Lucio Zambon committed
			for (let i=1; i<32; i++) {
				if (i<dist/pow10 && distPixel>50) setTick(x, y, cx, cy, dist, distPixel, i, pow10); else setTick(x, y, x, y, dist, distPixel, i, pow10);
Lucio Zambon's avatar
Lucio Zambon committed
			}
Lucio Zambon's avatar
Lucio Zambon committed
			const vertex = [];
			let minDistance = Infinity;
			let dindex = -1;
			let mincDistance = Infinity;
			let dcindex = -1;
Lucio Zambon's avatar
Lucio Zambon committed
			// beam pattern measurement
			if (typeof measurementType == "object" && typeof lattice[measurementType[0]] == "object") {
Lucio Zambon's avatar
Lucio Zambon committed
				let d = 0;
				const x1 = (x - panZoomPanther.getPan().x) / panZoomPanther.getSizes().realZoom;
				const y1 = (y - panZoomPanther.getPan().y) / panZoomPanther.getSizes().realZoom;
				const xc1 = (cx - panZoomPanther.getPan().x) / panZoomPanther.getSizes().realZoom;
				const yc1 = (cy - panZoomPanther.getPan().y) / panZoomPanther.getSizes().realZoom;
Lucio Zambon's avatar
Lucio Zambon committed
				for (let i=0; i < lattice[measurementType[0]].sections.length; i++) {
					j = (i+1) % lattice[measurementType[0]].sections.length;
					vertex[i] = lattice[measurementType[0]].sections[i].start;
Lucio Zambon's avatar
Lucio Zambon committed
					// d = Math.sqrt(Math.pow(vertex[i].x - x, 2) + Math.pow(vertex[i].z - y, 2));
Lucio Zambon's avatar
Lucio Zambon committed
					d = pDistance(x1, y1, vertex[i].x, vertex[i].z, lattice[measurementType[0]].sections[j].start.x, lattice[measurementType[0]].sections[j].start.z);
Lucio Zambon's avatar
Lucio Zambon committed
					if (minDistance > d.dist) { minDistance = d.dist; dindex = i; p = d;}
Lucio Zambon's avatar
Lucio Zambon committed
					d = pDistance(xc1, yc1, vertex[i].x, vertex[i].z, lattice[measurementType[0]].sections[j].start.x, lattice[measurementType[0]].sections[j].start.z);
Lucio Zambon's avatar
Lucio Zambon committed
					if (mincDistance > d.dist) { mincDistance = d.dist; dcindex = i; pc = d;}
				}
				let pathd = 'M '+(pc.x*panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().x)+' '+(pc.y * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().y)+' ';				
				k = dcindex;
Lucio Zambon's avatar
Lucio Zambon committed
				j = (k+1) % lattice[measurementType[0]].sections.length;
				let dd = Math.sqrt(Math.pow(pc.x-lattice[measurementType[0]].sections[j].start.x, 2) + Math.pow(pc.y-lattice[measurementType[0]].sections[j].start.z, 2));
Lucio Zambon's avatar
Lucio Zambon committed
				if (dcindex == dindex) dd = Math.sqrt(Math.pow(pc.x-p.x, 2) + Math.pow(pc.y-p.y, 2));
				else {
					while (k != dindex) {
Lucio Zambon's avatar
Lucio Zambon committed
						j = (k+1) % lattice[measurementType[0]].sections.length;
						if (k != dcindex) dd = dd + Math.sqrt(Math.pow(lattice[measurementType[0]].sections[k].start.x-lattice[measurementType[0]].sections[j].start.x, 2) + Math.pow(lattice[measurementType[0]].sections[k].start.z-lattice[measurementType[0]].sections[j].start.z, 2));
						pathd = pathd + 'L '+(lattice[measurementType[0]].sections[j].start.x * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().x)+' '+(lattice[measurementType[0]].sections[j].start.z * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().y)+' ';
Lucio Zambon's avatar
Lucio Zambon committed
						k = j;
					}
Lucio Zambon's avatar
Lucio Zambon committed
					dd = dd + Math.sqrt(Math.pow(p.x-lattice[measurementType[0]].sections[dindex].start.x, 2) + Math.pow(p.y-lattice[measurementType[0]].sections[dindex].start.z, 2));
Lucio Zambon's avatar
Lucio Zambon committed
				}
				$('#bm').val(Math.round(dd)/1000);
				pathd = pathd + 'L '+(p.x * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().x)+' '+(p.y * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().y);
				//<path d="M 10 10 H 90 V 90 H 10 L 10 10"/>
				console.log('minDistance', mincDistance, dcindex, pc, minDistance, dindex, p, dd, 'pathd', pathd);
				$('#beam').attr('d', pathd);
Lucio Zambon's avatar
Lucio Zambon committed
				$('#measurementSide1').attr('x2', pc.x * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().x);
				$('#measurementSide1').attr('y2', pc.y * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().y);
				$('#measurementSide2').attr('x1', x);
				$('#measurementSide2').attr('y1', y);
				$('#measurementSide2').attr('x2', p.x * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().x);
				$('#measurementSide2').attr('y2', p.y * panZoomPanther.getSizes().realZoom + panZoomPanther.getPan().y);
Lucio Zambon's avatar
Lucio Zambon committed
			}
Lucio Zambon's avatar
Lucio Zambon committed
		}
Lucio Zambon's avatar
Lucio Zambon committed
	}
Lucio Zambon's avatar
Lucio Zambon committed
	function clearmeasurement() {
		$('#measurementLine').attr('x1', cx);
		$('#measurementLine').attr('y1', cy);
		$('#measurementLine').attr('x2', cx);
		$('#measurementLine').attr('y2', cy);
Lucio Zambon's avatar
Lucio Zambon committed
		$('#measurementLineStroke').attr('x1', cx);
		$('#measurementLineStroke').attr('y1', cy);
		$('#measurementLineStroke').attr('x2', cx);
		$('#measurementLineStroke').attr('y2', cy);
Lucio Zambon's avatar
Lucio Zambon committed
		$('#measurementSide1').attr('x1', cx);
		$('#measurementSide1').attr('y1', cy);
		$('#measurementSide1').attr('x2', cx);
		$('#measurementSide1').attr('y2', cy);
		$('#measurementSide2').attr('x1', cx);
		$('#measurementSide2').attr('y1', cy);
		$('#measurementSide2').attr('x2', cx);
		$('#measurementSide2').attr('y2', cy);
Lucio Zambon's avatar
Lucio Zambon committed
		$('#stright').val('');
Lucio Zambon's avatar
Lucio Zambon committed
		$('#bm').val('');
		$('#beam').attr('d', '');
Lucio Zambon's avatar
Lucio Zambon committed
		for (let i=1; i<32; i++) {setTick(cx, cy, cx, cy, 1, 1, i);}
Lucio Zambon's avatar
Lucio Zambon committed
	}
	function initCursorPosition(main, event) {
Lucio Zambon's avatar
Lucio Zambon committed
		if (measurementStart) { measurementStart = false; return;}
Lucio Zambon's avatar
Lucio Zambon committed
		const rect = main.getBoundingClientRect();
		cx = event.clientX - rect.left;
		cy = event.clientY - rect.top;
		console.log(Math.round(cx) + "," + Math.round(cy) + ",");
Lucio Zambon's avatar
Lucio Zambon committed
		if (!measurementStart) {
			// appendSvg("circle", {id: 'measurementStart', cx: cx, cy: cy, r:8, style:"display: block", fill:"none", stroke:"red","stroke-width":2});
			if ($('#measurementLine').length==0) {
Lucio Zambon's avatar
Lucio Zambon committed
				appendSvg("line", {id: 'measurementLineStroke', x1: cx, y1: cy, x2: cx, y2: cy, style:"display: block", fill:"yellow", stroke:"black","stroke-width":4});
				appendSvg("line", {id: 'measurementLine', x1: cx, y1: cy, x2: cx, y2: cy, style:"display: block", fill:"yellow", stroke:"yellow","stroke-width":2});
Lucio Zambon's avatar
Lucio Zambon committed
				appendSvg("path", {d: '', fill: "none", stroke: "limegreen", "stroke-width": 3, id:"beam"});
Lucio Zambon's avatar
Lucio Zambon committed
				appendSvg("line", {id: 'measurementSide1', x1: cx, y1: cy, x2: cx, y2: cy, style:"display: block", fill:"none", stroke:"pink","stroke-width":2});
				appendSvg("line", {id: 'measurementSide2', x1: cx, y1: cy, x2: cx, y2: cy, style:"display: block", fill:"none", stroke:"pink","stroke-width":2});
Lucio Zambon's avatar
Lucio Zambon committed
				for (let i=1; i<32; i++) {
Lucio Zambon's avatar
Lucio Zambon committed
					appendSvg("line", {id: 'tick'+i, x1: cx, y1: cy, x2: cx, y2: cy, style:"display: block", fill:"yellow", stroke:"black","stroke-width":1});
					appendSvg("text", {id: 'tickLabel'+i, x: cx, y: cy, fill:"white", stroke:"black","stroke-width":1, "font-family":"Arial", "font-size":20, "font-weight":"bold", "text-anchor": "start"});
Lucio Zambon's avatar
Lucio Zambon committed
				}
Lucio Zambon's avatar
Lucio Zambon committed
			}
			else {
Lucio Zambon's avatar
Lucio Zambon committed
				clearmeasurement();
Lucio Zambon's avatar
Lucio Zambon committed
			}
Lucio Zambon's avatar
Lucio Zambon committed
			measurementStart = true;
Lucio Zambon's avatar
Lucio Zambon committed
		}
		else {
Lucio Zambon's avatar
Lucio Zambon committed
			// $('#measurementStart').attr('cx', cx);	$('#measurementStart').attr('cy', cy);
			$('#measurementLine').attr('x1', cx);
			$('#measurementLine').attr('y1', cy);
Lucio Zambon's avatar
Lucio Zambon committed
			$('#measurementLineStroke').attr('x1', cx);
			$('#measurementLineStroke').attr('y1', cy);
Lucio Zambon's avatar
Lucio Zambon committed
		}
		main.addEventListener('mousemove', function(e) {
			getCursorPosition(main, e);
		});
	}
Lucio Zambon's avatar
Lucio Zambon committed
	if (document.location.search.indexOf('measurement')>-1) {
		measurementEnable();
	}
	function measurementToggle(enable) {
		for (let i=1; i<100; i++) {
			if ($('#lil-gui-name-'+i).html()=='measurement') {
				if (enable) {
					$('#lil-gui-name-'+(i+1)).parent().show();
					$('#lil-gui-name-'+(i+2)).parent().show();
				}
				else {
					$('#lil-gui-name-'+(i+1)).parent().hide();
					$('#lil-gui-name-'+(i+2)).parent().hide();
				}
				break;
			}
		}
	}
	function measurementDisable() {
		clearmeasurement();
		main.removeEventListener(measurementEvent, measurementListener, false);
		main.style.cursor = 'default';
		measurementToggle(false);
	}
	function measurementListener(e) {
		e.preventDefault();
		initCursorPosition(main, e);
		return false;
	}
	function measurementEnable() {
		$('#measurement').show();
Lucio Zambon's avatar
Lucio Zambon committed
		const main = document.getElementById('main');
Lucio Zambon's avatar
Lucio Zambon committed
		main.style.cursor = 'crosshair';
Lucio Zambon's avatar
Lucio Zambon committed
		main.addEventListener(measurementEvent, measurementListener, false);
		measurementToggle(true);
	}
	function measurementFacility(msg) {
		console.log('measurementFacility()', msg);
		if (msg=='left') {
			if (measurementEvent != 'mousedown') {
				measurementDisable();
				measurementEvent = 'mousedown';
				measurementEnable();
			}
		}
		else if (msg=='right') {
			if (measurementEvent == 'mousedown') {
				measurementDisable();
				measurementEvent = 'contextmenu';
				measurementEnable();
			}
		}
		else if (msg=='') {
			measurementDisable();
			measurementType = true;
			measurementEnable();
Lucio Zambon's avatar
Lucio Zambon committed
			$('#bm').hide();
Lucio Zambon's avatar
Lucio Zambon committed
		}
		else {
			measurementDisable();
			measurementType = [msg];
			measurementEnable();
Lucio Zambon's avatar
Lucio Zambon committed
			$('#bm').show();
Lucio Zambon's avatar
Lucio Zambon committed
		}
Lucio Zambon's avatar
Lucio Zambon committed
	}
Lucio Zambon's avatar
Lucio Zambon committed

Lucio Zambon's avatar
Lucio Zambon committed
	//https://puma-01.elettra.eu/rchan.php?json&valueOnly&src=srv-tango-srf-01.fcs.elettra.trieste.it:20000/f/access_control/safety/Undulator_access_state -> 5 FEL1, 6 FEL2
	if (machine.indexOf('fermi')>-1) {
		fetch(conf.rchan+'srv-tango-srf-01:20000/f/access_control/safety/Undulator_access_state').then((response) => {return response.json();}).then((fel) => {
			fel1 = fel[5] == 1;
			fel2 = fel[6] == 1;
		});
	}
Lucio Zambon's avatar
Lucio Zambon committed
	function resizeIframe(obj) {
		obj.style.height = obj.contentWindow.document.documentElement.scrollHeight + 'px';
	}
Lucio Zambon's avatar
Lucio Zambon committed
	let latticeFile = document.location.href.split('?')[0].split('/').slice(0,-1).join('/')+'/'+machine+'_lattice.json';
	if (machine.indexOf('simulator_')>-1) {latticeFile = document.location.href.split('?')[0].split('/').slice(0,-1).join('/')+'/'+'simulator.php?lattice&machine='+machine.split('simulator_')[1];}
Lucio Zambon's avatar
Lucio Zambon committed
	const menuParams = {machine: machineCaseSensitive.toLowerCase(), search: '', backgroundColor: '#333333'};
Lucio Zambon's avatar
Lucio Zambon committed
	gui.title('PAnTHer - controls');
	// if (navigator.userAgent.indexOf('Firefox/63')>-1) {$( "body" ).append('<button id="starter" style="align: center;height: 500px; width: 95%;background-color: #449944; font-size: 100px;" onClick="mystart()">START</button>');}
	function mystart() {
		panZoomPanther = svgPanZoom('#panther', {beforeZoom: myZoom, fit: false, contain: false});
		$("#sname").on("keydown", searchText);
		$('#starter').hide();
	}
Lucio Zambon's avatar
Lucio Zambon committed
	// Polyfill replaceAll()
	if (typeof String.prototype.replaceAll !== 'function') {
Lucio Zambon's avatar
Lucio Zambon committed
		String.prototype.replaceAll = function(search, replacement) {
			var target = this;
			return target.split(search).join(replacement);
		};
Lucio Zambon's avatar
Lucio Zambon committed
	}
Lucio Zambon's avatar
Lucio Zambon committed
	// Polyfill for parentNode.replaceChildren()
	if (typeof Element.prototype.replaceChildren !== 'function') {
		Object.defineProperty(Element.prototype, 'replaceChildren', {
			configurable: true,
			writable: true,
			value: function replaceChildren(...nodes) {
				// Remove all existing child nodes
				while (this.firstChild) {
					this.removeChild(this.firstChild);
				}
				// Append new DOM objects
				this.append(...nodes);
			}
		});
	}
	function toggleMachine(machine) {
		document.location = document.location.href.split('?')[0] + '?machine='+machine;
		/*if (document.location.search.indexOf('machine=')==-1) document.location = document.location.href + (document.location.href.indexOf('?')==-1? '?': '&') + 'machine='+machine;
		let search = document.location.search.split('machine=')[1].split('&')[0];
		document.location = document.location.href.replace('machine='+search, 'machine='+machine);*/
	}
Lucio Zambon's avatar
Lucio Zambon committed
	function compLink(id) {
		console.log('compLink()', id, document.getElementById("compdb").href);
		// window.open(document.getElementById("compdb").href, '_blank').focus();
		window.open(id, 'components').focus();
		// event.stopPropagation();
Lucio Zambon's avatar
Lucio Zambon committed
		return false;
	}
	function searchText(e) {
		console.log('searchText()', e, e.keyCode || e.which, $("#sname").val().toUpperCase().replace('.','_'));
Lucio Zambon's avatar
Lucio Zambon committed
		if (e.keyCode == 13) findComponent($("#sname").val().toUpperCase());
Lucio Zambon's avatar
Lucio Zambon committed
		// return -1;
	}
Lucio Zambon's avatar
Lucio Zambon committed
	function shrinkName(name) {
		return name.replaceAll('FEL0', 'FEL').replaceAll('PS_', 'PS').replaceAll('SIP_', 'SIP').replaceAll('KG0', 'KG').replaceAll('BC0', 'BC').replaceAll('_L0', 'L').replaceAll('_F0', 'F').replaceAll('_0', '').replaceAll('_', '');
	}
Lucio Zambon's avatar
Lucio Zambon committed
	// if (navigator.userAgent.indexOf('Firefox/63')==-1) {gui.add(menuParams, 'machine', conf.machineList).onChange(function() {toggleMachine(menuParams.machine);});}
	gui.add(menuParams, 'machine', conf.machineList).onChange(function() {toggleMachine(menuParams.machine);});
	gui.add(menuParams, 'search');
	$('.controller.string:last').parent().append('<iframe id="talk" style="height: 30px;" src="./speech/talk.php?background=black&token='+speechToken+'" frameborder="0" scrolling="no" onload="resizeIframe(this)"></iframe>');
	gui.addColor(menuParams, 'backgroundColor').onChange(function() {toggleParam('backgroundColor');});
	menuParams.vlv = document.location.search.indexOf('vlv')>-1;
	gui.add(menuParams, 'vlv').name('vlv & bst').onChange(function() {toggleParam('vlv');});
	menuParams.ps = document.location.search.indexOf('ps')>-1;
	gui.add(menuParams, 'ps').onChange(function() {toggleParam('ps');});
	menuParams.measurement = document.location.search.indexOf('measurement')>-1;
	gui.add(menuParams, 'measurement').onChange(function() {toggleParam('measurement');});
Lucio Zambon's avatar
Lucio Zambon committed
	const sstring = $('.controller.string').children().eq(1).children().eq(0);
	sstring.attr('id', 'sname');
	sstring.attr('name', 'sname');
	sstring.addClass("form-control sname");
	function findComponent(name) {
Lucio Zambon's avatar
Lucio Zambon committed
		// https://stackoverflow.com/questions/5497318/replace-last-occurrence-of-character-in-string
		if (name.indexOf('.')==-1 && name.indexOf('_')>-1) name = name.replace(/_([^_]*)$/, '.' + '$1');
		if (document.location.search.indexOf('debugfind')>-1) {console.log('findComponent('+name+')'); return 'OK';}
Lucio Zambon's avatar
Lucio Zambon committed
		let servicearea = false;
		console.log('lattice', lattice);
		if (lattice.servicearea) for (let i in lattice.servicearea.sections) {
			for (let j in lattice.servicearea.sections[i].components) {
				if (name.replace('.', '_')==lattice.servicearea.sections[i].components[j].name.replace('.', '_')) {servicearea = true;}
Lucio Zambon's avatar
Lucio Zambon committed
				for (let k in lattice.servicearea.sections[i].components[j].embedded) {
					if (name==lattice.servicearea.sections[i].components[j].embedded[k]) {servicearea = true;}
Lucio Zambon's avatar
Lucio Zambon committed
				}
			}
		}
		console.trace(name, servicearea, document.location.search.indexOf('servicearea'), document.location.search.indexOf('search='+name)); // return;
		if ((servicearea != document.location.search.indexOf('servicearea')>-1) && document.location.search.indexOf('search='+name)==-1) {
			document.location = './panther2d.php?machine='+machine+'&search='+name+(servicearea? '&servicearea': '');
		}
		if (name==null) name = document.getElementById('sname').value;
		for (let i=0; i<alias.length; i++) if (alias[i][1]==name) name = alias[i][0];
Lucio Zambon's avatar
Lucio Zambon committed
		let id = name.replace('.', '_');
Lucio Zambon's avatar
Lucio Zambon committed
		document.getElementById('sname').value = name;
Lucio Zambon's avatar
Lucio Zambon committed
		console.log(name, typeof $('#'+name)[0], shrinkName(name), shrinkedNames.indexOf(shrinkName(name)));
Lucio Zambon's avatar
Lucio Zambon committed
		if (typeof $('#'+id)[0] == 'undefined') {
			const sindex = shrinkedNames.indexOf(shrinkName(id));
			if (sindex>-1) id = names[sindex]; else return name+' Not found';
Lucio Zambon's avatar
Lucio Zambon committed
		}
Lucio Zambon's avatar
Lucio Zambon committed
		console.log(name, window.innerWidth/2, $('#'+id)[0].getCTM().e, $('#'+id)[0].getCTM().f);
Lucio Zambon's avatar
Lucio Zambon committed
		// panZoomPanther.zoomAtPoint(10, {x: window.innerWidth/2 - $('#'+name)[0].getCTM().e, y: window.innerHeight/2 - $('#'+name)[0].getCTM().f})
		panZoomPanther.zoom(10);
		// leave a delay between zoom and pan
Lucio Zambon's avatar
Lucio Zambon committed
		setTimeout(mypan, 1200, id);
Lucio Zambon's avatar
Lucio Zambon committed
		return 'OK';
Lucio Zambon's avatar
Lucio Zambon committed
	}
	function mypan(name) {
		$('.label').show(); 
		const x = window.innerWidth/2 - $('#'+name)[0].getCTM().e + panZoomPanther.getPan().x;
		const y = window.innerHeight/2 - $('#'+name)[0].getCTM().f + panZoomPanther.getPan().y;
		const m = $("svg")[0].getTransformToElement($('#'+name)[0]);
		panZoomPanther.pan({x: x, y: y});
		setTimeout(pinhide, 100, name,  $('#'+name).eq(0).attr('transform'));
	}
	function pinhide(name, transform) {
Lucio Zambon's avatar
Lucio Zambon committed
		// console.log(foundAnimate, foundScale);
Lucio Zambon's avatar
Lucio Zambon committed
		foundAnimate *= foundScale;
		if (foundAnimate>1.5) foundScale = 0.95;
		if (foundAnimate<1) {foundScale = 1.05; foundAnimate = 1;} else setTimeout(pinhide, 100, name, transform);
		$('#'+name).eq(0).attr('transform',transform+',scale('+foundAnimate+')');
	}
	// $(function() {$(".sname").autocomplete({source: names, close: function(event, ui) {findComponent($('#sname').val()); }, select: function(event, ui) {findComponent(ui.item.value); return false;}});});
	$(function() {$(".sname").autocomplete({source: names, select: function(event, ui) {findComponent(ui.item.value); return false;}});});
	function toggleParam(name) {
Lucio Zambon's avatar
Lucio Zambon committed
		if (name=='measurement') { measurement = !measurement; measurementType = measurement; if (measurement) measurementEnable(); else  measurementDisable(); return;}
Lucio Zambon's avatar
Lucio Zambon committed
		if (name=='backgroundColor') {$('body').css('backgroundColor', menuParams.backgroundColor); return;}
Lucio Zambon's avatar
Lucio Zambon committed
		const urlparam = {};
		let search = document.location.search.replace('?', '').split('&');
		if (search[0]=='') search.splice(0,1);
		const i=search.indexOf(name);
		if (i==-1) search.push(name); else search.splice(i,1);
		const res = search.join('&');
		document.location = document.location.href.split('?')[0]+(res.length? '?'+res: '');
	}
Lucio Zambon's avatar
Lucio Zambon committed
	// let ujiveStarted = false;
Lucio Zambon's avatar
Lucio Zambon committed
	async function subscribeSpeech() {
		mylog('subscribeSpeech()', 1, 2);
		let response = await fetch("./speech/talk.php?read&token="+speechToken);
Lucio Zambon's avatar
Lucio Zambon committed
		if (response.status == 502) {
Lucio Zambon's avatar
Lucio Zambon committed
			await subscribeSpeech();
Lucio Zambon's avatar
Lucio Zambon committed
		} else if (response.status != 200) {
			// An error - let's show it
Lucio Zambon's avatar
Lucio Zambon committed
			mylog('subscribeSpeech() ERROR ', response.statusText);
Lucio Zambon's avatar
Lucio Zambon committed
			// Reconnect in one second
			await new Promise(resolve => setTimeout(resolve, 1000));
Lucio Zambon's avatar
Lucio Zambon committed
			await subscribeSpeech();
Lucio Zambon's avatar
Lucio Zambon committed
		} else {
			// Get and show the message
			let message = await response.text();
Lucio Zambon's avatar
Lucio Zambon committed
			mylog('subscribeSpeech()', message);
Lucio Zambon's avatar
Lucio Zambon committed
			if (message=='ujive') {
Lucio Zambon's avatar
Lucio Zambon committed
				window.open('../ujive.php?token='+speechToken, 'ujive').focus();
				/*if (!ujiveStarted) ujiveWindow = window.open('../ujive.php?token='+speechToken, '_blank').focus();
				setTimeout(ujiveReset, 15000);
				ujiveStarted = true;*/
Lucio Zambon's avatar
Lucio Zambon committed
			}
			else {
				const msg = findComponent(message);
				// return feedback
				fetch("./speech/talk.php?readresult="+msg+"&token="+speechToken);
			}
Lucio Zambon's avatar
Lucio Zambon committed
			// Call subscribeSpeech() again to get the next message
			await subscribeSpeech();
Lucio Zambon's avatar
Lucio Zambon committed
		}
	}
Lucio Zambon's avatar
Lucio Zambon committed
	// function ujiveReset() {ujiveStarted = false;}
Lucio Zambon's avatar
Lucio Zambon committed
	function mylog(...args) {
Lucio Zambon's avatar
Lucio Zambon committed
		if (document.location.search.indexOf('debug')>-1) $('#debug').val($('#debug').val()+JSON.stringify(args)+'\n');
		console.trace.apply(null);
		console.log(args, JSON.stringify(args), $('#debug').val());
Lucio Zambon's avatar
Lucio Zambon committed
	}
	function initIndex(lattice) {
		const index = [];
		for (let l in lattice.conf.index) {
			if (l=='start') continue;
			const cmd = "findComponent('"+lattice.conf.index[l].replace('.','_')+"')";
			index.push('<button onclick="'+cmd+'">'+l+'</button>');
		}
		$('body').append('<div style="position: absolute; left: 5px; bottom: 5px;">'+index.join(' ')+'</div>');
	}
Lucio Zambon's avatar
Lucio Zambon committed
	function toggleFacility(value) {
		console.log('toggleFacility', value, this);
		if (value) $('.'+this.property).show(); else $('.'+this.property).hide();
	}
Lucio Zambon's avatar
Lucio Zambon committed
	function init() {
		fetch(latticeFile).then((response) => {return response.json();}).then((flattice) => {
			lattice = flattice;
			if (Object.keys(lattice).length>0) {
Lucio Zambon's avatar
Lucio Zambon committed
				gui.add(menuParams, 'measurement button', {Left: 'left', Right: 'right'}).onChange(measurementFacility);
Lucio Zambon's avatar
Lucio Zambon committed
				const measurementDevice = {'': ''};
Lucio Zambon's avatar
Lucio Zambon committed
				const machineFolder = gui.addFolder('toggle facility');
Lucio Zambon's avatar
Lucio Zambon committed
				for (let i in lattice) {if (i!='conf') facilities.push(i);}
Lucio Zambon's avatar
Lucio Zambon committed
				menuParams[' '] = false; machineFolder.add(menuParams, ' ').onChange(toggleFacility);
Lucio Zambon's avatar
Lucio Zambon committed
				// for (let i=0; i<facilities.length; i++) if (facilities[i]!='') {menuParams[facilities[i]] = true;}
Lucio Zambon's avatar
Lucio Zambon committed
				for (let i in lattice) {
					if (i == 'conf') continue;
Lucio Zambon's avatar
Lucio Zambon committed
					menuParams[i] = document.location.search.indexOf(i+'=hide')==-1;
Lucio Zambon's avatar
Lucio Zambon committed
					if (i != 'servicearea' && i != 'bl') measurementDevice[i] = i;
Lucio Zambon's avatar
Lucio Zambon committed
					console.log(i, menuParams[i]);
Lucio Zambon's avatar
Lucio Zambon committed
					// logic XOR https://stackoverflow.com/questions/2335979/is-there-anyway-to-implement-xor-in-javascript
Lucio Zambon's avatar
Lucio Zambon committed
					if ((document.location.search.indexOf('servicearea')==-1) != (i=='servicearea')) {
						initLattice(lattice[i].sections, i);
						// menuParams[i] = true;
					} 
					else {
						initLattice(lattice[i].sections, i);
						console.log('.', i, menuParams[i]);
						if (document.location.search.indexOf('+servicearea')>-1) {
							// menuParams[i] = true;
						}
						else {
							menuParams[i] = false;
						}
Lucio Zambon's avatar
Lucio Zambon committed
					}
Lucio Zambon's avatar
Lucio Zambon committed
					if (!menuParams[i]) $('.'+i).hide();
Lucio Zambon's avatar
Lucio Zambon committed
				}
Lucio Zambon's avatar
Lucio Zambon committed
				for (let i=0; i<facilities.length; i++) if (facilities[i]!='') {machineFolder.add(menuParams, facilities[i]).onChange(toggleFacility);}
Lucio Zambon's avatar
Lucio Zambon committed
				machineFolder.close();
Lucio Zambon's avatar
Lucio Zambon committed
				gui.add(menuParams, 'measurement device', measurementDevice).onChange(measurementFacility);
Lucio Zambon's avatar
Lucio Zambon committed
				if (document.location.search.indexOf('measurement')==-1) measurementToggle(false);
Lucio Zambon's avatar
Lucio Zambon committed
				if (document.location.search.indexOf('servicearea')>-1) initSearch(lattice.servicearea.sections, 'servicearea');
Lucio Zambon's avatar
Lucio Zambon committed
				if (typeof blm != 'undefined') blmMenu(lattice, facilities, menuParams);
Lucio Zambon's avatar
Lucio Zambon committed
				bpmInit(facilities); 
Lucio Zambon's avatar
Lucio Zambon committed
				if (typeof bpmData != 'undefined') bpmMenu(lattice, facilities, menuParams);
Lucio Zambon's avatar
Lucio Zambon committed
				if (lattice.conf && lattice.conf.index) initIndex(lattice);
			}
			$('.scale').attr('transform', "scale(2)");
			// {$('<div><iframe style="width: 100%;height:250px;" src="../misc/gauge.html?dark&r1only=1&r=100&max=360&throttlingPeriod=50&apply=rotate&val='+0+'"></iframe></div>').insertBefore('.function');}
			// panZoomPanther = svgPanZoom('#panther', {beforeZoom: myZoom, fit: false, contain: false}); // https://github.com/bastienmoulia/svg-pan-zoom-rotate
			// if( /Android|webOS|iPhone|iPad|Mac|Macintosh|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
			if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
				panZoomPanther = svgPanZoom('#panther', {
					zoomEnabled: true,
					controlIconsEnabled: false,
					fit: 0,
					center: 1,
					maxZoom: maxZoom*2,
					customEventsHandler: eventsHandler,
					//beforeZoom: myZoom,
				});
			}
			else {
				panZoomPanther = svgPanZoom('#panther', {
					zoomEnabled: true,
					zoomScaleSensitivity: 0.3,
					controlIconsEnabled: false,
					fit: false,
					center: false,
					minZoom: 0.2,
					maxZoom: maxZoom,
					beforePan: myPan,
					beforeZoom: myZoom,
				});
			}
			if (document.location.search.indexOf('debug')>-1) {
				$('#tooltip').show();
				$('#tooltip').css('width', '100%');
				$('#tooltip').html('<textarea id="debug" style="height: 100px; width:100%;"></textarea>');
			}
Lucio Zambon's avatar
Lucio Zambon committed
			subscribeSpeech();
Lucio Zambon's avatar
Lucio Zambon committed
			let pan = [window.innerWidth/2, window.innerHeight/2];
			if (document.location.search.indexOf('pan=')>-1) pan = document.location.search.split('pan=')[1].split('&')[0].split(',');
			if (document.location.search.indexOf('search=')>-1) findComponent(document.location.search.split('search=')[1].split('&')[0]);
			else {
Lucio Zambon's avatar
Lucio Zambon committed
				const default_zoom = typeof conf.default_zoom[machine.split('_')[0]]=='undefined'? conf.default_zoom.default: conf.default_zoom[machine.split('_')[0]];
				const zoom = document.location.search.indexOf('zoom=')>-1? document.location.search.split('zoom=')[1].split('&')[0]-0: default_zoom;
Lucio Zambon's avatar
Lucio Zambon committed
				panZoomPanther.zoom(zoom);
				setTimeout(panZoomPanther.pan, 600, {x: pan[0], y: pan[1]});
			}
			if (state) {
				fetch(conf.stateSrcUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
					const statSrc = data.toUpperCase().split('.').join('_').split(',');
					for (let j=0; j<statSrc.length; j++) {
						// if (statSrc[j].split('/')[2]=='POWER_SUPPLY' || statSrc[j].split('/')[2]=='INJECTION' || statSrc[j].split('/')[2]=='EXTRACTION') 
							statSrc[j] = statSrc[j].split('/')[3].replace('PS', '');
					}
					for (let i=0; i<status.length; i++) { 
							if (status[i].name.indexOf('KICK')>-1) console.log('KICK state', i, status[i].name, statSrc);
						for (let j=0; j<statSrc.length; j++) {
							if (status[i].name.indexOf(statSrc[j])>-1) {status[i].statsrc = state; status[i].statindex = j;}
						}
					}
					// console.log('statSrc', data, statSrc, status);
				});
				setInterval(updateStatus, 1000);
			}
			if (vlv) {
				for (let i in conf.bstmap) { if (i.indexOf('.')>-1) conf.bstmap[i.replace('.','_')] = conf.bstmap[i];}
				fetch(conf.vlvSrcUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
					const vlvSrc = data.toUpperCase().substring(14).split(',');
					for (let i=0; i<vlvs.length; i++) { 
						for (let j=0; j<vlvSrc.length; j++) {
Lucio Zambon's avatar
Lucio Zambon committed
							const vlva = vlvSrc[j].split('/');
							if (vlva.length < 4) continue;
							const name = vlva[3].replace('.','_');
Lucio Zambon's avatar
Lucio Zambon committed
							if (vlvs[i].name.replace('.','_').indexOf(name)>-1) {vlvs[i].vlvsrc = state; vlvs[i].vlvindex = j; vlvs[i].type = 'vlv';}
							if (vlvSrc[j].split('/')[2].indexOf(conf.bstmap.base)>-1) {
								if (conf.bstmap[vlvs[i].name] && conf.bstmap[vlvs[i].name].indexOf(vlvSrc[j].split('/')[4])>-1) {
									vlvs[i].vlvsrc = 'bst'; vlvs[i].vlvindex = j; vlvs[i].type = 'bst';
								}
							}
						}
					}
					//console.log('vlvSrc', data, vlvSrc, vlvs);
				});
				setInterval(updateVlv, 1000);
			}
			$("#sname").on("keydown", searchText);
Lucio Zambon's avatar
Lucio Zambon committed
			if (lattice.conf && lattice.conf.modules) {
Lucio Zambon's avatar
Lucio Zambon committed
				for (let i=0; i<lattice.conf.modules.length; i++) {
Lucio Zambon's avatar
Lucio Zambon committed
					window[lattice.conf.modules[i]+'2d'](lattice, menuParams, compData);
Lucio Zambon's avatar
Lucio Zambon committed
				}
			}
Lucio Zambon's avatar
Lucio Zambon committed
			menuParams.gotoAdmin = function() {document.location = './admin.php';};
			gui.add(menuParams, 'gotoAdmin').name('Admin');
			menuParams.goto3D =  function() {document.location = './panther.php?machine='+menuParams.machine;}; 
			gui.add(menuParams, 'goto3D').name('3D');
Lucio Zambon's avatar
Lucio Zambon committed
		});
	}
	function showStatus(i, stat) {
		if (stat == 0 || stat == 'null' || stat == '' || stat == 'ON' || stat == 'RUNNING' || (!fel1 && $('#'+status[i].name)[0].classList[0]=='fel1') || (!fel2 && $('#'+status[i].name)[0].classList[0]=='fel2')) {$('#'+status[i].name).hide();}
Lucio Zambon's avatar
Lucio Zambon committed
		else if (stat == 'ON' || stat == 'RUNNING') {$('#'+status[i].name).show();document.getElementById(status[i].name).style.fill = conf.stateLabelColor[stat];$('#'+status[i].name).addClass('noblink');}
		else {$('#'+status[i].name).show(); document.getElementById(status[i].name).style.fill = conf.stateLabelColor[stat];$('#'+status[i].name).removeClass('noblink');}
Lucio Zambon's avatar
Lucio Zambon committed
		// console.log(i, status[i], stat);
	}
	function clearStatus() {
Lucio Zambon's avatar
Lucio Zambon committed
		$('.ps:not(.noblink)').hide();
Lucio Zambon's avatar
Lucio Zambon committed
	}
	function updateStatus() {
		fetch(conf.stateUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
			const statVal = data.split(';');
			// console.log(conf.stateUrl, statVal, status);
			for (let i=0; i<status.length; i++) {
				if (status[i].statsrc==state) {
					if (status[i].statindex) showStatus(i, statVal[status[i].statindex]);
					// console.log(statVal, status, status[i].name, i, status[i].statindex, statVal[status[i].statindex]);
				}
			}
			setTimeout(clearStatus, 600);
		});
	}
	function updateVlv() {
		fetch(conf.vlvUrl, {cache: "no-store"}).then((response) => {return response.text();}).then((data) => {
			const vlvVal = data.split(':')[1].split(';');
			// console.log('updateVlv()', conf.vlvUrl, vlvVal, vlvs);
			for (let i=0; i<vlvs.length; i++) {
Lucio Zambon's avatar
Lucio Zambon committed
				if (vlvs[i].type=='vlv') $('#'+vlvs[i].name).css('fill', vlvVal[vlvs[i].vlvindex]=='CLOSED'? 'red': (vlvVal[vlvs[i].vlvindex]=='OPENED'? 'limegreen': 'grey'));
Lucio Zambon's avatar
Lucio Zambon committed
				if (vlvs[i].type=='bst') {
					if (typeof vlvVal[vlvs[i].vlvindex] != 'string') continue;
					const val = vlvVal[vlvs[i].vlvindex].split(',');
Lucio Zambon's avatar
Lucio Zambon committed
					$('#'+vlvs[i].name).css('fill', val[0]=='true'? 'limegreen': (val[1]=='true'? 'red': 'grey'));
Lucio Zambon's avatar
Lucio Zambon committed
				}
			}
		});
	}
	function rescale(x) {return x;}
	String.prototype.replaceAt = function(index, replacement) {
		return this.substring(0, index) + replacement + this.substring(index + replacement.length);
	};
	function evalId(base) {
		if (base.indexOf('.')>-1) return base;
		return base.replaceAt(base.lastIndexOf('_'), '.').replace('RTBPM','BPM');
	}
	function openTooltip(event) {
		if (document.location.search.indexOf('debug')==-1) {
			const type = this.href? this.href.baseVal.replace('#',''): (this.id.indexOf('BLM')>-1 || this.id.indexOf('BERGOZ')>-1? 'blm': '???');
Lucio Zambon's avatar
Lucio Zambon committed
			console.log('openTooltip()',type, this.id, this, event, event.clientY);
Lucio Zambon's avatar
Lucio Zambon committed
			$('#tooltip').css('left', event.clientX+30);
			$('#tooltip').css('top', event.clientY+30);
Lucio Zambon's avatar
Lucio Zambon committed
			const embedded = (typeof this.dataset.embedded == 'undefined' || this.id[0]=='R')? '': ','+this.dataset.embedded;
			document.getElementById('tooltipFrame').src = conf.tooltipApp+'?s='+type.replace('fast', '')+'&param='+this.id + embedded;
Lucio Zambon's avatar
Lucio Zambon committed
			console.log('openTooltip(event)', type.toLowerCase(), type.toLowerCase().indexOf('beamline'));
			document.getElementById('tooltip').style.display = 'block';
			if (hideTimeout!==false) clearTimeout(hideTimeout);
			hideTimeout = setTimeout(hideTooltip, 120000);
			const id = evalId(this.id);
Lucio Zambon's avatar
Lucio Zambon committed
			let buttons = '<button onClick="compLink(\''+conf.compdb + id+'\')">'+id+'</button> ';
Lucio Zambon's avatar
Lucio Zambon committed
			let rack = '';
Lucio Zambon's avatar
Lucio Zambon committed
			if (typeof this.dataset.embedded != 'undefined') {
				const emb = this.dataset.embedded.split(',');
				for (let e=0; e<emb.length; e++) {
					buttons = buttons + '<button onClick="compLink(\''+evalId(emb[e])+'\')">'+evalId(emb[e])+'</button> ';
				}
			}
Lucio Zambon's avatar
Lucio Zambon committed
			else {
				for (let i=0; i<lattice.servicearea.sections.length; i++) {
					if (lattice.servicearea.sections[i].components) for (let j=0; j<lattice.servicearea.sections[i].components.length; j++) {
						if (lattice.servicearea.sections[i].components[j].embedded && lattice.servicearea.sections[i].components[j].embedded.indexOf('PS'+id)>-1) rack = 'rack <button onClick="compLink(\'https://puma-01.elettra.eu/spa/index.html?s='+lattice.servicearea.sections[i].components[j].name.split('_')[0].toLowerCase()+'&param='+lattice.servicearea.sections[i].components[j].name+'\')">'+lattice.servicearea.sections[i].components[j].name+'</button> ';
					}
				}
			}
			buttons = buttons + rack;
Lucio Zambon's avatar
Lucio Zambon committed
			document.getElementById('compdb').innerHTML = buttons;
			document.getElementById('compdb').style.display = (type.indexOf('rv')==0 || type.indexOf('rc')==0 || type.indexOf('rid')==0 || type.indexOf('rd')==0 || type.indexOf('rps')==0 || type.indexOf('plc')==0)? 'none': 'block';
Lucio Zambon's avatar
Lucio Zambon committed
			if (document.getElementById('compname')) document.getElementById('compname').innerHTML = id;
Lucio Zambon's avatar
Lucio Zambon committed
			// document.getElementById('compdb').href = conf.compdb + id;
			// document.getElementById("compdb").addEventListener("click", compLink);
Lucio Zambon's avatar
Lucio Zambon committed
			if (type.toLowerCase().indexOf('beamline')>-1) {
				document.getElementById('compdb').href = 'http://adam.elettra.trieste.it/projects/blcs/beamwatch/';
Lucio Zambon's avatar
Lucio Zambon committed
				document.getElementById('compdb').innerHTML = 'search '+this.id+' in ADAM Beamwatch <span id="compname"/>';
Lucio Zambon's avatar
Lucio Zambon committed
			}
			else if (machine=='elettra') document.getElementById('compdb').setAttribute("disabled", true);
			event.stopPropagation();
		}
		else {
			for (let l in lattice) {
				if (l=='confg') continue;
				let servicearea = false;
				for (let i in lattice[l].sections) {
					for (let j in lattice[l].sections[i].components) {
						if (this.id==lattice[l].sections[i].components[j].name.replace('.', '_')) {mylog('openTooltip()', lattice[l].sections[i].components[j], lattice[l].sections[i].components[j].position-document.location.search.split('offset=')[1].split('&')[0]);}
					}
				}
			}
		}
	}
	function hideTooltip() {
		if (hideTimeout!==false) clearTimeout(hideTimeout);
		hideTimeout = false;
		// mylog('hideTooltip');
		if (document.location.search.indexOf('debug')==-1) {
			document.getElementById('tooltipFrame').src = '';
			document.getElementById('tooltip').style.display = 'none';
		}
	}
	function transformLabel(x, y, beta, labelReverse) {
		if (typeof labelReverse == 'object') return "translate("+rescale(x)+" "+rescale(y)+") rotate("+(beta+labelReverse[0])+") translate("+labelReverse[1]+" "+labelReverse[2]+")";
		return labelReverse==180? "translate("+rescale(x)+" "+rescale(y)+") rotate("+(beta-90)+") translate(1800 100)":
Lucio Zambon's avatar
Lucio Zambon committed
				"translate("+rescale(x)+" "+rescale(y)+") rotate("+(beta+90)+") translate("+(labelReverse? -350: 350)+" "+(labelReverse? 100: 200)+")";
Lucio Zambon's avatar
Lucio Zambon committed
	}
Lucio Zambon's avatar
Lucio Zambon committed
	function appendSvg(tagName, attrib, onClickCall=false, text=false, myclass=false, appendTo="svg") {
Lucio Zambon's avatar
Lucio Zambon committed
		const elem = document.createElementNS("http://www.w3.org/2000/svg", tagName);
		if (onClickCall) elem.addEventListener("click", onClickCall, false);
Lucio Zambon's avatar
Lucio Zambon committed
		const titelem = document.createElementNS("http://www.w3.org/2000/svg", 'title');
		const embedded = typeof attrib['data-embedded']=='object'? '\n'+attrib['data-embedded'].join(', '): '';
		const aka = typeof attrib['data-aka']=='object' && attrib['data-aka'].length>0? '\naka: '+attrib['data-aka'].join(', '): '';
		const title = document.createTextNode(attrib.id + aka + embedded);
		titelem.appendChild(title);
		elem.appendChild(titelem);
Lucio Zambon's avatar
Lucio Zambon committed
		if (text) {				
Lucio Zambon's avatar
Lucio Zambon committed
			// const textNode = document.createTextNode(text); elem.appendChild(textNode);
			elem.innerHTML = text;
Lucio Zambon's avatar
Lucio Zambon committed
		}
		const jelem = $(elem);
		if (myclass) {/*mylog(elem, jelem, myclass);*/ elem.classList.add(myclass);}
		for (let i in attrib) {
			jelem.attr(i, attrib[i]);
		}
Lucio Zambon's avatar
Lucio Zambon committed
		const hook = appendTo.indexOf('.')==0? appendTo.replace(' ','_'): appendTo.replace('.','_').replace(' ','_');
		$(hook).append(jelem);
Lucio Zambon's avatar
Lucio Zambon committed
	}
	function appendSearch(component, facility) {
		// mylog('appendSearch()',component, facility);
		if (component) {
			const comp = component.type.replace('booster', '');
			if (comp && comp!=' ' && $('#'+comp)[0]) {
				const id = extractId(component.name);
				names.push(id[0]);
Lucio Zambon's avatar
Lucio Zambon committed
				shrinkedNames.push(shrinkName(id[0]));
Lucio Zambon's avatar
Lucio Zambon committed
				if (facility=='servicearea') serviceareanames.push(id[0]);
Lucio Zambon's avatar
Lucio Zambon committed
				if (component.embedded) {
Lucio Zambon's avatar
Lucio Zambon committed
					for (let j=0; j<component.embedded.length; j++)  {
						names.push(component.embedded[j]);
						shrinkedNames.push(shrinkName(component.embedded[j]));
						alias.push([id[0],component.embedded[j]]);
					}
Lucio Zambon's avatar
Lucio Zambon committed
				}
Lucio Zambon's avatar
Lucio Zambon committed
				if (component.alias) {
					for (let j=0; j<component.alias.length; j++)  {
						names.push(component.alias[j]);
						shrinkedNames.push(shrinkName(component.alias[j]));
						alias.push([id[0],component.alias[j]]);
					}
				}
Lucio Zambon's avatar
Lucio Zambon committed
			}
		}
	}
Lucio Zambon's avatar
Lucio Zambon committed
	function appendLabel(id, labelclass, display, x, y, beta, labelReverse, suffix='label', fontSize=1, appendTo="svg") {
		if ((beta+3600)%360 <180 && typeof labelReverse != 'object') labelReverse = [-90, -250, -100];
		appendSvg("text", {
			id: (id+suffix).replace(' ','_'), 
Lucio Zambon's avatar
Lucio Zambon committed
			filter: "url(#solid)",
Lucio Zambon's avatar
Lucio Zambon committed
			class: labelclass, 
Lucio Zambon's avatar
Lucio Zambon committed
			x:0, y:0, style:"display: "+display, fill:"white", stroke:"#101020","stroke-width":0, "font-family":"Arial", "font-size":100*fontSize, "font-weight":"700",
Lucio Zambon's avatar
Lucio Zambon committed
			"text-anchor": (labelReverse? "end": "start"),
			transform: transformLabel(x, y, beta, labelReverse)
Lucio Zambon's avatar
Lucio Zambon committed
		}, false, appendTo=="svg"? id: '', false, appendTo);
		// }, false, id, false, appendTo);
Lucio Zambon's avatar
Lucio Zambon committed
	}
	function appendLabel2(param, labelclass, display, x, y, beta, labelReverse, suffix='label') {
		const id = param.name;
		const fontsize = labelclass.indexOf('bl')>-1? 800: 500;
		// console.log("appendLabel2()",param, labelclass, display, x, y, beta, labelReverse);
		if (labelclass.indexOf('bl')>-1 && typeof labelReverse != 'object') {
			labelReverse = [180, 17000, param.type=='beamlineUp'? -500: +800];
			if ((beta+3690)%360 < 180) labelReverse = [0, -14000, param.type=='beamlineUp'? 1000: -300];
		}
		else if ((beta+3600)%360 < 180 && typeof labelReverse != 'object') labelReverse = [-90, -250, -100];
		appendSvg("text", {
Lucio Zambon's avatar
Lucio Zambon committed
			id: id+suffix,
			// filter: "url(#solid)",
Lucio Zambon's avatar
Lucio Zambon committed
			class: labelclass, 
Lucio Zambon's avatar
Lucio Zambon committed
			x:0, y:0, style:"display: block", fill:"red", stroke:"pink","stroke-width":5, "font-family":"Arial", "font-size":fontsize, "font-weight":"700", 
Lucio Zambon's avatar
Lucio Zambon committed
			"text-anchor": (labelReverse? "end": "start"),
			transform: transformLabel(x, y, beta, labelReverse)
		}, false, id);
	}
Lucio Zambon's avatar
Lucio Zambon committed
	function appendComponent(components, x0, y0, x1, y1, facility) {
		const dx = x1 - x0;
		const dy = y1 - y0;
		const d = Math.sqrt(dx*dx + dy*dy);
		const beta = 180*Math.atan2(y0-y1, x0-x1)/Math.PI;
		if (components) for (let i=0; i<components.length; i++) {
Lucio Zambon's avatar
Lucio Zambon committed
			const comp = components[i].type; // .replace('booster', '');
Lucio Zambon's avatar
Lucio Zambon committed
			let x = x0+components[i].position/d*dx;
			let y = y0+components[i].position/d*dy;
			if (components[i].offset2d) {x += components[i].offset2d[0]; y += components[i].offset2d[1];}
			if (typeof blm != 'undefined' && comp=='blm') {
				const name = components[i].name.replace('BPM','BLM');
				// mylog('appendComponent(), ', name, blm.obj);
				blm.obj.push(name);
				blm.dir.push(beta);
				appendSvg("rect", {id:name, name:name, x:0, y:0, width:40, height:40, rx:20, ry:20, transform:"translate("+rescale(x)+" "+rescale(y)+") rotate("+(name.indexOf('_L')>-1? beta + 180: beta)+")"}, openTooltip, false, "blm");
			}
			if (typeof bpmData != 'undefined' && comp=='bpm') {
				// mylog('appendComponent()',components[i], x0, y0, x1, y1, beta, facility, 180*Math.atan2(y0-y1, x0-x1)/Math.PI);
				bpmData[facility].obj.push(components[i].name);
				bpmData[facility].dir.push(beta);
				bpmData[facility].pos.push([rescale(x), rescale(y)]);
			}
			if (typeof bpmData != 'undefined' && comp=='corrector') {
				corr[facility].obj.push(components[i].name);
				corr[facility].dir.push(beta);
				corr[facility].pos.push([x, y]);
			}
Lucio Zambon's avatar
Lucio Zambon committed
			compData[facility].obj.push(components[i].name);
			compData[facility].dir.push(beta);
			compData[facility].pos.push([rescale(x), rescale(y)]);
Lucio Zambon's avatar
Lucio Zambon committed
			if ($('#'+comp)[0]) {
				// mylog('components['+i+']',components[i]);
				const id = extractId(components[i].name);
				const section = components[i].name.indexOf('_')>-1? components[i].name.split('_')[1].split('.')[0]+' ': '';
				const offset = components[i].type == 'beamlineUp'? "-2100 -3500": "0 -200";
				const transform = "translate("+rescale(x)+" "+rescale(y)+") rotate("+(beta+180)+") translate("+offset+")";
Lucio Zambon's avatar
Lucio Zambon committed
				const compid = comp + (components[i].length > 0 && $('#'+comp+'_'+components[i].length)[0]? '_'+components[i].length: '');
				const aka = components[i].alias && components[i].alias.length? components[i].alias: [];
Lucio Zambon's avatar
Lucio Zambon committed
				const compClass = typeof components[i].class == 'undefined'? '': ' '+components[i].class;
				appendSvg("use", {href:"#"+compid, id: id[0], name:components[i].name, "data-embedded":components[i].embedded, "data-aka": aka, class: comp+' '+section+facility+compClass, style:"cursor: pointer", transform:transform}, openTooltip);
Lucio Zambon's avatar
Lucio Zambon committed
				if (components[i].type == 'label' || components[i].type == 'beamlineDown' || components[i].type == 'beamlineUp') 
					appendLabel2(components[i], section+facility, 'none', x, y, beta, components[i].labelReverse);
				else
Lucio Zambon's avatar
Lucio Zambon committed
					appendLabel(components[i].name, comp+' label '+section+facility+compClass, 'none', x, y, beta, components[i].labelReverse);
Lucio Zambon's avatar
Lucio Zambon committed
				if (id[0].indexOf('<')==-1) {
					appendSvg("g", {"id": id[0]+'_g'});
Lucio Zambon's avatar
Lucio Zambon committed
					appendLabel(components[i].name, comp+' value '+section+facility, 'none', x+600, y+400, 90, true, 'value', 0.7, '#'+id[0]+'_g');
Lucio Zambon's avatar
Lucio Zambon committed
				}
Lucio Zambon's avatar
Lucio Zambon committed
				names.push(id[0]);
Lucio Zambon's avatar
Lucio Zambon committed
				shrinkedNames.push(shrinkName(id[0]));
Lucio Zambon's avatar
Lucio Zambon committed
				
				if (typeof components[i].embedded == 'object') {
Lucio Zambon's avatar
Lucio Zambon committed
					for (let j=0; j<components[i].embedded.length; j++)  {names.push(components[i].embedded[j]); alias.push([id[0],components[i].embedded[j]]);}
Lucio Zambon's avatar
Lucio Zambon committed
				}
Lucio Zambon's avatar
Lucio Zambon committed
				if (typeof components[i].alias == 'object') {
					for (let j=0; j<components[i].alias.length; j++)  {names.push(components[i].alias[j]); alias.push([id[0],components[i].alias[j]]);}
				}
Lucio Zambon's avatar
Lucio Zambon committed
				if (id[1]) {names.push(id[1]); shrinkedNames.push(shrinkName(id[1])); alias.push(id);}
Lucio Zambon's avatar
Lucio Zambon committed
				if (state) {
					if (components[i].ps) {
						for (let pi=0; pi<components[i].ps.length; pi++) {
							const name = components[i].ps[pi].replace('PS','').replace('.','_') + '_status';
							status.push({name: name});
							appendSvg('circle', {id: name, class: facility+' ps', style:"display: none", cx: 150+pi*100, cy: 200, transform:transform, r: 80, stroke: 10, strokeColor: 'blue', fill: 'gray'}, false, false, 'status');
						}
					}
					else {
						status.push({name: id[0]+'_status'});
						appendSvg('circle', {id: id[0]+'_status', class: facility+' ps', style:"display: none", cx: 200, cy: 200, transform:transform, r: 80, stroke: 10, strokeColor: 'blue', fill: 'gray'}, false, false, 'status');
					}
					if (components[i].name.toUpperCase().indexOf('KICK')>-1) console.log('PS: ', components[i].name, components[i].name.toUpperCase().indexOf('KICK'), status);
				}
				if (vlv && (components[i].type == 'vlv' || components[i].type == 'bst')) { 
					// appendSvg('rect', {id: id[0]+'_disable', style:"display: none", x: x+75, y: y-90, width: 50, height: 200, stroke: 10, fill: 'black'}, false, false, 'vlvs');
					vlvs.push({name: id[0], type: components[i].type});
				}
			}
		}
	}
Lucio Zambon's avatar
Lucio Zambon committed
	/*if (!String.prototype.replaceAll) {
Lucio Zambon's avatar
Lucio Zambon committed
		String.prototype.replaceAll = function(search, replace) {
			return this.split(search).join(replace);
		};
Lucio Zambon's avatar
Lucio Zambon committed
	}*/
Lucio Zambon's avatar
Lucio Zambon committed
	function extractId(name) {
		if (name.indexOf('(')>-1) {
			let tok = name.split('(');
			return [tok[0].replaceAll('.','_').replaceAll(' ','_').replace(/_+$/, ''), tok[1].replaceAll('.','_').replaceAll(' ','_').replaceAll(')','').replace(/_+$/, '')];
		}
		// .replace(/_+$/, '') => https://stackoverflow.com/questions/8141718/how-to-trim-specific-characters-from-the-end-of-the-javascript-string
		return [name.replaceAll('.','_').replaceAll(' ','_').replace(/_+$/, ''), false];
	}
	function highlightobjects(objclass) {
		$("use").css('opacity',0.3);
		$("text").css('opacity',0.3);
		$("."+objclass).css('opacity',1);
	}
	function magnifyobjects(objclass) {
		$("text").css('opacity',0.15);
		$("text."+objclass).css('opacity',1);
		$('.scale').attr('transform', "scale(1) translate(90,100)");
		let x = -40;
		let y = -40;
		let s = 3;
		if (objclass=="vlv") {x = -50; y = -50; s = 5;}
		$('.'+objclass+'scale').attr('transform', "scale("+s+") translate("+x+","+y+")");
	}
	function initSearch(sections, facility) { 
Lucio Zambon's avatar
Lucio Zambon committed
		console.log('initSearch()', sections, facility);
Lucio Zambon's avatar
Lucio Zambon committed
		for (i=0; i<sections.length; i++) { // if(i>1) break;
Lucio Zambon's avatar
Lucio Zambon committed
			if (sections[i].bending && sections[i].bending.type) {
Lucio Zambon's avatar
Lucio Zambon committed
				// console.log('names.push()', sections[i].bending.name);
Lucio Zambon's avatar
Lucio Zambon committed
				names.push(sections[i].bending.name.replace('.','_'));
Lucio Zambon's avatar
Lucio Zambon committed
				shrinkedNames.push(shrinkName(sections[i].bending.name.replace('.','_')));
Lucio Zambon's avatar
Lucio Zambon committed
			}
Lucio Zambon's avatar
Lucio Zambon committed
			if (typeof sections[i].components == 'object') for (let j=0; j<sections[i].components.length; j++) appendSearch(sections[i].components[j], facility);
		}
	}
	function initLattice(sections, facility) { 
Lucio Zambon's avatar
Lucio Zambon committed
		initSearch(sections, facility);
Lucio Zambon's avatar
Lucio Zambon committed
		if (document.location.search.indexOf('facility=')>-1 && document.location.search.split('facility=')[1].split('&')[0].split(',').indexOf(facility)==-1) return;
Lucio Zambon's avatar
Lucio Zambon committed
		if (typeof bpmData != 'undefined') {
Lucio Zambon's avatar
Lucio Zambon committed
			compData[facility] = {obj: [], dir: [], pos: [], index: []};
Lucio Zambon's avatar
Lucio Zambon committed
			bpmData[facility] = {obj: [], dir: [], pos: []};
			corr[facility] = {obj: [], dir: [], pos: []};
		}
		// vacuum chamber
		let d = '';
		let m = true;
		let wall = false;
Lucio Zambon's avatar
Lucio Zambon committed
		let w = 20;
Lucio Zambon's avatar
Lucio Zambon committed
		for (let i=0; i<sections.length; i++) {
			d = d + (m? 'M ': ' L ')+rescale(sections[i].start.x)+' '+rescale(sections[i].start.z);
Lucio Zambon's avatar
Lucio Zambon committed
			if (i<sections.length-1 && typeof sections[i+1].chamber == 'undefined') {m = true;} else if (i<sections.length-1 && (sections[i+1].chamber.type=="chamber" || sections[i+1].chamber.type.indexOf("wall")>-1)) {m = false;}
			if (i<sections.length-1 && typeof sections[i+1].chamber != 'undefined' && sections[i+1].chamber.type.indexOf("wall")>-1) {
				if (sections[i+1].chamber.type.indexOf('_')>-1) w = sections[i+1].chamber.type.split('_')[1]-0;
				wall = true;
			}
Lucio Zambon's avatar
Lucio Zambon committed
		}
		if (sections[0].chamber && sections[0].chamber.type=='chamber') d = d + ' Z';
Lucio Zambon's avatar
Lucio Zambon committed
		if (facility=='sr') console.log('sections', sections, 'd', d);
Lucio Zambon's avatar
Lucio Zambon committed
		if (d!='') {
Lucio Zambon's avatar
Lucio Zambon committed
			if (wall) {
				console.log('w', w, sections, d);
				//appendSvg("path", {d: d, fill: "none", stroke: "#990000", "stroke-dasharray": "200 200", "stroke-width": 50, id:"wall"+facility});
Lucio Zambon's avatar
Lucio Zambon committed
				appendSvg("path", {d: d, fill: "none", stroke: "#f0fff0", "stroke-width": w+20, id:"chamber"+facility, class: facility});
				appendSvg("path", {d: d, fill: "none", stroke: "#ff0000", "stroke-width": w, id:"chamber"+facility, class: facility});
Lucio Zambon's avatar
Lucio Zambon committed
			}
Lucio Zambon's avatar
Lucio Zambon committed
			else appendSvg("path", {d: d, fill: "none", stroke: "#999999", "stroke-width": 20, id:"chamber"+facility, class: facility});
Lucio Zambon's avatar
Lucio Zambon committed
		}
Lucio Zambon's avatar
Lucio Zambon committed
		// bending
Lucio Zambon's avatar
Lucio Zambon committed
		let j = 0;
		let i = sections.length - 1;
		let k = sections.length - 2;
		let alpha = 180/Math.PI*Math.atan2(sections[j].start.z-sections[i].start.z, sections[j].start.x-sections[i].start.x);
		for (i=0; i<sections.length; i++) { // if(i>1) break;
			j = (i + 1) % sections.length;
			k = (i + sections.length - 1) % sections.length;
			let beta = 180/Math.PI*Math.atan2(sections[j].start.z-sections[i].start.z, sections[j].start.x-sections[i].start.x);
			let gamma = (beta+alpha)/2;
			if (sections[k] && sections[j].start.z<sections[i].start.z && sections[i].start.z>sections[k].start.z) gamma = gamma + 180;
			if (alpha>beta && gamma<0) gamma = gamma + 180;
			if (sections[i].bending && sections[i].bending.type) {
				const section = sections[i].bending.name.indexOf('_')>-1? sections[i].bending.name.split('_')[1].split('.')[0]+' ': '';
Lucio Zambon's avatar
Lucio Zambon committed
				const comp = sections[i].bending.type.replace('dipolefermi','bending');
Lucio Zambon's avatar
Lucio Zambon committed
				const compid = comp + (sections[i].bending.length > 0 && $('#'+comp+'_'+sections[i].bending.length)[0]? '_'+sections[i].bending.length: '');
Lucio Zambon's avatar
Lucio Zambon committed
				appendSvg("use", {href:"#"+compid, id:sections[i].bending.name.replace('.','_'), class: 'bending '+section+facility, style:"cursor: pointer", transform:"translate("+rescale(sections[i].start.x)+" "+rescale(sections[i].start.z)+") rotate("+gamma+") translate(-600 -200)"}, openTooltip);
Lucio Zambon's avatar
Lucio Zambon committed
				appendLabel(sections[i].bending.name, 'bending '+section+facility, 'block', sections[i].start.x, sections[i].start.z, gamma+180, sections[i].bending.labelReverse);
			}
			alpha = beta;
			appendComponent(sections[i].components, sections[i].start.x, sections[i].start.z, sections[j].start.x, sections[j].start.z, facility);
		}
	}
	$(document).ready(function() {
		$("svg").attr('height', window.innerHeight+'px');
		init();
	});

	var eventsHandler;
	let myhammer;
	eventsHandler = {
		haltEventListeners: ['touchstart', 'touchend', 'touchmove', 'touchleave', 'touchcancel','tap', 'pinch','pinchstart','pinchmove'], 
			init: function(options) {
			var instance = options.instance, initialScale = 1, pannedX = 0, pannedY = 0;
			// mylog('init', options, panZoomPanther);
			myhammer = Hammer(options.svgElement, {
				inputClass: Hammer.SUPPORT_POINTER_EVENTS ? Hammer.PointerEventInput : Hammer.TouchInput
			});
			myhammer.get('pinch').set({enable: true});
			myhammer.on('panstart panmove', function(ev){
				if (ev.type === 'panstart') {
					pannedX = 0;
					pannedY = 0;
				}
				panZoomPanther.panBy({x: ev.deltaX - pannedX, y: ev.deltaY - pannedY});
				pannedX = ev.deltaX;
				pannedY = ev.deltaY;
			});
			myhammer.on('pinchstart pinchmove', function(ev){
				if (ev.type === 'pinchstart') {
					initialScale = panZoomPanther.getZoom();
					panZoomPanther.zoomAtPoint(initialScale * ev.scale, {x: ev.center.x, y: ev.center.y}, zoom, ev.scale);
					// mylog(''); mylog('panZoomPanther.zoomAtPoint('+(initialScale * ev.scale)+', {x: '+ev.center.x+', y: '+ev.center.y+'})');
				}
				if (ev.type === 'pinchmove') {
					oldZoom = zoom;
					zoom = initialScale * ev.scale;
					// mylog('zoom', zoom, ev.center.x);