d = document, debug = (location.search && location.search.indexOf('debug')+1)? true:false;
/*
xpress notes:
currently the ve_miss_ruin interactive has items with body content like:
>>
lat: 30.29242307425725,
lon: -89.36038970947267,
address: "100 Nicholson Ave.
Waveland, Miss",
date: "11/19/05",
type: "360video",
flashvars: "something extra for your flash"
>>

strings are " delimited and using this character in the string may break the current scripting

lat/lon: can be found using debug mode of the map (use ?debug on the url), the lat/lon values are _not_ quoted
address: any string for that specific pin, line-breaks are preserved
date: expected format is numerical date representation ordered with Month first, day second, year last with 2 or 4 character year format
type: this is important and the expected types include: 360video, 360photo, photo, audio
*/

/* in ff ve api2 does not track pin positions properly, this seems to fix it */
function fffix(){ map.DetachEvent("onendzoom", fffix); setTimeout('map.SetZoom('+arguments.callee.z+')', 500); };

function compassEvent(e) { 
// Brendens compassevent code:
	if(!e)e=window.event;
	mouseDown = (e.type=="mousedown" || window.mouseDown);
	var w = (e.srcElement)? e.srcElement.clientWidth:e.target.clientWidth;
	var x = e.offsetX;
	var panUnit = 20;
	var deltaX = (x < w/3) ? -1 : (x > 2*(w/3)) ? 1 : 0;

	var h = e.srcElement.clientHeight;
	var y = e.offsetY;
	var deltaY = (y < h/3) ? -1 : (y > 2*(h/3)) ? 1 : 0;

	if (e.type == "mouseup") {
		mouseDown=0;
		map.StopContinuousPan();
	} else if (mouseDown) {
		map.ContinuousPan(deltaX*panUnit, deltaY*panUnit);
	}
	else if(e.type == 'click' && deltaX == 0 && deltaY == 0) map.PanToLatLong(map.definition.latitude, map.definition.longitude);
//output(deltaX+':'+deltaY+'/'+x+', '+y);
}

// simple interpreted variable
var xpress = {
interpret: function(raw){
//var str = '';
	for(var props in raw){
	//str+=props+':'+raw[props];
	this.data[props] = raw[props];
	}
this.data.item = new Array();
var key = new Array("idurl","headline","caption","imagepath","teasetype","alttext", "type", "category", "typeproperties", "target", "align", "byline", "credit", "imgheight", "imgwidth", "imgborder", "level", "timein", "timeout", "unknown");
	for(var i = 0; i<raw.length;i++){
	this.data.item[i] = new Object();
		for(var p = 0; p<raw[i].length;p++){
		// refer to elements like this: xpress.data.item[i].idurl
		this.data.item[i][key[p]] = raw[i][p];
		}
	this.data.item[i].body = raw[i].body;
	}
},
get: function(resource){ alert('method for json call for retrieving\nxpress javascript data\npassing this to interpret() method'); },
data: {}
};

xpress.definitions = 'todo, articulate these: ID, ID_WB, sPubDate, navsectionID, appFmt, itemsPerPage, appWidth, appHeight, appHeader, appDeck, appNavStyle, appLayout, copyMargin, sBodyFont,\narray elements contain arrays with:\n0 = ID/url,\n1 = headline,\n2 = caption,\n3 = tease code,\n4 = tease type [obs] ["":default, v:video, ss:slide show, cw:child window, sub:sub heading, a:audio, lv:vote, lv2:vote 2-col],\n5 = alt text,\n6 = link type,\n7 = label,\n8 = type-specific properties (for video and child-window links),\n9 = link target,\n10 = image align,\n11 = image byline,\n12 = image credit,\n13 = image height,\n14 = image width,\n15 = image border,\n16 = level,\n17 = time in,\n18 = time out (or duration),\n19 = unknown\neach array element also has: body\n';
// add window.onload events
function addLV1(fn) { var olv = window.onload;
if (typeof window.onload != 'function') { window.onload = fn;
} else { window.onload = function() { olv(); fn(); }
} }

addLV1(function(){ mapify(); });

var rfrsniff = {
dhtml: (!!d.getElementById && !!d.createElement),
opera: (!!window.opera),
ie: (!!d.all && !window.opera),
gecko: (!!window.find),
khtml: (d.childNodes && !d.all && !navigator.taintEnabled)
};

