/*

Copyright (c) 2005-2006, Andre Lewis, andre@earthcode.com

All rights reserved.



Redistribution and use in source and binary forms, with or without modification, are permitted provided 

that the following conditions are met:



    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

    * Neither the name of "Andre Lewis" nor the names of contributors to this software may be used to endorse or promote products derived from this software without specific prior written permission.



THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 

IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 

FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 

CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 

DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 

DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 

WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 

ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

/*

GZoom custom map control



To use:

  oMap = new GMap2($id("large-google-map"));	

  oMap.addControl(new GMapTypeControl());



Or with options:

  oMap.addControl(new GZoomControl({sColor:'#000',nOpacity:.3,sBorder:'1px solid yellow'}), new GControlPosition(G_ANCHOR_TOP_RIGHT,new GSize(10,10)));



More info at http://earthcode.com

*/



// base definition and inheritance

function GZoomControl(oOptions) {

  GZoomControl.G.style = {

    nOpacity:.2,

    sColor:"#000",

    sBorder:"2px solid blue"

  };

  var style=GZoomControl.G.style;

  for (var s in oOptions) {style[s]=oOptions[s]};

  var aStyle=style.sBorder.split(' ');

  style.nOutlineWidth=parseInt(aStyle[0].replace(/\D/g,''));

  style.sOutlineColor=aStyle[2];

  style.sIEAlpha='alpha(opacity='+(style.nOpacity*100)+')';

}



GZoomControl.prototype = new GControl();



//class globals

GZoomControl.G={

  bDragging:false,

  mct:null,

  mcr:null,

  mcb:null,

  mcl:null,

	oMapPos:null,

	oOutline:null,

	nMapWidth:0,

	nMapHeight:0,

	nMapRatio:0,

	nStartX:0,

	nStartY:0,

	nBorderCorrect:0

};





// ******************************************************************************************

// Methods required by Google maps -- initialize and getDefaultPosition

// ******************************************************************************************

GZoomControl.prototype.initialize = function(oMap) {

  //DOM:button

	var oMC=oMap.getContainer();

	var oButton = document.createElement('div');

	oButton.appendChild(document.createTextNode('ZoomBox'));

	oButton.id='gzoom-control';

	//DOM:map covers

	acl.style([oButton],{width:'52px',cursor:'pointer',background:'#FFF',border:'1px solid black',padding:'0px 5px 1px 5px',zIndex:200});

	oMC.appendChild(oButton);

	var o = document.createElement("div");

  o.id='gzoom-map-cover';

	o.innerHTML='<div id="gzoom-outline" style="position:absolute;display:none;"></div><div id="gzoom-mct" style="position:absolute;display:none;"></div><div id="gzoom-mcl" style="position:absolute;display:none;"></div><div id="gzoom-mcr" style="position:absolute;display:none;"></div><div id="gzoom-mcb" style="position:absolute;display:none;"></div>';

	acl.style([o],{position:'absolute',display:'none',overflow:'hidden',cursor:'crosshair',zIndex:101});

	oMC.appendChild(o);



  // add event listeners

	GEvent.addDomListener(oButton, 'click', GZoomControl.prototype.initCover_);

	GEvent.addDomListener(o, 'mousedown', GZoomControl.prototype.coverMousedown_);

	GEvent.addDomListener(document, 'mousemove', GZoomControl.prototype.drag_);

	GEvent.addDomListener(document, 'mouseup', GZoomControl.prototype.mouseup_);



  // get globals

  var G=GZoomControl.G;

	G.oMapPos=acl.getElementPosition(oMap.getContainer());

	G.oOutline=$id("gzoom-outline");	

	G.oButton=$id("gzoom-control");

	G.mc=$id("gzoom-map-cover");

	G.mct=$id("gzoom-mct");

	G.mcr=$id("gzoom-mcr");

	G.mcb=$id("gzoom-mcb");

	G.mcl=$id("gzoom-mcl");

	G.oMap = oMap;



	G.nBorderCorrect = G.style.nOutlineWidth*2;	

  this.setDimensions_();



  //styles

  this.initStyles_();

  /*G.mct.style.background='red';G.mcr.style.background='yellow';G.mcb.style.background='blue';*/



  debug("Finished Initializing gzoom control");  

  return oButton;

};



// Default location for the control

GZoomControl.prototype.getDefaultPosition = function() {

  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(3, 120));

};



// ******************************************************************************************

// Private methods

