﻿/*

               G A C - E P A 

Switch Language
---------------

Each page has a set of language-indicating flags (images).  A click on
such a flag will take the reader to the corresponding page in that language.

Conventions:
------------
The pages in different languages are next to each other at the same file system level.
They have the same names with a different ending:  -en for English, -fr for French etc.

How it works:
-------------
The click calls "SwitchLanguage", passing a two letter language code as a parameter.
The script obtains the URL of the current page, replaces the current two letter code
with the desired two letter code.  It then loads that page.

*/


function SwitchLanguage (fLanguage) {

	lURLOfThisPage = document.location.href;  lURLLength = lURLOfThisPage.length;

	// the pages all have names of the forms
	//
	//  xxxxxx-ll.html
	//  xxxxxx-ll.php
	//
	if (lURLOfThisPage.substring(lURLLength-3,lURLLength) == "php") {
		lFirstPart = lURLOfThisPage.substring(0,lURLLength-6);
		window.location = lFirstPart + fLanguage + ".php" ;
		}
	else {
		lFirstPart = lURLOfThisPage.substring(0,lURLLength-7);
		window.location = lFirstPart + fLanguage + ".html" ;
		};
	}






function Clean (fTextElement) {
	// strip comments and white space.  Necessary for getting at the values of TimeEstimated and BodyFontSize
	// because of use of Golive or DreamWeaver, both of necessity leave the template marks as comments.
	lChild = fTextElement.firstChild; lS = "";
	while (lChild != null ) { // concatenate all the text
		if ( lChild.nodeType == 3 ) { lS = lS + lChild.nodeValue; }; // text nodes only, throw away comments (type 8)
		lChild = lChild.nextSibling;
		};
	lL = lS.length;
	lResult = "";
	for ( i=0; i < lL; i++ ) {
		lCH = lS.charAt(i);
		if ( ( lCH == " ") || ( lCH == "\n") || ( lCH == "\r") || ( lCH == "\t") || ( lCH == "\l") ) { continue; };
		if ( lS.substr(i,4) == "<!--" ) { // comment begin, skip to its end:
			i = lS.indexOf("-->",i) + 2 ;
			continue;
			};
		lResult = lResult + lCH;
		};
	return lResult;
	}

// Adapt everything to the window size by setting the body's font size.
// If all measures in em units then this will work:

function ScaleContent () {

	if ( document.getElementById("BodyFontSize") == null ) { return; };

	// set the base font size in em relative to the browser preset; if all measures
	// in the style sheets are expressed in em, then the whole content will scale with the window width.

	lDefaultSize = Clean(document.getElementById("BodyFontSize"));
	document.body.style.fontSize = (lDefaultSize*(this.innerWidth/1024))+"em";

	}

window.onresize = ScaleContent;








/*   H A N D L E   S V G   D R A W I N G S   */

/* 

Allow the user to move and zoom SVG drawings.
Dragging moves the drawing,
Option-dragging left-right zooms out-in from centre of drawing
Shift-clicking restores the original view.


Assume that SVG drawings are present in the page code with this structure:


-------------------------------------------------------------------------------
<div id="SVGN-div" style="width: w; height: h; ">

	<svg:svg id="SVGN-svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1"
		viewBox="0 0 vbw vbh"
		preserveAspectRatio="xMinYMin meet" >

	<svg:g id="SVGN-OuterGroup" transform="translate(tx,ty) scale(s)">

		<svg:...

		... [svg code] ...

	</svg:g><!-- end of outer group -->

	<svg:rect id="SVGN-Tracker" width="100%" height="100%" opacity="0"
		onload      = "SVGInitialise(event);"
		onmousedown = "SVGStartInteraction(event);"
		onmousemove = "SVGDoInteraction(event);"
		onmouseup   = "SVGStopInteraction(event);"
		onmouseout  = "SVGStopInteraction(event);"
		/>
	</svg:svg>
	</div>
-------------------------------------------------------------------------------

Where:

N is a small integer, unique to each SVG,
w and h are the dimensions of the enclosing div element in em units
vbw and vbh are the sizes of the viewbox
SVGN-OuterGroup is the id of a group that is used exclusively for allowing
the user to translate and scale the drawing interactively.  The drawing
may be placed at a point tx,ty and on scale s so that the space in which
the user can zoom in is larger than the minimum rectangle around the svg. 

SVGN-Tracker is a rectangle that captures the user interaction.
This rectangle triggers the onload event because the SVG elements
need to be loaded before the info can be accessed.

The SVG is rendered in a viewport of pixel dimensions pw,ph (the div element) but declares
a viewbox of unit dimensions bw,bh.  We assume the preserveAspectRatio is always
set to "xMinYMin meet" so that the SVG is pushed into the upper left corner but made
as large as possible while still being viewed in total.  Thus:

For a rectangle of width w and height h the value w/h is >1 if it is "wide" ("landscape") and
it is <1 if it is "narrow" ("portrait").

if bw/bh < pw/ph the SVG looks "narrower" than the port; it will adopt the port's
height, leaving space at the right.  The viewbox height then corresponds to the
viewport's height and the unit factor (SVG units/pixel) is bh/ph.

When dragging the SVG around, the mouse distance m is in pixels and must be
multiplied by the unit factor to obtain the value for the translate transformation.

if bw/bh > pw/ph the SVG looks "wider" than the port; it will adopt the port's
width, leaving space at the bottom.  The unit factor is then bw/pw.

Because there is no reliable method of finding the position of the enclosing box,
zooming must be done around a point fixed to the SVG and not fixed at the point
where the mouse went down.

*/

