/*
Zoombox funktionen er udviklet af Atkins Danmark for KRAK A/S, målrettet mod Kraks kort web service.
Funktionen er kort sagt en zoombox, som vises på kortet når brugeren trykker venstre museknap ned og 
trækker musen i en retning, og som returnerer et nyt kortområde når museknappen slippes.

Fordelen med dette javascript er, at det er implementerbart i flere forskellige web programmeringssprog 
(ASP, ASP.NET, JAVA etc.)

Funktionen indeholder flere funktioner / muligheder. Der er således også mulighed for at aktivere zoom ud 
og panorer funktionalitet, samt zoom ind / ud med en zoomfaktor. Dette kræver dog nogle elementer på 
websiden, hvor brugeren kan aktivere disse. Default er zoom ind.

Hvis brugeren ikke markerer et område, men blot klikker et vilkårligt sted på kortet, zoomes ind med default 
zoomfaktor, som er sat til 2. Dette kan ændres ved at sætte en anden zoomfaktor i variablen, se vejledning.

Koden er sammensat af flere forskellige javascript filer og tilrettet til formålet, derfor kan der godt være
en variation mellem dansk og engelsk i forklaringerne, og steder kunne koden godt være optimeret. Vigtigst er
dog, at den virker.

/21. juni 2006 - Morten Hjelmsmark

Vejledning:
1.  Inkluder link til denne fil i HTML headeren på web siden.

2.  Inkluder et et DIV element i dokumentet med id = 'mapholder', som skal virke som den container der bliver tilknyttet 
    museklik events. Denne DIV indeholder et billede element med id="imap" (<input type="Image" /> eller 
    <asp:ImageButton ect.), samt endnu en DIV med id = 'box', som vil være den visuelle del af funktionen, som vil 
    repræsentere det nye kortområde. Hvis panorer funktionen skal benyttes, er det vigtigt at billedeelementet er 
    tilknyttet css stylen position:absolute.
    Billedeelementet tilknyttes url'en fra KRAK's kort webservice i kode delen, samt højde og bredde. Ændres navnet 
    på billede elementet skal dette også ændres i funktionerne i denne fil og i Variable.js filen.  
    Div elementet (mapholder), kan sættes ind i andre HTML elementer hvis dette er ønskeligt. Herunder følger et eksempel.  

    Eksempel:
   <div onmouseup="if (document.z_box){document.z_box.processEvent(event);}" class="clMap"
      onmousemove="if (document.z_box){document.z_box.processEvent(event);}" 
      onmousedown='document.z_box = new ZoomBox(event, box, "clZoomBox"); document.z_box.processEvent(event);'
      id="mapholder" style="Z-INDEX: 100;top:70px;" runat="server">
      <asp:ImageButton id="imap" runat="server" Height="30" Width="30" CssClass="climap" 
                       style="position:absolute;"></asp:ImageButton>
      <div id="box" style="VISIBILITY: hidden">
         <div style="VISIBILITY: hidden"></div>
      </div>
   </div> 

3.  Inkluder Hidden elementerne herunder:
    <!-- Indeholder nuværende extent; top|bund|venstre|højre  -->
    <input type="hidden" id="curExtent" runat="server" value="0|0|0|0"/>
    <!-- Her skrives det nye extent som kan bruges til webservice kaldet; top|bund|venstre|højre  -->
    <input type="hidden" id="newExtent" runat="server" value="0|0|0|0" />
    <!-- Previous extent gemmes, såfremt man ønsker en 'tilbage til forrige zoom knap -->
    <input type="hidden" id="prevExtent" runat="server" value="0|0|0|0"/>
    <!-- First extent gemmes, såfremt man ønsker at komme tilbage til udgangskortet -->
    <input id="firstExtent" type="hidden" value="0|0|0|0" name="firstExtent" runat="server"/> 
    <!-- Extent for hele DK gemmes, såfremt man ønsker en 'zoom to fullextent' knap -->
    <input id="maxExtent" type="hidden" value="641300000|603300000|39360000|93650000" name="maxExtent" runat="server"/>
    <!-- Default value sat til 'zoomin', hvis der ønskes panorer eller zoomud, skal værdierne være 'pan' eller 'zoomout' -->
    <input type="hidden" id="activetool" runat="server" value="zoomin"/>

4.  Tilføj Styles for de omtalte elementer i headeren på web siden, eller i den allerede tilknyttede css fil.
    Eksempel: 
    <style type="text/css">
DIV.clMap 
{
   BORDER-RIGHT: #6699cc 1px solid; 
   BORDER-TOP: #6699cc 1px solid; 
   LEFT: 50px; 
   BORDER-LEFT: #6699cc 1px solid; 
   WIDTH: 640px; 
   BORDER-BOTTOM: #6699cc 1px solid; 
   POSITION: absolute; 
   TOP: 130px; 
   HEIGHT: 512px;
   overflow:hidden; 
}
.clZoomDiv 
{
   BORDER-RIGHT: #660000 2px solid; 
   BORDER-TOP: #660000 2px solid; 
   FILTER: alpha(opacity=25); 
   BORDER-LEFT: #660000 2px solid; 
   BORDER-BOTTOM: #660000 2px solid; 
   POSITION: absolute; 
   BACKGROUND-COLOR: silver; 
   opacity: .45; 
   moz-opacity: 0.45 
}
    </style>
    
5.   Inkluder link til Variable.js filen et sted i websidens Frame element. 
   <script type="text/javascript" src=Javascript/Variable.js ></script>

6.  Tilret de 'specielle' variable. Det er status, zoomlevel, mainform og zb_css og de findes 
    umiddelbart som det første herunder.

Et simpelt ASP.NET eksempel vil blive vedhæftet.



Rettelser:
- Koden justeret til Firefox og Opera.
- ID-variable læses fra eksterne variable i stedet for hardcodede strings.

/Kristian Thy, Atkins -- 20070815

------------------------------------------------------------------------------------------------------------------------------
*/
//*******************************************************************************
//
// KODE START
//
//*******************************************************************************

