/*
 * $Workfile: MapViewerControl.js $
 * 
 * $Logfile: /CheshireCCSolutions/DiscoverCheshireEnhancements/CheshireCC.DCEnhancements.Web.Internet/Scripts/MapViewerControl.js $
 * 
 * $Revision: 99 $
 * 
 * $Date: 05/01/09 11:09 $
 * 
 * Original Author: Andrew Montgomery
 * 
 * $Author: Jon Satchwell $
 * 
 * Copyright(c) Cheshire County Council All Rights Reserved.
 * 
 */		
// This script uses Object-Oriented JavaScript.
// Please ensure you are familiar with the concepts of OOJ
// before attempting to make changes.
function btnClickEventFilter(){
          Map.refresh();
}
var obj = null;
//******************************************************
//MapInfoBox object.  Shows when the map first opens on the
//default page
//******************************************************
function MapInfoBoxObject(){
    this.infoBox = document.getElementById("map_info_box"); 
    this.infoText = "";
    this.infoChkBox = document.getElementById('chkShowMapInfoBox');    
    //Name this by region so each individual site is a different info box.
    this.infoBoxCookieTxt = "showMapInfoBox" + Map.mapRegion.toString();    
    obj = new wp_Cookie({
		                    expires : 1,
		                    expires_unit : "weeks"
	                    });
}

	//check for the info box cookie
MapInfoBoxObject.prototype.checkInfoBoxCookie = function(){
    var blnShowInfoBox = obj.get(this.infoBoxCookieTxt);
    if(blnShowInfoBox == "false"){
        this.infoBox.style.display = 'none';
    }
    else{
        this.infoBox.style.display = '';
    }       
}
//Handle request to not show the box again using Cookies.
MapInfoBoxObject.prototype.closeClick = function(){
    if(this.infoChkBox.checked){
        if(obj.test()){          
            obj.set(this.infoBoxCookieTxt,"false");           
        }
        else{
            alert("Your browser does not accept cookies. \r\n  \r\n Please enable cookies to save this option");
        } 
    }
    this.close();
    return false;  
}
//Close the info box
MapInfoBoxObject.prototype.close = function(){
    this.infoBox.style.display = 'none';
}
//******************************************************
//Event filter object
//******************************************************
function EventFilterObject(){
    this.eventFilterContainer = document.getElementById("divEventFilter"); 
    this.filter = false;
    this.currentTime = new Date();
    this.currentDay = this.currentTime.getDate();
    this.currentMonth = this.currentTime.getMonth();
    //this.currentYear = this.currentTime.getYear();
    this.currentYear = this.currentTime.getUTCFullYear();     
    this.selDuration = document.getElementById('ddDuration');    
    this.selD = document.getElementById('ddDays');
    this.selY = document.getElementById('ddYears');
    this.selM = document.getElementById('ddMonths');
    this.arrMonths = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');    
    this.arrYears = new Array(this.currentYear, this.currentYear+1, this.currentYear+2, this.currentYear+3, this.currentYear+4);      
    this.setSelectLists();        
}
EventFilterObject.prototype.getEndDate = function(){    
    var intDaysToAdd = this.selDuration.options[this.selDuration.selectedIndex].value;
    return Date.DateAdd('d',intDaysToAdd,this.getStartDate() );
}
EventFilterObject.prototype.strEndDate = function(){
    return Date.Format(this.getEndDate(),'dd/mm/yyyy');
}
EventFilterObject.prototype.strStartDate = function(){
    return Date.Format(this.getStartDate(),'dd/mm/yyyy');
}
EventFilterObject.prototype.getStartDate = function(){
    var dt = new Date(this.yearSelected(), this.monthSelected(), this.daySelected() );
    return dt;
}
EventFilterObject.prototype.daySelected = function(){
    return parseInt(this.selD.options[this.selD.selectedIndex].value);
}
EventFilterObject.prototype.monthSelected = function(){
    return parseInt(this.selM.options[this.selM.selectedIndex].value);
}
EventFilterObject.prototype.yearSelected = function(){
    return parseInt(this.selY.options[this.selY.selectedIndex].value);
}
EventFilterObject.prototype.setSelectLists = function(){
    for(i=0; i<31; i++){
        var intDay = i+1;
        var option = new Option(intDay.toString(), intDay.toString());
        this.selD.options[i] = option; 
    }    
    this.selD.selectedIndex = this.currentDay -1;    
    for(i=0;i < this.arrMonths.length;i++){
        var option = new Option(this.arrMonths[i], i);
        this.selM.options[i] = option;
    }
    this.selM.selectedIndex = this.currentMonth;    
    for(i=0;i < this.arrYears.length;i++){
        var option = new Option(this.arrYears[i], this.arrYears[i]);
        this.selY.options[i] = option;
        if(this.arrYears[i].toString() == this.currentYear.toString()) this.selY.selectedIndex = i;
    }
}
//*************************************************************************
// Route Search Object handles the map searches from the leftNav search control
// for WLK,RID,CYC,PRK and EVT.
//*************************************************************************
function RouteSearchObject(){
    this.txtRouteSearch = document.getElementById("txtSearch");
    this.optRouteSearch = document.getElementById("srchCategory");
    this.search = false;
    this.routeFilter = false; 
    this.activeLayerCategory = "";
    this.divSearchArea = document.getElementById("divSearchArea");  
    this.clearSelectedSearchItem();    
    this.hasRouteCategories = (document.aspnetForm.findRb != null) ? true : false;                  
}
RouteSearchObject.prototype.routeFilter = function(){
    if(this.txtRouteSearch.value.length > 0){
        return true;
    }
    else{
        return false;
    }
}
RouteSearchObject.prototype.getSelectedSearchItem = function(){
    //if the route options are not present exit the function
    if(!this.hasRouteCategories)return;    
    var pageForm = document.aspnetForm;
    var chosen = "";
    var len = pageForm.findRb.length;
    for (i = 0; i <len; i++) {
        if (pageForm.findRb[i].checked){
            chosen = pageForm.findRb[i].value;
            break;
        }
    }
    return chosen;
}
RouteSearchObject.prototype.clearSelectedSearchItem = function(){
    //if the route options are not present exit the function
    if(!this.hasRouteCategories)return;
    var pageForm = document.aspnetForm;
    if(pageForm.findRb != null){
        var len = pageForm.findRb.length;
        for (i = 0; i <len; i++) {
            if (pageForm.findRb[i].checked){
                pageForm.findRb[i].checked = false;
               // alert(chosen);
                break;
            }
        }
    }
}
//Sets the selected search option
RouteSearchObject.prototype.setSelectedSearchOption = function(mapCat){
    //if the route options are not present exit the function
    if(!this.hasRouteCategories)return false;
    var pageForm = document.aspnetForm;
    var len = pageForm.findRb.length;
    for (i = 0; i <len; i++) {
        if (pageForm.findRb[i].value == mapCat){
            pageForm.findRb[i].checked = 'checked';
            break;
        }
    }
    return false;
}
RouteSearchObject.prototype.clearSearch = function(){
    //clear the search box
    this.txtRouteSearch.value = ""; 
    //if the route options are not present exit the function
    if(!this.hasRouteCategories)return false;
    //Deselect the radio button
    var pageForm = document.aspnetForm;
    var len = pageForm.findRb.length;
    for (i = 0; i <len; i++){
      pageForm.findRb[i].checked = false;
    }    
    //Both Map.RS and RouteSearch.search stop the map refreshing after each layer has been turned off
    //this is done at the end when all have been removed
    Map.RS = true;
    RouteSearch.search = true;    
    layerList.clearAllLayers();    
    //hide the layerlist box on the map
    Map.mapLayerCatDetails.style.visibility = "hidden";        
    Map.reset();
    Map.refresh();
    Map.RS = false;
    RouteSearch.search = false;    
    return false;
}

function removeAllFromMap()
{
    //arrDCELayers is created from the webconfig and registered on the page load.  it is a collection
    //of all the layers available WLK1P, CYC2P, EVT1P etc...
    var arrTypes = arrDCESiteLayers;
    var strElementID = "";
    for(x=0; x <arrTypes.length ; x++){
            strElementID = arrTypes[x];
            var cb = document.getElementsByName(strElementID)[0];
            if(cb != null){
               if (cb.checked){
		            cb.click();
		       }
            }
	}			
}
//Handles the option group category click event 
RouteSearchObject.prototype.selectCat = function(optVal){
    //Both Map.RS and RouteSearch.search stop the map refreshing after each layer has been turned off
    //this is done at the end when all have been removed
    Map.RS = true;
    RouteSearch.search = true;
    layerList.clearAllLayers();
    layerList.setDefaultMapLayers();
    //Map.reset();
    //Map.refresh();
    Identify.clearSelectionRS();
    Map.RS = false;
    RouteSearch.search = false;
    Identify.hide();
    this.searchForRoutes(optVal);
    MapInfoBox.infoBox.style.display = 'none';  
}
//Handles the search BUTTON event click - redirects if this is a route / thematic trail page.
RouteSearchObject.prototype.searchForRoutesClick = function(){
    var selectedOption = this.getSelectedSearchItem();
    if(!this.hasRouteCategories) {
        alert("Search is not enabled for this site yet.");
        return;
    }
    if (selectedOption == ""){
        alert("Please choose a category!");
        return;
    }       
    if(Map.mapIsRoute || Map.mapIsTheme){
        window.location.href="default.aspx?region="+ Map.mapRegion.toString() + 
                                "&mapCategory="+ selectedOption +
                                "&routeSearchTxt=" + this.txtRouteSearch.value;
        return;
    }
    this.searchForRoutes()    
}
//Main route search procedure
RouteSearchObject.prototype.searchForRoutes = function(){        
    EventFilter.filter = false;
    EventFilter.eventFilterContainer.style.display = 'none';             
    var selectedOption = this.getSelectedSearchItem();    
    if(selectedOption == "999"){
        alert("This feature is coming soon");
        window.location.href="default.aspx?region="+ Map.mapRegion.toString();
        return;
    }
    if(this.search){       
        removeAllFromMap();
		Map.reset();
		Map.refresh();	
    }    
    //Event filter control
    if(selectedOption == "EVT"){
        EventFilter.filter = true;
        EventFilter.eventFilterContainer.style.display = '';        
	}
    //make the layer list visible
    Map.mapLayerCatDetails.style.visibility = "visible";
    Map.mapCategory = selectedOption;
    this.search = true;    
    //if there's already an active showing in the layer list remove it
    if(this.activeLayerCategory != ""){       
        layerList.hideActiveLayer(this.activeLayerCategory);
    }                                
    //Set the active layer category which will not be hidden on the layer list (WLK,RID,CYC etc...).
    this.activeLayerCategory = "dt_" + Map.mapCategory;
    layerList.showActiveLayer(this.activeLayerCategory);
    if(this.txtRouteSearch.value.length > 0){
        var newExtent = Map.getExtent();
        this.routeFilter = true;        
        Map.refreshToExtent(newExtent);
    }
    else{
        this.routeFilter = false;    
        Map.refresh();        
    }
    if(Map.isLargeMap){    
        layerList.clickMoreSerialiseIdentify();
    }
    this.search = false;   
}
// Coordinates object #1
function CoordsMap(_e,_n) {
	this.e = 0;
	this.n = 0;
	if (arguments.length == 2) {
		this.e = _e;
		this.n = _n;
	}
}
CoordsMap.prototype.ToScreenPoint = function() {
	var env = Map.getExtent();
	var cs = new CoordsScreen();
	cs.x = Math.round((this.e - env.minx) / Map.scale);
	cs.y = Math.round((env.maxy - this.n) / Map.scale);
	return cs;
}
CoordsMap.prototype.getGridRef = function() {
	var gridrefs = new Array(13);
	gridrefs[12] = new Array(""  ,""  ,""  ,""  ,"HP",""  ,""  );
	gridrefs[11] = new Array(""  ,""  ,""  ,"HT","HU",""  ,""  );
	gridrefs[10] = new Array(""  ,"HW","HX","HY","HZ",""  ,""  );
	gridrefs[ 9] = new Array("NA","NB","NC","ND",""  ,""  ,""  );
	gridrefs[ 8] = new Array("NF","NG","NH","NJ","NK",""  ,""  );
	gridrefs[ 7] = new Array("NL","NM","NN","NO",""  ,""  ,""  );
	gridrefs[ 6] = new Array(""  ,"NR","NS","NT","NU",""  ,""  );
	gridrefs[ 5] = new Array(""  ,"NW","NX","NY","NZ",""  ,""  );
	gridrefs[ 4] = new Array(""  ,""  ,"SC","SD","SE","TA",""  );
	gridrefs[ 3] = new Array(""  ,""  ,"SH","SJ","SK","TF","TG");
	gridrefs[ 2] = new Array(""  ,"SM","SN","SO","SP","TL","TM");
	gridrefs[ 1] = new Array(""  ,"SR","SS","ST","SU","TQ","TR");
	gridrefs[ 0] = new Array("SV","SW","SX","SY","SZ","TV",""  );
	var x = Math.floor(this.e / 100000);
	var y = Math.floor(this.n / 100000);
	var tile = gridrefs[y][x];
	//if (tile=="") alert("Outside UK boundary");
	var textE = Math.floor((this.e % 100000) / 10);
	var textN = Math.floor((this.n % 100000) / 10);
	// Force to four digits
	if (textE < 10) textE = "000" + textE;
	else if (textE < 100) textE = "00" + textE;
	else if (textE < 1000) textE = "0" + textE;
	if (textN < 10) textN = "000" + textN;
	else if (textN < 100) textN = "00" + textN;
	else if (textN < 1000) textN = "0" + textN;
	return tile + " " + textE + " " + textN;
}
// Coordinates object #2
function CoordsScreen(_x,_y){
	this.x = 0;
	this.y = 0;
	if (arguments.length == 2){
		this.x = _x;
		this.y = _y;
	}
}
CoordsScreen.prototype.ToMapCoords = function(){
	var env = Map.getExtent();
	var cm = new CoordsMap();
	cm.e = Math.round((this.x * Map.scale + env.minx)*100)/100;
	cm.n = Math.round((env.maxy - (this.y * Map.scale))*100)/100;
	return cm;
}
CoordsScreen.prototype.LimitToMap = function(padding){
	var changed = false;
	if (this.x < padding.x)			  { changed = true; this.x = padding.x; }
	if (this.y < padding.y)			  { changed = true; this.y = padding.y; }
	if (this.x >= Map.width  - padding.x) { changed = true; this.x = (Map.width  - 1) - padding.x; }
	if (this.y >= Map.height - padding.y) { changed = true; this.y = (Map.height - 1) - padding.y; }
	return changed;
}
// Coordinates object #3
function ImageSize(_w,_h) {
	this.w = 0;
	this.h = 0;
	if (arguments.length == 2) {
		this.w = _w;
		this.h = _h;
	}
}
// MouseObject is used for all methods requiring mouse positioning,
// including drag-n-move and identify.
function MouseObject() {
	this.startPoint = new CoordsScreen(0,0);	
	//Register event listener for the mouse scroll so the user can zoom the map
    if(window.addEventListener) document.addEventListener('DOMMouseScroll', this.scrollZoom, false);
	//for IE/OPERA etc
    document.onmousewheel = this.scrollZoom;
}
MouseObject.prototype.scrollZoom2 = function(event){
}
//Jon Satchwell 26/09/2008.
//Scroll zoom event handler.
MouseObject.prototype.scrollZoom = function(event){
	var mouseonmap = Map.mapActive;//document.getElementById("hidMouseOnMap").checked;
	if(mouseonmap) {
	    if(Map.mapLayerDivOver)return false; 	    
	    var delta = 0;    	
	    if (!event) event = window.event;  
	     // normalize the delta
        if (event.wheelDelta){
		    // IE & Opera
      	    delta = event.wheelDelta / 120;
	    }
	    else if (event.detail) // W3C
	    {
		    delta = -event.detail / 3;
	    }    	
	    //Use delta value to determine if the user wants to zoom in or out.
	    switch(delta)
	    {
		    case 1:
			    ZoomMarker.zoomIn();
		    break;
    		
		    case -1:
			    ZoomMarker.zoomOut();
		    break;
	    }	
	    return false;	   
	}
	else
	{
	    return true;        
	}    	
}
MouseObject.prototype.start = function(eventObject) {
	this.startPoint.x = eventObject.clientX;
	this.startPoint.y = eventObject.clientY;
}
MouseObject.prototype.getShift = function(eventObject) {
	var pt = new CoordsScreen(0,0);
	pt.x = eventObject.clientX - this.startPoint.x;
	pt.y = eventObject.clientY - this.startPoint.y;
	return pt;
}
MouseObject.prototype.getOffset = function(eventObject) {
	var pt = new CoordsScreen(0,0);
	if (eventObject.offsetX) {
		pt.x = eventObject.offsetX;
		pt.y = eventObject.offsetY;
	} else {
		pt.x = eventObject.layerX;
		pt.y = eventObject.layerY;
	}
	return pt;
}
// START method for finding offset relative to element of mouse event
/**
  * Retrieve the coordinates of the given event relative to the center
  * of the widget.
  *
  * @param event
  *  A mouse-related DOM event.
  * @param reference
  *  A DOM element whose position we want to transform the mouse coordinates to.
  * @return
  *    A hash containing keys 'x' and 'y'.
  */