// ******************************************************************************************

GZoomControl.prototype.coverMousedown_ = function(e){

  var G=GZoomControl.G;

  var oPos = GZoomControl.prototype.getRelPos_(e);

  debug("Mouse down at "+oPos.left+", "+oPos.top);

  G.nStartX=oPos.left;

  G.nStartY=oPos.top;

  

	acl.style([G.mc],{background:'transparent',opacity:1,filter:'alpha(opacity=100)'});

  acl.style([G.oOutline],{left:G.nStartX+'px',top:G.nStartY+'px',display:'block',width:'1px',height:'1px'});

  G.bDragging=true;



  G.mct.style.top=(G.nStartY-G.nMapHeight)+'px';

  G.mct.style.display='block';

  G.mcl.style.left=(G.nStartX-G.nMapWidth)+'px';

  G.mcl.style.top=(G.nStartY)+'px';

  G.mcl.style.display='block';



  G.mcr.style.left=(G.nStartX)+'px';

  G.mcr.style.top=(G.nStartY)+'px';

  G.mcr.style.display='block';

  G.mcb.style.left=(G.nStartX)+'px';

  G.mcb.style.top=(G.nStartY)+'px';

  G.mcb.style.width='0px';

  G.mcb.style.display='block';



  debug("mouse down done");

  return false;

};



GZoomControl.prototype.drag_=function(e){

  var G=GZoomControl.G;

  if(G.bDragging) {

    var oPos=GZoomControl.prototype.getRelPos_(e);

    oRec = GZoomControl.prototype.getRectangle_(G.nStartX,G.nStartY,oPos,G.nMapRatio);

    G.oOutline.style.width=oRec.nWidth+"px";

    G.oOutline.style.height=oRec.nHeight+"px";

    

    G.mcr.style.left=(oRec.nEndX+G.nBorderCorrect)+'px';

    G.mcb.style.top=(oRec.nEndY+G.nBorderCorrect)+'px';

    G.mcb.style.width=(oRec.nWidth+G.nBorderCorrect)+'px';

    return false;

  }  

};

GZoomControl.prototype.mouseup_=function(e){

  var G=GZoomControl.G;

  if (G.bDragging) {

    var oPos = GZoomControl.prototype.getRelPos_(e);

    G.bDragging=false;

    

    var oRec = GZoomControl.prototype.getRectangle_(G.nStartX,G.nStartY,oPos,G.nMapRatio);

    debug("mouse up at "+oRec.nEndX+", "+oRec.nEndY+". Height/width="+oRec.nWidth+","+oRec.nHeight); 



    GZoomControl.prototype.resetDragZoom_();



    sw = G.oMap.fromContainerPixelToLatLng(new GPoint(oRec.nStartX,oRec.nEndY) ); 

    ne = G.oMap.fromContainerPixelToLatLng(new GPoint(oRec.nEndX,oRec.nStartY) ); 

    

    nw = G.oMap.fromContainerPixelToLatLng(new GPoint(oRec.nStartX,oRec.nStartY) ); 

    se = G.oMap.fromContainerPixelToLatLng(new GPoint(oRec.nEndX,oRec.nEndY) ); 

    var oZoomArea = new GPolyline([nw,ne,se,sw,nw],G.style.sOutlineColor,G.style.nOutlineWidth+1,.4);

    try{

      G.oMap.addOverlay(oZoomArea);

      setTimeout (function(){G.oMap.removeOverlay(oZoomArea)},6000);      

    }catch(e){

      jslog.error("error adding zoomarea overlay:"+e.message);

    }

    

    oBounds=new GLatLngBounds(sw,ne);

    nZoom=G.oMap.getBoundsZoomLevel(oBounds);

    oCenter=oBounds.getCenter();

    G.oMap.setCenter(oCenter, nZoom);

  }

};



// set the cover sizes according to the size of the map

GZoomControl.prototype.setDimensions_=function() {

  var G=GZoomControl.G;

  var oSize = G.oMap.getSize();

  G.nMapWidth  = oSize.width;

  G.nMapHeight = oSize.height;

  G.nMapRatio  = G.nMapHeight/G.nMapWidth;

	acl.style([G.mc,G.mct,G.mcr,G.mcb,G.mcl],{width:G.nMapWidth+'px', height:G.nMapHeight+'px'});

};