/********************************************************************************
* Specielle variable
*********************************************************************************/

// viser markørens koordinater i status bjælken 
var status = true;

//Default zoomlevel hvis mousedown og mouseup er identiske
var zoomlevel = 2;

// Navnet på den definerede CSS klasse til zoombox'en 
var zb_css = 'clZoomDiv';

/*********************************************************************************
* ZoomBox functions
**********************************************************************************/

function ZoomBox(box, cssName)
{
   // Hvis boxen er udefineret er funktionen kaldt med den hensigt at kreere klasse
   // prototype objektet for at tilknytte funktioner til elementerne
   if (box)
   {
      // den visuelle komponent til klassen er div'en mapholder som er en div der 
      // har position: absolute. Div'en har fordelen at den kan tilknyttes styles
      // og er browser uafhængig
      this.box = box;
      // Boxen tilknyttes css klassen som indgår i kaldet
      this.box.className = cssName;
      //this.box.style.position = 'relative';
      //preset the zoomboxing flag
      this.zoomboxing = false;
      
   }
}

//main event handler function, this function handles all drawing based on events
ZoomBox.prototype.processEvent = function(e)
{
   var customerPositionOffsetX = 0; 
   if(ff())
   {
    customerPositionOffsetX = document.getElementById(mapholder).offsetParent.offsetLeft;//200;
   }
   var customerPositionOffsetY = 0; 
   if (!e) var e = window.event;
   if (e.offsetX === undefined)
   {
      var map = document.getElementById(mapholder);
      e.offsetX = e.pageX - map.offsetLeft;
      e.offsetY = e.pageY - map.offsetTop;
   }
   
   switch (e.type)
   {
   case 'mousedown':      
         // only respond to left mouse clicks
      if (!this.zoomboxing && left(e))
      {
        MapSearchValidate();
        if(!zoomallowed){return false;};
         // offsetX og offsetY korrigerer for kortets (div'en map's) placering på hjemmesiden!
         if(ff()){
            offsetX = e.clientX - (e.offsetX - customerPositionOffsetX); offsetY = e.clientY - e.offsetY;
         }else{
            offsetX = e.clientX - e.offsetX; offsetY = e.clientY - e.offsetY;
         }
         // Gemmer værdierne for mouse down (udgangspunktet) 
         this.absOrigX = e.clientX - offsetX; this.absOrigY = e.clientY - offsetY;
         if (ff()) { this.absOrigX -= 8; this.absOrigY -= 28; }
         this.absDestX = e.clientX - offsetX - 8; this.absDestY = e.clientY - offsetY - 8;
         if (ff()) { this.absDestX -= 8; this.absDestY -= 28; }
         this.relOrigX = e.offsetX - customerPositionOffsetX; this.relOrigY = e.offsetY;
         this.relDestX = e.offsetX - customerPositionOffsetX; this.relDestY = e.offsetY;
            
         // konverterer pixel til geo koordinater
         if (ff()) getMapXY(parseInt(this.relOrigX) - 8,parseInt(this.relOrigY) - 28);
         else getMapXY(parseInt(this.relOrigX),parseInt(this.relOrigY));
         tmpX = mapX; tmpY = mapY;

         // Aktiverer zoombox'en så det vil blive rendret dynamisk
         this.zoomboxing = true;

         // localiserer div (map) og initialiser dens dimensioner
         if (ff())
         {
            this.box.style.left = this.relOrigX - 8 + 'px'; this.box.style.top = this.relOrigY - 28 + 'px';
         }
         else
         {
            this.box.style.left = this.relOrigX + 'px'; this.box.style.top = this.relOrigY + 'px';
         }
         this.box.style.height = '0px'; this.box.style.width = '0px';
         this.box.style.visibility = 'visible';
      }
      break;

   case 'mousemove':
      if (this.zoomboxing && left(e))
      {
         // Offset skal også trækkes fra box'ens andet hjørne
         this.absDestX = e.clientX - offsetX; this.absDestY = e.clientY - offsetY;
         if (ff()) { this.absDestX -= 8; this.absDestY -= 28; }
         // Højden og bredden vil altid være den absolutte værdi af forskellen mellem e.client koordinaterne
         var height = Math.abs(this.absOrigY - this.absDestY);
         var width  = Math.abs(this.absOrigX - this.absDestX);
         this.box.style.height = height + 'px'; this.box.style.width = width + 'px';
                
         // Resten beregner hvilke koordinater som skal udgøre left og top for box'en
         if (this.absDestX > this.absOrigX && this.absDestY < this.absOrigY) // I
         {
            this.box.style.left = this.absOrigX + 'px'; this.box.style.top = this.absDestY + 'px';
            this.relDestX = this.relOrigX + width; this.relDestY = this.relOrigY - height;
         }
         else if (this.absDestX < this.absOrigX && this.absDestY < this.absOrigY) // II
         {
            this.box.style.left = this.absDestX + 'px'; this.box.style.top = this.absDestY + 'px';
            this.relDestX = this.relOrigX - width; this.relDestY = this.relOrigY - height;
         }
         else if (this.absDestX < this.absOrigX && this.absDestY > this.absOrigY) // III
         {
            this.box.style.left = this.absDestX + 'px'; this.box.style.top = this.absOrigY + 'px';
            this.relDestX = this.relOrigX - width; this.relDestY = this.relOrigY + height;
         }
         else if (this.absDestX > this.absOrigX && this.absDestY > this.absOrigY) // IV
         {
            this.box.style.left = this.absOrigX + 'px'; this.box.style.top = this.absOrigY + 'px';
            this.relDestX = this.relOrigX + width;  this.relDestY = this.relOrigY + height;
         }
         else if (this.absDestX > this.absOrigX && this.absDestY == this.absOrigY) // 0 degrees
         {
            this.box.style.left = this.absOrigX + 'px'; this.box.style.top = this.absOrigY + 'px';
            this.relDestX = this.relOrigX + width; this.relDestY = this.relOrigY;
         }
         else if (this.absDestX == this.absOrigX && this.absDestY < this.absOrigY) // 90 degrees
         {
            this.box.style.left = this.absOrigX + 'px'; this.box.style.top = this.absDestY + 'px';
            this.relDestX = this.relOrigX; this.relDestY = this.relOrigY - height;
         }
         else if (this.absDestX < this.absOrigX && this.absDestY == this.absOrigY) // 180 degrees
         {
            this.box.style.left = this.absDestX + 'px'; this.box.style.top = this.absOrigY + 'px';
            this.relDestX = this.relOrigX - width; this.relDestY = this.relOrigY;
         }
         else if (this.absDestX == this.absOrigX && this.absDestY > this.absOrigY) // 270 degrees
         {
            this.box.style.left = this.absOrigX + 'px'; this.box.style.top = this.absOrigY + 'px';
            this.relDestX = this.relOrigX; this.relDestY = this.relOrigY + height;
         }
      }
      break;

   case 'mouseup':
      if (this.zoomboxing && left(e))
      {
         var act = document.getElementById(activetool).value;
         //konverterer pixel til geo koordinater
         if (ff()) getMapXY(this.relDestX - 8,this.relDestY - 28);
         else getMapXY(this.relDestX,this.relDestY);
         if ((parseInt(tmpX) == parseInt(mapX)) || (parseInt(tmpY) == parseInt(mapY)))
         {
            //Musen har ikke været flyttet mellem mus ned og mus op, derfor zoomes med zoomfaktor
            if (act=='zoomin') { mapZoomIn(); } else if (act=='zoomout') { mapZoomOut(); }
         }
         else if (act=='zoomout')
         {
            var diffX = Math.abs(parseInt(tmpX) - parseInt(mapX));
            var diffY = Math.abs(parseInt(tmpY) - parseInt(mapY));
            var rel = ((xDistance/diffX) + (yDistance/diffY))/2;
            var distX = parseInt((xDistance*rel)/2); eLeft = parseInt(mapX-distX); eRight = parseInt(mapX+distX);
            var distY = parseInt((yDistance*rel)/2); eBottom = parseInt(mapY-distY); eTop = parseInt(mapY+distY);
            fullExtCTrl();
         }
         else
         {
            //sikrer at right er større end left    
            if (parseInt(tmpX) > parseInt(mapX)) { eRight = tmpX; eLeft = mapX; }
            else { eLeft = tmpX; eRight = mapX; }
            //sikrer at top er større end bottom    
            if (parseInt(tmpY) < parseInt(mapY)) { eTop = mapY; eBottom = tmpY; }
            else { eTop = tmpY;   eBottom = mapY; }
          }

          //afslutter box'en og skjuler den   
          this.zoomboxing = false; this.box.style.visibility = 'hidden';
          //skriver extent værdierne til newExtent 
          document.getElementById('newExtent').value = String(eTop+'|'+eBottom+'|'+eLeft+'|'+eRight);
          //kalder et postback
          __doPostBack('zoomin','');
      }
      break;
   }
}