MouseObject.prototype.getRelativeCoordinates = function(event, reference) {
	var x = 0, y = 0;
	event = event || window.event;
	var el = event.target || event.srcElement;
	if (!window.opera && typeof event.offsetX != 'undefined') {
		// Use offset coordinates and find common offsetParent
		var pos = { x: event.offsetX, y: event.offsetY };
		// Send the coordinates upwards through the offsetParent chain.
		var e = el;
		while (e) {
			e.mouseX = pos.x;
			e.mouseY = pos.y;
			pos.x += e.offsetLeft;
			pos.y += e.offsetTop;
			e = e.offsetParent;
		}
		// Look for the coordinates starting from the reference element.
		var e = reference;
		var offset = { x: 0, y: 0 }
		while (e) {
			if (typeof e.mouseX != 'undefined') {
				x = e.mouseX - offset.x;
				y = e.mouseY - offset.y;
				break;
			}
			offset.x += e.offsetLeft;
			offset.y += e.offsetTop;
			e = e.offsetParent;
		}
		// Reset stored coordinates
		e = el;
		while (e) {
			e.mouseX = undefined;
			e.mouseY = undefined;
			e = e.offsetParent;
		}
	} else {
		// Use absolute coordinates
		var pos = this.getAbsolutePosition(reference);
		x = event.pageX - pos.x;
		y = event.pageY - pos.y;
	}
	// Subtract distance to middle
	return new CoordsScreen(x, y);
}
MouseObject.prototype.getAbsolutePosition = function(element) {
	// part of getRelativeCoordinates above; not to be used in isolation (because it doesn't work in IE)
	var r = { x: element.offsetLeft, y: element.offsetTop };
	if (element.offsetParent) {
		var tmp = this.getAbsolutePosition(element.offsetParent);
		r.x += tmp.x;
		r.y += tmp.y;
	}
	return r;
}
// END method for finding offset relative to element of mouse event
// The following functions are event-handlers for the mouse on the map
var bMoving = false;
function mapMouseDown(evt) {
	if(Map.mapLayerDivOver)return false;	
	//Switch to ZoomBox tool
//	if ((NavTool.Mode == "zoomin" || NavTool.Mode == "zoomout" )){ZoomBox.startZoomBox(evt); return false;}	
	var e = (window.event) ? window.event : evt;
	if (bMoving) return false;
	bMoving = true;
	Mouse.start(e);
	Map.divPrev.childNodes[0].style.width  = Map.width  + "px";
	Map.divPrev.childNodes[0].style.height = Map.height + "px";
	Map.mapWrap.style.cursor = Map.cursorGrabbing; // grabbing cursor

	// This block allows the user to drag the map, release, then quickly do a new drag before the new image has loaded
	if (true) {
		var currX = Map.divCurr.childNodes[0].style.marginLeft;
		var currY = Map.divCurr.childNodes[0].style.marginTop;
		if (currX != "") currX = parseInt(currX); else currX = 0;
		if (currY != "") currY = parseInt(currY); else currY = 0;
		Mouse.startPoint.x -= currX;
		Mouse.startPoint.y -= currY;
	}
	return false; // this stops FireFox from selecting text or images
}
function mapMouseMove(evt) {
//	if ((NavTool.Mode == "zoomin" || NavTool.Mode == "zoomout" ) && ZoomBox.zooming==true){
//	ZoomBox.resizeZoomBox(evt);
//	}
//	flagMouseMove(evt); // In FireFox the mouse can diverge from the flag and accidentally trigger mapMouseMove instead of flagMouseMove
	var e = (window.event) ? window.event : evt;
	// For grid references
	var pnt = Mouse.getRelativeCoordinates(e, Map.divCurr);
	Map.updateGridRef(pnt,bMoving);
	// For moving the map (and infobox)
	if (!bMoving) return false;
	var pt = Mouse.getShift(e);	
	Map.divOlde.childNodes[0].style.marginLeft = pt.x + "px";
	Map.divCurr.childNodes[0].style.marginLeft = pt.x + "px";
	Map.divPrev.childNodes[0].style.marginLeft = pt.x + "px";
	Map.divOlde.childNodes[0].style.marginTop  = pt.y + "px";
	Map.divCurr.childNodes[0].style.marginTop  = pt.y + "px";
	Map.divPrev.childNodes[0].style.marginTop  = pt.y + "px";
	Identify.drift(pt);
//Attempt at disabling panning past a certain extent.   
//   	var mapHalfWidth = Map.width / 2;
//	Map.eTemp = ((mapHalfWidth * Map.scale) + Map.e);
//	Map.eTemp -= pt.x * Map.scale;
//	if(Map.eTemp = 426520)
//	{

//	    Map.e -= pt.x * Map.scale;
//		Map.n += pt.y * Map.scale;
//		Map.e = Math.round(Map.e*100)/100;
//		Map.n = Math.round(Map.n*100)/100;

//	//    bMoving = false;
//	    Map.mapWrap.style.cursor = Map.cursorGrab;
//	    Map.refresh();
//	    alert('edge');
//	    return false;
//	}
//    Map.divCurrCoords.innerHTML = "Map.e: " + Map.e + "; Map.scale: " + Map.scale + "; e2: " + Map.eTemp;
//	
	return false;
}
function mapMouseUp(evt) {	
//	if ((NavTool.Mode == "zoomin"|| NavTool.Mode == "zoomout" )){
//		ZoomBox.stopZoomBox(evt); 
//		return false;
//	}
	var e = (window.event) ? window.event : evt;
	if (!bMoving) return false;
	bMoving = false;
	var shiftBy = Mouse.getShift(e);
	Map.mapWrap.style.cursor = Map.cursorGrab; // grabbing cursor
	if (shiftBy.x == 0 && shiftBy.y == 0) {
		// identify mode
		var pnt = Mouse.getRelativeCoordinates(e, Map.divCurr);
		//Identify.identifyPoint(pnt);
	} else {
		// map move mode
		// apply screen shift to map location, by multiplying by scale
		Map.e -= shiftBy.x * Map.scale;
		Map.n += shiftBy.y * Map.scale;
		Map.e = Math.round(Map.e*100)/100;
		Map.n = Math.round(Map.n*100)/100;
		// then load new image
		Identify.shift(shiftBy);
		Map.refresh();
     
	var e2 = ((Map.width / 2) * Map.scale) + Map.e;
        
    //Map.divCurrCoords.innerHTML = "width: " + Map.width + " Map.e: " + Map.e + "; Map.scale: " + Map.scale + "; e2: " + e2;

	}
	return false;
}
function mapMouseOut(evt) {
	Map.updateGridRef(null,null);
	//set control to determine if the mouse is over the map
	Map.mapActive = false;
	return mapMouseUp(evt);
}

function mapMouseOver(evt) {
	//set control to determine if the mouse is over the map
	Map.mapActive = true;
	return mapMouseUp(evt);
}

//============================================
//Mouse over events for Layerlist divs that are positioned over the map
function mapLayerDivMouseOver() {
	Map.mapLayerDivOver = true;
	Map.mapWrap.style.cursor = "default";
	//Map.cursorZoomin;
}

function mapLayerDivMouseOut() {
	Map.mapLayerDivOver = false;
	Map.mapWrap.style.cursor = Map.cursorGrab;
//	NavTool.setCursor(NavTool.Mode);
}
//============================================


// A map requires 5 or 6 key parameters:
//   Either an Envelope: minX, minY, maxX, maxY,   width, height
//   or  Center + Scale: centerE, centerN, scale,  width, height

// EnvelopeObject is exactly what it sounds like
function EnvelopeObject(_minx, _miny, _maxx, _maxy) {
	if (arguments.length != 4) {
		this.minx = -1;
		this.miny = -1;
		this.maxx = -1;
		this.maxy = -1;
	} else {
		this.minx = _minx;
		this.miny = _miny;
		this.maxx = _maxx;
		this.maxy = _maxy;
	}
}
// Convert an EnvelopeObject to a CenterAndScale object
EnvelopeObject.prototype.ToCAS = function(width, height) {
	var cas = new CenterAndScale();
	cas.e = (this.minx + this.maxx) / 2;
	cas.n = (this.miny + this.maxy) / 2;
	cas.scale = Math.max((this.maxx - this.minx) / width, (this.maxy - this.miny) / height);
	return cas;
}
// CenterAndScale is exactly what is says on the tin
function CenterAndScale() {
	this.e = -1;
	this.n = -1;
	this.scale = -1;
}
CenterAndScale.prototype.ToEnvelope = function(width, height) {
	var env = new Envelope();
	env.minx = this.e - ((width  * this.scale) / 2);
	env.miny = this.n - ((height * this.scale) / 2);
	env.maxx = this.e + ((width  * this.scale) / 2);
	env.maxy = this.n + ((height * this.scale) / 2);
	return env;
}


// OverviewObject controls the overview map, the red box, 
// and clicking on the overview map.
function OverviewObject() {
    
    this.div = document.getElementById("divOverview");
	this.red = document.getElementById("divRedBox"); // red box element
    this.divMaster = document.getElementById("divOverviewMaster");
    //this.divMaster.style.display = 'none';
    this.visible = false;
    this.ovImg = document.getElementById("imgOverview");
    
    
    this.overviewVisible(false);
    
    if(Map.mapOverview != "")
    {
        this.overviewArray = new Array();
        this.overviewArray = Map.mapOverview.split(";");
        if(this.overviewArray.length > 3)
        {
        //change the overview map visibility here
	        this.divMaster.style.display = '';
        	
	        this.div.style.display = '';
	        
            this.ovInitE = parseInt(this.overviewArray[0]);
	        this.ovInitN = parseInt(this.overviewArray[1]);
	        this.ovInitMpp = parseInt(this.overviewArray[2]);
	        this.ovFileName = this.overviewArray[3].toString();
	        this.ovImg.src = "Map/Images/" + this.ovFileName;
	       
	         
	        this.ovImageWidth = 140;
	        this.ovImageHeight = 360;
	        this.ovTotalE = this.ovInitMpp * this.ovImageWidth;
	        this.ovTotalN = this.ovInitMpp * this.ovImageHeight;
	        this.ovEmin = this.ovInitE - (this.ovInitMpp * (this.ovImageWidth /2));
	        this.ovEmax = this.ovInitE + (this.ovInitMpp * (this.ovImageWidth /2));
	        this.ovNmin = this.ovInitN - (this.ovInitMpp * (this.ovImageHeight /2));
	        this.ovNmax = this.ovInitN + (this.ovInitMpp * (this.ovImageHeight /2));
        	
	        this.div.onmousedown = overviewMouseDown;
	        this.div.onmousemove = overviewMouseMove;
	        this.div.onmouseup   = overviewMouseUp;
	        this.div.onmouseout  = overviewMouseOut;
        	
	        
        	
	        //For debugging
	        this.dInfo = document.getElementById("divCurrCoords");
        	
	        //move the zoom bar if the overview map is showing
	        document.getElementById('divZoomBarWhole').style.left = "160px";
	        document.getElementById('divMarker').style.left = "160px";
	        
	        this.visible = true;
	        
        }
        
    }
    
    
    return;
    
	
	
}

OverviewObject.prototype.overviewVisible = function(blnVisible) {
    if(blnVisible)
    {
	    this.divMaster.style.display = '';
	    this.div.style.display = '';
    }
    else{
	    this.divMaster.style.display = 'none';
	    this.div.style.display = 'none';
    }
}

OverviewObject.prototype.moveZoomBar = function(blnShift) {

	//move the zoom bar if the overview map is showing
	if(blnShift){
	    document.getElementById('divZoomBarWhole').style.left = "10px";
	    document.getElementById('divMarker').style.left = "10px";
	    document.getElementById('divBGAerialMap').style.left = "10px";
	    
	}
	else{
	    document.getElementById('divZoomBarWhole').style.left = "160px";
	    document.getElementById('divMarker').style.left = "160px";
	    document.getElementById('divBGAerialMap').style.left = "160px";
	    
	}
}

OverviewObject.prototype.setDimensions = function(w,h) {
	this.div.style.marginLeft = (0) + "px";
	this.div.style.marginTop  = (0) + "px";
}

OverviewObject.prototype.updateOverview = function() {
    if(!this.visible) return;
    
    //get point centre for overview map.
    var ovPercentageX = (Map.e - this.ovEmin) / this.ovTotalE;
    var ovCentreX = Math.round(ovPercentageX * this.ovImageWidth);
    
    var ovPercentageY = (Map.n - this.ovNmin) / this.ovTotalN;
    var ovCentreY = Math.round(this.ovImageHeight - (ovPercentageY * this.ovImageHeight));
    
    var ovHeight = Math.round(((this.ovImageHeight * Map.scale) / this.ovTotalN) * this.ovImageHeight) - 2;
    var ovWidth = Math.round(((Map.width * Map.scale) / this.ovTotalE) * this.ovImageWidth) - 2;
    
    if (ovWidth  < 22) 
    {
        ovWidth = 22;
        ovHeight = 8;
    }
	
    var ovLeft = Math.round(ovCentreX - (ovWidth  / 2));
	var ovTop  = Math.round(ovCentreY - (ovHeight / 2));
	this.red.style.marginLeft = ovLeft + "px";
	this.red.style.marginTop  = ovTop  + "px";
	
    this.red.style.width  = ovWidth  + "px";
	this.red.style.height = ovHeight + "px";
	this.red.childNodes[0].style.height = ovHeight + "px";
    this.red.childNodes[0].style.width = ovWidth  + "px";

}
OverviewObject.prototype.ClickMe = function(evt) {
    if(!this.visible) return;

	var e = (window.event) ? window.event : evt;
	var pnt = Mouse.getRelativeCoordinates(e, this.div);
	pnt.x -= 0; // adjust 7px for the border around the overview map
	pnt.y -= 0; // adjust 7px for the border around the overview map
    
	var ovE = this.ovInitMpp * this.ovImageWidth;
	var ovN = this.ovInitMpp * this.ovImageHeight;
	var newE = ((pnt.x / this.ovImageWidth) * ovE) + this.ovEmin;
	var newN = (((this.ovImageHeight - pnt.y) / this.ovImageHeight) * ovN) + this.ovNmin;
	var oldExtent = Map.getExtent();
	Map.e = newE;
	Map.n = newN;
	Identify.repositionForScale(Map.scale, oldExtent);

	Map.clearImage();
	Map.refresh();
}
// Event-handlers for the Overview object
function overviewMouseDown(evt) {
	var e = (window.event) ? window.event : evt;
	if (e.stopPropagation)
		e.stopPropagation();
	else
		e.cancelBubble = true;
	return false;
}
function overviewMouseMove() {
	return false;
}
function overviewMouseUp() {
	return false;
}
function overviewMouseOut() {
	return false;
}

// Three special functions for window.setTimeout (which can't call object methods)
function Map_slideAlong()     { Map.slideAlong();    }
function Map_waitForResize()  { Map.waitForResize(); }
function Map_setMapSize()     { Map.setMapSize();    }
// One special function for onload (which can call object methods, but this keeps it tidy)
function Map_ImageLoaded(ix) { 
if(Map != undefined){Map.imageLoaded(ix);
//alert("Map loaded: " + ix);
}
else{return;}
}
// MapObject is the main map object; it does most of the work in this application
function MapObject() {
	// initial constants
	this.initE = 363000;
	this.initN = 363000;
	this.initScale = 160; // equivalent to approx 1:600'000
	
	this.hidInitE =	document.getElementById(userControlMapText().toString() + "hidInitialEasting");
	this.hidInitN =	document.getElementById(userControlMapText().toString() + "hidInitialNorthing");
	this.hidInitMpp =	document.getElementById(userControlMapText().toString() + "hidInitialMpp");
	
	this.hidInitHLayer = document.getElementById(userControlMapText().toString() + "hidInitialHLayer");
	this.hidInitHField = document.getElementById(userControlMapText().toString() + "hidInitialHField");
	this.hidInitHValue = document.getElementById(userControlMapText().toString() + "hidInitialHValue");
	
	this.hidInitMapCategory = document.getElementById(userControlMapText().toString() + "hidMapCategory");
	this.hidInitMapRegion = document.getElementById(userControlMapText().toString() + "hidMapRegion");
	this.hidMapRefNum = document.getElementById(userControlMapText().toString() + "hidMapRefNum");
	
	this.hidMapBackLayers = document.getElementById(userControlMapText().toString() + "hidMapBackLayers");
	this.hidMapBackE = document.getElementById(userControlMapText().toString() + "hidMapBackE");
	this.hidMapBackN = document.getElementById(userControlMapText().toString() + "hidMapBackN");
	this.hidMapBackMpp = document.getElementById(userControlMapText().toString() + "hidMapBackMpp");
	this.hidMapBackSearchTxt = document.getElementById(userControlMapText().toString() + "hidMapBackSearchTxt");

	this.hidThematicId = document.getElementById(userControlMapText().toString() + "hidThematicId");
    this.hidOverview = document.getElementById(userControlMapText().toString() + "hidOverview");

	
	// initialise member variables
	this.e = this.initE;
	this.n = this.initN;
	this.scale = this.initScale;
	this.width = 280;
	this.height = 200;
	this.highlightLayer = "";
	this.highlightField = -1;
	this.highlightValue = -1;
	this.thematicId = ""; // "" or null means no report, any other value means show a report
    this.mapCategory = "";
    this.mapRegion = "1";
    this.mapRefNum = "";
    this.RS = false;
    this.hidRouteSearchTxt = "";
    
	this.gLastImageSize = new ImageSize();
	this.bLoading = true; // freeze all buttons from start
	this.smoothZoomDirection = 0;
	this.smoothZoomFactor = 1;
	this.smoothZoomRatio = 1;
	this.smoothZoomShift = new CoordsScreen(0,0);
	this.mapWrap = null;
	this.divPrev = null;
	this.divCurr = null;
	this.divOlde = null;
	this.divOver = null;
	this.divInfo = null;
	this.divLoad = null;
	
	this.gSlideDirection = "";
	this.gSlideOffset = 0;

	this.resizeWaitId = false;
	
	this.mapActive = false;
	this.mapIsFirefox = false;
	this.divCurrCoords = document.getElementById("divCurrCoords");
	
	this.eTemp = this.e;
	this.nTemp = this.n;
	
	//Map position on the page
	this.mapContainer = document.getElementById(userControlMapText().toString() +"divMapContainer");
	this.mleft = this.mapContainer.style.left;
	this.mtop = this.mapContainer.style.top;

	// cursor
	this.cursorZoomin	= navigator.userAgent.indexOf("Gecko") == -1 ? ["url('Map/images/zoom-in.cur'),move"]  : ["-moz-zoom"];
	this.cursorGrab     = navigator.userAgent.indexOf("Gecko") == -1 ? ["url('Map/images/grab.cur'),move"]     : ["-moz-grab"];
	this.cursorGrabbing = navigator.userAgent.indexOf("Gecko") == -1 ? ["url('Map/images/grabbing.cur'),move"] : ["-moz-grabbing"];
	
	this.mapLayerCatDetails = null;
	this.mapLayerDivOver = false;
	
	this.isLargeMap = null;
	this.hrefLargeMap = null;
	this.mapOverview = "";
	this.hrefMapBack = null;
	
    
}



