//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//	Gatekeeper Educational Ltd
//	Contents of this file copyright F J Ahearn
//	If you use significant portions of the jscript much as is please leave this notice intact
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


//debugging
//wint=open("","test");
//wint.document.open("text/plain");
//wint.document.writeln("test"," ",n," ",category[n]);
//document.getElementById("test").innerHTML += "Point A " + left + " " + top + "<br>";

//interactive parameters
var param=new Array();
var numimgs; //number directly scaleable images

//pointers to all elements - firefox cannot use .all
var imgs=new Array();  //contain drag and drop image items
var spans=new Array(); //contain drag and drop text items
var h2s=new Array(); //contain non drag and drop but possibly moveable captions
var divs=new Array(); //containers for both text and images - controls etc

//drag and drop variables
var dragitem; // item being dragged
var dragged=false; // item was dragged not just clicked on
var xoff,yoff; //offset of dragged span top/left from start mouse x,y
var xold,yold; //previous position of dragged span
var numsrcs=0; //Number drag & drop source pictures
var numtgts=0; //Number drag & drop source targets
var srcs=new Array(); //drag&drop sources
var tgts=new Array(); //drag&drop targets

//animation
var wonky=1; //Degree of wonkiness in bfly flight adjust from 1 to 5
var moving=false; //still moving last item
var xmin,xmax,ymin,ymax; //Limits of final animation
var imgsrc=""; //to store image name during animation
var step; var steps;
var xp=new Array();
var yp=new Array();
var ascale=200; //max size of each movement

//tracking progress and scoring
var nleft;
var score=0;

//Size of main content area as designed and as used (1152*864 screen)
cw=1148.0; ch=718.0;
var wa;
var ha;

//browser flag
brflag="ie";

//initial tasks on opening or refresh

//this is alternative to <body onresize= which also works in firefox
window.onresize = new Function("window.location.href=window.location.href;");

//parts are fairly standard, may need specific changes
window.onload = init;
function init()
{

  //identify if browser is not IE and turn off default dragging behaviour on images - this is mainly a problem in opera
  var ua = navigator.userAgent.toLowerCase(); 
  if ( ua.indexOf( "msie" ) == -1 )
  {
	brflag = "ff";
  	imgs=new Array();
  	imgs=document.getElementsByTagName("IMG");
  	for (n=0;n<imgs.length;n++)
  	{
     	    imgs[n].addEventListener("mousedown", preventDrag, false);
  	}
  }

  //get interactive parameters
  getparams();

  //get pointers to all elements - firefox does not recognise .all
  divs = document.getElementsByTagName("DIV");
  h2s = document.getElementsByTagName("H2");
  spans = document.getElementsByTagName("SPAN");
  imgs = document.getElementsByTagName("IMG");

  //number directly scaled images - not in divs
  numimgs = param[0];

  //drag&drop sources the number and offset are passed in params control
  numsrcs = param[1]; off = param[2];
  for (m=0,n=off;n<off+numsrcs;m++,n++) srcs[m]=imgs[n];	

  //drag&drop targets the number and offset are passed in params control
  numtgts = param[3]; off = param[4];
  for (m=0,n=off;n<off+numtgts;m++,n++) tgts[m]=imgs[n];	

  //items left to drag
  nleft = numsrcs;

  //rescale all used elements
  resize();

  //Show randomly
  shuffle();

  //set up drag and drop
  document.onmousedown = OnMouseDown;
}


//Get parameters for interactive from a hidden control
//standard function
function getparams()
{
  str = document.getElementById("params").value;
  n = 0; p1=0;
  do
  {
	p2 = str.indexOf(",",p1);
        if (p2>0) param[n] = str.substring(p1,p2);
        n++; 
        p1=p2+1
  }
  while (p2>0 && p2<str.length);
}


//rescale all elements to screen
//standard function apart from last part about animation limits
function resize()
{

//Size according to actual required width in VB at 1152 screen res
wa = document.body.clientWidth; ha = ch * wa / cw;
if (ha>document.body.clientHeight)
{	
  ha=document.body.clientHeight;
  wa = cw * ha / ch;
}
wf=wa / cw; hf=wf;  lf = 0.5 * (document.body.clientWidth - wa);

//god knows why this is needed - scale/offset have to be primed ?????
x = rescale('1px',1);
x = offset('1px',1);

// rescale all original pos & sizes
//not all images rescaled here as some contained in divs and rescale with them
for (n=0; n<numimgs; n++) 
{  
  with (imgs[n].style)
  {  
    left = (pos(left) * wf + lf) + 'px';
    top = rescale(top,hf);
    width = rescale(width,wf);
    height = rescale(height,hf);
  }
}
for (n=0; n<spans.length; n++) 
{  
  with (spans[n].style)
  {  
    left = (pos(left) * wf + lf) + 'px';
    top = rescale(top,hf);
    width = rescale(width,wf);
    height = rescale(height,hf);
  }
}
for (n=0; n<h2s.length; n++) 
{  
  with (h2s[n].style)
  {  
    left = (pos(left) * wf + lf) + 'px';
    top = rescale(top,hf);
    width = rescale(width,wf);
    height = rescale(height,hf);
    fontSize = rescale(fontSize,hf);
  }
}
for (n=0; n<divs.length; n++) 
{  
  with (divs[n].style)
  {  
    left = (pos(left) * wf + lf) + 'px';
    top = rescale(top,hf);
    width = rescale(width,wf);
    height = rescale(height,hf);
    fontSize = rescale(fontSize,hf);
  }
}

//Set limits of drag drop and final animation
with (document.getElementById("lastanim").style)
{
  xmin = lf; xmax = wa-lf;
  ymin = 0; ymax = ha;
}
}