/**********************************************************************************
 * Initialise mouse events                                                        *
 **********************************************************************************/
function initMap()
{
   var map = document.getElementById(mapholder);   
   map.onmousedown = Map_onMouseDown;
   map.onmousemove = Map_onMouseMove;
   map.onmouseup = Map_onMouseUp;
}

function Map_onMouseDown(e)
{
   if (!e) var e = window.event;
   if (e.offsetX === undefined)
   {
      var map = document.getElementById(mapholder);
      e.offsetX = e.pageX - map.offsetLeft;
      e.offsetY = e.pageY - map.offsetTop;
   }
   // Gemmer extent i prevExtent, så der er mulighed for en tilbage knap
   document.getElementById('prevExtent').value = String(eTop+'|'+eBottom+'|'+eLeft+'|'+eRight);
   if (document.getElementById(activetool).value.toLowerCase() != 'pan')
   {
      if (!box) var box = document.getElementById('box');
      z_box = new ZoomBox(box, zb_css); z_box.processEvent(e);
   }
   else
   {
      // Ved panorering skal der ikke tegnes en box
      // OffsetX og offsetY korrigerer for kortets (div'en map's) placering på hjemmesiden
      offsetX =  e.clientX - e.offsetX - 3; offsetY = e.clientY - e.offsetY - 3;
      pixX = e.clientX - offsetX; pixY = e.clientY - offsetY; 
      // Konverterer pixel til geo koordinater
      getMapXY(pixX,pixY); tmpX = mapX; tmpY = mapY;
      click = 1;
   }
}

