// $Id: bevp.js 165 2006-07-31 18:36:16Z cdahlquist $
// Client side routines for Bird's Eye View public UI.
// by John Fieber

function bevinit()
{
    initDHTMLAPI();
    be_resize();
}
window.onload = bevinit;

var stickydotmenu = false;

// cross-browser event listener assignment
function addEvent(obj, evType, fn, useCapture){
  if (obj.addEventListener){
    obj.addEventListener(evType, fn, useCapture);
    return true;
  } else if (obj.attachEvent){
    var r = obj.attachEvent("on"+evType, fn);
    return r;
  } else {
    return false;
    //alert("Handler could not be attached");
  }
}

/**
 * Prints to a debug console for FireBug
 * http://joehewitt.com/software/firebug/
**/
/*
function printfire()
{
    if (document.createEvent)
    {
        printfire.args = arguments;
        var ev = document.createEvent("Events");
        ev.initEvent("printfire", false, true);
        dispatchEvent(ev);
    }
}
*/
// Return the available content width space in browser window
function bevGetInsideWindowWidth(window) {
    body = getBody(window.document);
    if (window.innerWidth) {
        return window.innerWidth;
    } else if (isIE6CSS) {
        // measure the html element's clientWidth
        // watchout for a base element between html and body!
        p = body.parentElement;
        if (typeof p.clientWidth == 'undefined') {
            p = p.parentElement;
        }
        return p.clientWidth;
    } else if (body && body.clientWidth) {
        return body.clientWidth;
    }
    return 0;
}
   
// Return the available content height space in browser window
function bevGetInsideWindowHeight(window) {
    body = getBody(window.document);
    if (window.innerHeight) {
        return window.innerHeight;
    } else if (isIE6CSS) {
        // measure the html element's clientHeight
        // watchout for a base element between html and body!
        p = body.parentElement;
        if (!p.clientHeight)
            p = p.parentElement;
        return p.clientHeight;
    } else if (body && body.clientHeight) {
        return body.clientHeight;
    }
    return 0;
}