MapObject.prototype.imageLoaded = function(ix) {
	var src = document.getElementById("imgMap" + ix).src;
	if (src.indexOf("transparent.gif") != -1) return; // ignore load events for transparent.gif
	this.divLoad.style.display = "none";
}
MapObject.prototype.clearHighlight = function() {
	this.updateHighlight("","","");
}
MapObject.prototype.updateHighlight = function(newHighlightLayer, newHighlightField, newHighlightValue) {
	if (this.highlightLayer != newHighlightLayer || 
		this.highlightField != newHighlightField ||
		this.highlightValue != newHighlightValue
		) {
		this.highlightLayer = newHighlightLayer;
		this.highlightField = newHighlightField;
		this.highlightValue = newHighlightValue;
		//Identify.highlightLayer = newHighlightLayer;
		//Identify.highlightField = newHighlightField;
		//Identify.highlightValue = newHighlightValue;

		this.refresh();
	}
}
MapObject.prototype.reset = function() {
	Identify.hide(); // hide the identify box; if this line is removed, don't forget to re-position the identify box to match the new extents
	ZoomMarker.moveToNewLocation(this.initE, this.initN, this.initScale);

}
MapObject.prototype.getExtent = function() {
	var env = new EnvelopeObject();
	env.minx = this.e - ((this.width  * this.scale) / 2);
	env.maxx = this.e + ((this.width  * this.scale) / 2);
	env.miny = this.n - ((this.height * this.scale) / 2);
	env.maxy = this.n + ((this.height * this.scale) / 2);
	return env;
}
MapObject.prototype.clearImage = function() {
	this.divCurr.childNodes[0].src = "Map/images/transparent.gif";
}
MapObject.prototype.refresh = function() {
	this.swapPrevCurrNext();
	this.divCurr.childNodes[0].style.marginTop  = "0px";
	this.divCurr.childNodes[0].style.marginLeft = "0px";
	this.gLastImageSize.w = this.width;
	this.gLastImageSize.h = this.height;
	var testW = this.width;
	
	var layers = layerList.serialiseVisible();
	var layers1 = layerList.serialiseIdentify();
  //  alert(layers + '/r/n' + layers1);
    
    this.divCurr.childNodes[0].src = this.strMapCall();
    
	Overview.updateOverview();
	Identify.identifyWholeMap();
	var pnt = new CoordsMap(this.e,this.n);
	
	this.largeMapUrl();
	this.hidInitE.value = this.e; //document.getElementById(userControlMapText().toString() + "hidInitialEasting").value = this.e;
	this.hidInitN.value =  this.n;
	this.hidInitMpp.value =  this.scale;

    
}

MapObject.prototype.strMapCall = function() {

        var mapCall = "";
        var searchValue = "";
        if(RouteSearch.txtRouteSearch != null){
            searchValue = encodeURIComponent(RouteSearch.txtRouteSearch.value);
        }
       
        mapCall = "Map/MapImage.ashx"+  
        "?w="+this.width+  
        "&h="+this.height+  
        "&e="+this.e+  
        "&n="+this.n+  
        "&mpp="+this.scale+  
        "&layers="+layerList.serialiseVisible()+  
        "&hLayer="+this.highlightLayer+  
        "&hField="+this.highlightField+  
        "&hValue="+this.highlightValue+  
        "&thematicId="+this.thematicId + 
        "&mapCategory="+this.mapCategory + 
        "&mapRegion="+this.mapRegion + 
        "&refNum="+this.mapRefNum + 
        "&isLargeMap="+this.isLargeMap;
        if(EventFilter.filter)
        {
             mapCall += "&eventStartDate="+encodeURIComponent(EventFilter.strStartDate()) +
             "&eventEndDate="+encodeURIComponent(EventFilter.strEndDate());
        }
        if(RouteSearch.routeFilter)
        {
            //mapCall += "&routeSearchTxt="+encodeURIComponent(RouteSearch.txtRouteSearch.value);
            mapCall += "&routeFilter=true" + 
            "&routeSearchTxt="+searchValue;
        }
        return mapCall;

}

//sets the large map url
MapObject.prototype.largeMapUrl = function() {
    
    var strPage = "LargeMap.aspx?";
    
    var searchValue = "";
    if(RouteSearch.txtRouteSearch != null){
        searchValue = encodeURIComponent(RouteSearch.txtRouteSearch.value);
    }
    
    var strQuery = "region="+this.mapRegion + 
        "&e="+this.e+  
        "&n="+this.n+  
        "&mpp="+this.scale+  
        "&mapCategory="+this.mapCategory + 
        "&refNum="+this.mapRefNum;
        if(!this.mapIsTheme) {
            strQuery += "&layers="+layerList.serialiseIdentify();
        }
        else{
            strQuery += "&thematicId="+this.thematicId;
        }        
        if(RouteSearch.routeFilter)
        {
            strQuery += "&routeSearchTxt="+searchValue;
        }
   // this.hrefLargeMap.href = strPage + strQuery;
    this.hrefLargeMap1 = strPage + strQuery;
}

//opens the large map url in a new window.
MapObject.prototype.openLargeMapUrl = function() {
    window.open(this.hrefLargeMap1,"mywindow","status=1,width=1000,height=750");
}

//opens the large map url in existing window.
MapObject.prototype.openhrefMapBack = function() {
    window.open(this.hrefMapBack.href, "_self");
}

//opens the large map url in existing window.
MapObject.prototype.openMapStart = function() {
    window.open("Default.aspx?region=" + Map.mapRegion + 
                                "&page=Home" + 
                                "&e=" + Map.hidMapBackE.value +
                                "&n=" + Map.hidMapBackN.value + 
                                "&mpp=" + Map.hidMapBackMpp.value +
                                "&mapCategory=" + Map.mapCategory, "_self");
}

//Called via Search button only - all other map moves call standard Map.refresh function but checks search variable
MapObject.prototype.refreshToExtent = function(env) {
    //this.swapPrevCurrNext();
	this.divCurr.childNodes[0].style.marginTop  = "0px";
	this.divCurr.childNodes[0].style.marginLeft = "0px";
	this.gLastImageSize.w = this.width;
	this.gLastImageSize.h = this.height;	
	//Set Search flag to true
	this.RS = true;
	layerList.activateSearchLayers();
	//Set Search flag to false
	this.RS = false;
	this.divCurr.childNodes[0].src = this.strMapCall();	
	Overview.updateOverview();	
	Identify.identifyWholeMap();	
	//Identify.identifyWholeMapJS(env);
	var pnt = new CoordsMap(this.e,this.n);
    this.hidInitE.value = this.e;
	this.hidInitN.value = this.n;
	this.hidInitMpp.value = this.scale;    
}

MapObject.prototype.refreshForZoomBox = function() {
	this.divCurr.childNodes[0].style.marginTop  = "0px";
	this.divCurr.childNodes[0].style.marginLeft = "0px";
	this.gLastImageSize.w = this.width;
	this.gLastImageSize.h = this.height;
	
	this.divCurr.childNodes[0].src = this.strMapCall();
	
	//swapPrevCurrNext is called after the new image is generated when using the zoom box.  This is because the old(prev) map view remains
	//visible while the new one is loaded.  when the zoom box is used the map has to be recentred which makes the swapping of map images
	//flicker.

	this.swapPrevCurrNext();
	
	Overview.updateOverview();
	Identify.identifyWholeMap();
	var pnt = new CoordsMap(this.e,this.n);
	
	this.hidInitE.value = this.e; //document.getElementById(userControlMapText().toString() + "hidInitialEasting").value = this.e;
	this.hidInitN.value =  this.n;
	this.hidInitMpp.value =  this.scale;
}
MapObject.prototype.swapPrevCurrNextForZoomBox = function() {
// Swaps: the current map image is sent back to divPrev; it is left visible.
	var tmp = this.divPrev;
	this.divPrev = this.divCurr;
	this.divCurr = this.divOlde;
	this.divOlde = tmp;
	tmp = null;
	this.divCurr.style.zIndex = 4;
	this.divPrev.style.zIndex = 3;
	this.divOlde.style.zIndex = 2;
	this.divOlde.childNodes[0].src = "Map/Images/transparent.gif"; // hide image before last
	this.divOlde.style.visibility = "hidden";
	this.divOlde.childNodes[0].style.marginLeft = "";
	this.divOlde.childNodes[0].style.marginTop = "";
	this.divOlde.childNodes[0].style.width  = this.width  + "px";
	this.divOlde.childNodes[0].style.height = this.height + "px";

	this.divCurr.style.visibility = "";
	this.divCurr.childNodes[0].style.width  = this.divCurr.style.width;
	this.divCurr.childNodes[0].style.height = this.divCurr.style.height;
	this.divLoad.style.display = "block";}

MapObject.prototype.updateGridRef = function(point,bMoving) {
	
//	var gr = document.getElementById("divGridRef");
//	if (point != null) {
//		if (!bMoving) {
//			var coords = point.ToMapCoords();
//			var gref = coords.getGridRef();
//			gr.innerHTML = "Grid ref: " + gref;//coords.e + "," + coords.n;
//		} else {
//			//gr.innerHTML = "(moving)";
//		}
//	} else {
//		gr.innerHTML = "&nbsp;";
//	}
}


MapObject.prototype.loadStepOne = function() {
	this.mapWrap = document.getElementById(userControlMapText().toString() + "divMapContainer");
	this.divCurr = document.getElementById("divMap1");
	this.divPrev = document.getElementById("divMap2");
	this.divOlde = document.getElementById("divMap3");
	this.divInfo = document.getElementById("bubble_box");
	this.divLoad = document.getElementById("divLoad");
    
    this.initE = parseFloat(this.hidInitE.value);
	this.initN = parseFloat(this.hidInitN.value);
	this.initScale = parseFloat(this.hidInitMpp.value);
	
	this.e = parseFloat(this.hidInitE.value);
	this.n = parseFloat(this.hidInitN.value);
	this.scale = parseFloat(this.hidInitMpp.value);
	
	this.hidInitHLayer = document.getElementById(userControlMapText().toString() + "hidInitialHLayer");
	this.hidInitHField = document.getElementById(userControlMapText().toString() + "hidInitialHField");
	//this.hidInitHValue
	
	this.highlightLayer = this.hidInitHLayer.value;//document.getElementById(userControlMapText().toString() + "hidInitialHLayer").value;
	this.highlightField = this.hidInitHField.value;
	this.highlightValue = this.hidInitHValue.value;
    
    this.thematicId = this.hidThematicId.value;
    this.mapIsTheme = this.thematicId > 0;
    this.hidRouteSearchTxt = document.getElementById(userControlMapText().toString() + "hidRouteSearchTxt");
    
    this.mapCategory = this.hidInitMapCategory.value;
    this.mapRegion = this.hidInitMapRegion.value;
    this.mapRefNum = this.hidMapRefNum.value;
    this.mapIsRoute = this.mapRefNum.length > 0;
    this.mapOverview = this.hidOverview.value; //string of overview map settings
    
    this.mapLayerCatDetails = document.getElementById(userControlMapText().toString() + "divMapLayerCatDetails");
    this.mapLayerCatDetails.onmouseover	= mapLayerDivMouseOver;
    this.mapLayerCatDetails.onmouseout = mapLayerDivMouseOut;
    
	this.mapWrap.onmousedown = mapMouseDown;
	this.mapWrap.onmousemove = mapMouseMove;
	this.mapWrap.onmouseup   = mapMouseUp;
	this.mapWrap.onmouseout  = mapMouseOut;
	this.mapWrap.onmouseover  = mapMouseOver;

    this.hidIsLargeMap = document.getElementById(userControlMapText().toString() + "hidLargeMap"); 
    if(this.hidIsLargeMap.value == "True")
    {
        this.isLargeMap = true;    
		document.getElementById('map_box_top').style.display = 'none';
		this.mapOverview = ""; //remove overview map settings.
    }
    else
    {
        this.isLargeMap = false;
    }
    
    this.hrefLargeMap = document.getElementById("hrefLargeMap");
    this.hrefLargeMap1 = "";
    this.hrefMapBack = document.getElementById("hrefMapBack");
	// Set the window resize event
	window.onresize = Map_waitForResize; // works in FFX and IE 
	document.body.onresize = Map_waitForResize; // only works in IE

}
MapObject.prototype.loadStepTwo = function() {
	this.scale = ZoomMarker.cleanDirtyScale(this.scale);
	this.setMapSize();
	this.bLoading = false;
}


MapObject.prototype.loadStepThree = function()
{
    this.mapLayerCatDetails.style.display = '';
    
    var pageForm = document.aspnetForm;
    if(pageForm.findRb != null)
    {
        var len = pageForm.findRb.length;

        for (i = 0; i <len; i++) {
            if (pageForm.findRb[i].checked) 
            {
                pageForm.findRb[i].checked = false;
               // alert(chosen);
                break;
            }
        }
    }
                   
    //this.hrefMapBack.style.display = "none";
    
    layerList.showInitialMapLayers();

    if(this.isLargeMap){
     if(this.mapIsTheme || this.mapIsRoute)RouteSearch.divSearchArea.style.visibility = "hidden";
    
    }                 
    
    //Map is new, no layerlist needed... usually default / home page
    if(this.mapCategory.toLowerCase() == "undefined" || this.mapCategory == "")
    {   
        this.mapLayerCatDetails.style.visibility = "hidden";
        
        if(!this.isLargeMap)MapInfoBox.checkInfoBoxCookie();
        
        return;        
    }
    else
    {
        
        //The map category has been passed in querystring.
        RouteSearch.setSelectedSearchOption(this.mapCategory)
        if(Map.mapIsTheme)
        {
            showDCEProducts();
            var newExtent = Map.getExtent();
            
            Map.refreshToExtent(newExtent);
            return;
        }

        if(this.mapIsRoute)
        {
            //this.hrefMapBack.style.display = '';
           
            this.setMapBackHref();
            this.mapLayerCatDetails.style.visibility = "visible";
            showDCEProducts();
            
        }
        else
        {     
            this.mapLayerCatDetails.style.visibility = "hidden";

            //Values passed along the query string.  Show the layer list and corresponding map category options
            if(this.hidRouteSearchTxt.value.length > 0)
            {
                RouteSearch.txtRouteSearch.value = this.hidRouteSearchTxt.value;
            }
            this.mapLayerCatDetails.style.visibility = "visible";

            //search for routes/ or map category which shows the layer list (walking/riding/cycling etc...)
            RouteSearch.searchForRoutes(); 
            
            return; 
        }
            
        
    }
}

MapObject.prototype.setMapBackHref = function() {

    if(Map.hidMapBackE.value != "0")
    {
     this.hrefMapBack.href = "Default.aspx?region=" + Map.mapRegion + 
                                "&page=Home" + 
                                "&e=" + Map.hidMapBackE.value +
                                "&n=" + Map.hidMapBackN.value + 
                                "&mpp=" + Map.hidMapBackMpp.value +
                                "&mapCategory=" + Map.mapCategory +
                                "&layers=" + Map.hidMapBackLayers.value; 
                                
                                if (Map.hidMapBackSearchTxt.value != "")
                                {
 	                                this.hrefMapBack.href += "&routeFilter=true" + 
 	                                "&routeSearchTxt="+Map.hidMapBackSearchTxt.value;
	                            }
	                                else
	                            {
	                                this.hrefMapBack.href +=  "&routeFilter=false";
	                            }
    }
    else
    {
        this.hrefMapBack.href = "Default.aspx?region=" + Map.mapRegion + 
                                "&page=Home"
    }
     //this.hrefMapBack.href = left(this.hrefMapBack.href, this.hrefMapBack.href.length - 1);
}

MapObject.prototype.setMapSize = function() {
	var blnSetDimensions;
	if(this.isLargeMap)
	{
	    blnSetDimensions = this.setDimensionsLargeMap();
	}
	else
	{
	    blnSetDimensions = this.setDimensions();
	}
	
	if (!blnSetDimensions) return;
	this.refresh();
}

MapObject.prototype.setDimensionsLargeMap = function() {
	var oldW = Map.width;
	var oldH = Map.height;
	var windowW, windowH;
	var adjustW, adjustH;
	var dthAdjust;
	if (self.innerWidth)
	{
		// FireFox
		windowW = self.innerWidth;
		windowH = self.innerHeight;
		adjustW = 470;
		adjustH = 128;
		dthAdjust = 27;
	}
	else if (document.documentElement && document.documentElement.clientWidth)
	{
		// IE6+ (standards mode)
		windowW = document.documentElement.clientWidth;
		windowH = document.documentElement.clientHeight;
		adjustW = 215;
		adjustH = 7;
		dthAdjust = 25;
	}
	else if (document.body)
	{
		// IE5.5-, IE6 (quirks mode)
		windowW = document.body.clientWidth;
		windowH = document.body.clientHeight;
		adjustW = 492;
		adjustH = 103;
		dthAdjust = 25;
	} 
	else 
	{
		// unknown
		alert("This map may not work in your browser");
		windowW = -1;
		windowH = -1;
		adjustW = 0;
		adjustH = 0;
		dthAdjust = 0;
	}
	this.width  = windowW - adjustW; // adjust for table
	this.height = windowH - adjustH; // adjust for table
	var wMin = 200, hMin = 200; // minimums
	var wMax = 1024, hMax = 1024; // maximums
	if (this.width  < wMin)  this.width  = wMin;
	if (this.height < hMin)  this.height = hMin;
	if (this.width  > wMax)  this.width  = wMax;
	if (this.height > hMax)  this.height = hMax;
	
	document.getElementById('map_box').style.width = this.width + "px";
	document.getElementById('map_box').style.height = this.height + "px";
	var fullwidth = this.width + 179;
	
	
	if (oldW == this.width && oldH == this.height)
	{
		if (this.gLastImageSize.w==oldW && this.gLastImageSize.h==oldH)
			return false;
		else
			return true;
	} 
	else 
	{
		this.divPrev.style.width   = this.width  + "px";
		this.divPrev.style.height  = this.height + "px";
		this.divCurr.style.width   = this.width  + "px";
		this.divCurr.style.height  = this.height + "px";
		this.divOlde.style.width   = this.width  + "px";
		this.divOlde.style.height  = this.height + "px";
		this.mapWrap.style.width   = this.width  + "px";
		this.mapWrap.style.height  = this.height + "px";
		this.divLoad.childNodes[0].style.marginLeft = (Math.round(this.width  / 2) - 48) + "px";
		this.divLoad.childNodes[0].style.marginTop  = (Math.round(this.height / 2) - 22) + "px";
	//	Overview.setDimensions(this.width,this.height);
	//	var dthHeight = this.height - dthAdjust;
	//	this.dth.style.height = dthHeight + "px";// 300 by default
	//	this.dth16.style.height = (dthHeight+16) + "px"; // always +16 to hide horizontal scrollbar
		return true;
	}
}