/* audio sample:
http://risingfromruin.msnbc.com/2006/02/bay_st_louis_mi.html
*/

	function mapify(){
	if(!rfrsniff.dhtml) return;
	if(rfrsniff.khtml){
var flashFile = "http://msnbcmedia.msn.com/i/msnbc/Components/Blogs/RisingFromRuin/tour/virtualTour_v1.swf?v5";
var flashAlt = "";

var swfstr = '<object id="touraltcontent" type="application/x-shockwave-flash" data="'+flashFile+'" width="805" height="430">\n<param name="movie" value="'+flashFile+'" />\n<param name="allowScriptAccess" value="always" />\n<param name="FlashVars" value="movieid=touraltcontent" />\n<a href="http://sdc.shockwave.com/shockwave/download/alternates/" title="Flash Plugin Required"><img src="'+((typeof flashAlt == 'string' && flashAlt)? (flashAlt):(flashFile.replace(/\.swf/, '.jpg')) )+'" alt="Flash Plugin Required" /></a>\n</object>';

d.getElementById('tour').innerHTML = swfstr;
return;
	}

xpress.interpret(ve_miss_ruin);
if(debug){
var outputel = d.createElement('div');
outputel.id = 'output';
outputel.style.position = 'absolute';
outputel.style.visibility = 'visible';
outputel.style.display = 'block';
outputel.style.zIndex = '8797';
outputel.style.background = 'white';
outputel.style.top = '5px';
outputel.style.left = '1006px';
outputel.style.width = '350px';
outputel.style.height = 'auto';
outputel.style.border = '1px solid black';
outputel.style.overflow = 'hidden';
d.body.appendChild(outputel);
window.onscroll = d.body.parentNode.onscroll = function(){ d.getElementById('output').style.top = d.documentElement.scrollTop + 5 + 'px'; };
/* "DOMMouseScroll" */
}
var userdef = location.search;
var myoverlay = (userdef && userdef.match(/btn\d/))? userdef.match(/btn\d+/):null;
var mymapstyle = (userdef && userdef.match(/a[ei]r/))? 'a':'r';
var myzoom = (userdef && userdef.match(/zoom\d/))? userdef.match(/zoom(\d+)/)[1]:13;

var mapdefinition = {
latitude: 30.30969657880265,
longitude: -89.37068754613811,
zoomlevel: myzoom,
mapstyle: mymapstyle,
showScaleBar: 0,
showDashboard: 0
}

var smallmapdef = {
latitude: mapdefinition.latitude,
longitude: mapdefinition.longitude,
zoomlevel: 15,
mapstyle: 'r',
showScaleBar: 0,
showDashboard: 0
	}

window.mapsm = new Msn.VE.MapControl(d.getElementById('ve_mapsm'), smallmapdef);
window.map = new Msn.VE.MapControl(d.getElementById('ve_map'), mapdefinition);

map.Init();
mapsm.Init();
map.definition = mapdefinition;
mapsm.definition = smallmapdef;
map.preferredzoom = 13;
map.maxzoom = 15;
map.minzoom = 11;
map.preferredstyle = 'r';

map.bugfix = false;
mapsm.AttachEvent('onchangeview', function(){ output('end SMALL MAP view change'); setup360videoroute(0); });
map.AttachEvent('onendzoom', function(){ if(launchme.busy) d.getElementById('overlay').style.left = d.getElementById('overlay').style.top = '1px'; output('zoom event'+map.GetZoomLevel()); updateZoomKontroll() });
map.AttachEvent('onchangeview', function(){ if(launchme.busy) d.getElementById('overlay').style.left = d.getElementById('overlay').style.top = '1px'; output('view event '); updateViewKontroll(); });

if(debug){
	map.AttachEvent('onclick', function(e){ output('lat: '+e.view.latlong.latitude+', long: '+e.view.latlong.longitude); });
	mapsm.AttachEvent('onclick', function(e){ output('pinlat: '+e.view.latlong.latitude+',<br>pinlon: '+e.view.latlong.longitude); });
	map.AttachEvent('onmouseup', function(e){ output('centerlat: '+map.GetCenterLatitude()+',<br>centerlon: '+map.GetCenterLongitude()); });
	mapsm.AttachEvent('onmouseup', function(e){ output('centerlat: '+map.GetCenterLatitude()+',<br>centerlon: '+map.GetCenterLongitude()); });
	}

// setup compass
var compass = d.getElementById('compass');
compass.onmousedown = compass.onmouseup = compass.onmousemove = compass.onclick = compassEvent;

// create pins
initpins();

// setup toolbelt/controls
givekontroll();

//map.AttachEvent('onchangeview', function(){ alert('map updated'); });

d.getElementById('overlay').onclick = function(e){
var v = e || window.event;
if(v.srcElement && !v.target) v.target = v.srcElement;
output('mouse x/y: '+v.x+'/'+v.y+', '+v.target.id);
if(v.stopPropagation) v.stopPropagation();
v.cancelBubble = true;
//output(v.target.id+', '+t);
var testel = (v.target.id == 'overlaybg')? v.target.parentNode:v.target;
if( testel.id == 'overlay' && (
( testel.className.indexOf('360video')+1 && (v.x < 95 || v.x > 785 || v.y < 21 || v.y > 502 ) ) ||
( testel.className.indexOf('360video') < 0 && (v.x < 151 || v.x > 652 || v.y < 43 || v.y > 487) )
) ) closeme(); //output('close window '+v.target.id+', '+v.target.className);
	};

if(myoverlay) setTimeout('launchme("'+myoverlay+'")', 1000);
} // end mapify