// For all SVGs on the page:
// store the viewbox and viewport dimensions and keep the automatic scale

var SVGList					= new Array ();  // the list of active SVGs, they must all have different numbers.

var SVGViewBoxWidth			= new Array ();  // from the code; never changes
var SVGViewBoxHeight		= new Array ();
var SVGOrgTranslateX		= new Array ();  // from the code; never changes
var SVGOrgTranslateY		= new Array ();
var SVGOrgScale				= new Array ();

var SVGViewPortWidth		= new Array ();  // may change when browser window is resized
var SVGViewPortHeight		= new Array ();
var SVGUnitFactor			= new Array ();  // may change when browser window is resized

var SVGTranslateX			= new Array ();  // where the user left it interactively
var SVGTranslateY			= new Array ();
var SVGScale				= new Array ();  // where the user left it interactively

var SVGCurrentTranslateX	= new Array ();  // for use during mouse moves only
var SVGCurrentTranslateY	= new Array ();
var SVGCurrentScale			= new Array ();

var TheMouse = { IsDown: false, SVGN: -1, DownPointX: 0, DownPointY: 0, AltKey: false, ShiftKey: false };



function SVGNumber (fEvent) {

	// Returns the number of the SVG concerned by the event.
	// id is of the form "SVGN-Tracker" where N is a small integer.

	lIDParts = fEvent.target.id.split("-");
	n = lIDParts[0].substr(3)*1;
	if (SVGList[n] == null) { // this number is not yet taken, OK.
		SVGList[n] = 1;
		}
	else {
//		alert("SVGs do not all have different numbers ("+n+")");
		};
	return n;

	}



function SVGInitialise (fEvent) {

	// Set up the SVG viewing state for an SVG in the page.
	// The original translate and scale may be different from (0,0) and 1, store them.
	// This routine is called at loading of the tracker of each SVG.
	// It is assumed that all SVGs have a different id.

	n = SVGNumber(fEvent);

	lOrgTransform = document.getElementById("SVG"+n+"-OuterGroup").getAttribute("transform");  // "translate(tx,ty) scale(s)"
	lTransPart = lOrgTransform.substr(10);  // "tx,ty) scale(s)"
	lTrans = lTransPart.substr( 0 , lTransPart.indexOf(")") );  // "tx,ty"
	lTransXY = lTrans.split(","); lTX = lTransXY[0]*1; lTY = lTransXY[1]*1;
	lTransPart = lTransPart.substr( 1+lTransPart.indexOf(")") );  // "scale(s)"
	lScale = lTransPart.substring( 1+lTransPart.indexOf("(") , lTransPart.indexOf(")") )*1;  // "s"
	SVGOrgTranslateX[n]     = lTX; SVGOrgTranslateY[n]     = lTY; SVGOrgScale[n]     = lScale;
	SVGTranslateX[n]        = lTX; SVGTranslateY[n]        = lTY; SVGScale[n]        = lScale;
	SVGCurrentTranslateX[n] = lTX; SVGCurrentTranslateY[n] = lTY; SVGCurrentScale[n] = lScale;

	lViewBox = document.getElementById("SVG"+n+"-svg").getAttribute("viewBox");
	lViewBoxParts = lViewBox.split(" ");
	SVGViewBoxWidth[n] = lViewBoxParts[2]; SVGViewBoxHeight[n] = lViewBoxParts[3];

	}