//general routines for scaling & offsetting of position and dimensions
//firefox does not have posLeft, posWidth etc
//standard functions

//take val as Npx, mult by numeric sc and return Mpx
function rescale(val,sc)
{
    num = 1.0 * parseInt(val,10);
    return Math.round(sc * num) + "px";
}
//take val as Npx, add numeric off and return Mpx
function offset(val,off)
{
  num = parseInt(val,10); 
  return (1*num + 1*off) + "px";
}
//take val as Npx, return N
function pos(val)
{
    return parseInt(val,10);
}


//Place random items
//standard function
function shuffle()
{

//swap around each top picture with its caption
for (t=0; t<numsrcs; ++t) 
{  
 
  //Randomly selected item
  tmp = numsrcs * Math.random();
  m=Math.round(tmp); if (m>tmp) m--;

  //swap image positions
  o = imgs[m].style;
  with (imgs[t].style)
  {
     tmp = left
     left =  o.left;
     o.left = tmp;
  }

  //captions same
  o = h2s[m].style;
  with (h2s[t].style)
  {
    tmp = left
    left =  o.left;
    o.left = tmp;
  }

  //swap text positions when applicable
  //o = spans[m].style;
  //etc
 }
}


//drag and drop - mousedown, move and up
//fairly standard functions, may need some specific changes

//This turns off the default drag of images in firex/opera/safari
function preventDrag(event)
{
if (event.preventDefault)
event.preventDefault();
}

//mouse down - start drag
function OnMouseDown(e)
{

   //get event and target for ie or firefox
   if (e==null)
   {   
      e = window.event;
      x=e.clientX; y=e.clientY; dragitem=e.srcElement;
   }
   else
   {   
      x=e.pageX; y=e.pageY; dragitem=e.target;
   }

  //If not a drag/drop source or if object is being animated or is already placed do nothing else
  with (dragitem)
  {
      if (moving || className!="src" || lang=="X") return;
  }

  //sets cursor off on all active items
  changecursor("default") 
  dragitem.style.cursor = "move";

  //Get offset mouse from top left
  with (dragitem.style)
  {
    xoff = x-pos(left);
    yoff = y-pos(top);

    //Store previous position
    xold = pos(left); yold=pos(top);

    //Put in front of other items
    zIndex = 10;
  }

  //start drag
  dragged=false;
  document.onmousedown = null;
  document.onmousemove = OnMouseMove;
  document.onmouseup = OnMouseUp;

  // cancel out any text selections
  document.body.focus();
  document.onselectstart = function () { return false; };
  dragitem.ondragstart = function() { return false; };
  return false;
}
//mouse move - drag
function OnMouseMove(e)
{

   //get event and target for ie or firefox
   if (e==null)
   {   
      e = window.event;
      x=e.clientX; y=e.clientY;
   }
   else
   {   
      x=e.pageX; y=e.pageY;
   }
 
   //move target
   with (dragitem.style)
   {
     left=(x-xoff)+'px'; top=(y-yoff)+'px';
   }

   dragged=true;
}
//mouse up - end drag
function OnMouseUp(e)
{

//stop dragging
document.onmouseup = null;
document.onmousemove = null;
dragitem.style.cursor = "default";
doDrag=false;

//if dragged and not just clicked on
if (dragged)
{
   //get event and target for ie or firefox
   if (e==null)
   {   
      e = window.event;
      x=e.clientX; y=e.clientY;
   }
   else
   {   
      x=e.pageX; y=e.pageY;
   }

  //Drop onto target images
  num = -1;
  for (n=0; n<numtgts; n++) 
  {  
    with (tgts[n].style)
    {  

      //If cursor within drop area note drop item
      if (x>=pos(left))
        if (x<(pos(left)+pos(width)))
           if (y>=pos(top))
             if (y<(pos(top)+pos(height)))
             {
		num=n;

                //Centre drag item on drop item - assumes same size here
                dragitem.style.left = left;
                dragitem.style.top = top;
                break;
             }
    }
  }

  //If over do checks
  if (num>=0)
    checkitem(tgts[num])

  //Otherwise put item back where it was and enable next selection
  else 
  {
     with (dragitem.style){left = xold+'px';  top = yold+'px'; zIndex = 3;}
     document.onmousedown = OnMouseDown;
     changecursor("pointer");
  }
}

//if not dragged just reenable
else
{
  document.onmousedown = OnMouseDown;
  changecursor("pointer"); 
}
}