var map = {
    
    frame: function() {
	var mf = top.frames['mapframe'];
	if (mf)
	    return mf;
	return window;
    },

    center: function() {
	var mapimage = this.frame().document.getElementById('mapimage');
	var x = Math.round(mapimage.width /  2);
	var y = Math.round(mapimage.height / 2);
	this.snapTo(x, y);
    },

    snapTo: function(x, y) {
	var map_frame = this.frame();
	var frsz = this.viewSize();
	x2 = x - Math.round(frsz.width / 2);
	y2 = y - Math.round(frsz.height / 2);
	this.frame().scrollTo(x2, y2);
    },

    slideTo: function(x, y) {
	var mapimage = this.frame().document.getElementById('mapimage');
	var frame_size = this.viewSize();
	var from = this.currentScroll();
	var view_center_x = Math.round(frame_size.width / 2);
	var view_center_y = Math.round(frame_size.height / 2);
	// Adjust destination for targets close to the map edge. 
	// 70 is a fudge factor since popups can extend beyond the map.
	x = Math.max(x, view_center_x);
	x = Math.min(x, mapimage.width + 70 - view_center_x);
	y = Math.max(y, view_center_y);
	y = Math.min(y, mapimage.height - view_center_y);
	x = x - view_center_x;
	y = y - view_center_y;
	this.slideStep(from.left, from.top, x, y, 0);
    },

    movetime: 100,
    movesteps: 180,
    steptime: 1,
    steptimer: null,

    slideStep: function(sx, sy, ex, ey, a) {
	if (this.steptimer)
	    clearTimeout(this.steptimer);
	// If we are at our destination...
	if (a > this.movesteps) {
	    this.frame().scrollTo(ex, ey);
	    return;
	}

	// Figure out where we are on our journey
	var dx = (ex - sx) / 2;
	var dy = (ey - sy) / 2;
	var p = Math.sin((a - 90) * (2 * Math.PI / 360));
	var nx = Math.round(sx + (p * dx) + dx);
	var ny = Math.round(sy + (p * dy) + dy);
	this.frame().scrollTo(nx, ny);
	var timecall = "top.map.slideStep("
	  + sx.toString() + ","
	  + sy.toString() + ","
	  + ex.toString() + ","
	  + ey.toString() + ","
	  + (a + 5).toString() + ")";
	this.steptimer = setTimeout(timecall, 20);

    },

    viewSize: function() {
	var result = {height:0, width:0};
	result.height = bevGetInsideWindowHeight(this.frame());
	result.width = bevGetInsideWindowWidth(this.frame());
	return result;
    },

    currentScroll: function() {
	var result = {top:0, left:0};
	frame = this.frame();
	d = frame.document;
        body = getBody(frame.document)
	if (body && typeof body.scrollTop != "undefined") {
	    result.left += body.scrollLeft;
	    result.top += body.scrollTop;
	    if (body.parentNode && typeof body.parentNode.scrollTop != "undefined") {
		result.left += body.parentNode.scrollLeft;
		result.top += body.parentNode.scrollTop;
	    }
	} else if (typeof window.pageXOffset != "undefined") {
	    result.left += window.pageXOffset;
	    result.top += window.pageYOffset;
	}
	return result;
    },

    load: function(map_id, callback) {
	if (map_id != this.map_id) {
	    this.loadFinishCallback = callback;
	    //printfire("loading map_id: " + map_id);
	    this.frame().location.href = bevbase + 'bev/map.cgi?m=' + map_id;
	    // set thumbnail nav
	    if (MainThumbKey) {
	        alert('set:' + map_id);
	    }
	    return false;
	} else {
	    this.loadFinishCallback = null;
	    return true;
	}
    },

    hand_current_x: 0,
    hand_current_y: 0,
    hand_is_mousedown: false,
    hand_stack: Array(),
    
    /*
     * Handtool: override default browser behaviour for mousedown on images
     */
    clobberImages: function() {
        images = this.frame().document.getElementsByTagName('img');
        for (i=0; i<images.length; i++) {
            images[i].onmousedown = function() { return false; }
        }
    },
    
    setCursorStyle: function(cursor_style) {
        this.frame().document.getElementsByTagName('body')[0].style.cursor = cursor_style;
    },

    snapRelative: function(x, y) {
        this.frame().scrollBy(x, y);
    },
    
    // x-browser mouse event x y coords
    eventCoords: function(mouse_event) {
        xy_coords = Array();
        if (mouse_event.pageX) { 
            xy_coords[0] = mouse_event.pageX; 
            xy_coords[1] = mouse_event.pageY; 
        } else if (mouse_event.offsetY) { 
            xy_coords[0] = mouse_event.offsetX; 
            xy_coords[1] = mouse_event.offsetY;
        }
        // returns array[0] = x, array[1] = y
        return xy_coords;
    },
    
    /*
     * Handtool: attach mouse events to iframe to scroll the map
     */
    init_handtool: function() {
        this.clobberImages();
        _this = this;
        addEvent(this.frame().document, 'mousedown', function(evt) {
            _this.setCursorStyle("move");
            _this.hand_is_mousedown = true;
            _this.hand_current_x = _this.eventCoords(evt)[0];
            _this.hand_current_y = _this.eventCoords(evt)[1];
            return false;
        });      
        addEvent(this.frame().document, 'mouseup', function(evt) {
            _this.hand_is_mousedown = false;
            _this.setCursorStyle("auto");
        });
        addEvent(this.frame().document, 'mouseout', function(evt) {
            _this.hand_is_mousedown = false;
            _this.setCursorStyle("auto");
        });
        addEvent(this.frame().document, 'mousemove', function(evt) {
            //evt.cancelBubble = true;
            if (_this.hand_is_mousedown) {
                //alert("event_: " + event_x + ", " + event_y);
                //alert("_current_: " + _this.hand_current_x + ", " + _this.hand_current_y);
                _this.snapRelative(
                    _this.hand_current_x - _this.eventCoords(evt)[0], 
                    _this.hand_current_y - _this.eventCoords(evt)[1]
                    );                
            }
            return false;
        });
    },
    
    /**
     * Thumbnail map key
     * Depends on Prototype library
    **/
    setThumbnail: function(map_id)
    {
        var thumb = $('legend');
        var img_src = "images/thumbnav.php?map_id=" + map_id;
        Element.setStyle(thumb, { backgroundImage: 'url("' + img_src + '")' });
        Element.setStyle(thumb, { backgroundPosition: '50% 50%' });
        Element.setStyle(thumb, { backgroundRepeat: 'no-repeat' });
    },

    /*
     * Called when the map has finished loading.
     */
    loadFinish: function(map_id, map_name, dot_id) 
    {
        this.init_handtool();
        this.setThumbnail(map_id);
        this.map_id = map_id;
        if (dot_id) {
            this.loadFinishCallback = "top.showDotMenu(" + map_id + "," + dot_id + ")";
        }
        this.center();
        var loadingdiv = this.frame().document.getElementById('loading');
        if (loadingdiv) {
	        loadingdiv.style.display = 'none';
        }
	    var mapdiv = this.frame().document.getElementById('map');
	    if (mapdiv) {
            mapdiv.style.visibility = 'visible';
        }
    	setsbmb(map_id);
    	stickydotmenu = false;
    	if (this.loadFinishCallback) {
    	    setTimeout(this.loadFinishCallback, 300);
    	    this.loadFinishCallback = null;
    	}
    },

    /*
     * Get a dot element.
     */
    getDotElement: function(dot_id) {
	var de = this.frame().document.getElementById('d' + dot_id);
	return de;
    }

};