function Map_onMouseMove(e)
{
   if (!e) var e = window.event;
   if (e.offsetX === undefined)
   {
      var map = document.getElementById(mapholder);
      e.offsetX = e.pageX - map.offsetLeft;
      e.offsetY = e.pageY - map.offsetTop;
   }
   getMapXY(e.offsetX, e.offsetY);
   if (status) { window.status = 'Koordinater: X=' + parseInt(mapX) + ', Y=' + parseInt(mapY); }
   var act = document.getElementById(activetool).value.toLowerCase();
   if (act != 'pan' )
   {
      if (z_box) { z_box.processEvent(e); }
   }
   else if (act == 'pan' && click == 1)
   {
      var mx = e.clientX - offsetX; var my = e.clientY - offsetY; getMapXY(mx,my);
      if (status) { window.status = 'Koordinater: X=' + parseInt(mapX) + ', Y=' + parseInt(mapY); }
      var xMove = parseFloat(mx) - parseFloat(pixX); //xvector 
      var yMove = parseFloat(my) - parseFloat(pixY); //yvector
      // Beregner vektoren i forhold til mousedown
      var newLeft = offsetX + xMove;
      var newTop  = offsetY + yMove;
      // Flytter billedet med musen, ved at flyttet top og left i vektorens retning
      moveLayer('imap', xMove, yMove);
      if (poiLayer) moveLayer(poiLayer, xMove, yMove);
   }
}