MapObject.prototype.setDimensions = function() {
	var oldW = Map.width;
	var oldH = Map.height;
	var windowW, windowH;
	var mapW, mapH;

	if (self.innerWidth)
	{
		// FireFox
		windowW = self.innerWidth;
		windowH = self.innerHeight;
		mapW = windowW - 774;
		mapH = 505;
		this.mapIsFirefox = true;
	}
	else if (document.documentElement && document.documentElement.clientWidth)
	{
		// IE6+ (standards mode)
		windowW = document.documentElement.clientWidth;
		windowH = document.documentElement.clientHeight;
		mapW = windowW - 774;
		mapH = 453;
	}
	else if (document.body)
	{
		// IE5.5-, IE6 (quirks mode)
		windowW = document.body.clientWidth;
		windowH = document.body.clientHeight;
		mapW = 350;
		mapH = 453;
	} 
	else 
	{
		// unknown
		alert("This map may not work in your browser");
		windowW = -1;
		windowH = -1;
		mapW = 0;
		mapH = 0;
	}
	this.width  = 774; // adjust for table
	this.height = 362;
	
	if (oldW == this.width && oldH == this.height)
	{
		if (this.gLastImageSize.w==oldW && this.gLastImageSize.h==oldH)
			return false;
		else
			return true;
	} 
	else 
	{
		this.divPrev.style.width   = this.width  + "px";
		this.divPrev.style.height  = this.height + "px";
		this.divCurr.style.width   = this.width  + "px";
		this.divCurr.style.height  = this.height + "px";
		this.divOlde.style.width   = this.width  + "px";
		this.divOlde.style.height  = this.height + "px";
		this.mapWrap.style.width   = this.width  + "px";
		this.mapWrap.style.height  = this.height + "px";
		
	    document.getElementById("imgLoading").style.marginLeft = (Math.round(this.width  / 2) - 48) + "px";
	    document.getElementById("imgLoading").style.marginTop  = (Math.round(this.height / 2) - 22) + "px";
		Overview.setDimensions(this.width,this.height);

		return true;
	}
}
MapObject.prototype.panClick = function(dir) {
	if (this.bLoading) return false;
	this.bLoading = true;
	var midOffset = 0;
	var oldExtent = Map.getExtent();
	for (var i=0; i<dir.length; i++)
	{
		var dir2 = dir.substr(i,1);
		switch (dir2) {
			case "n": this.n += Math.round((this.height * this.scale) / 2); midOffset = Math.round(this.height / 2); break;
			case "s": this.n -= Math.round((this.height * this.scale) / 2); midOffset = Math.round(this.height / 2); break;
			case "e": this.e += Math.round((this.width  * this.scale) / 2); midOffset = Math.round(this.width  / 2); break;
			case "w": this.e -= Math.round((this.width  * this.scale) / 2); midOffset = Math.round(this.width  / 2); break;
		}
	}
	Identify.repositionForScale(this.scale, oldExtent);
	this.gSlideDirection = dir;
	this.refresh();
	for (var i=0; i<dir.length; i++)
	{
		var dir2 = dir.substr(i,1);
		switch (dir2) {
			case "n": this.divCurr.childNodes[0].style.marginTop  = (-1*midOffset) + "px"; break;
			case "s": this.divCurr.childNodes[0].style.marginTop  =     midOffset  + "px"; break;
			case "e": this.divCurr.childNodes[0].style.marginLeft =     midOffset  + "px"; break;
			case "w": this.divCurr.childNodes[0].style.marginLeft = (-1*midOffset) + "px"; break;
		}
	}
	window.setTimeout(Map_slideAlong,10);
}
MapObject.prototype.slideAlong = function() {
	var midOffset;
	for (var i=0; i<this.gSlideDirection.length; i++)
	{
		var dir2 = this.gSlideDirection.substr(i,1);
		switch (dir2) {
			case "n":
			case "s": midOffset = Math.round(Map.height/2); break;
			case "e":
			case "w": midOffset = Math.round(Map.width/2); break;
		}
	}
	if (this.gSlideOffset >= midOffset) {
		this.gSlideOffset = 0;
		this.bLoading = false;
	} else {
		this.gSlideOffset += 10;
		if (this.gSlideOffset > midOffset)  this.gSlideOffset = midOffset; // limit to maximum movement (half-map)
		for (var i=0; i<this.gSlideDirection.length; i++)
		{
			var dir2 = this.gSlideDirection.substr(i,1);
			switch (dir2) {
				case "n": 
					this.divPrev.childNodes[0].style.marginTop = this.gSlideOffset + "px";
					this.divCurr.childNodes[0].style.marginTop = (-1 * (midOffset - this.gSlideOffset)) + "px";
					break;
				case "s": 
					this.divPrev.childNodes[0].style.marginTop = (-1 * this.gSlideOffset) + "px";
					this.divCurr.childNodes[0].style.marginTop = (midOffset - this.gSlideOffset) + "px";
					break;
				case "e":
					this.divPrev.childNodes[0].style.marginLeft = (-1 * this.gSlideOffset) + "px";
					this.divCurr.childNodes[0].style.marginLeft = (midOffset - this.gSlideOffset) + "px";
					break;
				case "w":
					this.divPrev.childNodes[0].style.marginLeft = this.gSlideOffset + "px";
					this.divCurr.childNodes[0].style.marginLeft = (-1 * (midOffset - this.gSlideOffset)) + "px";
					break;
			}
		}
		window.setTimeout(Map_slideAlong,10);
	}
}
MapObject.prototype.swapPrevCurrNext = function() {
	// Swaps: the current map image is sent back to divPrev; it is left visible.
	var tmp = this.divPrev;
	this.divPrev = this.divCurr;
	this.divCurr = this.divOlde;
	this.divOlde = tmp;
	tmp = null;
	this.divCurr.style.zIndex = 4;
	this.divPrev.style.zIndex = 3;
	this.divOlde.style.zIndex = 2;
	    
	this.divOlde.childNodes[0].src = "Map/images/transparent.gif"; // hide image before last
	this.divOlde.style.visibility = "hidden";
	this.divOlde.childNodes[0].style.marginLeft = "";
	this.divOlde.childNodes[0].style.marginTop = "";
	this.divOlde.childNodes[0].style.width  = this.width  + "px";
	this.divOlde.childNodes[0].style.height = this.height + "px";
	
	this.divCurr.style.visibility = "";
	this.divCurr.childNodes[0].style.width  = this.divCurr.style.width;
	this.divCurr.childNodes[0].style.height = this.divCurr.style.height;
	this.divLoad.style.display = "block";
}
MapObject.prototype.waitForResize = function() {
	if (this.resizeWaitId !== false)
		window.clearTimeout(this.resizeWaitId);
	this.setDimensions();
	this.resizeWaitId = window.setTimeout(Map_setMapSize,500);
}
function map_SmoothZoomInStep(ratio, diffOldNew, isStarting) {
	if (arguments.length == 3)  { // isStarting
		Map.smoothZoomDirection = 1;
		Map.smoothZoomFactor = 1;
		Map.smoothZoomRatio = ratio; // usually 2.0, sometimes 2.5
		Map.smoothZoomShift = diffOldNew; // the difference in pixels between the starting center-point and the ending center-point (not necessarily the same if we are zooming in to a flag)
	}
	Map.smoothZoomFactor += (Map.smoothZoomRatio / 20); // increase from 1.0 to 2.0 in steps of 0.1
	Map.divPrev.childNodes[0].style.marginLeft = 
		  Math.round(Map.smoothZoomShift.x * (Map.smoothZoomFactor - 1) * 2) 
		+ Math.round(0 - (Map.width  * (Map.smoothZoomFactor - 1)) / 2) 
		+ "px";
	Map.divPrev.childNodes[0].style.marginTop  = 
		  Math.round(Map.smoothZoomShift.y * (Map.smoothZoomFactor - 1) * 2) 
		+ Math.round(0 - (Map.height * (Map.smoothZoomFactor - 1)) / 2) 
		+ "px";
	//Map.divPrev.childNodes[0].style.zoom = Map.smoothZoomFactor;
	Map.divPrev.childNodes[0].style.width  = Math.round(Map.width  * Map.smoothZoomFactor) + "px";
	Map.divPrev.childNodes[0].style.height = Math.round(Map.height * Map.smoothZoomFactor) + "px";
	if (Map.smoothZoomFactor < Map.smoothZoomRatio && Map.smoothZoomDirection == 1) {
		window.setTimeout(map_SmoothZoomInStep,12);
	} else {
		Map.smoothZoomDirection = 0;
		Map.smoothZoomFactor = 1;
		Map.smoothZoomRatio = 1;
	}
}
function map_SmoothZoomOutStep(ratio, starting) {
	if (arguments.length == 2)  { // starting
		Map.smoothZoomDirection = -1;
		Map.smoothZoomFactor = 1;
		Map.smoothZoomRatio = ratio;
	}
	Map.smoothZoomFactor -= (Map.smoothZoomRatio / 10);
	Map.divPrev.childNodes[0].style.marginLeft = Math.round((Map.width * (1-Map.smoothZoomFactor)) / 2) + "px";
	Map.divPrev.childNodes[0].style.marginTop = Math.round((Map.height * (1-Map.smoothZoomFactor)) / 2) + "px";
	//Map.divPrev.childNodes[0].style.zoom = Map.smoothZoomFactor; // using style Width/Height instead of Zoom
	Map.divPrev.childNodes[0].style.width  = Math.round(Map.width  * Map.smoothZoomFactor) + "px";
	Map.divPrev.childNodes[0].style.height = Math.round(Map.height * Map.smoothZoomFactor) + "px";
	if (Map.smoothZoomFactor > Map.smoothZoomRatio && Map.smoothZoomDirection == -1) {
		window.setTimeout(map_SmoothZoomOutStep,15);
	} else {
		Map.smoothZoomDirection = 0;
		Map.smoothZoomFactor = 1;
	}
}



// ================== IMapArea STUFF =============
// Image map area object.  Data container for area values and 
// can be returned as a new html element.
// =================================================
function IMapArea(id,href,title,shape,coords,i,j)
{
    this.id = id;
    this.href = href;
    this.title = title;
    this.shape = shape;
    this.coords = coords;

    this.onClick = "return alert('hello');";//);strOnClick;
    this.layerIndex = i;
    this.featureIndex = j;
}
//returns an HTML image map area which can be apended to the image map.
//Currently not used as not working for Firefox.
IMapArea.prototype.toImageMapArea = function()
{

    var newArea = document.createElement("AREA");
    newArea.id = this.id;
    //newArea.href = "#";//"javascript:;";//this.href;
    newArea.title = this.title;
    newArea.shape = this.shape;
    newArea.coords = this.coords;
    newArea.onmouseover = cursorPoint;
    newArea.onmouseout = cursorDefault;
    var strFeat = this.featureIndex;
    var strLayer = this.layerIndex;

    if (window.attachEvent) 
    {
            newArea.attachEvent('onclick',
                                function() { 
                                        Identify.RenderSingleFeature('this',strLayer,strFeat);
                                        }
                                        );
    } 
    else 
    { 
            
            newArea.addEventListener('onclick',
                                        function() { 
                                        Identify.RenderSingleFeature('this',strLayer,strFeat);
                                        },
                                        false);
    }
        
    return newArea;
}
function cursorPoint()
{
    Map.mapWrap.style.cursor = "pointer";
}
function cursorDefault()
{
    Map.mapWrap.style.cursor = Map.cursorGrab;
}

IMapArea.prototype.cursorPoint = function()
{
    Map.mapWrap.style.cursor = "pointer";
}
IMapArea.prototype.cursorDefault = function()
{
    Map.mapWrap.style.cursor = Map.cursorGrab;
}

// End of IMapArea

// ================== IMapObject STUFF =============
// Map Image map object.  Controls and manages the image map 
// created over the map.  this provides hyperlinks for the map pins
// =================================================
function IMapObject()
{
    this.imageMap = document.getElementById("imageMap1");
    this.rectHalfWidth = 12; //pixel width of image map rectangle over map point.
    this.rectHalfHeight = 20; //pixel height of image map rectangle over map point.
    this.yCorrection = 15; //corrects the Y axis coordinate for image map areas.
}

IMapObject.prototype.removeAreas = function()
{
    var arrChilds = this.imageMap.childNodes;
    var intCount = arrChilds.length;
    
    this.imageMap.innerHTML = "";
}

IMapObject.prototype.appendAreas = function(iMapAreaCollection)
{
    var imc = iMapAreaCollection;
    var intLength = imc.length;
    var strFeat = "";
    var strLayer = "";

    var newArea = null;
    var s = "";
    for(var i=0; i < intLength; i++)
    {   
        var objArea = imc[i];
            
            s += "<AREA href=\"javascript:;\" id=" + imc[i].id + " coords=" + imc[i].coords+ " title=\"" + imc[i].title +  "\"  " + 
            " onmouseover=\"cursorPoint()\" shape=\"RECT\" onmouseout=\"cursorDefault()\" " +
            "onclick=\"return Identify.RenderSingleFeature(this," + imc[i].layerIndex + "," + imc[i].featureIndex + ");\">" + 
            "</AREA>";
	}
	 this.imageMap.innerHTML = s;
}

IMapObject.prototype.createRectangleFromCoords = function (e,n)
{
    var cm = new CoordsMap(e,n);
	var cs = cm.ToScreenPoint();
	var y = cs.y - this.yCorrection;
	
    var strRect = (cs.x - this.rectHalfWidth).toString() + "," + (y - this.rectHalfHeight).toString() +
    "," + (cs.x + this.rectHalfWidth).toString() + "," + (y + this.rectHalfHeight).toString();
    return strRect;
}

//=========================== End of IMapObject