/*
 * Toggle a category list menu.
 */
function mtoggle(evt) {
    evt = (evt) ? evt : ((window.event) ? event : null);
    if (evt) {
	var elem = (evt.target) ? evt.target : 
	    ((evt.srcElement) ? evt.srcElement : null);
	if (elem.nodeType == 3) 
	    elem = elem.parentNode;
	if (elem.parentNode.nodeName != "LI")
	    elem = elem.parentNode;
	if (elem) {
	    var siblings = elem.parentNode.childNodes;
	    for (var c = 0; c < siblings.length; c++) {
		var n = siblings[c];
		if (n.nodeName == "UL")
		    if (n.style.display == 'none')
			n.style.display = 'block';
		    else
			n.style.display = 'none';
	    }
	}
    }
}

/*
 * An index click popup
 */
function showDotMenu(map_id, dot_id) {
    stickydotmenu = true;
    if (map.load(map_id, 'top.showDotMenu(' + map_id + ',' + dot_id + ')')) {
       var d = map.getDotElement(dot_id);
       if (d) {
           popupDotMenu(map_id, dot_id);
           var x = parseInt(d.style.left);
           var y = parseInt(d.style.top);
           map.slideTo(x, y);
       }
    }
}

/*
 * A mouseover popup
 */
function popupDotMenu(map_id, dot_id) {
	var d = map.getDotElement(dot_id);
	if (!d)
	    return;
	hideAllMenus();
	d.style.zIndex = 10; // This gets reset in hideAllMenus()
	var nl = d.getElementsByTagName("div");
	for (var i = 0; i < nl.length; i++) {
	    if (nl[i].className == 'dotlabel') {
		nl[i].style.visibility = 'visible';
	    }
	}
}

function isPoppedUp(dot_id) {
    var d = map.getDotElement(dot_id);
    if (!d)
	return false;
    var nl = d.getElementsByTagName("div");
    for (var i = 0; i < nl.length; i++) {
	if (nl[i].className == 'dotlabel') {
	    if (nl[i].style.visibility == 'visible')
		return true;
	    else
		return false;
	}
    }
}

/*
 * Given an event, return the element in which the event occured.
 * If the element is text, return the parent element.
 *
 * May return null.
 */
function elemOfEvt(evt) {
    evt = (evt) ? evt : ((window.event) ? event : null);
    if (evt) {
	var elem = (evt.currentTarget) ? evt.currentTarget : 
	    ((evt.srcElement) ? evt.srcElement : null);
	if (elem.nodeType == 3) 
	    elem = elem.parentNode; 
	return elem;
    }
    return null;
}

/*
 * Climb up the element tree until we get to the containing
 * div for the dot.
 */
function dotIdOfEvt(evt)
{
    var elem = elemOfEvt(evt);
    if (elem) {
	while (elem && elem.className != 'dot')
	    elem = elem.parentNode;
	return elem.id.substring(1);
    }
    return null;
}
    

function hideAllMenus() {
    var dotdiv = map.frame().document.getElementById("dotlist");
    var dotlist = dotdiv.getElementsByTagName("div");
    for (var i = 0; i < dotlist.length; i++) {
	if (dotlist[i].className == "dotlabel") {
	    dotlist[i].style.visibility = 'hidden';
	}
	if (dotlist[i].className == 'dot') {
	    dotlist[i].style.zIndex = 0;
	}
    }
}


function tabselect(tab, me) {
    var activebg = '#eadaba';
    var inactivebg = '#cabaaa';

    var listframe = document.getElementById('navcontent');
    var nl = listframe.getElementsByTagName("div");
    for (var i = 0; i < nl.length; i++) {
	e = nl[i];
	if (e.className == "tab") 
	    e.style.display = 'none';
    }
    for (var i = 0; i < nl.length; i++) {
	e = nl[i];
	if (e.className == "tab" && e.id == tab) {
	    e.style.display = 'block';
	}
    }

    var listframe = document.getElementById('indextabs');
    var nl = listframe.getElementsByTagName("span");
    for (var i = 0; i < nl.length; i++) {
	e = nl[i];
	if (e.className == "indextab") {
	    if (e.id == (tab + 'tab')) {
		e.style.background = activebg;
		/* e.style.borderBottomColor = activebg;*/
		e.style.zIndex = 3;
	    }
	    else {
		e.style.background = inactivebg;
		/* e.style.bottomBorderColor = inactivebg;*/
		e.style.zIndex = 1;
	    }
	}
    }
}


// Get an event in a portable way
function getEvent(e)
{
    evt = (e) ? e : ((window.event) ? window.event : null);
    return evt;
}