function SVGStartInteraction (fEvent) {

	// Remember in which SVG and where the mouse went down and what modifier keys were down at that time.
	// Adjust the viewport dimensions and the unitfactor to the potentially resized window.

	TheMouse.IsDown = true;
	TheMouse.SVGN = n = SVGNumber(fEvent);
	TheMouse.DownPointX = fEvent.clientX; TheMouse.DownPointY = fEvent.clientY;
	TheMouse.AltKey = fEvent.altKey; TheMouse.ShiftKey = fEvent.shiftKey;
	// To calculate the current unit factor (SVG units / pixel) we need to update the viewport dimensions
	// since the window may have been resized:
	lDiv = document.getElementById("SVG"+n+"-div");
	SVGViewPortWidth[n] = lDiv.offsetWidth; SVGViewPortHeight[n] = lDiv.offsetHeight;
	// if bw/bh > pw/ph the SVG looks "wider" than the port; it will adopt the port's
	// width, leaving space at the bottom.  The unit factor is then bw/pw otherwise it is bh/ph.
	if ( SVGViewBoxWidth[n]/SVGViewBoxHeight[n] > SVGViewPortWidth[n]/SVGViewPortHeight[n] ) {
		SVGUnitFactor[n] = SVGCurrentScale[n]*SVGViewBoxWidth[n]/SVGViewPortWidth[n];
		}
	else {
		SVGUnitFactor[n] = SVGCurrentScale[n]*SVGViewBoxHeight[n]/SVGViewPortHeight[n];
		};
	// prepare for mousemoves:
	SVGCurrentTranslateX[n] = SVGTranslateX[n];
	SVGCurrentTranslateY[n] = SVGTranslateY[n];
	SVGCurrentScale[n]      = SVGScale[n];

	}



function SVGDoInteraction (fEvent) {

	// While the mouse moves the translate and scale are based on those in effect at the time of the mousedown.
	// The current values are updated so that they can replace the stored ones when the mouse goes up.
	if ( TheMouse.IsDown ) {
		n = SVGNumber(fEvent);
		lSVG = document.getElementById("SVG"+n+"-OuterGroup");
		lDeltaX = fEvent.clientX - TheMouse.DownPointX;
		lDeltaY = fEvent.clientY - TheMouse.DownPointY;
		if (TheMouse.AltKey) { // Zoom on the centre of the SVG
			lScale = SVGScale[n]*(SVGViewPortWidth[n] + lDeltaX)/SVGViewPortWidth[n];
			// the translate point is also affected since we scale around the centre of the SVG:
			lTX = SVGTranslateX[n] + SVGViewBoxWidth[n] *(SVGScale[n]-lScale)/2;
			lTY = SVGTranslateY[n] + SVGViewBoxHeight[n]*(SVGScale[n]-lScale)/2;
			lSVG.setAttribute("transform","translate("+lTX+","+lTY+") scale("+lScale+")");
			SVGCurrentTranslateX[n] = lTX; SVGCurrentTranslateY[n] = lTY;
			SVGCurrentScale[n] = lScale;
			}
		else { // Drag
			lTX = SVGTranslateX[n] + lDeltaX*SVGUnitFactor[n]/SVGScale[n];
			lTY = SVGTranslateY[n] + lDeltaY*SVGUnitFactor[n]/SVGScale[n];
			lSVG.setAttribute("transform","translate("+lTX+","+lTY+") scale("+SVGScale[n]+")");
			SVGCurrentTranslateX[n] = lTX; SVGCurrentTranslateY[n] = lTY;
			};
		};

	}



function SVGStopInteraction (fEvent) {

	// Clean up:
	n = SVGNumber(fEvent);
	if ( TheMouse.ShiftKey ) { // reset to original view
		lSVG = document.getElementById("SVG"+n+"-OuterGroup");
		lSVG.setAttribute("transform","translate("+SVGOrgTranslateX[n]+","+SVGOrgTranslateY[n]+") scale("+SVGOrgScale[n]+")");
		SVGCurrentTranslateX[n] = SVGTranslateX[n] = SVGOrgTranslateX[n];
		SVGCurrentTranslateY[n] = SVGTranslateY[n] = SVGOrgTranslateY[n];
		SVGCurrentScale[n]      = SVGScale[n]      = SVGOrgScale[n];
		}
	else { // store the state where the user left the drawing
		SVGTranslateX[n] = SVGCurrentTranslateX[n];
		SVGTranslateY[n] = SVGCurrentTranslateY[n];
		SVGScale[n]      = SVGCurrentScale[n];
		};
	TheMouse.IsDown = false;
	TheMouse.SVGN = -1;

	}