// ZoomMarkerObject is used to control the zoom markers / sliders; 
// it is also used to zoom the map.
// Any changes to the scale should be done via this object, not via tha Map object;
// this object will adjust the Map object as required.
function ZoomMarkerObject() {
	this.notchIndex = 0;
	this.previousNotchIndex = 0;
	this.clickedNotchIndex = 0;
	this.moving = false;
	this.divMarker = document.getElementById("divMarker");
	this.divZoomBarWhole = document.getElementById("divZoomBarWhole");
	this.notchHeight = 8; // each notch is 8px tall
	this.scales = new Array(160,80,50,25,10,5,2,1,0.635,0.3175,0.15875);
	this.friendlyScales = new Array(600000,300000,200000,100000,40000,20000,7560,3780,2400,1200,600);
	this.initialise(Map.scale);
}
// Private method
ZoomMarkerObject.prototype.zoomToCurrentNotch = function(bClearMap) {
	// bClearMap decides whether to clear the current image;
	// basically this should be true for all zooms except the smooth zooms
	var oldScale = Map.scale;
	var newScale = this.scales[this.notchIndex];
	// when zooming in, zoom in to flag

	var oldExtent = Map.getExtent();
	Map.scale = newScale;
	Identify.repositionForScale(oldScale, oldExtent);
	
	if (bClearMap) {
		Map.clearImage();
	}
	Map.refresh();
}	
// Private method
ZoomMarkerObject.prototype.moveNotchToIndex = function(newIndex) {
	this.divMarker.style.marginTop = (169 - (this.notchHeight * newIndex)) + "px";
	this.divMarker.firstChild.alt = "Scale is 1:" + this.friendlyScales[newIndex];
	this.notchIndex = newIndex;
}
// Public method
ZoomMarkerObject.prototype.initialise = function(newScale) {
	// find the index of this new scale, erring on the side of higher scales; e.g. mNTS(60) will move to 100
	var i;
	for (i=0; i<this.scales.length; i++)
	{
		if (newScale >= this.scales[i]) break;
	}
	if (i == this.scales.length) i--;
	this.moveNotchToIndex(i);
}
// Public method
ZoomMarkerObject.prototype.mClick = function(ix) {
	if (ix != this.notchIndex) {
		this.moveNotchToIndex(ix);
		this.zoomToCurrentNotch(true);
	}
	return false;
}
// Public method
ZoomMarkerObject.prototype.mDown = function(evt,ix) {
	var e = (window.event) ? window.event : evt;
	this.previousNotchIndex = this.notchIndex;
	if (ix != this.notchIndex) {
		this.moveNotchToIndex(ix);
	}
	this.clickedNotchIndex = this.notchIndex;
	this.moving = true;
	Mouse.start(e);
	return false;
}
// Public method
ZoomMarkerObject.prototype.mMove = function(evt) {
	if (!this.moving) return false;
	var e = (window.event) ? window.event : evt;
	var shift = Mouse.getShift(e);
	var newIndex = this.clickedNotchIndex + Math.round(shift.x/this.notchWidth);
	if (newIndex < 0) newIndex = 0;
	if (newIndex >= this.scales.length)  newIndex = this.scales.length-1;
	if (newIndex != this.notchIndex) {
		this.moveNotchToIndex(newIndex);
	}
	return false;
}
// Public method
ZoomMarkerObject.prototype.mUp = function(evt) {
	if (!this.moving) return false;
	this.mMove(evt); // one last move
	var e = (window.event) ? window.event : evt;
	this.moving = false;
	if (this.notchIndex != this.previousNotchIndex) {
		this.zoomToCurrentNotch(true);
	}
	return false;
}
// Public method
ZoomMarkerObject.prototype.mOut = function(evt) {
	if (!this.moving) return false;
	var e = (window.event) ? window.event : evt;
	var ToRelatedTarget = e.toElement;
	var nn = "" + ToRelatedTarget.nodeName; // make sure it's a string
	if (nn.toUpperCase() != "IMG") {
		this.moving = false;
		this.moveNotchToIndex( this.previousNotchIndex ); // revert to original
	}
	return false;
}
// Public method
ZoomMarkerObject.prototype.zoomIn = function() {
	if (this.notchIndex == this.scales.length-1) {
		alert("You can't zoom in any further");
	} else {
		var curScale = this.scales[this.notchIndex];
		
		this.moveNotchToIndex(this.notchIndex+1);
		var newScale = this.scales[this.notchIndex];
	//	window.status = curScale + " : " +newScale;
	
		this.zoomToCurrentNotch(false); // this call sometimes changes Map.e and Map.n
		
		var newPoint = (new CoordsMap(Map.e, Map.n)).ToScreenPoint();
		
		var diffOldNew = new CoordsScreen(0,0);
		var ratio = curScale/newScale;
		map_SmoothZoomInStep(ratio, diffOldNew, true);
	}
	return false;
}
// Public method
ZoomMarkerObject.prototype.zoomOut = function() {
	if(Map.isLargeMap)
	{
	    if (this.notchIndex == 1) {
		alert("You can't zoom out any further");	  
    	return false;
		  
	    }
	}
	if (this.notchIndex == 0) {
		alert("You can't zoom out any further");
	} else {
		var curScale = this.scales[this.notchIndex];
		this.moveNotchToIndex(this.notchIndex-1);
		var newScale = this.scales[this.notchIndex];
		this.zoomToCurrentNotch(false);
		var ratio = curScale/newScale;
		map_SmoothZoomOutStep(ratio, true);
	}
	return false;
}
// Public method
ZoomMarkerObject.prototype.cleanDirtyScale = function(newScale) {
	// find the index of this new scale, erring on the side of higher scales; e.g. mNTS(60) will move to 100
	var i;
	for (i=this.scales.length-1; i>0; i--)
	{
		if (newScale <= this.scales[i]) return this.scales[i];
	}
	return this.scales[i];
}
// Public method
ZoomMarkerObject.prototype.zoomToDirtyScale = function(newScale) {
	// find the index of this new scale, erring on the side of higher scales; e.g. mNTS(60) will move to 100
	var i;
	for (i=0; i<this.scales.length; i++)
	{
		if (newScale >= this.scales[i]) break;
	}
	if (i == this.scales.length) i--;
	this.moveNotchToIndex(i);
	this.zoomToCurrentNotch(true);
}
// Public method
ZoomMarkerObject.prototype.moveToNewLocation = function(newE, newN, newScale) {
	// find the index of this new scale, erring on the side of higher scales; e.g. mNTS(60) will move to 80
	var i;
	for (i=0; i<this.scales.length-1; i++)
	{
		if (newScale >= this.scales[i]) break;
	}
	//if (i!=0) i--; // remove this line to err on the side of lower scales
	Map.e = newE;
	Map.n = newN;

	this.moveNotchToIndex(i);
	this.zoomToCurrentNotch(true, true);
	return false;
}
ZoomMarkerObject.prototype.mt = ZoomMarkerObject.prototype.moveToNewLocation; // short name
// END OF ZoomMarkerObject



// ================== PAGEINFO STUFF =============
//Handy for screen width details.  
function PageInfoObject()
{

    this.screen= null;
	this.divContainer = null;
	this.divContainerWidth =null;
    this.divContainerOffsetDOM = null;
    this.divContainerOffset = null;
    this.diff = 0;
    this.registerResizeEvent();
}

PageInfoObject.prototype.loadPageInfo = function() 
{
	this.containerOffset = null;
	this.divContainer = document.getElementById("container");
	this.divContainerOffsetDOM = this.divContainer.offsetLeft;
    this.diff = 112;
}


PageInfoObject.prototype.registerResizeEvent = function() 
{
       	 if (window.attachEvent) 
        {
                window.attachEvent("onresize",function() {PageInfo.resizeEvent()});
        } 
        else 
        { 
                window.addEventListener("resize",function() {PageInfo.resizeEvent()},false);
        }
        
        return false;
        
}        
//function resizeEvent() 
PageInfoObject.prototype.resizeEvent = function() 
{
    //hide the popup box
    Identify.clearSelection();
}


PageInfoObject.prototype.adjustXforScreen = function(x) 
{
    this.divContainerOffset = parseInt((this.screenWidth() - this.divContainer.offsetWidth) / 2);
    if(this.divContainerOffset < 0)this.divContainerOffset = 0;
    //if(this.diff > this.divContainerOffset)
    //{
        x = x - (this.diff - this.divContainerOffset)
    //}
    return x ;    
}


PageInfoObject.prototype.screenWidth = function() 
{
    return document.body.clientWidth;
}
// END of PageInfoObject

// ================== IDENTIFY STUFF =============

function IdentifyObject() {
	this.infoWin = document.getElementById("bubble_box"); // this object is used for positioning
	this.infoArrow = document.getElementById("infoArrow"); // this is the arrow of the box
	this.infoBody = document.getElementById("bubble_box_content").childNodes[0]; // this object is used for content
	this.curBG = ""; // current background image of infobox (four different options: high-arrow, mid-arrow, low-arrow, and none)

	// location of identify box
	this.hasContent = false;
	this.xml = null;
	this.hasArrow = true;
	this.point = new CoordsScreen(0,0);
	this.loading = false;
}
IdentifyObject.prototype.show = function() {
	this.hasContent = true;
	this.infoWin.style.display = "";
}
IdentifyObject.prototype.hide = function(bClearContent) {
	if (typeof(bClearContent) == "undefined") bClearContent = false;
	if (bClearContent)
		this.hasContent = false;
    this.innerHTML = "";
	this.infoWin.style.display = "none";
}
IdentifyObject.prototype.clearSelection = function() {
	this.hide();
	Map.highlightLayer = "";
	Map.highlightField = "";
	Map.highlightValue = "";
	Map.refresh();
}

IdentifyObject.prototype.clearSelectionRS = function() {
//as clearSelection but without the map refresh
	this.hide();
	Map.highlightLayer = "";
	Map.highlightField = "";
	Map.highlightValue = "";
}
IdentifyObject.prototype.isVisible = function() {
	return (this.infoWin.style.display == "none") ? false : true;
}
IdentifyObject.prototype.showSimpleMessageAtMapCoord = function(e,n,title,text) {
	// Translate map coords to screen point
	var cm = new CoordsMap(e,n);
	var cs = cm.ToScreenPoint();
	return this.showSimpleMessageAtScreenCoord(cs.x,cs.y,title,text);
}
IdentifyObject.prototype.showSimpleMessageAtScreenCoord = function(x,y,textTitle,textHTML) {
	var html = '<div class="infoTitle">' + textTitle + '</div><div class="infoText">' + textHTML + '</div>';
	this.showHtmlAtScreenCoord(x,y,html,true);
	return false;
}
IdentifyObject.prototype.showHtmlAtMapCoord = function(e,n,html,bHasArrow) {
	// Translate map coords to screen point
	var cm = new CoordsMap(e,n);
	var cs = cm.ToScreenPoint();
	var newX = PageInfo.adjustXforScreen(cs.x);
	return this.showHtmlAtScreenCoord(newX,cs.y,html,bHasArrow);
}
IdentifyObject.prototype.showHtmlAtScreenCoord = function(x,y,html,bHasArrow) {
	// Enforce min/max bounds
	x = parseInt(x);
	y = parseInt(y);
	if (x < 0) x = 5;
	if (y < 0) y = 5;
	if (x >= Map.width)  x = Map.width  - 10;
	if (y >= Map.height) y = Map.height - 10;
	// Set properties
	this.point.x = x;
	this.point.y = y;
	this.hasArrow = bHasArrow;
	this.setPosition(null);
	this.showHtml(html);
}
IdentifyObject.prototype.showHtml = function(html) {
		    //alert(html);
	if(html == "")
	{
	    this.hide();
	    return;
	}
	this.infoBody.innerHTML = html;
	this.show();
}



IdentifyObject.prototype.identifyPoint = function(pnt) {
	if (this.loading) return;
	this.loading = true;
	
	//newX used to adjust the left positioning of the info box if the window size is has been changed.
	var newX = PageInfo.adjustXforScreen(pnt.x);
	var ajax = new AJAXObject();
	
    var searchValue = "";
    if(RouteSearch.txtRouteSearch != null){
        searchValue = encodeURIComponent(RouteSearch.txtRouteSearch.value);
    }

    	
	var identifyUrl = "Map/IdentifyPoint.aspx?w="+Map.width+  "&h="+Map.height+  "&e="+Map.e+  "&n="+Map.n+  "&mpp="+Map.scale+  "&x="+pnt.x+  "&y="+pnt.y+  "&layers="+layerList.serialiseIdentify()+ "&thematicId="+Map.thematicId + "&rnd="+Math.random()+  "&mapCategory="+Map.mapCategory  +  "&mapRegion="+Map.mapRegion + "&routeFilter=false" + "&mapBackLayers="+layerList.serialiseIdentify()+ "&mapBackE="+Map.e + "&mapBackN="+Map.n + "&mapBackMpp="+Map.scale + "&mapBackSearchTxt="+searchValue;//this.strIdentifyCall();
	
	ajax.loadXMLDoc(identifyUrl, function() {
		if (ajax.req) {
			if (ajax.req.readyState == 4) {
				if (ajax.req.status == 200) { // only if "OK"
					var x = ajax.getXml();
	                Identify.showSimpleMessageAtScreenCoord(newX,pnt.y,"Loading details...",".....");
					Identify.RenderPointXml(x);
				} else {
					Identify.hide();
					var s = ajax.req.responseText;
					if (s.indexOf("<exception")!=-1) {
						var x = ajax.getXml();
						alert("An error occurred while retrieving the data. Please try again. \n(" + x.documentElement.childNodes[0].nodeValue + ")");
					} else {
						alert("An error occurred while retrieving the data. Please try again. (Unknown error)");
					}
				}
				Identify.loading = false;
			}
		}
	});
	return false;
}
IdentifyObject.prototype.identifyWholeMap = function() {
	// Calculate scale
	var commaScale = "" + (Map.scale * 4000);
	commaScale = commaScale.substring(0,commaScale.length-3) + "," + commaScale.substr(commaScale.length-3);
	//var scaleText = "Map is at scale 1:" + commaScale + "."; //<br />&nbsp;<br />\n ";

	// Only identify if some layers are selected
	var llsc = layerList.serialiseCounting();
	var llsd = layerList.serialiseDetail();
	var llzo = layerList.serialiseZoomOut();
	var llzi = layerList.serialiseZoomIn();
	
	if (llsc == "" && llsd == "") {
		return;
	}
	// Identify
	var identifyUrl = this.strIdentifyCall();
   
	//alert(identifyUrl);
	var ajax = new AJAXObject();
	ajax.loadXMLDoc(identifyUrl, function() {
		if (ajax.req) {
			if (ajax.req.readyState == 4) {
				if (ajax.req.status == 200) { // only if "OK" (status 200)
					Identify.xml = ajax.getXml();
					Identify.RenderWholeXml(Identify.xml);
				} else {
					var x = ajax.getXml();
					if (x != null) {
						if (x.documentElement != null) {
							if (x.documentElement.tagName == "exception") {
								if (x.documentElement.childNodes.length == 1)
									alert(x.documentElement.childNodes[0].nodeValue);
								else
									alert("x.documentElement.childNodes.length = " + x.documentElement.childNodes.length);
							} else {
								alert("An error occurred in retrieving data from the server. Please try again.");
							}
						} else {
							alert("An error occurred in retrieving data from the server.\n" + ajax.req.responseText);
						}
					} else {
						alert(ajax.req.responseText);
					}
				}
			}
		}
	});
}

IdentifyObject.prototype.strIdentifyCall= function() {
    var llsc = layerList.serialiseCounting();
    //llsc += ".RID1P";
	var llsd = layerList.serialiseDetail();
   
    var searchValue = "";
    if(RouteSearch.txtRouteSearch != null){
        searchValue = encodeURIComponent(RouteSearch.txtRouteSearch.value);
    }
   
	var identifyUrl = "Map/IdentifyWhole.aspx?w="+
	                    Map.width+  
	                    "&h="+Map.height+  
	                    "&e="+Map.e+  
	                    "&n="+Map.n+  
	                    "&mpp="+Map.scale+  
	                    "&layersCounting="+llsc+  
	                    "&layersDetail="+llsd+  
	                    "&rnd="+Math.random()+  
	                    "&mapCategory="+Map.mapCategory + 
	                    "&mapRegion="+Map.mapRegion + 
	                    "&thematicId="+Map.thematicId +
	                    "&mapIsRoute="+Map.mapIsRoute +
	                    "&mapBackLayers="+layerList.serialiseIdentify()+ 
	                    "&mapBackE="+Map.e + 
	                    "&mapBackN="+Map.n + 
	                    "&mapBackMpp="+Map.scale + 
	                    "&mapBackSearchTxt="+ searchValue;
	//alert(identifyUrl);                       
    if (RouteSearch.routeFilter)
    {
 	    identifyUrl += "&routeFilter=true" + 
 	    "&routeSearchTxt="+searchValue;
	}
	else
	{
	    identifyUrl +=  "&routeFilter=false";
	}
	if(EventFilter.filter)
    {
         identifyUrl += "&eventStartDate="+encodeURIComponent(EventFilter.strStartDate()) +
         "&eventEndDate="+encodeURIComponent(EventFilter.strEndDate());
    }
    return identifyUrl;
    
}



//Called via Search button only - all other map moves call standard identifyWholeMap but checks search variable
IdentifyObject.prototype.identifyWholeMapJS = function(env) {
	// Calculate scale
	var commaScale = "" + (Map.scale * 4000);
	commaScale = commaScale.substring(0,commaScale.length-3) + "," + commaScale.substr(commaScale.length-3);
	//var scaleText = "Map is at scale 1:" + commaScale + "."; //<br />&nbsp;<br />\n ";

	// Only identify if some layers are selected
	var llsc = layerList.serialiseCounting();
	var llsd = layerList.serialiseDetail();
	var llzo = layerList.serialiseZoomOut();
	var llzi = layerList.serialiseZoomIn();


	
	if (llsc == "" && llsd == "") {
		return;
	}
	// Identify
	//var identifyUrl = "IdentifyWhole.aspx?w="+Map.width+  "&h="+Map.height+  "&e="+Map.e+  "&n="+Map.n+  "&minx=0&maxx=0&miny=0&maxy=0&mpp="+Map.scale+ "&layersCounting="+llsc+  "&layersDetail="+llsd+  "&rnd="+Math.random();
	var identifyUrl = this.strIdentifyCall();
	
	var ajax = new AJAXObject();
	ajax.loadXMLDoc(identifyUrl, function() {
		if (ajax.req) {
			if (ajax.req.readyState == 4) {
				if (ajax.req.status == 200) { // only if "OK" (status 200)
					Identify.xml = ajax.getXml();
					Identify.RenderWholeXml(Identify.xml);
				} else {
					var x = ajax.getXml();
					if (x != null) {
						if (x.documentElement != null) {
							if (x.documentElement.tagName == "exception") {
								if (x.documentElement.childNodes.length == 1)
									alert(x.documentElement.childNodes[0].nodeValue);
								else
									alert("x.documentElement.childNodes.length = " + x.documentElement.childNodes.length);
							} else {
								alert("An error occurred in retrieving data from the server. Please try again.");
							}
						} else {
							alert("An error occurred in retrieving data from the server.\n" + ajax.req.responseText);
						}
					} else {
						alert(ajax.req.responseText);
					}
				}
			}
		}
	});
}