function Map_onMouseUp(e)
{
   if (!e) var e = window.event;
   var act = document.getElementById(activetool).value.toLowerCase();
   if (act != 'pan')
   {
      if (z_box) { z_box.processEvent(e); }
   }
   else if (act == 'pan' && click == 1)
   {
      // Hvis panorer er aktiveret
      var mx = e.clientX - offsetX; var my = e.clientY - offsetY; getMapXY(mx,my);
      if (status) { window.status = 'Koordinater: X=' + parseInt(mapX) + ', Y=' + parseInt(mapY); }
      var xMove = parseInt(parseFloat(tmpX) - parseFloat(mapX)); //xvector
      var yMove = parseInt(parseFloat(tmpY) - parseFloat(mapY)); //yvector
      if ((xMove==0) && (yMove==0))
      {
         // Så har brugeren klikket på et nyt centrum uden at trække musen
         var centX = parseInt(eLeft + (xDistance/2)); xMove = parseInt(parseFloat(mapX) - centX); 
         var centY = parseInt(eBottom + (yDistance/2)); yMove = parseInt(parseFloat(mapY) - centY); 
      }
      eLeft = parseInt(eLeft + xMove); eRight = parseInt(eRight + xMove);
      eTop = parseInt(eTop + yMove); eBottom = parseInt(eBottom + yMove);
      // Skriver nyt extent til hidden elementet
      document.getElementById('newExtent').value = String(eTop+'|'+eBottom+'|'+eLeft+'|'+eRight);
      click = 0;
      __doPostBack('pan','');
   }
}

//on load map the event handlers
window.onload = initMap;

//create a variable to hold the z_box
var z_box;

/*********************************************************************************
* Map functions
**********************************************************************************/

//funktion til konvertering fra pixel til koordinater
function getMapXY(xIn,yIn)
{
   pixelX = xDistance / iWidth;  mapX = parseInt(pixelX * xIn + eLeft);
   var mouseY = iHeight - yIn; pixelY = yDistance / iHeight; mapY = parseInt( pixelY * mouseY + eBottom);
}