//Change mouse cursor for last specific (hdr) style rule
//this is browser dependent - prevents other elements looking active during animation
function changecursor(str) 
{
var formats = new Array();
var browser=navigator.userAgent.toLowerCase();
if (browser.indexOf("msie") != -1)
	formats = document.styleSheets[0].rules;
else
	formats = document.styleSheets[0].cssRules;
formats[formats.length-1].style.cursor = str;
}


//check results and perform appropriate steps

//Check if item in right place
//may need various changes specific to interactive
function checkitem(o) 
{

//Right if index of dragitem as drop item. 
if (o.lang==dragitem.lang)
{

  //Update score
  score += 10;
  document.getElementById("scoreboard").innerHTML = "You have<br>"+score+"<br>points";

  //Hide caption of dragged item, the index should match that of image
  h2s[dragitem.lang].style.visibility="hidden";
 
  //mark source and target as used
  dragitem.lang="X"	
  o.lang="X";

  //To do
  nleft--;

  //enable next selection
  document.onmousedown = OnMouseDown;
  changecursor("pointer") 
}

//Wrong
else
{
  //store normal image src and use animated version of image src
  //note last index as full path searched - online indexOf would find . in www.
  with (dragitem)
  {
     imgsrc = src;
     p = imgsrc.lastIndexOf(".");
     src = imgsrc.substring(0,p) + "_ani" + imgsrc.substring(p,imgsrc.length);
  }

  //Prevent further choice until animation finished
  moving = true;

  //Put the dragged item back
  flyback();

  //Update score
  score -= 5;
  with (document.getElementById("scoreboard")){innerHTML="You have<br>"+score+"<br>points";}
}

//If all done show result and finish
if (nleft <= 0)
{
  showresult();
  return;
}
}
//Return an incorrect item to previous position
//standard function if needed
function flyback()
{

with (dragitem.style)
{

  //set up position array with 1st pos as current last as previous and rest between two points
  l=pos(left); t=pos(top);
  dx=xold-l; dy=yold-t;

  //Set number steps according to pixel distance approx 4 steps if straight up about 200 pixels
  dist = Math.sqrt(dx*dx + dy*dy);
  steps=Math.round(0.02 * dist);
  if (steps<1) steps=1;

  //Do a straight path
  for (n=0;n<=steps;n++)
  {
    xp[n]=l+(n*dx)/steps; yp[n]=t+(n*dy)/steps;
  }

  //Add a bit of wobble to all but 1st and last
  for (n=1;n<steps;n++)
  {
    xp[n] += (wonky * (Math.random()-0.5) * dist)/steps;
    yp[n] += (wonky * (Math.random()-0.5) * dist)/steps;
  }

  //Move back along path
  step=0;
  dopath();
}
}
//Animate along path
//standard function if needed
function dopath()
{

//Drag item
with (dragitem.style){left=xp[step]+'px'; top=yp[step]+'px';}

//If another step in path do next after delay 
if (++step<=steps) 
{   
  setTimeout("dopath()",200);
}

//De-Animate the image at end and allow choice
else
{
  dragitem.src=imgsrc;
  dragitem.style.zIndex = 3;
  moving = false;
  changecursor("pointer") 
  dragitem.style.cursor = "pointer";
  document.onmousedown = OnMouseDown;
}
}


//final stuff

//Show results and finish
//may need various changes specific to interactive
function showresult()
{

//Hide everything
for (n=0; n<numimgs; n++) imgs[n].style.visibility="hidden";
for (n=0; n<spans.length; n++) spans[n].style.visibility="hidden";
for (n=0; n<h2s.length; n++) h2s[n].style.visibility="hidden";
for (n=0; n<divs.length; n++) divs[n].style.visibility="hidden";

//Except score stuff
with (document.getElementById("resulttext"))
{
  style.visibility ="visible";

  //Show score
  innerHTML = "You scored<br><br>"+score+"<br><br>Points";
}
document.getElementById("resultmain").style.visibility ="visible";
document.getElementById("lastanim").style.visibility="visible";

//Do last animation
wander();
}
//Animate along erratic path
//standard function if needed
function wander()
{

  //get end animation position  
  with (document.getElementById("lastanim").style) {l = pos(left); t =pos(top);}

  //wander about within limits
  dx = ascale*wonky*(Math.random()-0.5); dy = ascale*wonky*(Math.random()-0.5);
  l += dx; if (l<xmin || l>xmax) l -= 2*dx;
  t += dy; if (t<ymin || t>ymax) t -= 2*dy;

  //set new position
  with (document.getElementById("lastanim").style)
  {
     left=l+'px'; top=t+'px';
  }
  setTimeout("wander()",200);
}

//general Button processing 
//fairly standard functions, may need some changes
//Show all boxes hidden before show to ensure only one at a time
function showhelp(helpbox)
{
if (moving) return;
document.getElementById("help").style.visibility="hidden";
document.getElementById("info").style.visibility="hidden";
document.getElementById(helpbox).style.visibility="visible";
}
function hidehelp(helpbox)
{
if (moving) return;
document.getElementById(helpbox).style.visibility="hidden";
}