IdentifyObject.prototype.RenderWholeXml = function(x) {

        
    //Clear Imap.
    Imap.removeAreas();
    
	var time = x.documentElement.getAttribute("time");
	var layerNodes = x.documentElement.childNodes;
	    
    //Create new ImapArray for the mouse over image map.
	var IMapArray = new Array();
	for (var i=0; i<layerNodes.length; i++) {
		var layerNode = layerNodes[i];
		var id = layerNode.getAttribute("id");
		var name = layerNode.getAttribute("name");
		var detail = layerNode.getAttribute("detail");
		var featurecount = parseInt(layerNode.getAttribute("featurecount"));
		var spn = document.getElementById("spn_" + id);
		spn.innerHTML = "(" + featurecount + ")";
	    
	    //don't open the details div if no data, saves space on the small layerlist
	    var vd = document.getElementById("vd_" + id);
	    if(featurecount < 1){
	        if(vd != null){
	            vd.style.display = 'none';
	            var s = "";
	            s += "<br/>No results, change zoom level.";
	            spn.innerHTML = s;  
			    s = "";
	        }
	    }
	    else{
	        if(vd != null){
    	       vd.style.display = 'block';
	        }
	    }
		if (detail == "true") {
			var s = "";
			if (featurecount > 20) { // see FeatureManager.cs for hard-coded limit of 21 items
				
				if(featurecount < 101){
				    s += "<br/>More than 20 results, zoom in for details.";
				    var featureNodes1 = layerNode.childNodes;
				    for (var j=0; j<featureNodes1.length; j++) {
					    var featureNode1 = featureNodes1[j];
					    var minx1 = parseFloat(featureNode1.getAttribute("minx"));
					    var miny1 = parseFloat(featureNode1.getAttribute("miny"));
					    var lefttext1  = featureNode1.getAttribute("lefttext");
				        var areaId1 = "area" + i.toString() + "_" + j.toString() ;
				        var imapArea1 = new IMapArea(areaId1,
				                                    "#",
				                                    lefttext1,
				                                    "\'RECT\'", 
				                                    Imap.createRectangleFromCoords(minx1,miny1),
				                                    i.toString(),
				                                    j.toString()
				                                    );
				       IMapArray.push(imapArea1);
				    }
				}
			
				else{
				    s += "<br/>There are more than 100 results. Cannot create mouse hover info. zoom in for more details.";
				}
			    spn.innerHTML += s;  
			    s = "";
			} 
			else {
				var featureNodes = layerNode.childNodes;
				s = "";
				
				for (var j=0; j<featureNodes.length; j++) {
					var featureNode = featureNodes[j];
					var minx = parseFloat(featureNode.getAttribute("minx"));
					var miny = parseFloat(featureNode.getAttribute("miny"));
					var maxx = parseFloat(featureNode.getAttribute("maxx"));
					var maxy = parseFloat(featureNode.getAttribute("maxy"));
					var href = featureNode.getAttribute("href");
					var hLayer = layerNode.getAttribute("id");
					var hField = featureNode.getAttribute("hfield");
					var hValue = featureNode.getAttribute("hvalue");
					var centerX = (minx + maxx) / 2;
					var centerY = (miny + maxy) / 2;
					var lefttext  = featureNode.getAttribute("lefttext");
					var lefttextShort = this.shortenString(lefttext);
					//var righttext = featureNode.getAttribute("righttext");
					var style = "";
					if (hLayer == Map.highlightLayer && hField == Map.highlightField && hValue == Map.highlightValue) {
						style = 'style="background-color: #ffff00; font-style: italic;"';
					}
					s += "<li>";
					s += "<a href=\"javascript:;\" "+style+" title=\"" + lefttext + "\" "+style+" onclick=\"return Identify.RenderSingleFeature(this," + i + "," + j + ");\">" + lefttextShort + "</a>";
					s += "</li>";
                   // document.getElementById('divCurrCoords').innerHTML += j + ": " + centerX + "," + centerY +";" ;
				   var areaId = "area" + i.toString() + "_" + j.toString() ;
				   var imapArea = new IMapArea(areaId,
				                                "#",
				                                lefttext,
				                                "\'RECT\'", 
				                                Imap.createRectangleFromCoords(minx,miny),
				                                i.toString(),
				                                j.toString()
				                                );
				   IMapArray.push(imapArea);
				}
			}
			var vd = document.getElementById("vd_" + id); 
			vd.innerHTML = s;
		    
		}
	}
	
	if (detail == "true")Imap.appendAreas(IMapArray);
}

IdentifyObject.prototype.shortenString = function(strText) {	
    var intLength = 30;
    if(strText.length > intLength)strText = strText.substring(0,intLength) + "..."; 
    return strText;
}

IdentifyObject.prototype.RenderSingleFeature = function(anchor,layerIndex,featureIndex) {
   
   
	var layerNodes = this.xml.documentElement.childNodes;
	var layerNode = layerNodes[layerIndex];
	var layerId = layerNode.getAttribute("id");
	var layerName = layerNode.getAttribute("name");
	var layerType = layerNode.getAttribute("type");
	var featureNodes = layerNode.childNodes;
	var featureNode = featureNodes[featureIndex];
	var layerObj = layerList.findById(layerId);
	var minx = parseFloat(featureNode.getAttribute("minx"));
	var miny = parseFloat(featureNode.getAttribute("miny"));
	var maxx = parseFloat(featureNode.getAttribute("maxx"));
	var maxy = parseFloat(featureNode.getAttribute("maxy"));
	var href = featureNode.getAttribute("href");
	var iguide = featureNode.getAttribute("iguide");
	var thumbnail = featureNode.getAttribute("thumbnail");
	var lefttext  = featureNode.getAttribute("lefttext");
	var righttext = featureNode.getAttribute("righttext");
	if (righttext == "") righttext = lefttext;
	var hLayer = layerId;
	var hField = featureNode.getAttribute("hfield");
	var hValue = featureNode.getAttribute("hvalue");

	// Compare existing highlight with selected highlight
	if (Map.highlightLayer == hLayer && Map.highlightField == hField && Map.highlightValue == hValue) {
		// Remove highlight
//		anchor.style.backgroundColor = "";
//		anchor.style.fontStyle = "";
		Map.highlightLayer = "";
		Map.highlightField = "";
		Map.highlightValue = "";
		this.hide();
	} else {
		// Add highlight
//		anchor.style.backgroundColor = "#ffff00";
//		anchor.style.fontStyle = "italic";
		Map.highlightLayer = hLayer;
		Map.highlightField = hField;
		Map.highlightValue = hValue;
		this.hasArrow = (layerType=="point") ? true : false;
		var centerX = (minx + maxx) / 2;
		var centerY = (miny + maxy) / 2;
		
		var strHTML = "";
		var str = "";
		var strTitle = "";
		str += righttext;
		strTitle = lefttext;
		if(thumbnail == "(blank)")
		{	    
		    strHTML = this.BuildSimpleInfoBubbleHTML(strTitle, str, href, iguide);
        }
        else
        {
		    strHTML = this.BuildInfoBubbleHTML(thumbnail, strTitle, str, href, iguide);
        }
		if (layerType != "point") {
			this.hide(true);
		} else {
		
			this.showHtmlAtMapCoord(centerX, centerY, strHTML, this.hasArrow);
		}
	}
	Map.refresh();
	return false;
}

//builds the info bubble/popup box with title and description.
IdentifyObject.prototype.BuildSimpleInfoBubbleHTML = function(strTitle, strText, href, iguide) {
    var strHTML = "";

        strHTML += "<div id=\"bubble_box_content\">";
        if (href.substring(0,1)!= '&')
        {
            strHTML += "<div id=\"bubble_box_top\"><h3>" + this.BuildHyperlink(href,strTitle) + "</h3></div>";
        } 
        else
        {
            strHTML += "<div id=\"bubble_box_top\"><h3>" + strTitle + "</h3></div>";
        }
        strHTML += "<div id=\"bubble_box_bottom\">";
        strHTML += " <p>" + strText + "</p>";
        if (href.substring(0,1)!= '&')
        {
            strHTML += "<p>" + this.BuildHyperlink(href,"more details") + "</p>";
        }
        else
        {
            strHTML += "<p><b>Further details below</b></p>";
        }
        
        if(iguide!="")
        {        
            strHTML += "<p>" + this.BuildHyperlink(iguide,"iVisitor Guide") + "</p>";
        }
        strHTML += "</div>";

return strHTML;

}

//builds the info bubble/popup box with a thumbnail image.
IdentifyObject.prototype.BuildInfoBubbleHTML = function(strThumbnail, strTitle, strText, href, iguide) {

    var strHTML = "";

        strHTML += "<div id=\"bubble_box_content\">";
        if (href.substring(0,1)!= '&')
        {
            strHTML += "<div id=\"bubble_box_top\"><h3>" + this.BuildHyperlink(href,strTitle) + "</h3></div>";
        } 
        else
        {
            strHTML += "<div id=\"bubble_box_top\"><h3>" + strTitle + "</h3></div>";
        }
        
        strHTML += "<div id=\"bubble_box_bottom\"><div id=\"bubble_box_bottom_col1\"><img src=\"" + strThumbnail + "\" alt=\"Bubble image\" width=\"96\" height=\"96\" /></div>";
        strHTML += " <div id=\"bubble_box_bottom_col2\"><p>" + strText + "</p>";
        if (href.substring(0,1)!= '&')
        {
            strHTML += "<p>" + this.BuildHyperlink(href,"more details") + "</p>";
        }
        else
        {
            strHTML += "<p><b>Further details below</b></p>";
        }
        if(iguide!="")
        {        
            strHTML += "<p>" + this.BuildHyperlink(iguide,"I Guides") + "</p>";
        }
        strHTML += "</div></div>";

return strHTML;


}

IdentifyObject.prototype.BuildHyperlink = function(href,strTitle) {
      
        //Is this is thematic or route map
        if(Map.mapIsRoute || Map.mapIsTheme)
        {
           // return "<a href=javascript:popup('" + href + "')>" + strTitle + "</a>";
            strTarget = 'target="_blank"';
            return "<a href=" + href + " " + strTarget + ">" + strTitle + "</a>"
        }
        else
        {
            //For main map page links to route details
            if (href.substring(0,7)!= 'product')
            {
                return "<a href=" + href + ">" + strTitle + "</a>"
            }
            //Event links
            else
            {
                strTarget = 'target="_blank"';
                return "<a href=" + href + " " + strTarget + ">" + strTitle + "</a>"

            } 
        }
}

IdentifyObject.prototype.RenderPointXml = function(x) {
	
	//alert(x);
	var time = x.documentElement.getAttribute("time");
	var layerNodes = x.documentElement.childNodes;
	var str = "";
	var cntItems= 0;
	var strHTML = "";
	for (var i=0; i<layerNodes.length; i++) {
		
		if(cntItems > 0)break;
		var layerNode = layerNodes[i];
		var id = layerNode.getAttribute("id");
		var name = layerNode.getAttribute("name");
		
		var featureNodes = layerNode.childNodes;
		if (featureNodes.length > 0) {
			cntItems = cntItems + 1; 
			
			//alert(featureNodes.length);
			for (var j=0; j<featureNodes.length; j++) 
			{
				var featureNode = featureNodes[j];
				var href = featureNode.getAttribute("href");
				var lefttext  = featureNode.getAttribute("lefttext");
				var righttext = featureNode.getAttribute("righttext");
	            var thumbnail = featureNode.getAttribute("thumbnail");
				if (righttext == "") righttext = lefttext;
				str = righttext;
				strTitle = lefttext;
				if(thumbnail == "(blank)")
	            {
	                strHTML = this.BuildSimpleInfoBubbleHTML(strTitle, str, href);
                }
                else
                {
	                strHTML = this.BuildInfoBubbleHTML(thumbnail, strTitle, str, href);
                }
				
			}
			
		} else {
			strHTML = "<div style=\"margin-left:10px;margin-top:10px\">None found at this location</div>";
			//alert("Nothing found");
			strHTML = "";
		}
	}
	
	this.showHtml(strHTML);
}

// IdentifyObject positioning methods
IdentifyObject.prototype.repositionForScale = function(oldScale, oldExtent) {
	// Translate screen point to map coords under the old scale and extent
	var newExtent = Map.getExtent();
	var mapPoint = new CoordsMap();
	mapPoint.e = (this.point.x * oldScale) + oldExtent.minx;
	mapPoint.n = ((Map.height - this.point.y) * oldScale) + oldExtent.miny;
	// Translate map coords to new screen point under the new scale and extent
	this.point.x = (mapPoint.e - newExtent.minx) / Map.scale;
	this.point.y = Map.height - ((mapPoint.n - newExtent.miny) / Map.scale);
	this.setPosition(null);
	// if new position is off the map then hide
	if (this.point.x > Map.width || this.point.x < 0 || this.point.y > Map.height || this.point.y < 0)
	{
		this.hide(false);
	} else {
		if (Map.highlightLayer != "" && this.hasContent)
			this.show();
	}
}
IdentifyObject.prototype.setPosition = function(addPoint) {
	if (addPoint == null)
		addPoint = new CoordsScreen(0,0);
	var actualPointX = this.point.x + addPoint.x;
	var actualPointY = this.point.y + addPoint.y;
	var newMarginLeft = actualPointX;
	var newMarginTop  = actualPointY;
	var bArrowLeft = (newMarginLeft < 300);
	this.infoArrow.src = bArrowLeft ? "Map/images/infobox_arrow_left.gif" : "Map/images/infobox_arrow_right.gif";
	
	if (!bArrowLeft) newMarginLeft -= 128;
	else newMarginLeft += 186;
	var arrowLeft = bArrowLeft ? -17 : 283;
	
	if(Map.mapIsFirefox) newMarginLeft = newMarginLeft + 5;
	
	var arrowTop = 19; // by default arrow sits near top of infobox (change to 69, 84, 84 for middle of infobox instead)
	if (newMarginTop < 34) {
		arrowTop -= (34 - newMarginTop);
	}
	if (newMarginTop > (Map.height - 100)) {
		arrowTop -= (Map.height - 100) - newMarginTop ;
	}
	newMarginTop -= arrowTop - 50;
	
	if(Map.isLargeMap){
	   //arrowTop = arrowTop - 30;
	   newMarginTop = newMarginTop - 175;
	}
	this.infoWin.style.marginLeft = newMarginLeft + "px";
	this.infoWin.style.marginTop  = newMarginTop  + "px";
	this.infoArrow.style.marginLeft = arrowLeft + "px"
	this.infoArrow.style.marginTop  = arrowTop + "px";
	if (actualPointX < 5 || actualPointX > (Map.width-5) ||actualPointY < 25 || actualPointY > (Map.height-20)) {
		this.hide();
	} else {
		if (Map.highlightLayer != "" && this.hasContent)
			this.show();
	}
}

IdentifyObject.prototype.drift = function(driftBy) {
	// onMouseMove
	this.setPosition(driftBy);
}
IdentifyObject.prototype.shift = function(shiftBy) {
	// onMouseUp
	this.point.x += shiftBy.x;
	this.point.y += shiftBy.y;
	this.setPosition(null);
}
IdentifyObject.prototype.viewCount = function(layerId) {
	var vt = document.getElementById("vt_" + layerId);
	var spn = vt.getElementsByTagName("span")[0];
	
	var vc = document.getElementById("vc_" + layerId);

	this.hide(true); // hide the infobox after changing visible layers
}
IdentifyObject.prototype.hideCount = function(layerId) {

	var vt = document.getElementById("vt_" + layerId);
	var spn = vt.getElementsByTagName("span")[0];
	spn.innerHTML = "";
	
	var vc = document.getElementById("vc_" + layerId);
	vc.style.display = "none";
}
IdentifyObject.prototype.viewDetail = function(layerId) {
	var vd = document.getElementById("vd_" + layerId);
	vd.innerHTML = "<i>Loading.....</i>";
	vd.style.display = "block";
	// add to detail layers list

	var lyr = layerList.findById(layerId);
	lyr.detail = true;
}
IdentifyObject.prototype.hideDetail = function(layerId) {
	var vd = document.getElementById("vd_" + layerId);
	vd.style.display = "none";
	// remove from detail layers list
	var lyr = layerList.findById(layerId);
	lyr.detail = false;
}


// ================== LAYERS STUFF ==============
function LayerListObject() {
	this.list = new Array();
	this.countVisible = 0;
	this.maxLayers = 10;
	this.maxLayersText = "ten";
	this.aerialIsVisible = false;
	this.divBGMap = document.getElementById('divBGMap');
	this.divBGAerial = document.getElementById('divBGAerial');
	
}
LayerListObject.prototype.toggleAerial = function(str) { 
    if(str == 'map'){
        if(this.aerialIsVisible){
            //document.getElementById('divBGMap').style.borderWidth = "2px"; 
            //document.getElementById('divBGAerial').style.borderWidth = "1px"; 

            this.divBGMap1 = document.getElementById('ctl00_ctl00_ContentsBody_ucMap_divBGMap');
            this.divBGAerial1 = document.getElementById('ctl00_ctl00_ContentsBody_ucMap_divBGAerial');
            
            if (this.divBGMap1 == null) {
                document.getElementById('ctl00_ctl00_ContentsBody_MapArea_ucMap_divBGMap').style.fontWeight = "bold"; 
                document.getElementById('ctl00_ctl00_ContentsBody_MapArea_ucMap_divBGAerial').style.fontWeight = "normal"; 
            } 
            else 
            {
                document.getElementById('ctl00_ctl00_ContentsBody_ucMap_divBGMap').style.fontWeight = "bold"; 
                document.getElementById('ctl00_ctl00_ContentsBody_ucMap_divBGAerial').style.fontWeight = "normal";
            }
            
            //document.getElementById('divBGMap').style.height = "11px"; 
            //document.getElementById('divBGAerial').style.height = "12px"; 
            this.aerialIsVisible = false;
            layerList.clickId('AER');
            return false;
        }
    }
    if(str == 'aer'){
        
        if(!this.aerialIsVisible){
        
            this.divBGMap1 = document.getElementById('ctl00_ctl00_ContentsBody_ucMap_divBGMap');
            this.divBGAerial1 = document.getElementById('ctl00_ctl00_ContentsBody_ucMap_divBGAerial');
            
            if (this.divBGMap1 == null) {
                document.getElementById('ctl00_ctl00_ContentsBody_MapArea_ucMap_divBGMap').style.fontWeight = "normal"; 
                document.getElementById('ctl00_ctl00_ContentsBody_MapArea_ucMap_divBGAerial').style.fontWeight = "bold"; 
            } 
            else 
            {
                document.getElementById('ctl00_ctl00_ContentsBody_ucMap_divBGMap').style.fontWeight = "normal"; 
                document.getElementById('ctl00_ctl00_ContentsBody_ucMap_divBGAerial').style.fontWeight = "bold";
            }
            
            //document.getElementById('divBGMap').style.borderWidth = "1px"; 
            //document.getElementById('divBGAerial').style.borderWidth = "2px"; 

            //document.getElementById('divBGMap').style.height = "12px"; 
            //document.getElementById('divBGAerial').style.height = "11px"; 
            this.aerialIsVisible = true;
            layerList.clickId('AER');
            
            return false;
        }
    }
}
LayerListObject.prototype.push = function(obj) {
	this.list.push(obj);
	if (obj.visible && obj.queryable) this.countVisible++;
}
LayerListObject.prototype.pop = function() {
	var obj = this.list.pop();
	if (obj.visible) obj.click(); // when removing from list, delete from map too
	return this.list.pop();
}
LayerListObject.prototype.length = function() {
	return this.list.length;
}
LayerListObject.prototype.findById = function(layerId) {
	var i;
	for (i=0; i<this.list.length; i++) {
		if (this.list[i].id == layerId) break;
	}
	if (i == this.list.length) {
		alert("Warning: layer '" + layerId + "' not found");
		return null;
	}
	return this.list[i];
}
LayerListObject.prototype.clickId = function(layerId) {
	if(Map.RS)
    {
    	this.clickIdJS(layerId);
		return true;
	}
	var lyr = this.findById(layerId);
	if (lyr.queryable) {
		if (!lyr.visible) {
			// trying to show a layer					            		                												
			if (this.countVisible >= this.maxLayers) {
				// warn
				alert("Maximum of " + this.maxLayersText + " layers per map; please remove other layers before adding more");
				return false; // don't allow the box to be checked
			} else {
				// show
				var cb = document.getElementsByName("cb_" + layerId)[0];
				cb.checked = true;
				this.countVisible++;
				Identify.viewCount(layerId);
				lyr.click();
				
				this.clickMore(layerId);
				return true;
			}
		} else {
			// hide
			var cb = document.getElementsByName("cb_" + layerId)[0];
			cb.checked = false;
			this.countVisible--;
			this.clickMore(layerId,true);
			Identify.hideCount(layerId);
			Identify.hide();
			lyr.click();
			return true;
		}
	} else {
		// This is for non-queryable layers, e.g. Aerial Photos
		// Just show it
		lyr.click();
		return true;
	}
}