/*
 * dot events
 */

// Mouse over
function de_movr(e)
{
    evt = getEvent(e);
    if (!stickydotmenu)
	popupDotMenu(map.map_id, dotIdOfEvt(evt));
}

// Mouse out
function de_mout(e)
{
    return;
    evt = getEvent(e);
    if (isPoppedUp(dotIdOfEvt(evt))) {
	stickydotmenu = false;
    }
}

// Mouse up
function de_mup(e)
{
    evt = getEvent(e);
    stickydotmenu = false;
    if (isPoppedUp(dotIdOfEvt(evt)))
	hideAllMenus();
    else
	popupDotMenu(map.map_id, dotIdOfEvt(evt));
}

// Mouse click anywhere else on the map
function mapclick(e)
{
    evt = getEvent(e);
    stickydotmenu = false;
    hideAllMenus();
}

/*
 * When the window resizes, resize the map frame and
 * the index column.
 */
function be_resize(e)
{
    var divpos = getElementPosition('mapdiv');
    var divheight = bevGetInsideWindowHeight(window) - divpos.top - 3;
    var div = document.getElementById('mapdiv');
    if (div && div.style)
	div.style.height = divheight + 'px';
    divpos = getElementPosition('navcontent');
    divheight = bevGetInsideWindowHeight(window) - divpos.top - 8;
    div = document.getElementById('navcontent');
    if (div && div.style)
	div.style.height = divheight + 'px';
    tabrefresh();
}

/*
 * For some reason, IE/Windows doesn't properly resize the
 * index tabs on a window resize without some kick.  Here
 * we just flip the display from block to none and back.
 */
function tabrefresh() {
    var listframe = document.getElementById('navcontent');
    var nl = listframe.getElementsByTagName("div");
    for (var i = 0; i < nl.length; i++) {
	var e = nl[i];
	if (e.className == "tab") {
	    if (e.style.display == 'block') {
		e.style.display = 'none';
		e.style.display = 'block';
	    }
	}
    }
}


/*
 * Putting a <base> in the <head>, where it belongs, messes
 * up the DOM in IE, so we have to look for the body.
 */
function getBody(doc)
{
    var body = doc.getElementsByTagName('body');
    if (body.length > 0)
        return body[0];
    return undefined;
}


function getElementPosition(elemID) {
    var offsetTrail = document.getElementById(elemID);
    var offsetLeft = 0;
    var offsetTop = 0;
    while (offsetTrail) {
        offsetLeft += offsetTrail.offsetLeft;
        offsetTop += offsetTrail.offsetTop;
        offsetTrail = offsetTrail.offsetParent;
    }
    body = getBody(document);
    if (body && navigator.userAgent.indexOf("Mac") != -1 && 
        typeof body.leftMargin != "undefined") {
        offsetLeft += body.leftMargin;
        offsetTop += body.topMargin;
    }
    return {left:offsetLeft, top:offsetTop};
}

/*
 * Color Key popup
 */
function colorkey()
{
    var newWindow = window.open("colorkey.php","colorkeywin",
				"menubar,height=300,width=300", 1);
    newWindow.focus();
}

/*
 * Status bar
 */
function setsbmb(map_id)
{
    var sbe = document.getElementById('statusbar');
    var mbs = sbe.getElementsByTagName('a');
    for (var i = 0; i < mbs.length; i++) {
	if (mbs[i].id == 'sbmb' + map_id) {
	    mbs[i].className = 'sbmba';
	} else {
	    mbs[i].className = 'sbmb';
	}
    }
}

/*
 * A location with a link
 */
function dotlink(e, link, external)
{
    var evt = getEvent(e);
    if (external) {
	return true;
    }
    else {
	var w = window.open(link, 'bev_adwin', 'width=480,titlebar,resizable,scrollbars', 1);
	w.focus();
	return false;
    }
}

/*
 * Toggle the map legend
 */
function legendtoggle()
{
    var maplegend_element = document.getElementById('legend');
    var button_element = document.getElementById('legendbuttontext');
    if (maplegend_element && button_element) {
	if (maplegend_element.className == 'legendv') {
	    maplegend_element.className = 'legendh';
	    button_element.innerHTML = 'Show';
	}
	else {
	    maplegend_element.className = 'legendv';
	    button_element.innerHTML = 'Hide';
	}
	be_resize();
    }
}


/*
 * Home page section mouseovers.
 */
function section_over(section) {
    var section_image = map.frame().document.getElementById(section);
    if (section_image) {
	section_image.style.visibility = 'visible';
    }
}

function section_out(section) {
    var section_image = map.frame().document.getElementById(section);
    if (section_image) {
	section_image.style.visibility = 'hidden';
    }
}