// zoom controls: +/-
function givekontroll(){
d.getElementById('ve_map').className = '';
var zin = d.getElementById('btnzoomin');
var zout = d.getElementById('btnzoomout');
zout.defaultClassName = zin.defaultClassName = zin.className;
zout.hoverClassName = zin.hoverClassName = zin.className + ' hover';
zout.activeClassName = zin.activeClassName = zin.className + ' active';
zout.disabledClassName = zin.disabledClassName = zin.className + ' disabled';
zin.onmousemove = zout.onmousemove = zin.onmouseover = zout.onmouseover = function(){ if(this.className == this.disabledClassName) return; if(launchme.busy) return; this.className = this.hoverClassName; };
zin.onclick = zout.onclick = function(){
	if(launchme.busy) closeme();
	var step = (this.id.indexOf('out')+1)? -1:1;
	var zoom = map.GetZoomLevel()+step;
	//if(zoom < map.minzoom || zoom > map.maxzoom) return;
	if(zoom < map.minzoom) zoom = map.minzoom;
	else if(zoom > map.maxzoom) zoom = map.maxzoom;
	map.SetZoom(zoom);
	};
zin.onmouseout = zout.onmouseout = function(){ if(this.className == this.disabledClassName) return; if(launchme.busy) return; this.className = this.defaultClassName; };

// more zoom controls: the tile/steps
var zoomctrl = d.getElementById('btnzoomsteps');
var zoomsteps = zoomctrl.getElementsByTagName('img');
zoomctrl.activeStep = d.getElementById('zoom0');
for(var e = 0;e<zoomsteps.length;e++){
var el = zoomsteps[e];
el.zout = d.getElementById('btnzoomout');
el.zin = d.getElementById('btnzoomin');
el.defaultClassName = el.className = 'zoomstep';
el.hoverClassName = el.className + ' hover';
el.selectedClassName = el.className + ' selected';
el.zoomlevel = (el.id.indexOf('out')+1)? -1:((el.id.indexOf('in')+1)? 1:0);
el.zoomlevel = map.preferredzoom + el.id.match(/\d+$/)[0] * el.zoomlevel;

el.onmouseover = function(){ if(!launchme.busy && this != this.parentNode.activeStep) this.className = this.hoverClassName };
el.onclick = function(){
	if(launchme.busy) closeme();
	map.SetZoom(this.zoomlevel);
	};
el.onmouseout = function(){ if(this != this.parentNode.activeStep) this.className = this.defaultClassName; }
// set currently active item
if(el == zoomctrl.activeStep) el.className = el.selectedClassName;
}

// view controls
var viewctrl = d.getElementById('ctrlview');
var viewopts = viewctrl.getElementsByTagName('div');
var myactiveView = (map.definition.mapstyle == 'a')? 'ctrlviewair':'ctrlviewroad';
viewctrl.activeView = d.getElementById(myactiveView);
for(var e = 0;e<viewopts.length;e++){
var el = viewopts[e];
el.defaultClassName = el.className = 'ctrlview';
el.hoverClassName = el.className + ' hover';
el.selectedClassName = el.className + ' selected';
el.onmouseover = function(){ if(this != this.parentNode.activeView) this.className = this.hoverClassName; }
el.onclick = function(){
	if(launchme.busy) closeme();
	output('change view: '+this.id);
	var style = (this.id.indexOf('air')+1)? 'a':((this.id.indexOf('road')+1)? 'r':null);
	if(style) map.SetMapStyle(style);
/*
	var activeEl = this.parentNode.activeView;
	activeEl.className = activeEl.defaultClassName;
	this.parentNode.activeView = this;
	this.className = this.selectedClassName;
*/
};

el.onmouseout = function(){ if(this != this.parentNode.activeView) this.className = this.defaultClassName; }
// set currently active item
if(el == viewctrl.activeView) el.className = el.selectedClassName;
}

// pin controls
var pinctrl = d.getElementById('ctrlpin');
var pinopts = pinctrl.getElementsByTagName('div');
for(var e = 0;e<pinopts.length;e++){
var el = pinopts[e];
el.defaultClassName = el.className = 'ctrlpin';
el.selectedClassName = el.className + ' selected';
el.map = d.getElementById('ve_map');
el.checkbox = el.getElementsByTagName('img')[0];
el.onclick = function(e){
	if(launchme.busy) closeme();
	/*output('icon controller '+(typeof e.target));*/
	if(!this.re) this.re=new RegExp('\\s?'+this.id);
	var isselected = (this.className.indexOf('selected')+1)? true:false;
	this.className = (isselected)? this.defaultClassName:this.selectedClassName;
	this.map.className = (isselected)? this.map.className.replace(this.re, ''):(this.map.className +' '+this.id);
	output('=='+this.map.className); };
}

// start over control
d.getElementById('ctrlstartover').onclick= function(){
	output('RESET');
	map.definition.mapstyle = map.preferredstyle;
	var z = map.definition.zoomlevel = map.preferredzoom;
	if(launchme.busy) closeme(d.getElementById('closeoverlay'));
	map.SetMapStyle(map.preferredstyle);
	if(window.find){ fffix.z = z; z = (z>1)? z-1:z+1;
	map.AttachEvent("onendzoom", fffix);
	 };
	map.SetCenterAndZoom(map.definition.latitude, map.definition.longitude, z);
	givekontroll();
	};
d.getElementById('ctrlstartover').onmouseover = function(){ this.className='hover'};
d.getElementById('ctrlstartover').onmouseout = function(){ this.className=''};
if(typeof d.getElementById('tourasphotos').onclick != 'function') d.getElementById('tourasphotos').onclick = function(){ var active = (this.className == 'active')? true:false; this.className = (active)? '':'active'; var str = (active)? 'show as video':'show as photos'; output(str); };

} // end givekontroll