//Same as clickId but does not refresh map at this point
LayerListObject.prototype.clickIdJS = function(layerId) {
	var lyr = this.findById(layerId);
	if (lyr.queryable) { 
		if (!lyr.visible) {
			// trying to show a layer
			if (this.countVisible >= this.maxLayers) {
				// warn
				alert("Maximum of " + this.maxLayersText + " layers per map; please remove other layers before adding more");
				return false; // don't allow the box to be checked
			} else {
				// show
				var cb = document.getElementsByName("cb_" + layerId)[0];
				cb.checked = true;
				this.countVisible++;
				Identify.viewCount(layerId);
				
				lyr.visible = true;
				//lyr.clickJS();
				
				this.clickMoreJS(layerId);
				return true;
			}
		} else {
			// hide
		    var cb = document.getElementsByName("cb_" + layerId)[0];
			cb.checked = false;
			this.countVisible--;
			this.clickMoreJS(layerId,true);
			Identify.hideCount(layerId);
			Identify.hide();
			lyr.visible = false;
			
			//lyr.clickJS();
			return true;
		}
	} else {
		// This is for non-queryable layers, e.g. Aerial Photos
		// Just show it
		lyr.clickJS();
		return true;
	}
}

// serialiseVisible is used to display the map image; it includes background rasters
// Checks layer.visible
LayerListObject.prototype.serialiseVisible = function() {
	var a = new Array();
	for (var i=0; i<this.list.length; i++) {
		if (this.list[i].visible)
			a.push(this.list[i].id);
	}
	return a.join(".");
}
// serialiseIdentify is used to identify from a click on the map
// Checks layer.visible, layer.queryable
LayerListObject.prototype.serialiseIdentify = function() {
	var a = new Array();
	for (var i=0; i<this.list.length; i++) {
		if (this.list[i].visible && this.list[i].queryable &&
		this.list[i].minscale <= Map.scale && this.list[i].maxscale >= Map.scale)
			a.push(this.list[i].id);
	}
	return a.join(".");
}

LayerListObject.prototype.clickMoreSerialiseIdentify = function() {
	var a = new Array();
	for (var i=0; i<this.list.length; i++) {
		if (this.list[i].visible && this.list[i].queryable &&
		this.list[i].minscale <= Map.scale && this.list[i].maxscale >= Map.scale)
			this.clickMore(this.list[i].id);
			
	}
	return false;
}

// serialiseCounting is used to identify the counting feature layers on the layers list
// Checks layer.visible, layer.queryable, !layer.detail
LayerListObject.prototype.serialiseCounting = function() {
	var a = new Array();
	for (var i=0; i<this.list.length; i++) {
		if (this.list[i].visible && this.list[i].queryable && !this.list[i].detail && 
			this.list[i].minscale <= Map.scale && this.list[i].maxscale >= Map.scale)
			a.push(this.list[i].id);
	}
	return a.join(".");
}
// serialiseDetail is used to identify the detail-requested feature layers on the layers list
// Checks layer.visible, layer.queryable, layer.detail
LayerListObject.prototype.serialiseDetail = function() {
	var a = new Array();
	for (var i=0; i<this.list.length; i++) {
		if (this.list[i].visible && this.list[i].queryable && this.list[i].detail && 
			this.list[i].minscale <= Map.scale && this.list[i].maxscale >= Map.scale)
			a.push(this.list[i].id);
	}
	return a.join(".");
}
// serialiseZoomIn is used to work out which layers are visible and queryable but not shown 
// at this scale because the user needs to zoom in to see them.
// Checks layer.visible, layer.queryable, layer.maxscale
LayerListObject.prototype.serialiseZoomIn = function() {
	var a = new Array();
	for (var i=0; i<this.list.length; i++) {
		if (this.list[i].visible && this.list[i].queryable && 
			this.list[i].maxscale < Map.scale)
			a.push(this.list[i].id);
	}
	return a.join(".");
}
// serialiseZoomOut is used to work out which layers are visible and queryable but not shown 
// at this scale because the user needs to zoom out to see them.
// Checks layer.visible, layer.queryable, layer.minscale
LayerListObject.prototype.serialiseZoomOut = function() {
	var a = new Array();
	for (var i=0; i<this.list.length; i++) {
		if (this.list[i].visible && this.list[i].queryable && 
			this.list[i].minscale > Map.scale)
			a.push(this.list[i].id);
	}
	return a.join(".");
}

// This method is only used to display words "zoom in closer" at high scales
LayerListObject.prototype.getArrayOfQueryableNames = function() {
	var a = new Array();
	for (var i=0; i<this.list.length; i++) {
		if (this.list[i].visible && this.list[i].queryable && 
			this.list[i].minscale <= Map.scale && this.list[i].maxscale >= Map.scale)
			a.push(this.list[i].name);
	}
	return a;
}
LayerListObject.prototype.catClick = function(span) {
	var dt = span.parentNode;
	var dd = dt.nextSibling;
	var img = span.childNodes[0];
	while (dd.nodeName.toUpperCase() != "DD") dd = dd.nextSibling;
	switch (dt.className) {
		case "closed": 
			dt.className = "opened";
			dd.className = "opened";
			img.src = "images/tree/minusopen.png";
			break;
		case "opened":
			dt.className = "closed";
			dd.className = "closed";
			img.src = "images/tree/plusclose.png";
			break;
		default:
			alert("Program error (category neither opened nor closed)");
	}
}
LayerListObject.prototype.clickMore = function(layerId, bForceClose) {

	bForceClose = bForceClose ? true : false; // convert undefined to false
	var lyr = this.findById(layerId);
	
	if (lyr.maxscale >= Map.scale && lyr.minscale <= Map.scale) {
		if (!bForceClose) {
			Identify.viewDetail(layerId);

			Map.refresh();
		}
		else
		{
			Identify.hideDetail(layerId);
		}
	} else {
		if (!bForceClose) {
			if (lyr.maxscale < Map.scale)
				alert("Zoom in for more detail");
			else
				alert("Zoom out for more detail");
		}
	}
}

LayerListObject.prototype.clickMoreJS = function(layerId, bForceClose) {
	bForceClose = bForceClose ? true : false; // convert undefined to false
	var lyr = this.findById(layerId);
	if (lyr.maxscale >= Map.scale && lyr.minscale <= Map.scale) {
		    
		if(!RouteSearch.search)Map.refresh();
		if (!bForceClose) 
		{
		    Identify.viewDetail(layerId);
		}
		else
		{
		    Identify.hideDetail(layerId);
		}
	} else {
		if (!bForceClose) {
			if (lyr.maxscale < Map.scale)
				alert("Zoom in for more detail");
			else
				alert("Zoom out for more detail");
		}
	}
}

LayerListObject.prototype.resetCheckboxes = function() {
	for (var i=0; i<this.list.length; i++) {
		var vis = this.list[i].visible;
		var id = this.list[i].id;
		var cb = document.getElementsByName("cb_"+id)[0];
		if (cb!=null) {
			if (vis != cb.checked)
				cb.checked = vis;
		}
	}
	// Now also check if there's a highlight, and if so expand its layer
	var hLayer = Map.highlightLayer;
	if (hLayer != "") {
		// highlight exists
		var lyr = this.findById(hLayer);
		if (lyr != null && lyr.visible) {
			// clickmore
			this.clickMore(hLayer);
		}
	}
}

LayerListObject.prototype.clearAllLayers = function(){
    //Use the selected mapCategory to (WLK, CYC etc) to loop through default layers array list
    var arrDefaultLayers = arrDCESiteLayers;
    var arrayLength = arrDefaultLayers.length;
    for(var x=0; x < arrayLength; x++)//
    {
            var strId = arrDefaultLayers[x].toString();
            var cb = document.getElementsByName("cb_" + strId)[0];
            var lyr = this.findById(strId);
	        if(cb != null)
           {
                if (cb.checked) 
		            {
		                cb.checked = false;
		                this.clickId(strId);
		           }
		        
		        if (lyr.visible)
		        {
		            //alert(strId);
		            cb.checked = false;
		            Map.RS = false;
		            this.clickId(strId);
		            Map.RS = true;
		        }
            }       
	}

		
}
LayerListObject.prototype.activateSearchLayers = function() {

    var arrDefaultLayers = arrDCESiteLayers;
    for(var x=0; x < arrDefaultLayers.length; x++){
            var strId = arrDefaultLayers[x].toString();
            var strSubId = strId.substring(0,3) 
            if(strSubId == Map.mapCategory){
                var cb = document.getElementsByName("cb_" + strId)[0];
	            if (!cb.checked) 
		            cb.click();
            }
	}
	if(Map.mapIsTheme) {	      
        var cb = document.getElementsByName("cb_DCTT")[0];
        if (!cb.checked) cb.click();        
        var llsc = layerList.serialiseCounting();
	    var llsd = layerList.serialiseDetail();
    }   
}
//sets detail value of layers to true if they were passed in the query string
LayerListObject.prototype.showInitialMapLayers = function(activeLayer){ 
    var arrDefaultLayers = arrDCESiteLayers;
    var arrayLength = arrDefaultLayers.length;
    for(var x=0; x < arrayLength; x++)//
    {
            var strId = arrDefaultLayers[x].toString();
            var cb = document.getElementsByName("cb_" + strId)[0];
	        if(cb != null)
            {
                if (cb.checked) 
		            {
		                lyr = layerList.findById(strId);
                        lyr.detail = true;
                        //alert(strId);
		            
		            }
            }
            
	}
	
}

//sets detail value of layers to true
LayerListObject.prototype.setDefaultMapLayers = function(){
 
    var arrSiteLayers = arrDCESiteLayers;
    var arrDefaultLayers = arrDCEDefaultLayers;
    
    var arraySiteLength = arrSiteLayers.length;
    var arrayDefaultLength = arrDefaultLayers.length;
    
    for(var x=0; x < arraySiteLength; x++)//
    {
            var strId1 = arrSiteLayers[x].toString();
            for(var x2=0; x2 < arrayDefaultLength; x2++)//
            {
                var strId2 = arrDefaultLayers[x2].toString();
                if (strId1 == strId2)
                {
                    var selectedOption = RouteSearch.getSelectedSearchItem();
                    if(selectedOption == strId1.substring(0,3))
	                {
                        lyr = layerList.findById(strId1);
                        lyr.detail = true;
                        var cb = document.getElementsByName("cb_" + strId1)[0];
                        if(cb != null)
                        {
                            cb.checked = true;
                            this.clickId(strId1);
                        }
	                }
                } 
           } 
	}
}

LayerListObject.prototype.showActiveLayer = function(activeLayer){
    document.getElementById(activeLayer).style.display = '';
}

LayerListObject.prototype.hideActiveLayer = function(activeLayer){
    document.getElementById(activeLayer).style.display = 'none';
}
function showDCEProducts(){
    var arrProducts = arrDCEProductCat;
    for(var i=0; i < arrProducts.length; i++)
    {
        var strLayer = "dt_" + arrProducts[i];
        document.getElementById(strLayer).style.display = '';
        //this.showActiveLayer(strLayer);
    }
    return false;    
}
                
                
//End of LAYERLIST OBJECT 


// ================== LAYER STUFF =============
function LayerObject(newId, newName, newVisible, newMin, newMax, newQueryable, newShapeType) {
	this.id = newId;
	this.name = newName;
	this.visible = newVisible;
	this.minscale = newMin;
	this.maxscale = newMax;
	this.queryable = newQueryable;
	this.shapetype = newShapeType;
	this.detail = false;
}
LayerObject.prototype.click = function() {
	this.visible = !this.visible;
	this.updateMap();
}

LayerObject.prototype.clickJS = function() {
	this.visible = !this.visible;
}

LayerObject.prototype.updateMap = function() {
	Map.refresh();
}



// ================== SEARCH STUFF =============
function SearchObject() {
	this.btn = document.getElementById("btnLocationSearch");
	this.txt = document.getElementById("txtLocationSearch");
	this.loading = false;
}
SearchObject.prototype.disable = function() {
	this.btn.innerText = "Searching....";
	this.btn.disabled = "disabled";
	this.txt.disabled = "disabled";
}
SearchObject.prototype.enable = function() {
	this.btn.innerText = "Location Search";
	this.btn.disabled = "";
	this.txt.disabled= "";
}
function doLocationSearch() {
	if (Search.txt.value.length < 2) {
		alert("Please enter some search text");
		Search.txt.focus();
		return;
	}
	Search.disable();
	var url = "EmbeddedSearch.aspx?txt=" + encodeURIComponent(Search.txt.value);
	var ajax = new AJAXObject();
	ajax.loadXMLDoc(url, function() {
		if (ajax.req) {
			if (ajax.req.readyState == 4) { // only if "OK"
				Search.enable();
				if (ajax.req.status == 200) {
					var x = ajax.getXml();
					if (x == null)
					{
						alert("Invalid XML (1):\n" + ajax.req.responseText);
						return;
					}
					if (x.documentElement == null) 
					{
						// this happens if the response content-type isn't set to text/xml
						alert("Invalid XML (2):\n" + ajax.req.responseText);
						return;
					}
					if (x.documentElement.nodeName == "error") {
						alert("Error: " + x.documentElement.childNodes[0].text);
						return;
					}
					var count = x.documentElement.childNodes.length;
					if (count == 0) 
					{
						// no results found
						alert("Location '" + Search.txt.value + "' not found");
						Search.txt.focus();
						return;
					} 
					else if (count == 1) 
					{
						// one result found - go straight there
						var node = x.documentElement.childNodes[0];
						var easting  = parseInt(node.getAttribute("easting"));
						var northing = parseInt(node.getAttribute("northing"));
						var type = node.getAttribute("type");
						var name = node.getAttribute("name");
						ZoomMarker.moveToNewLocation(easting, northing, 0.635);
						Identify.showSimpleMessageAtMapCoord(easting, northing, type, name);
						return;
					} 
					else 
					{
						// show list, allow user to select from list
						var div = document.getElementById("divLocationSearchResults");
						div.style.display = "";
						var s = "";
						s += '<div onclick="document.getElementById(\'divLocationSearchResults\').style.display=\'none\';"><b>Did you mean:</b></div>\n';
						s += '<div><select size="8" style="background-color: #FFF4D0;" onchange="srchGoto(this.options[this.selectedIndex].value);">\n';
						for (var i=0; i<count; i++) {
							var xe = x.documentElement.childNodes[i].getAttribute("easting");
							var xn = x.documentElement.childNodes[i].getAttribute("northing");
							var xm = x.documentElement.childNodes[i].getAttribute("name");
							s += '<option value="' + xe + ',' + xn + '">' + xm + '</option>\n';
						}
						s += '</select></div>\n';
						div.innerHTML = s;
					}
					return;
				} else {
					var s = ajax.req.responseText;
					alert("Unexpected error finding postcode; please try again.\n\n" + s);
				}
			}
		}
	});
}
SearchObject.prototype.show = function() {
	this.addrWin.style.display = "";
}
SearchObject.prototype.hide = function() {
	this.addrWin.style.display = "none";
}
SearchObject.prototype.clear = function() {
	for (var r=this.addrTbl.rows.length-1; r>=1; r--) {
		this.addrTbl.rows[r].deleteCell();
		this.addrTbl.rows[r].deleteCell();
		this.addrTbl.deleteRow();
	}
	document.getElementById("txtAddrStreet").value = "";
	document.getElementById("selAddrTown").selectedIndex = 0;
}
SearchObject.prototype.view = function(e,n,text) {
	// Move map
	ZoomMarker.moveToNewLocation(e, n, 2);
	// Show infobox
	Identify.showMessageMapCoord(e, n, "Search", text);
	return false;
}

// ------------ THEMES -------------

// Controls the Themes tree; to be completed
function ThemesObject() {
	// empty object
}
ThemesObject.prototype.flip = function(span) {
	var newClass = "";
	if (span.nodeName.toUpperCase() != "SPAN")
		alert("ThemesObject.flip may only be attached to nodes of type SPAN");
	var dt = span.parentNode;
	if (dt.nodeName.toUpperCase() != "DT")
		alert("ThemesObject.flip may only be attached to nodes of type SPAN with a parent of type DT");
		
	var dd = dt.nextSibling;
	var img = span.childNodes[0];
	while (dd.nodeName.toUpperCase() != "DD") dd = dd.nextSibling;
	while (dd.nodeName.toUpperCase() != "DD") dd = dd.nextSibling;
	switch (dt.className) {
		case "closed": 
			dt.className = "opened";
			dd.className = "opened";
			img.src = "images/tree/minusopen.png";
			break;
		case "opened":
			dt.className = "closed";
			dd.className = "closed";
			img.src = "images/tree/plusclose.png";
			break;
		default:
			alert("Program error");
	}
}


