/*
	O'Reilly Conference Map Version 1.0
	(c) 2008 MakaluMedia Inc.
	Author: Alex Bendiken
	
	A conference attendee mapper utilizing Google Maps
	and Martin Pearman's ClusterMarker library:
	http://googlemapsapi.martinpearman.co.uk/clustermarker
	
	Last updated May 9th 2008
*/
var US_STATES=$H({'AL':"Alabama",'AK':"Alaska",'AZ':"Arizona",'AR':"Arkansas",'CA':"California",'CO':"Colorado",'CT':"Connecticut",'DE':"Delaware",'DC':"District Of Columbia",'FL':"Florida",'GA':"Georgia",'HI':"Hawaii",'ID':"Idaho",'IL':"Illinois",'IN':"Indiana",'IA':"Iowa",'KS':"Kansas",'KY':"Kentucky",'LA':"Louisiana",'ME':"Maine",'MD':"Maryland",'MA':"Massachusetts",'MI':"Michigan",'MN':"Minnesota",'MS':"Mississippi",'MO':"Missouri",'MT':"Montana",'NE':"Nebraska",'NV':"Nevada",'NH':"New Hampshire",'NJ':"New Jersey",'NM':"New Mexico",'NY':"New York",'NC':"North Carolina",'ND':"North Dakota",'OH':"Ohio",'OK':"Oklahoma",'OR':"Oregon",'PA':"Pennsylvania",'RI':"Rhode Island",'SC':"South Carolina",'SD':"South Dakota",'TN':"Tennessee",'TX':"Texas",'UT':"Utah",'VT':"Vermont",'VA':"Virginia",'WA':"Washington",'WV':"West Virginia",'WI':"Wisconsin",'WY':"Wyoming"})
var ConferenceMap={_lastGUID:0,_infoWindowMaximized:false,loadMap:function(options){if(!GBrowserIsCompatible()){return false;}
this.options={apiKey:'',size:null,mapDiv:'conference_map',people:'people.json',events:'events.json',clusterTitle:'%count cities',iconBasePath:'http://www.makalumedia.com/projects/oreilly/images/icons/',imageBasePath:'http://www.makalumedia.com/projects/oreilly/images/',largeIconLimit:10,clusterIntersectPadding:0,bioTeaserLength:130,fullscreen:false,animated:false,animationPause:5000};Object.extend(this.options,options||{});this.map=new GMap2($(this.options.mapDiv),{size:this.options.size});this._defaultMapControl=new GLargeMapControl();this._overviewMapControl=new GOverviewMapControl();this._typeMapControl=new GMapTypeControl();this.map.addControl(this._defaultMapControl);this.map.addControl(this._overviewMapControl);this.map.addControl(this._typeMapControl);this.map.addMapType(G_PHYSICAL_MAP);this.map.enableDoubleClickZoom();this.map.enableContinuousZoom();this.map.setCenter(new GLatLng(37.4419,-122.1419),2);this.infoWindow=this.map.getInfoWindow();var clusterIcon=new ConferenceMap.Icon('cluster',{size:new GSize(25.0,30.0),shadowSize:new GSize(42.0,30.0),iconAnchor:new GPoint(13.0,15.0),infoWindowAnchor:new GPoint(13.0,15.0),imageMap:[0,30,11,0,13,0,25,30]})
this.cluster=new ClusterMarker(this.map);this.cluster.refreshCallback=this.bindMarkerEvents.bind(this);this.cluster.clusterMarkerIcon=clusterIcon.GIcon;this.cluster.clusterMarkerClick=this._toggleClusterInfoWindow.bind(this);this.cluster.clusterMarkerTitle=this.options.clusterTitle;this.cluster.intersectPadding=this.options.clusterIntersectPadding;GEvent.addListener(this.infoWindow,'maximizeclick',function(){this._returnToSavedPosition=true;this.map.savePosition();}.bind(this))
GEvent.addListener(this.infoWindow,'restoreclick',function(){if(this._returnToSavedPosition){this.map.returnToSavedPosition();}
this._returnToSavedPosition=false;}.bind(this));GEvent.addListener(this.infoWindow,'closeclick',function(){if(this._returnToSavedPosition){this.map.returnToSavedPosition();}
this._returnToSavedPosition=false;this._infoWindowMaximized=false;}.bind(this));GEvent.addListener(this.map,'dragend',function(){this._returnToSavedPosition=false;}.bind(this));GEvent.addListener(this.infoWindow,'maximizeend',function(){this._infoWindowMaximized=true;}.bind(this));GEvent.addListener(this.infoWindow,'restoreend',function(){this._infoWindowMaximized=false;}.bind(this));GEvent.addListener(this.map,'infowindowopen',function(){if(this._infoWindowMaximized)this.maximizeInfoWindow(true);}.bind(this));this.icons={attendee:new ConferenceMap.Icon('attendee'),attendeeGroupLarge:new ConferenceMap.Icon('attendeeGroupLarge',{size:new GSize(36.0,41.0),shadowSize:new GSize(57.0,41.0),iconAnchor:new GPoint(18.0,20.0),infoWindowAnchor:new GPoint(18.0,20.0),imageMap:[0,11,5,4,15,4,15,0,22,0,32,5,36,10,36,21,28,38,22,41,14,41,3,33,1,21,0,11]}),attendeeGroupMedium:new ConferenceMap.Icon('attendeeGroupMedium',{size:new GSize(30.0,35.0),shadowSize:new GSize(48.0,35.0),iconAnchor:new GPoint(15.0,17.0),infoWindowAnchor:new GPoint(15.0,17.0),imageMap:[0,8,5,0,26,0,30,8,30,19,19,35,10,35,0,18,0,8]}),attendeeGroupSmall:new ConferenceMap.Icon('attendeeGroupSmall',{size:new GSize(23.0,35.0),shadowSize:new GSize(41.0,35.0),iconAnchor:new GPoint(11.0,17.0),infoWindowAnchor:new GPoint(11.0,17.0),imageMap:[0,13,13,0,19,0,22,8,23,19,12,35,3,35,0,22,0,13]}),speaker:new ConferenceMap.Icon('speaker'),mixedGroupLarge:new ConferenceMap.Icon('mixedGroupLarge',{size:new GSize(36.0,41.0),shadowSize:new GSize(57.0,41.0),iconAnchor:new GPoint(18.0,20.0),infoWindowAnchor:new GPoint(18.0,20.0),imageMap:[0,11,5,4,15,4,15,0,22,0,32,5,36,10,36,21,28,38,22,41,14,41,3,33,1,21,0,11]}),mixedGroupMedium:new ConferenceMap.Icon('mixedGroupMedium',{size:new GSize(30.0,35.0),shadowSize:new GSize(48.0,35.0),iconAnchor:new GPoint(15.0,17.0),infoWindowAnchor:new GPoint(15.0,17.0),imageMap:[0,8,5,0,26,0,30,8,30,19,19,35,10,35,0,18,0,8]}),mixedGroupSmall:new ConferenceMap.Icon('mixedGroupSmall',{size:new GSize(23.0,35.0),shadowSize:new GSize(41.0,35.0),iconAnchor:new GPoint(11.0,17.0),infoWindowAnchor:new GPoint(11.0,17.0),imageMap:[0,13,13,0,19,0,22,8,23,19,12,35,3,35,0,22,0,13]})}
new Ajax.Request(this.options.people,{method:'get',requestHeaders:{Accept:'application/json'},onSuccess:function(transport){if(this.options.fullscreen)this._setFullScreen();this._parseData($A(transport.responseText.evalJSON(true)));if(this.options.animated){this._startAnimation();}else{this.populateMap();}}.bind(this)});},_parseData:function(data){var duplicates=$A([]);data.each(function(params){if(!duplicates.include(params)){var matches=data.without(params).findAll(function(city){return city.name.toLowerCase()==params.name.toLowerCase()&&(city.state.toLowerCase()==params.state.toLowerCase()||city.state.substr(0,2).toLowerCase()==params.state.toLowerCase()||city.state=='');})
if(matches&&matches.length>0){matches.each(function(match){params.people=params.people.concat(match.people).sortBy(function(person){return person.fullName;});duplicates.push(match);data=data.without(match);})}}})
this.cities=data.collect(function(params){if(params.people.length>0)
return new ConferenceMap.City(params);}).compact();this.people=this.cities.pluck('people').flatten();},_setFullScreen:function(){var div=$(this.options.mapDiv);var body=$(document.body);body.innerHTML='';body.addClassName('fullscreen');body.insert(div);div.setStyle({position:'absolute',top:0,left:0,height:'100%',width:'100%',zIndex:9999})
this.map.removeControl(this._defaultMapControl);this.map.removeControl(this._overviewMapControl);this.map.removeControl(this._typeMapControl);this.map.setMapType(G_PHYSICAL_MAP);this.map.checkResize();this.map.setCenter(new GLatLng(37.604763,-122.376752),3);},_startAnimation:function(){this._animationTimeout=setTimeout(this._openRandomInfoWindow.bind(this),this.options.animationPause);},_stopAnimation:function(){clearTimeout(this._animationTimeout);},_openRandomInfoWindow:function(){var random=Math.floor(Math.random()*this.people.length);var person=this.people[random];if(this._lastPerson){if(this._lastPerson.city.state==person.city.state){return this._openRandomInfoWindow();}else{this.map.removeOverlay(this._lastMarker);}}
var marker=new GMarker(person.marker.getLatLng(),{icon:(person.type=='speaker'?this.icons.speaker:this.icons.attendee).GIcon});this.map.addOverlay(marker);this.panToMarker(marker);marker.openInfoWindowHtml(person._infoWindow(),{suppressMapPan:true,maxWidth:300})
if(this.options.animated){this._lastMarker=marker;this._lastPerson=person;this._startAnimation();}},_delegateTwitterData:function(tweets){if(tweets&&tweets.length>0){var screenName=tweets[0].user.screen_name;var person=ConferenceMap.people.find(function(p){return p.twitter==screenName;})
person.updateTweets(tweets);}},populateMap:function(){var markers=[];this.cities.each(function(city){markers.push(city.marker);})
this.addMarkers(markers);},addMarkers:function(markers){this.cluster.addMarkers(markers);this.cluster.refresh();this.cluster.fitMapToMarkers();},changeMarkerIcon:function(marker,state){if(marker&&!marker.isHidden()){var icon=marker.getIcon().image.split('.');var extension=icon.pop();marker.setImage(icon.join('.')+(state?'_'+state:'')+'.'+extension);}},triggerInfoWindow:function(index){this.cluster.triggerClick(index);},bindMarkerEvents:function(marker){GEvent.addListener(marker,'infowindowopen',function(marker){this.isInfoWindowOpen=true;}.bind(marker,marker))
GEvent.addListener(marker,'infowindowclose',function(marker){this.isInfoWindowOpen=false;if(!marker.clusterGroupBounds)ConferenceMap.changeMarkerIcon(marker);}.bind(marker,marker))
GEvent.addListener(marker,'mouseover',function(marker){if(!this.isInfoWindowOpen)ConferenceMap.changeMarkerIcon(marker,'hover');}.bind(marker,marker))
GEvent.addListener(marker,'mouseout',function(marker){if(!this.isInfoWindowOpen)ConferenceMap.changeMarkerIcon(marker);}.bind(marker,marker))
GEvent.addListener(marker,'mousedown',function(marker){ConferenceMap.changeMarkerIcon(marker,'pressed');}.bind(marker,marker))
GEvent.addListener(marker,'mouseup',function(marker){if(marker.clusterGroupBounds)ConferenceMap.changeMarkerIcon(marker);}.bind(marker,marker))
GEvent.addListener(marker,'click',function(marker){ConferenceMap._infoWindowMaximized=false;}.bind(marker,marker))},openCityInfoWindow:function(guid,options){var city=this.cities.find(function(c){return c.guid==guid;})
if(city.marker.index&&!city.marker._isVisible)
this.triggerInfoWindow(city.marker.index);else
city.openInfoWindow();},openPersonInfoWindow:function(guid){var person=this.people.find(function(p){return p.guid==guid;})
person.openInfoWindow();},zoomTo:function(marker){this.map.setCenter(marker.getLatLng(),10);},zoomToCluster:function(index){var clusterMarker=this.cluster._clusterMarkers[index];if(clusterMarker){this.map.setCenter(clusterMarker.getLatLng(),this.map.getBoundsZoomLevel(clusterMarker.clusterGroupBounds));}},panToMarker:function(marker){var xy=ConferenceMap.map.fromLatLngToContainerPixel(marker.getLatLng());var latlng=ConferenceMap.map.fromContainerPixelToLatLng(new GPoint(xy.x,xy.y-75));ConferenceMap.map.panTo(latlng);},maximizeInfoWindow:function(noAnimation){noAnimation=noAnimation||false;this.infoWindow.maximize(noAnimation);},_toggleClusterInfoWindow:function(args){if(args.clusterMarker.isInfoWindowOpen){args.clusterMarker.closeInfoWindow();return;}
var clusterMarkerIndex=this.cluster._clusterMarkers.indexOf(args.clusterMarker);var infoWindow='';var infoWindowMax='';var cities='';var markerCoords=$A([]);var marker;var people=0;for(i=0;i<args.clusteredMarkers.length;i++){marker=args.clusteredMarkers[i];cities+=templates.city.listItem.evaluate({city:'<a href="javascript:ConferenceMap.openCityInfoWindow('+marker._city.guid+')" class="highlighted zoom city">'+marker._city.label+'</a>',guid:marker._city.guid,peopleCount:marker._city.people.length+(marker._city.people.length>1?' people':' person'),teaser:marker._city.people.slice(0,12).collect(function(p){return'<a href="#" onclick="ConferenceMap.openPersonInfoWindow('+p.guid+');return false;" class="'+p.type+'">'+p.fullName+'</a>';}).join(", ")+(marker._city.people.length>12?' and '+(marker._city.people.length-12)+' more...':''),moreLink:''});markerCoords.push(marker.getLatLng().lat()+','+marker.getLatLng().lng());people+=marker._city.people.length;}
var percentage=Math.round((people/this.people.length)*100);infoWindow=templates.cluster.infoWindow.evaluate({peopleCount:people,cityCount:args.clusteredMarkers.length,cities:cities,clusterIndex:clusterMarkerIndex});infoWindowMax=templates.cluster.infoWindowMax.evaluate({markers:markerCoords.join('%7C'),cityCount:args.clusteredMarkers.length,cities:cities,clusterIndex:clusterMarkerIndex,peopleCount:people,percentage:percentage,apiKey:this.options.apiKey})
this.panToMarker(args.clusterMarker);args.clusterMarker.openInfoWindowHtml(infoWindow,{maxWidth:450,suppressMapPan:true,maxContent:infoWindowMax,maxTitle:args.clusteredMarkers.length+' Cities, '+people+' People'+' ('+percentage+'%)'});},generateGUID:function(){return this._lastGUID++;}}
ConferenceMap.City=Class.create({guid:null,isInfoWindowOpen:false,initialize:function(params){Object.extend(this,params||{});this.lat=parseFloat(this.lat);this.lng=parseFloat(this.lng);this.guid=ConferenceMap.generateGUID();this.name=this.name.titleize();if(this.state&&this.state.length>2){var match=US_STATES.find(function(s){return this.state.toLowerCase()==s.last().toLowerCase()}.bind(this));if(match){this.state=match.first();}}
var state=US_STATES.get(this.state);var location=$A([this.name]);location.push((this.country=='US'||this.country=='United States'?state:this.country));this.label=location.compact().join(', ');this.icon=this._getBaseIcon();this.marker=this._createMarker();GEvent.addListener(this.marker,'infowindowopen',ConferenceMap.panToMarker.bind(this,this.marker));this.people=this.people.collect(function(params){return new ConferenceMap.Person(this,params);}.bind(this))
return this;},hasSpeakers:function(){return this.people.find(function(p){return p.type=='speaker'});},hasAttendees:function(){return this.people.find(function(p){return p.type=='attendee'});},_geocode:function(){ConferenceMap.Geocoder.geocodeAddress(this._formattedAddress(),function(point){if(point){this.lat=point.lat()
this.lng=point.lng();}}.bind(this))},_getBaseIcon:function(){var icon;if(this.people.length>ConferenceMap.options.largeIconLimit){if(this.hasSpeakers()){icon=ConferenceMap.icons.mixedGroupLarge;}else{icon=ConferenceMap.icons.attendeeGroupLarge;}}else if(this.people.length>2){if(this.hasSpeakers()){icon=ConferenceMap.icons.mixedGroupMedium;}else{icon=ConferenceMap.icons.attendeeGroupMedium;}}else if(this.people.length==2){if(this.hasSpeakers()){icon=ConferenceMap.icons.mixedGroupSmall;}else{icon=ConferenceMap.icons.attendeeGroupSmall;}}else if(this.people.length==1&&this.people[0].type=='speaker'){icon=ConferenceMap.icons.speaker;}else{icon=ConferenceMap.icons.attendee;}
return icon;},_createMarker:function(){var title=this.name+': ';if(this.people.length>1)
title+=this.people.length+' people';else
title+=this.people[0].fullName;var marker=new GMarker(new GLatLng(this.lat,this.lng),{title:title,icon:this.icon.GIcon});marker._city=this;ConferenceMap.bindMarkerEvents(marker);GEvent.addListener(marker,'click',function(marker){if(marker.isInfoWindowOpen){marker.closeInfoWindow();return;}
if(this.people.length==1){this.people[0].openInfoWindow();}else{this.openInfoWindow();}}.bind(this,marker))
return marker;},_formattedAddress:function(){return[this.name,this.state,this.country].join(', ');},_infoWindow:function(){output='';this.people.each(function(person){output+=templates.person.listItem.evaluate($H({special:(person.organization?'<span class="supersubtle">(</span>'+person.organization+'<span class="supersubtle">)</span>':'')}).update(person));}.bind(this))
output=templates.city.infoWindow.evaluate({cityName:this.name,peopleCount:this.people.length+(this.people.length>1?' people':' person'),people:output});return output;},_infoWindowMax:function(){output='';this.people.each(function(person){output+=templates.person.listItem.evaluate($H({special:(person.organization?'<span class="supersubtle">(</span>'+person.organization+'<span class="supersubtle">)</span>':'')}).update(person));}.bind(this))
output=templates.city.infoWindowMax.evaluate({cityName:this.name,peopleCount:this.people.length,people:output});return output;},openInfoWindow:function(){this.marker.openInfoWindowHtml(this._infoWindow(),{maxWidth:300,suppressMapPan:true,maxContent:this._infoWindowMax(),maxTitle:this.name})
ConferenceMap.changeMarkerIcon(this.marker,'pressed');}})
ConferenceMap.Person=Class.create({_tweetsLastUpdated:null,tweets:[],city:null,guid:null,initialize:function(city,params){Object.extend(this,params||{});this.teaser=this.bio?this.bio.truncate(ConferenceMap.options.bioTeaserLength):'';if(this.website){this.websiteTitle=(this.website+'/').split('http://')[1].split('/')[0];}else{this.websiteTitle=null;}
this.photo=this.photo||ConferenceMap.options.imageBasePath+'avatar_'+this.type+'.png';this.city=city;this.marker=this.city.marker;this.guid=ConferenceMap.generateGUID();return this;},updateTweets:function(tweets){var container=$$('ul.twitter');if(container&&container.length>0){this.tweets=tweets;this._tweetsLastUpdated=new Date();container.first().innerHTML=$A(tweets).collect(function(t){return templates.twitter.tweet.evaluate(t)}).join("\n");}},renderLocation:function(){return this.city.label;},_renderPaginator:function(truncate){var pos=this.city.people.indexOf(this);var length=this.city.people.length;var prev=this.city.people[pos-1];var next=this.city.people[pos+1];output='<div class="paginator"><div class="inner">';if(prev){output+='<a href="#" onclick="ConferenceMap.openPersonInfoWindow('+prev.guid+');return false;" class="prev '+prev.type+'">&laquo; '+(truncate?prev.fullName.truncate(15):prev.fullName)+'</a>';}
output+='<div class="label">'+(pos+1)+' of '+length+' <span class="back inline subtle">('+'<a href="javascript:ConferenceMap.openCityInfoWindow('+this.city.guid+')" class="back inline">Back to '+this.city.name+'</a>'+')</span></div>';if(next){output+='<a href="#" onclick="ConferenceMap.openPersonInfoWindow('+next.guid+');return false;" class="next '+next.type+'">'+(truncate?next.fullName.truncate(15):next.fullName)+' &raquo;</a>';}
output+='<span class="back"><a href="javascript:ConferenceMap.openCityInfoWindow('+this.city.guid+')" class="back">Back to '+this.city.name+'</a></span>';output+='</div></div>';return output;},_infoWindow:function(){if(this.city.people.length>1){var paginator='<hr />'+this._renderPaginator(true);}
return templates.person.infoWindow.evaluate($H({location:this.renderLocation(),paginator:paginator,websiteLink:(this.websiteTitle?templates.person.websiteLink.evaluate(this):''),moreLink:(this.bio?templates.person.moreLink.evaluate(this):'')}).update(this));},_infoWindowMax:function(){var tabs=$A([]);var contents=$A([]);var sessions='';if(this.sessions&&this.sessions.length>0){sessions=this.sessions.collect(function(s){return templates.sessions.session.evaluate(s);}).join("\n")}else{sessions='No sessions';}
if(this.sessions){tabs.push(templates.tabContainer.tab.evaluate({id:'sessions',label:'Sessions'}));contents.push(templates.tabContainer.content.evaluate({id:'sessions',content:sessions}));}
if(this.twitter){tabs.push(templates.tabContainer.tab.evaluate({id:'twitter',label:'Twitter'}));contents.push(templates.tabContainer.content.evaluate({id:'twitter',content:'Loading tweets...'}));}
if(tabs.length>0&&contents.length>0){var tabContainer=templates.tabContainer.wrapper.evaluate({tabs:tabs.join("\n"),contents:contents.join("\n")})}
if(this.city.people.length>1){var paginator=this._renderPaginator();}
return templates.person.infoWindowMax.evaluate($H({tabContainer:tabContainer,websiteLink:(this.websiteTitle?templates.person.websiteLink.evaluate(this):''),paginator:paginator}).update(this));},openInfoWindow:function(){var twitterListener=GEvent.addListener(ConferenceMap.infoWindow,"maximizeclick",function(){if(this.twitter&&this.twitter!=''&&this.tweets.length==0){var url='http://www.twitter.com/statuses/user_timeline/'+this.twitter+'.json?count=5&callback=ConferenceMap._delegateTwitterData';var script=new Element('script',{src:url});document.getElementsByTagName('head')[0].appendChild(script);}
GEvent.removeListener(twitterListener);}.bind(this))
var tabListener=GEvent.addListener(ConferenceMap.infoWindow,"maximizeend",function(){setTimeout('ConferenceMap.Tabs.init()',0);GEvent.removeListener(tabListener);})
if(!this.marker._isVisible){ConferenceMap.triggerInfoWindow(this.marker.index);}
this.marker.openInfoWindowHtml(this._infoWindow(),{maxWidth:300,suppressMapPan:true,maxContent:this._infoWindowMax(),maxTitle:this.fullName+' - '+this.renderLocation()})
ConferenceMap.changeMarkerIcon(this.marker,'active'+(this.city.people.length>1&&this.type=='speaker'?'_alt':''));}})
ConferenceMap.Event=Class.create({initialize:function(params){Object.extend(this,params||{});return this;},openInfoWindow:function(){}})
ConferenceMap.Geocoder={init:function(){this._geocoder=new GClientGeocoder();},geocodeAddress:function(address,callback){if(!this._geocoder)this.init();return this._geocoder.getLatLng(address,callback);}}
ConferenceMap.Icon=Class.create({initialize:function(icon,options){this.icon=icon;this.options={basePath:ConferenceMap.options.iconBasePath,size:new GSize(16,31),anchor:new GPoint(8,15),infoWindowAnchor:new GPoint(8,15),shadowSize:new GSize(32,31),imageMap:[0,7,6,0,12,0,16,8,16,19,12,31,4,31,0,19,0,7]};Object.extend(this.options,options||{});this.GIcon=new GIcon();this.GIcon.image=this.path();this.GIcon.iconSize=this.options.size;this.GIcon.iconAnchor=this.options.anchor;this.GIcon.infoWindowAnchor=this.options.infoWindowAnchor;this.GIcon.shadow=this.path('shadow');this.GIcon.shadowSize=this.options.shadowSize;this.GIcon.imageMap=this.options.imageMap;this.GIcon.transparent=this.path('transparent');return this;},path:function(state){return this.options.basePath+this.icon+(state?'_'+state:'')+'.png';}})
ConferenceMap.Tabs={init:function(){if($$('.tabContainer').length>0){$$('.tabNavigation li a').first().addClassName('active');$$('.tabContent ul').first().show();}},swap:function(tab){$$('.tabNavigation li a').invoke('removeClassName','active');$$('.tabNavigation .'+tab+' a').invoke('addClassName','active');$$('.tabContent ul').invoke('hide');$$('.tabContent .'+tab).invoke('show');}}
var templates={cluster:{infoWindow:new Template('\
      <div class="bubble cluster">\
        <div class="header">\
          <h3 style="line-height:1;margin:0;padding:0">#{peopleCount} people from #{cityCount} cities <span style="font-size:12px;font-weight:normal"><a href="javascript:ConferenceMap.zoomToCluster(#{clusterIndex})" class="highlighted zoom">Zoom</a> in to reveal all cities</span></h3>\
        </div>\
        <div class="scroll">\
          <ul class="cities">#{cities}</ul>\
        </div>\
      </div>\
    '),infoWindowMax:new Template('\
      <div class="bubble big cluster clearfix">\
        <div class="column left">\
          <div class="header">\
            <h3 style="line-height:1;margin:0;padding:0">#{peopleCount} people from #{cityCount} cities <span class="subtle">(#{percentage}%)</span></h3>\
            <span class="subtle">#{organization}</span>\
          </div>\
          <ul class="cities">#{cities}</ul>\
        </div>\
        <div class="column right">\
          <div class="header">\
            <a href="javascript:ConferenceMap.zoomToCluster(#{clusterIndex})" class="highlighted zoom">Zoom in to show these locations</a>\
          </div>\
          <img src="http://maps.google.com/staticmap?size=310x250&markers=#{markers}&key=#{apiKey}" class="static-map" />\
        </div>\
      </div>\
    ')},city:{listItem:new Template('\
      <li>\
        <div class="clearfix"><strong>#{city}</strong> <span class="subtle">#{peopleCount}</span></div>\
        <div class="people">\
          #{teaser}\
        </div>\
        #{moreLink}\
      </li>\
    '),infoWindow:new Template('\
      <div class="bubble">\
        <div class="header">\
          <h3 style="line-height:1;margin:0;padding:0">#{cityName} <span class="subtle" style="font-size:12px;font-weight:normal">#{peopleCount}</span></h3>\
        </div>\
        <div class="scroll">\
          <ul class="people">\
            #{people}\
          </ul>\
        </div>\
      </div>\
    '),infoWindowMax:new Template('\
      <div class="bubble big city">\
        <div class="column">\
          <div class="header">\
            <h3 style="line-height:1;margin:0;padding:0">#{cityName} <span class="subtle" style="font-weight:normal">#{peopleCount} people</span></h3>\
          </div>\
          <ul class="people">\
            #{people}\
          </ul>\
        </div>\
      </div>\
    ')},person:{moreLink:new Template('<a href="#" onclick="ConferenceMap.maximizeInfoWindow();return false;" class="highlighted">More information &raquo;</a>'),websiteLink:new Template('<a href="#{website}" class="external website" target="_blank">#{websiteTitle}</a>'),listItem:new Template('<li class="#{type}"><a href="#" onclick="ConferenceMap.openPersonInfoWindow(#{guid});return false;" class="#{type}">#{fullName}</a> #{special}</li>'),infoWindow:new Template('\
      <div class="bubble">\
        <div class="header clearfix">\
          <span class="location">#{location}</span>\
          <div class="photo"><span class="mask"><img src="#{photo}" /></span></div>\
          <h3>#{fullName}</h3>\
          <span class="organization">#{organization}</span>\
          #{websiteLink}\
        </div>\
        <p class="teaser">\
          #{teaser}\
        </p>\
        <div class="footer">\
          #{moreLink}\
          #{paginator}\
        </div>\
      </div>\
    '),infoWindowMax:new Template('\
      <div class="bubble big person clearfix">\
        #{paginator}\
        <div class="column left">\
          <div class="header clearfix">\
            <div class="photo"><span class="mask"><img src="#{photo}" /></span></div>\
            <h3>#{fullName}</h3>\
            <span class="organization">#{organization}</span>\
            #{websiteLink}\
          </div>\
          <p class="bio">\
            #{bio}\
          </p>\
        </div>\
        <div class="column right">\
          #{tabContainer}\
        </div>\
      </div>\
    ')},tabContainer:{wrapper:new Template('\
      <div class="tabContainer">\
        <ul class="tabNavigation clearfix">\
          #{tabs}\
        </ul>\
        <div class="tabContent">\
          #{contents}\
        </div>\
      </div>\
    '),tab:new Template('\
      <li class="#{id}"><a href="#" onclick="ConferenceMap.Tabs.swap(\'#{id}\');return false;" class="#{class}">#{label}</a></li>\
    '),content:new Template('\
      <ul class="#{id}" style="display:none">\
        #{content}\
      </ul>\
    ')},twitter:{tweet:new Template('<li>#{text}</li>')},sessions:{session:new Template('<li><span class="time">#{time}</span><br /><strong>#{title}</strong><br /><span class="location">#{location}</span></li>')}}
Event.observe(window,'unload',function(){GUnload();})