//funktion til zoom ind med default zoomlevel 
function mapZoomIn()
{
   var distX = parseInt((xDistance/zoomlevel)/2); eLeft = parseInt( mapX-distX);eRight = parseInt( mapX+distX);
   var distY = parseInt((yDistance/zoomlevel)/2); eBottom = parseInt( mapY-distY);eTop = parseInt( mapY+distY);
}

//funktion til zoom ud med default zoomlevel 
function mapZoomOut()
{
   var distX = parseInt((xDistance*zoomlevel)/2); eLeft = parseInt( mapX-distX);eRight = parseInt( mapX+distX);
   var distY = parseInt((yDistance*zoomlevel)/2); eBottom = parseInt( mapY-distY);eTop = parseInt( mapY+distY);
   fullExtCTrl();
}

//funktion til zoom tilbage til første loadede kort 
function getFirstExt()
{
   var firstE = String(document.getElementById('firstExtent').value);
   var a_firstE = firstE.split('|');
   document.getElementById('newExtent').value = String(parseInt(a_firstE[0])+'|'+
                                                       parseInt(a_firstE[1])+'|'+
                                                       parseInt(a_firstE[2])+'|'+
                                                       parseInt(a_firstE[3]));
}

//funktion til zoom til max extent (Danmark) 
function getFullExtent()
{
   var maxE = String(document.getElementById('maxExtent').value);
   var a_maxE = maxE.split('|');
   document.getElementById('newExtent').value = String(parseInt(a_maxE[0])+'|'+parseInt(a_maxE[1])+'|'+parseInt(a_maxE[2])+'|'+parseInt(a_maxE[3]));
}

//Kontrollerer at vi ikke kommer uden for vore max extent
function fullExtCTrl()
{
   var maxE = String(document.getElementById('maxExtent').value);
   var a_maxE = maxE.split('|');
   //order maxy(top)|miny(bottom)|minx(left)|maxx(right)
   var maxdistX = parseInt(a_maxE[0]) - parseInt(a_maxE[1]);
   var maxdistY = parseInt(a_maxE[3]) - parseInt(a_maxE[2]);
   var meTop = parseInt(a_maxE[0]);  var meBottom = parseInt(a_maxE[1]);
   var meLeft = parseInt(a_maxE[2]); var  meRight = parseInt(a_maxE[3]);
   if((maxdistX < xDistance) || (maxdistY < yDistance)) {setFullExtent(); }
   else if (meLeft>eLeft) { eLeft= meLeft; eRight= parseInt(meLeft+xDistance); }
   else if (meRight<eRight) { eRight= meRight; eLeft= parseInt(meRight-xDistance); }
   else if (meTop<eTop) { eTop= meTop; eBottom= parseInt(meTop-yDistance); }
   else if (meBottom>eBottom) { eBottom= meBottom; eTop= parseInt(meBottom+yDistance); }
}

//funktion som sætter det nye extent til fullextent
function setFullExtent()
{
   var maxE = String(document.getElementById('maxExtent').value);
   var a_maxE = maxE.split('|');
   eTop = parseInt(a_maxE[0]); eBottom = parseInt(a_maxE[1]);
   eLeft = parseInt(a_maxE[2]);  eRight = parseInt(a_maxE[3]);
}

//funktion til at flytte rundt på HTML elementer (billede elementet ved Panorer) 
function moveLayer(name, x, y)
{
   var theObj = document.getElementById(name);
   theObj.style.left = x + 'px';
   theObj.style.top  = y + 'px';
}

//funktion til at detektere venstre museknap
//se http://www.quirksmode.org/js/events_properties.html#button
function left(e)
{
   if (e.which) return (e.which == 1);
   else return (e.button == 1);
}

//funktion til at afgøre om vi er Firefox
function ff()
{
   return (navigator.userAgent.indexOf('Firefox') > -1);
}

//Eksekverer postback
function __doPostBack(eventTarget, eventArgument)
{
   var theform = document.getElementById(mainform);
   document.getElementById('srchZipCode').value='';
   theform.submit();
}