GZoomControl.prototype.initStyles_=function(){

  var G=GZoomControl.G;

	acl.style([G.mc,G.mct,G.mcr,G.mcb,G.mcl],{filter:G.style.sIEAlpha,opacity:G.style.nOpacity,background:G.style.sColor});

  G.oOutline.style.border=G.style.sBorder;  

  debug("done initStyles_");	

};



GZoomControl.prototype.initCover_=function(){

  var G=GZoomControl.G;

  if (G.mc.style.display=='block'){ // reset if clicked before dragging

    GZoomControl.prototype.resetDragZoom_();

  } else {

    G.oButton.innerHTML='Zoom rettangolo Zoom rectangle';

  	G.oButton.style.background='#fc6';

  	acl.style([G.mc],{display:'block',background:G.style.sColor});

    debug("done initCover_");

  }

};



GZoomControl.prototype.getRelPos_=function(e) {

  var oPos=acl.getMousePosition (e);

  var G=GZoomControl.G;

  return {top:(oPos.top-G.oMapPos.top),left:(oPos.left-G.oMapPos.left)};

};



GZoomControl.prototype.getRectangle_=function(nStartX,nStartY,oPos,nRatio){

	var dX=oPos.left-nStartX;

	var dY=oPos.top-nStartY;

	if (dX <0) dX =dX*-1;

	if (dY <0) dY =dY*-1;

	delta = dX > dY ? dX : dY;



  return {

    nStartX:nStartX,

    nStartY:nStartY,

    nEndX:nStartX+delta,

    nEndY:nStartY+parseInt(delta*nRatio),

    nWidth:delta,

    nHeight:parseInt(delta*nRatio)

  }

};



GZoomControl.prototype.resetDragZoom_=function() {

	var G=GZoomControl.G;

	acl.style([G.mc,G.mct,G.mcr,G.mcb,G.mcl],{display:'none',opacity:G.style.nOpacity,filter:G.style.sIEAlpha});

	G.oOutline.style.display='none';	

	G.oButton.innerHTML='ZoomBox';

	G.oButton.style.background='white';

  debug("done with reset drag zoom");

};



/* alias get element by id */

function $id(sId) { return document.getElementById(sId); }

/* utility functions in acl namespace */

if (!window['acldefined']) {var acl={};window['acldefined']=true;}//only set the acl namespace once, then set a flag



/* A general-purpose function to get the absolute position of

the mouse */

acl.getMousePosition=function(e) {

	var posx = 0;

	var posy = 0;

	if (!e) var e = window.event;

	if (e.pageX || e.pageY) {

		posx = e.pageX;

		posy = e.pageY;

	} else if (e.clientX || e.clientY){

		posx = e.clientX + (document.documentElement.scrollLeft?document.documentElement.scrollLeft:document.body.scrollLeft);

		posy = e.clientY + (document.documentElement.scrollTop?document.documentElement.scrollTop:document.body.scrollTop);

	}	

	return {left:posx, top:posy};  

};



/*

To Use: 

	var pos = acl.getElementPosition(element);

	var left = pos.left;

	var top = pos.top;

*/

acl.getElementPosition=function(eElement) {

		var nLeftPos = eElement.offsetLeft;          // initialize var to store calculations

	var nTopPos = eElement.offsetTop;            // initialize var to store calculations

	var eParElement = eElement.offsetParent;     // identify first offset parent element  

	while (eParElement != null ) {                // move up through element hierarchy

				nLeftPos += eParElement.offsetLeft;      // appending left offset of each parent

				nTopPos += eParElement.offsetTop;  

				eParElement = eParElement.offsetParent;  // until no more offset parents exist

		}

		return {left:nLeftPos, top:nTopPos};

};

//elements is either a coma-delimited list of ids or an array of DOM objects. o is a hash of styles to be applied

//example: style('d1,d2',{color:'yellow'});  

acl.style=function(a,o){

	if (typeof(a)=='string') {a=acl.getManyElements(a);}

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

		for (var s in o) { a[i].style[s]=o[s];}

	}

};

acl.getManyElements=function(s){		

	t=s.split(',');

	a=[];

	for (var i=0;i<t.length;i++){a[a.length]=$id(t[i])};

	return a;

};

	

var jslog = {debug:function(){},info:function(){}, 

	warning:function(){}, error:function(){},

	text:function(){}}; var debug=function(){};

if (location.href.match(/enablejslog/)){

		document.write('<script type="text/javascript" src="http://earthcode.com/include/javascripts/jslog.js"></script>');};	