// ------------ AJAX -------------

// Centred-on AJAX stuff
function AJAXObject() {
	this.req = false;
	this.capitalCaseXml = false;
}
AJAXObject.prototype.getXml = function() {
	if (this.capitalCaseXml) 
		return this.req.responseXML;
	else
		return this.req.responseXml;
}
AJAXObject.prototype.loadXMLDoc = function(url, callbackFunction) {
	if (this.req !== false) {
		this.req.abort();
	}
	this.req = false;
	
	// branch for native XMLHttpRequest object
	if (window.XMLHttpRequest) {
		this.capitalCaseXml = true;
		try {
			this.req = new XMLHttpRequest();
		} catch(e) {
			this.req = false;
		}
	// branch for IE/Windows ActiveX version
	} else if (window.ActiveXObject) {
		this.capitalCaseXml = false;
		try {
			this.req = new ActiveXObject("Msxml2.XMLHTTP");
		} catch(e) {
			try {
				this.req = new ActiveXObject("Microsoft.XMLHTTP");
			} catch(e) {
				this.req = false;
			}
		}
	}
	if (this.req) {
		this.req.onreadystatechange = callbackFunction;
		this.req.open("GET", url, true);
		this.req.send("");
	}
}


// =====================

function LeftMenuObject() {
	this.direction = true; // true=opening, false=closing
	this.startPosition = -166;
	this.position = this.startPosition;
	this.step = 10;
	this.delay = 15; // lower = faster slide
}
LeftMenuObject.prototype.mOver = function() {
	this.direction = true;
	document.getElementById("divLeftMenu").style.height = (Map.height + 6) + "px";
	this.timer();
}
LeftMenuObject.prototype.mOut = function() {
	this.direction = false;
	this.timer();
}
LeftMenuObject.prototype.timer = function() {
	var bRepeat = true;
	if (this.direction) {
		this.position += this.step;
		if (this.position >= 0) {
			this.position = 0;
			bRepeat = false;
		}
	} else {
		this.position -= this.step;
		if (this.position <= this.startPosition)
		{
			this.position = this.startPosition;
			bRepeat = false;
		}
	}
	document.getElementById("divLeftMenu").style.left = this.position + "px";
	if (bRepeat)  window.setTimeout(LeftMenu_timer,this.delay);
	else if (!this.direction)
		document.getElementById("divLeftMenu").style.height = "350px";
}
function LeftMenu_timer() {
	LeftMenu.timer();
}


// ================== ZoomBoxObject Stuff =============
function ZoomBoxObject(){

    this.ZoomMode = "ZoomIn";
    this.x1 = null;
    this.y1 = null;
    this.x2 = null;
    this.y2 = null;
    this.zbWidth = null;
    this.zbHeight = null;
    this.zooming = null;
    this.minX = null;
    this.minY = null;
    this.maxX = null;
    this.maxY = null;
    this.pxString = null;
    this.dragging = false;
    
}

//* Jon Satchwell 14/10/2008
//On mouse down record the first relative coordinates and the map coordinates.
ZoomBoxObject.prototype.startZoomBox = function(evt){

	if (NavTool.Mode== "zoomin" || NavTool.Mode == "zoomout") {
	
		if (navigator.appName == "Netscape"){
				this.x1=evt.pageX;
				this.y1=evt.pageY;
		} 
		else{
    			this.x1=event.clientX;
				this.y1=event.clientY;
		}
	
		//NavTool.Mode=NavTool.Mode;
	
		if(Map.mapActive && (NavTool.Mode == "zoomin" || NavTool.Mode == "zoomout")){
			this.zooming=true;
		}
		else {
			this.zooming=false;
		}
	
	//get the relative coordinates on the map div	
    var pnt = Mouse.getRelativeCoordinates(evt, Map.divCurr);
    //convert to the map coordinates
    var coords = pnt.ToMapCoords();
    
    //set private easting and northing coord variables for the zoom box object
    this.e1 = coords.e;
    this.n1 = coords.n;
    
    //set the zoom box layer to be the zoom box div.
    this.layer = getLayer("zoomBox");
    }
}

//* Jon Satchwell 14/10/2008
//Resizes and draws the temporary zoom box while the user is dragging on the mouse down event.
ZoomBoxObject.prototype.resizeZoomBox = function(evt){

	if (NavTool.Mode== "zoomin" || NavTool.Mode == "zoomout") {
	    
	    //determine current mouse location
    	if (navigator.appName == "Netscape") {
		    var mouseX=evt.pageX;
		    var mouseY=evt.pageY;
		    this.pxString = "px";    	
		} else {
		    var mouseX=event.clientX;
		    var mouseY=event.clientY;
		    this.pxString = "";    	
		}
		
		//determine if the mouse goes off the Map image
			if(!Map.mapActive){
					
					//alert("Zoom Box stopped!!!");
					ZoomBox.stopZoomBox();
			} 
			else {
			  	
			  	//determine if zooming has begun from the startZoomBox funtion. if so resize the box.
		  		if (this.zooming) {
		  		
			    this.dragging = true;
		  		
				this.x2=mouseX;
				this.y2=mouseY;
				this.zbWidth=this.x2-this.x1;
				this.zbHeight=this.y2-this.y1;
				
				//determine the direction in which the zoom box is drawn and set the appropriate
				// left and top properties
				if (this.zbWidth > 0) {this.layer.left = (this.x1 - 7) + this.pxString;} 
				else {this.layer.left = (this.x2 + 15)+this.pxString;}
				
				if (this.zbHeight > 0) {this.layer.top = (this.y1 - 7) + this.pxString;} 
				else {this.layer.top = (this.y2 + 7)+this.pxString;}
					//Set the this.width and height of the zoom box
					
					this.layer.width = Math.abs(this.zbWidth) + this.pxString;
					this.layer.height = Math.abs(this.zbHeight) + this.pxString;
					this.layer.visibility = "visible";
				 }
			}
			
		return false;
    	}
}

//* Jon Satchwell 14/10/2008
//Occurs on the mouse up event and checks if the map has been clicked or dragged.  
//This enables the user to either click once and zoom in/out on any map coordinate on the screen by one notch, or
//create a bounding box and zoom to exactly that box.
ZoomBoxObject.prototype.stopZoomBox = function(e){
	
	if (NavTool.Mode == "zoomin" || NavTool.Mode == "zoomout") {
		
		this.layer = getLayer("zoomBox");
		this.layer.visibility="hidden";
				
		if (this.zooming){
		
			if(!this.dragging){
			
				this.zooming=false;
				
				Map.e = this.e1;
				Map.n = this.n1;
				switch (NavTool.Mode){
					case "zoomin":
					ZoomMarker.zoomIn();
					break;
					case "zoomout":
					ZoomMarker.zoomOut();
					break;
				}
				return;
			}
			else{
				//showLayer("LoadData");
				if ((this.x2-this.x1)>0){
					this.minX = this.x1-Map.mleft;
					this.maxX = this.x2-Map.mleft;
				}
				else {
					this.minX = this.x2-Map.mleft;
					this.maxX = this.x1-Map.mleft;
				}
				
				this.y1=this.y1-Map.mtop
				this.y2=this.y2-Map.mtop
				
				if (this.y1>this.y2){
					this.minY = this.y2;
					this.maxY = this.y1;
				}
				else {
					this.minY = this.y1;
					this.maxY = this.y2;
				}
				
				// get the relative screen coordinates in the map div.
				var pnt = Mouse.getRelativeCoordinates(e, Map.divCurr);
				//convert to the map coordinates.
				var coords = pnt.ToMapCoords();
			    
			    //set the ending zoombox easting and northing
				this.e2 = coords.e;
				this.n2 = coords.n;
			    
				//document.getElementById("mapdetails").innerHTML += "x2: " + coords.e + ", y2: " + coords.n + "<br/>";
				
				this.zooming=false;
				this.dragging=false;
				//
				this.zoomToZoomBox();
			}
			
		}
	
	}
}

// Public method
//Checks the scale of the x axis for the zoom box realtive to the current map extent.
//finds the mid point of the box which is required for the Map.refresh() method.
//If the Mode is to zoom out then the zoomOut method is called which zooms out by one notch.
ZoomBoxObject.prototype.zoomToZoomBox = function() {
		
		var e, n,customScale;
		var mapWidth = 775;// use actual map width in here.
		
		//work out centre of box coords and scale, depending on how it has been drawn.
		if(this.e1 > this.e2){
			customScale = (this.e1 - this.e2) / mapWidth;
			e = ((this.e1 - this.e2)/2)+this.e2;
		}
		else{
			customScale = (this.e2 - this.e1) / mapWidth;
			e = ((this.e2 - this.e1)/2)+this.e1;
		}
		if(this.n1 > this.n2){
			n = ((this.n1 - this.n2)/2)+this.n2;
		}
		else{
			n = ((this.n2 - this.n1)/2)+this.n1;
		}
			
		var intCustomScale = parseInt(customScale);
		
		var curScale = ZoomMarker.scales[ZoomMarker.notchIndex];
		var arrLength = ZoomMarker.scales.length - 1;
		var scaleUpper, scaleLower, indexUpper, indexLower, newIndexScale;
		
		var scaleBand, diffToLower;
		
		scaleUpper = ZoomMarker.scales[0]; 
		scaleLower = ZoomMarker.scales[1];
		indexUpper = 0; indexLower = 1;
		
//		if(NavTool.Mode=="zoomout"){
//			if(ZoomMarker.notchIndex == 0) return; //drop out if at max zoom out extent.
//			newIndexScale = ZoomMarker.notchIndex - 1;
//		}
//		else{	
				if(ZoomMarker.notchIndex == 10) return; //drop out if at max zoom in extent
				//get hold of the position of the new scale value for zoom based on the 
				//pre-determined zoom scales set up.
				for (var i=0; i<arrLength; i++)
				{
					if(customScale < ZoomMarker.scales[i]){
							scaleUpper = ZoomMarker.scales[i]; 
							scaleLower = ZoomMarker.scales[i+1];
							indexUpper = i; indexLower = i+1;
					}
				
	//			}
		//decide on how close the new scale is compared to the predetermined ones.				
		scaleBand = (scaleUpper - scaleLower);
		//calculate the percentage.
		diffToLower = ((customScale - scaleLower) / scaleBand) * 100;
			//decide if custom(zoom box scale) is closer to the upper or lower band.					
			if(diffToLower <= 50){//use the lower scale value
				newIndexScale = indexLower;
			}
			else{ //stick with upper scale
				newIndexScale = indexUpper;
			}	
				
		}
		//move the zoom tool notch				
		ZoomMarker.moveNotchToIndex(newIndexScale);
		var newScale = ZoomMarker.scales[newIndexScale];


		
		ZoomMarker.zoomToCurrentNotch(false); // this call sometimes changes Map.e and Map.n
		
		//set new map easting and northings and refresh.
		Map.e = e; 
		Map.n = n;
		Map.scale = newScale;
		Map.refreshForZoomBox();
	return false;
}


// get the layer object called "name"
function getLayer(name) {


	  if (BrowserDetails.isNav4)
			return(document.layers[name]);
	  else if (BrowserDetails.isIE4) {
	    this.layer = eval('document.all.' + name + '.style');
	    return(this.layer);
	    
	  } else if (BrowserDetails.is5up) {
		var theObj = document.getElementById(name);
		
		return theObj.style
	  }
	  else if (BrowserDetails.is6up) {
		var theObj = document.getElementById(name);
		return theObj.style
	  }
	  else
	    return(null);
	    

}

// =====================



// ================== Browser Details Stuff =============

function BrowserDetailsObject()
{
    this.isIE = false;
    this.isNav = (navigator.appName.indexOf("Netscape")>=0);
    this.isNav4 = false;
    this.isIE4 = false;
    this.is5up = false;
    this.is6up = false;
    if (this.isNav) {
	    if (parseFloat(navigator.appVersion)<5) {
		    this.isNav4=true;
		    alert("Netscape 4.x or older");
	    } else {
		    this.is5up = true;		    
	    }
    } else {
	    
	    this.isIE4=true;
	    this.isIE=true;
	    if (navigator.appVersion.indexOf("MSIE 5")>0) {
		    this.isIE4 = false;
		    this.is5up = true;
		    alert("IE5");
	    }
	    if (navigator.appVersion.indexOf("MSIE 6")>0) {
		    this.isIE4 = false;
		    this.is5up = false;
		    this.is6up = true;
	    }
    }	
    
    this.Name = navigator.appName;
  
    
}
// =====================

// ================== Navigation Tool Bar Stuff =============
//Initialise with pan enabled
function NavToolObject(blnIncludeNavTool){
	this.Mode = "pan";
	this.NavTool = document.getElementById('divNavTools');
	if(blnIncludeNavTool)this.NavTool.style.visibility = 'visible';
}


NavToolObject.prototype.setCursor = function(toolMode){

    if(toolMode == "zoomin" || toolMode == "zoomout"){
		Map.mapWrap.style.cursor = "crosshair";	//Map.cursorZoomin;
	}
	else{
		Map.mapWrap.style.cursor = Map.cursorGrab;
	}
}

//Sets the tool when the Navtool bar is clicked.
NavToolObject.prototype.setTool = function(imgId, toolMode){
	
	this.setCursor(toolMode);
	this.Mode = toolMode;
	this.resetNavButtons();
	
	switch(toolMode)
		{
			case "zoomin":
				document[imgId].src = "Map/Images/zoom-in_ON.gif";
			break;
			case "zoomout":
				document[imgId].src = "Map/Images/zoom-out_ON.gif";
			break;
			case "pan":
				document[imgId].src = "Map/Images/pan_ON.gif";
			break;
		
		}
	
}

NavToolObject.prototype.resetNavButtons = function(){
	document["zoomin"].src = "Map/Images/zoom-in_OFF.gif";
	document["zoomout"].src = "Map/Images/zoom-out_OFF.gif";
	document["pan"].src = "Map/Images/pan_OFF.gif";
	
}

NavToolObject.prototype.mOver = function(imgId, toolMode){
	if(this.Mode == toolMode)return;
	switch(toolMode)
	{
		case "zoomin":
			if(this.Mode !="zoomin")document[imgId].src = "Map/Images/zoom-in_HOVER.gif";
		break;
		case "zoomout":
			document[imgId].src = "Map/Images/zoom-out_HOVER.gif";
		break;
		case "pan":
			document[imgId].src = "Map/Images/pan_HOVER.gif";
		break;
	
	}
	//return false;
}

NavToolObject.prototype.mOut = function(imgId, toolMode){
	if(this.Mode == toolMode)return;
	switch(toolMode)
	{
		case "zoomin":
			document[imgId].src = "Map/Images/zoom-in_OFF.gif";
		break;
		case "zoomout":
			document[imgId].src = "Map/Images/zoom-out_OFF.gif";
		break;
		case "pan":
			document[imgId].src = "Map/Images/pan_OFF.gif";
		break;
	
	}
	//return false;
}


// =============== Slide Close and open - JQuery======


$(function () {
    
    var intSpeed = 800;
    var $divOverviewInner = $('#divOverview-inner'), $divOverview = $('#divOverview'), $splitterOv = $('#splitterOv'), $imgOverview = $('#imgOverview');
    var $routeContent = $('#route_options_box_content'), $splitterRoute = $('#splitterRoute');
    var $eventFilter= $('#event_filter_box_content'), $splitterEvent = $('#splitterEvent');
    var $attractionsContent = $('#attractions_box_content'), $splitterAttractions = $('#splitterAttractions');
    var $mapOptionsContent = $('#map_options_box_content'), $splitterMapOptions = $('#splitterMapOptions');
    
    
    $splitterOv.toggle(
        function() { 
            document.getElementById('divRedBoxMaster').style.visibility = "hidden";
            document.getElementById('imgOverviewBar').alt = "Click to show";
            $divOverview.animate({ width: 'hide' }, intSpeed);
            $divOverviewInner.animate({ width: 'hide' }, intSpeed);
            Overview.moveZoomBar(true);
        },
        function() {
            document.getElementById('divRedBoxMaster').style.visibility = "visible";
            document.getElementById('imgOverviewBar').alt = "Click to hide";
            $divOverview.animate({ width: 'show' }, intSpeed);
            $divOverviewInner.animate({ width: 'show' }, intSpeed);
            Overview.moveZoomBar(false);
        }
    );

    $splitterRoute.toggle(
        function() { 
            $routeContent.animate({ height: 'hide' }, intSpeed);
            swapMinMaxButton('Maximise',1);
        },
        function() {
            $routeContent.animate({ height: 'show' }, intSpeed);
            swapMinMaxButton('Minimise',1);
        }
    );
    
     $splitterEvent.toggle(
        function() { 
            $eventFilter.animate({ height: 'hide' }, intSpeed);
            swapMinMaxButton('Maximise',2);
        },
        function() {
            $eventFilter.animate({ height: 'show' }, intSpeed);
            swapMinMaxButton('Minimise',2);
        }
    );
    
    $splitterAttractions.toggle(
        function() { 
            $attractionsContent.animate({ height: 'hide' }, intSpeed);
            swapMinMaxButton('Maximise',3);
        },
        function() {
            $attractionsContent.animate({ height: 'show' }, intSpeed);
            swapMinMaxButton('Minimise',3);
        }
    );
    
   $splitterMapOptions.toggle(
        function() { 
            $mapOptionsContent.animate({ height: 'hide' }, intSpeed);
            swapMinMaxButton('Maximise',4);
        },
        function() {
            $mapOptionsContent.animate({ height: 'show' }, intSpeed);
            swapMinMaxButton('Minimise',4);
        }
    );
    

   
    
});