// setup pins
function initpins(){ // get xpress data, pass items off for pin creation
xpress.pinlist = new Object();
	// build href from typeproperties based on item 'type' setting
	for(var i =0;i<xpress.data.item.length;i++){
var el = xpress.data.item[i];
var data = el.body;
var m = data.match(/lon:\s*?(-?\d+\.\d*)/);
var n = data.match(/lat:\s*?(-?\d+\.\d*)/);
var o = data.match(/address:\s*?(['"])(.*?)\1,?/);
var p = data.match(/date:\s*?(['"])(.*?)\1,?/);
var q = data.match(/type:\s*?(['"])(.*?)\1,?/);
var r = data.match(/flashvars:\s*?(['"])(.*?)\1/i);
q = (q && q.length > 2)? q[2]:'';
// derive a type as 1 of (photo is default): 360video, 360photo, audio, photo
q = (q.indexOf('360')+1)? ((q.toLowerCase().indexOf('vid')+1)? '360video':'360photo'):((q.toLowerCase().indexOf('audio')+1)? 'audio':'photo');
el.pin = ((m && n) && (m.length > 0 && n.length > 0))? {lon: parseFloat(m[1]), lat: parseFloat(n[1]), address: ((o && o.length > 2)? o[2]:''), date: ((p && p.length > 2)? p[2]:''), no: i, type: q}:null;
if(r) el.pin.flashvars = r[2].replace(/[\\'"]/g,''); // strip quotes from flashvars

// setup subpins and smallmap zoom for 360videos
if(el.pin.type == '360video'){
output(el.pin.type);
var subpins = data.match(/subpins:\s*?(['"])(.*?)\1/i);
var sz = data.match(/zoom:\s*?(['"])?(\d+)\1?(,|<)?/);
//output('zoom: '+((sz)? sz[2]:sz));
if(sz && sz.length > 2) el.pin.zoom = parseInt(sz[2]);
if(subpins && subpins.length > 1){
/*
extend to allow sequence of subpins

current:
subpins: "lat,lon,file|lat,long,file|..."

new:
subpins: "lat,lon,file|lat,long,file|lat,lon... & second series & third & ..."

*/
	el.pin.subpins = [];
	if(/&/.test(subpins)) subpins = subpins[2].split('&');
	else subpins = [subpins[2]];
	for(var g=0;g<subpins.length;g++){
	// change this
	suds = subpins[g].split('|');

	var tosave = [];
	for(var sc=0;sc<suds.length;sc++){
	var sp = suds[sc];
	sp = sp.split(',');
//	var inc = el.pin.subpins.length;
	if(sp.length > 1) tosave.push({lat: sp[0], lon: sp[1], swf: ((sp.length > 2)? sp[2].replace(/\s/, ''):false), audio: ((sp.length > 3 && parseInt(sp[3]) > 0)? 1:0)});
	}
	el.pin.subpins.push(tosave);

	}
} }
//if(i == 4) el.pin.subpins = [{lat: 30.321563114476348, lon: -89.32282269001008}, {lat: 30.318562442479045, lon: -89.3265026807785}, {lat: 30.320470287784662, lon: -89.32683527469635}, {lat: 30.322109523250724, lon: -89.32771503925323}, {lat: 30.323387552211827, lon: -89.32799398899078}, {lat: 30.323952472742878, lon: -89.32774722576141}, {lat: 30.32378577522009, lon: -89.3273288011551}, {lat: 30.323313464031674, lon: -89.32686746120453}, {lat: 30.321785382820092, lon: -89.3254190683365}, {lat: 30.32035915218399, lon: -89.32421743869783}, {lat: 30.322554056954427, lon: -89.32654559612274}, {lat: 30.321211188567403, lon: -89.32542443275451}];

if(el.pin) createpin(el.pin);
}

// sort and setup lists
for(var list in xpress.pinlist){
	// look through the pinlist lists and sort each one
	xpress.pinlist[list].sort(byDateThenNumAndName);
	var mylist = xpress.pinlist[list];
	// tack the list values (1 for each pin) onto an element with a name that is the 'list' value prefixed by 'list' (eg listvideo360)
	var listel = d.getElementById('list'+list);
	for(var i=0;i<mylist.length;i++){ listel.innerHTML += mylist[i].html; }
	}

	}

function byDateThenNumAndName(a, b){
if(a.date != b.date){ return b.date - a.date;
} else {
var anum = a.key.match(/^\d*/);
var bnum = b.key.match(/^\d*/);
anum = (anum)? parseInt(anum[0]):false;
bnum = (bnum)? parseInt(bnum[0]):false;
// compare numbers
if( (anum && bnum) && (!isNaN(anum) && !isNaN(bnum)) ) return anum - bnum;
// numbers first
else if( (anum || bnum) && (!isNaN(anum) || !isNaN(bnum)) ) return ( isNaN(anum) )? 1:-1;
// compare string keys
else return ((a.key<b.key)? -1:((a.key>b.key)? 1:0));
} }

// setup pins step 2
function createpin(data){
// expect data{lon, lat, address, date, no, type}
/* for pins the following is created:
pin with id 'pin1' where 1 is the index for the item array element and classname of 'pin'
link inside with id 'btn1' where 1 is the index for the item array el and className of 'btn': the button later has state(s) associated via additional (the btn class remains) classnames: visited, etc (eg class="btn visited")
image inside link with className 'ico' plus the data type (360video, 360photo, audio, photo) for the element (eg 'ico360video')
*/
var w = 32, h = 38;
var pinid = 'pin'+data.no;
//var alttxt = data.type.replace(/(360)/, '$1 ') +' of '+ data.address;
var alttxt = data.type.replace(/(360)/, '$1 ') +' of '+data.address.replace(/<br>.*/, '');
var myhtml = '<div onclick="if(this.parentNode.defaultClassName) this.parentNode.className = this.parentNode.defaultClassName; launchme(this.id);" onmouseover="if(!this.defaultClassName) this.defaultClassName = this.className; if(!this.activeClassName || (this.activeClassName && this.className.indexOf(\'active\')<0) ){ this.className += \' hover\'; if(!this.parentNode.defaultClassName) this.parentNode.defaultClassName = this.parentNode.className; this.parentNode.className += \' hover \'; }" onmouseout="if(!this.activeClassName || (this.activeClassName && this.className != this.activeClassName)){ this.className = this.defaultClassName; this.parentNode.className = this.parentNode.defaultClassName; }" id="btn'+data.no+'" class="btn" title="'+alttxt+'"><img src="/images/ico.gif" class="ico'+data.type+'" alt="'+alttxt+'" /></div>';
var classnammen = 'pin pin'+data.type;
var z = (/360video/i.test(data.type))? 222:111;
//xpress.pinlist[data.type.replace(/^(360).*/, "$'$1")]
var handle = data.type.replace(/^(\d*)(.*)/, "$2$1");
if(typeof xpress.pinlist[handle] == 'undefined') xpress.pinlist[handle] = new Array();
var addrsml = data.address.slice(data.address.indexOf("<br>")+4);
var naddress = data.address.slice(0,data.address.indexOf("<br>"));
var str = "<p onmouseover=\"this.className='hover'\" onmouseout=\"this.className=''\" onclick=\"launchme('btn"+data.no+"');\" title=\"launch\">"+naddress+"<br><span>"+addrsml+" - "+data.date+"</span></p>";
var strkey = data.address.replace(/[^a-zA-Z0-9]/, '');
// expecting format MM/DD/YY or MM/DD/YYYY where '/' is any non-number character
var dateval = data.date.match(/(\d+)([^0-9])(\d+)\2(\d+)/);
if(!dateval || (dateval && dateval.length < 5)) dateval = [0, 0, 0, 0];
var year = dateval[4]; if(year.length < 4) year = '20'+year;
var month = dateval[1]; if(month.length < 2) month = '0'+month;
var day = dateval[3]; if(day.length < 2) day = '0'+day;
dateval = parseInt(year+month+day);
//output(dateval);
var listitm = {html: str, key: strkey, date: dateval};
xpress.pinlist[handle].push(listitm);
map.AddPushpin(pinid, data.lat, data.lon, w, h, classnammen, myhtml, z)

if(!map.$pins) map.$pins = [];
map.$pins.push({'data':data, el:document.getElementById(pinid), id:pinid});

if(xpress.data.item[data.no].pin.subpins){
	var subpins = xpress.data.item[data.no].pin.subpins;
	output('create subpins');

	for(var i = 0;i<subpins.length;i++){
	for(var p=0,pt;pt=subpins[i][p];p++){
	pt.latitude = pt.lat, pt.longitude = pt.lat;
	var subpinhtml = (debug)? '.':'';
	mapsm.AddPushpin('subpin'+i+'_'+p, pt.lat, pt.lon, 10, 10, 'subpin', subpinhtml, 111);
	}
		}

	}

}

function closeme(x){
// add el.StopPlay() to flash objects
// turn off the close button hover state
if(typeof x == 'object') x.className='';
// get the pin btn id

var pin = d.getElementById(launchme.busy);
if(!pin) return;
var el = d.getElementById('overlay');

for(i=0; fob=el.getElementsByTagName("object")[i]; ++i){ fob.parentNode.removeChild(fob); }

d.getElementById('mapsmroute').innerHTML = '';
// hide the overlay
el.style.top = el.style.left = '-1000px';
// deactivate the pin state
pin.className = pin.defaultClassName;
output(launchme.busy);
// move pin to specific position on left:
// get pin lat, lon
//
//map.SetCenter(lat, lon);

// toggle the busy state
launchme.busy = false;
}

function launchme(elstr){
output('launch: '+elstr);
var item = launchme.getCurrent(elstr);
if(!item) return;
if(arguments.callee.busy){
	closeme();
	}
var pin = (typeof elstr == 'object')? elstr:d.getElementById(elstr);
if(!pin){ arguments.callee.busy = false; return; }

/* show associated icon type on the map */
if(d.getElementById('ve_map').className.indexOf('ctrlpin'+item.pin.type)+1){
//output('icon type hidden ('+item.pin.type+')');
d.getElementById('ctrlpin'+item.pin.type).onclick();
}

scrollme2map();
arguments.callee.busy = elstr;

// move pin to targetted visual point of overlay: x 46, y 237
/*
// line up next to point
var tx = 55, ty = 210;
if(item.pin.type.indexOf('360video')<0) tx = 112, ty = 233;
*/
// line up next to icon
var tx = 46, ty = 237;
if(item.pin.type.indexOf('360video')<0) tx = 103, ty = 259;
/*
switch(item.pin.type){
case: '360video' ;
case: '360video' ;
case: '360video' ;
default: swfw = , swfh = ; // default to photo

}
*/
 
//output(item.pin.type+'\n'+(item.pin.type.indexOf('360video')+1));
/* when the map is hidden on init the center = 0,0 = top:0px;left:0; */
var rx = map.GetX(item.pin.lon), ry = map.GetY(item.pin.lat);
//output(item.pin.lon+'/'+item.pin.lat+'BUGGGG::'+rx+', '+ry);
// there was a data error: lat and long mislabelled (swapped labels)
var center = d.getElementById('ve_map');
var cx = center.offsetWidth/2, cy = center.offsetHeight/2;
var myx = cx + (rx - tx), myy = cy + (ry - ty);
var z = map.GetZoomLevel();
//output('BUG:: '+myx+', '+myy+', '+z);
var coords = map.PixelToLatLong({x:myx, y:myy}, z);
//output(coords.latitude+', '+coords.longitude);
var noviewchange = (coords.latitude == map.GetCenterLatitude() && coords.longitude == map.GetCenterLongitude() )? true:false;
/////////////////////////// BUG
/*
var at = new Msn.VE.MapView();
var e = at.MakeCopy();
e.SetZoomLevel(m);
au(e); this.SetView(e);
this.SetView = au;
Msn.VE.LatLong creates {latitude: A, longitude: O}
*/
if(window.find && !noviewchange){ // bugfix pin positions
window.fffix.z = z; map.AttachEvent("onendzoom", fffix);
map.SetCenterAndZoom(coords.latitude, coords.longitude, ((z>1)? z-1:z+1));
}
else map.SetCenter(coords.latitude, coords.longitude);

var el = d.getElementById('overlay');
// setup overlay before showing it
el.className = 'ovr'+item.pin.type;
d.getElementById('ovrHeadline').innerHTML = '<img src="/images/ico.gif" alt="" class="ico'+item.pin.type+'" /> '+item.headline+' <span>- '+item.pin.date+'</span>';

var contenttext = item.caption;

if(item.pin.type != 'photo'){
var swf = d.getElementById('ovrswfbox');
if(item.pin.type == '360video') setup360videoflashvars();
if(item.pin.flashvars) output('item has '+item.pin.flashvars+'<br>...'+item.pin.imgpath);
var swfstr = '<object id="ovrswf" type="application/x-shockwave-flash" data="'+item.imagepath+'" >\n<param name="movie" value="'+item.imagepath+'" />\n<param name="allowScriptAccess" value="always" />\n<param name="FlashVars" value="movieid=ovrswf'+((item.pin.flashvars)? '&'+item.pin.flashvars:'')+((item.pin.subpins && item.pin.subpins[0].flashvarscoords)? (item.pin.subpins[0].flashvarscoords):'')+'" />\n<a href="http://sdc.shockwave.com/shockwave/download/alternates/" title="Flash Plugin Required"><img src="'+item.imagepath.replace(/\.swf/, '.jpg')+'" alt="Flash Plugin Required" /></a>\n</object>';
swf.innerHTML = swfstr;

/*
rx = mapsm.GetX(item.pin.lon), ry = mapsm.GetY(item.pin.lat);
center2 = d.getElementById('ve_mapsm');
cx = center2.offsetWidth/2, cy = center2.offsetHeight/2;
myx = rx - cx, myy = ry - cy;
z = mapsm.GetZoomLevel();
coords = mapsm.PixelToLatLong({x:myx, y:myy}, z);
mapsm.SetCenter(coords.latitude, coords.longitude);
*/
// setbestmapview() does not work
//mapsm.SetBestMapView(item.pin.subpins);

// loop thru subpins and get their x and y coordinates for passing to flash
//if(item.pin.subpins)
// use map methods to GetX and GetY coords for passing as list with obj {x: x, y: y}
if(item.pin.type == '360video'){
// if no zoom change && no lat change && no long change
if( item.pin.lat == mapsm.GetCenterLatitude() && item.pin.lon == mapsm.GetCenterLongitude() ) { setup360videoroute(0); output('~~~~~NO change');
//if( ( (item.pin.zoom && item.pin.zoom == mapsm.GetZoomLevel()) || (!item.pin.zoom && mapsm.definition.zoomlevel == mapsm.GetZoomLevel()) ) && item.pin.lat == mapsm.GetCenterLatitude() && item.pin.lon == mapsm.GetCenterLongitude() ) { setup360videoroute(0); output('~~~~~NO change');
} else { output('~~~~~~~~~change '+((item.pin.zoom)? item.pin.zoom:mapsm.definition.zoomlevel)); mapsm.SetCenterAndZoom(item.pin.lat, item.pin.lon, ((item.pin.zoom)? item.pin.zoom:mapsm.definition.zoomlevel));
}
// else it is a photo:
} } else { contenttext = '<img src="'+item.imagepath+'" alt="'+((item.alttext)? item.alttext:'')+'" /> '+contenttext; }

d.getElementById('ovrContent').innerHTML = contenttext;
var shareurl = location.toString().match(/(^[^?]*)/)[1]+'?'+((map.GetMapStyle() == 'a')? 'aerial':'road')+'zoom'+map.GetZoomLevel()+launchme.busy;
if(d.all && !window.opera) d.getElementById('Emailthis').onfocus = d.getElementById('Linktothis').onfocus = function(){ if(this.blur) this.blur(); };
var emailsubject = encodeURIComponent('MSNBC.com Exclusive: Virtual tour of towns rebuilding from Katrina');
var emailbody = encodeURIComponent("Experience the devastation and reconstruction of Bay St. Louis and Waveland, Miss., first-hand via 360-degree video, photos and audio using Windows Live Local map technology--part of MSNBC.com's continuing 'Rising from Ruin' coverage. ");
d.getElementById('Emailthis').href="mailto:user@localhost&subject="+emailsubject+"&body="+emailbody+encodeURIComponent(shareurl);
//output('linktothisbase = '+shareurl);
d.getElementById('Linktothis').href=shareurl;

// show the overlay (aka popup)
if(noviewchange) el.style.top = el.style.left = '1px';

if(!pin.defaultClassName) pin.defaultClassName = pin.className;
if(!pin.activeClassName) pin.activeClassName = pin.defaultClassName+' active';
if(pin.className.indexOf('active') < 0) pin.className = pin.activeClassName;
}

launchme.getCurrent = function(elstr){
if(!arguments.callee.re) arguments.callee.re = new RegExp('.*?(\\d+)');
var itemindex = elstr.match(arguments.callee.re);
if(!itemindex || (itemindex && itemindex.length < 2)) return false;
itemindex = itemindex[1];
return xpress.data.item[itemindex];
}

function setup360videoflashvars(n){
var item = launchme.getCurrent(launchme.busy);
// if flashvar is already setup we do not need anything else
if(item.pin.subpins && item.pin.subpins[n] && item.pin.subpins[n].flashvarcoords ) return true;

if( (!item.pin.subpins && n > 0) || (!item.pin.subpins[n]) ) return;

// setup flashvar and tack it onto item.pin.subpins[n]
if(n == 0 && !item.pin.subpins) item.pin.subpins = [{lon: item.pin.lon, lat: item.pin.lat}];
var swfcoords = [];

if(!item.pin.subpins.sequences){
var sequences = [];
	for(var l=0,p,pt,seq;seq=item.pin.subpins[l];l++){
var mysequence = [];
for(p=0;pt=seq[p];p++) if(pt.swf && (l==0 || (l>0 && p>0)) ) mysequence.push(pt.swf);
sequences.push( mysequence.join('|').replace(/\s/g, '') );
	}
	
item.pin.subpins.sequences = sequences.join('&').replace(/\s/g, '');
output('__end subpin sequence __');
output(item.pin.subpins.sequences);
output('__subpin sequence is: ');
/*
__subpin sequence is:
YachtClub00000.swf&YachtClub00300.swf|YachtClub00600.swf&YachtClub00900.swf|YachtClub01200.swf|YachtClub01500.swf
__end subpin sequence __
*/
};

for(l=0;pt=item.pin.subpins[n][l];l++){
	/* for subpins > 0 the first array value
	eg '30.123432, -80.1234, 13' is the map center and zoom
	so it is not needed for the swfcoords
	*/
	if(l== 0 && !item.pin.subpins[n].lat){ // make available pre mapsm onchangeview event
	item.pin.subpins[n].lat = (n==0)? item.pin.lat : pt.lat;
	item.pin.subpins[n].lon = (n==0)? item.pin.lon : pt.lon;
	item.pin.subpins[n].zoom = (n==0)? item.pin.zoom : pt.swf;
	};
	if(n > 0 && l== 0) continue;
	var x = mapsm.GetX(pt.lon);
	var y = mapsm.GetY(pt.lat);
	swfcoords.push(x+','+y+((pt.swf)? (','+pt.swf+((pt.audio)? (',1'):'')):'') );
} // end for l
item.pin.subpins[n].flashvarscoords = swfcoords.join('|').replace(/\s/g, '');
output('swfcoords '+swfcoords);
output(' /end swfcoords/ ');
/*
swfcoords 83,57,CourtHouse00000.swf|83,57,CourtHouse00300.swf|83,57,CourtHouse00600.swf|83,57,CourtHouse00900.swf|83,57,CourtHouse01200.swf|83,57,CourtHouse01500.swf|83,57,CourtHouse01800.swf|83,57,CourtHouse02100.swf|83,57,CourtHouse02400.swf|83,57,CourtHouse02700.swf|83,57,CourtHouse03000.swf|83,57,CourtHouse03300.swf|83,57,CourtHouse03600.swf|83,57,CourtHouse03900.swf|83,57,CourtHouse04200.swf|83,57,CourtHouse04500.swf|83,57,CourtHouse04800.swf|83,57,CourtHouse05100.swf|83,57,CourtHouse05400.swf|83,57,CourtHouse05700.swf|83,57,CourtHouse06000.swf|83,57,CourtHouse06300.swf|83,57,CourtHouse06600.swf|83,57,CourtHouse06900.swf|83,57,CourtHouse07200.swf|83,57,CourtHouse07500.swf|83,57,CourtHouse07800.swf"
HAVE 30.310699134575312

swfcoords 83,57,CourtHouse00000.swf|83,57,CourtHouse00300.swf|83,57,CourtHouse00600.swf|83,57,CourtHouse00900.swf|83,57,CourtHouse01200.swf|83,57,CourtHouse01500.swf|83,57,CourtHouse01800.swf|83,57,CourtHouse02100.swf|83,57,CourtHouse02400.swf|83,57,CourtHouse02700.swf|83,57,CourtHouse03000.swf|83,57,CourtHouse03300.swf|83,57,CourtHouse03600.swf|83,57,CourtHouse03900.swf|83,57,CourtHouse04200.swf|83,57,CourtHouse04500.swf|83,57,CourtHouse04800.swf|83,57,CourtHouse05100.swf|83,57,CourtHouse05400.swf|83,57,CourtHouse05700.swf|83,57,CourtHouse06000.swf|83,57,CourtHouse06300.swf|83,57,CourtHouse06600.swf|83,57,CourtHouse06900.swf|83,57,CourtHouse07200.swf|83,57,CourtHouse07500.swf|83,57,CourtHouse07800.swf
end SMALL MA

*/
}; // end setup360videoflashvars()
// advance360videoroute(1)

function advance360videoroute(n){
/* this does the mapsm.SetCenterAndZoom({latitude: , longitude: }, z) which, on completion redraws the 360videoroute
GetX/Y (in setup360videoflashvars) must happen after the map is in position
*/
var index = (n)? parseInt(n, 10) : 0;
output('advance to '+index+'/'+n);
d.getElementById('mapsmroute').innerHTML = ' ';
var item = launchme.getCurrent(launchme.busy).pin.subpins[index];
/* subpins[0] is setup with lat,lon,zoom, otherwise grab it from the first subpin{lat,lon,swf} and save for later */
if(!item.lat) item.lat = item[0].lat, item.lon = item[0].lon, item.zoom = item[0].swf;
setup360videoroute.index = index;
mapsm.AttachEvent("onchangeview", setup360videoroute);
mapsm.SetCenterAndZoom(item.lat, item.lon, item.zoom);
}

function setup360videoroute(n){
mapsm.DetachEvent("onchangeview", setup360videoroute);

var index = (typeof arguments.callee.index == 'number')? arguments.callee.index : 0;
arguments.callee.index = null;
setup360videoflashvars(index);
var item = launchme.getCurrent(launchme.busy);
output('setup360videoroute '+index+'; '+item.pin.subpins[index].flashvarscoords);

d.getElementById('mapsmroute').innerHTML = '<object id="mapsmrouteswf" type="application/x-shockwave-flash" data="/files/mapsmallroute.swf?'+(new Date()).getTime()+'" width="156" height="156">\n<param name="wmode" value="transparent" />\n<param name="movie" value="/files/mapsmallroute.swf?'+(new Date()).getTime()+'" />\n<param name="allowScriptAccess" value="always" />\n<param name="FlashVars" value="movieid=mapsmrouteswf&coords='+item.pin.subpins[index].flashvarscoords+('&sequences='+item.pin.subpins.sequences.replace(/&/g,'*'))+((debug)? '&debug=1':'')+'" />\n</object>';

}; // end setup360videoroute()

function scrollme2map(){
	if(!arguments.callee.maptop){
	var top = 0;
	var el = d.getElementById('vecredit');
	while(el){ if(el.offsetLeft) top+=el.offsetTop; el = (el.offsetParent)? el.offsetParent:null; }
	arguments.callee.maptop = top - 15;
	}
	output('maptop: '+scrollme2map.maptop+'/'+document.documentElement.scrollTop+' :scrolltop');
	while(scrollme2map.maptop < document.documentElement.scrollTop) window.scrollBy(0, -5);
	}

function output(str){ if(!debug) return; var el = d.getElementById('output'); el.innerHTML = str+'<br>'+el.innerHTML + '<div style="border:1px solid black;position:absolute;top:0;right:0;" onclick="this.parentNode.innerHTML=0">x</div>'; }

function updateViewKontroll(){
	var viewctrl = d.getElementById('ctrlview');
	var view = map.GetMapStyle();
	if(view == 'o') return; // o:birdseye h:hybrid a:aerial r:road
	var air = d.getElementById('ctrlviewair');
	var road = d.getElementById('ctrlviewroad');
if(view == 'h'){
	air.className = air.selectedClassName;
	road.className = road.selectedClassName;
	return;
	}
	viewctrl.activeView = (view == 'r')? road:air;
	inactiveView = (viewctrl.activeView == air)? road:air;
	viewctrl.activeView.className = viewctrl.activeView.selectedClassName;
	inactiveView.className = inactiveView.defaultClassName;
	}

function updateZoomKontroll(){
	var zoom = map.GetZoomLevel();
	if(zoom < map.minzoom || zoom > map.maxzoom) return;
	var zoomctrl = d.getElementById('btnzoomsteps');
var zout = d.getElementById('btnzoomout');
var zin = d.getElementById('btnzoomin');
zout.className = (zoom == map.minzoom)? zout.disabledClassName:zout.defaultClassName;
zin.className = (zoom == map.maxzoom)? zin.disabledClassName:zin.defaultClassName;
	zoomctrl.activeStep.className = zoomctrl.activeStep.defaultClassName;
	zoomctrl.activeStep = d.getElementById('zoom'+((zoom - map.preferredzoom < 0)? 'out':((zoom - map.preferredzoom > 0)? 'in':''))+Math.abs(zoom - map.preferredzoom ));
	zoomctrl.activeStep.className = zoomctrl.activeStep.selectedClassName;
	//this.className = (zoom == map.maxzoom || zoom == map.minzoom)? this.disabledClassName:this.activeClassName;
	}
<!-- ph=1 -->
<!-- nhm:from_kauri -->
