function toJSON(obj)
{if(typeof obj=='undefined')
return'undefined';else if(obj===null)
return'null';var stringescape={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'}
var json=null,i,l,v,a=[];switch(obj.constructor)
{case Array:l=obj.length;for(i=0;i<l;i++)
{if((v=toJSON(obj[i]))!==null)
a.push(v);}
json='['+a.join(',')+']';break;case Object:for(i in obj)
{if(obj.hasOwnProperty(i)&&(v=toJSON(obj[i]))!==null)
a.push(toJSON(String(i))+':'+v);}
json='{'+a.join(',')+'}';break;case String:json='"'+obj.replace(/[\x00-\x1f\\"]/g,function($0)
{var c;if((c=stringescape[$0]))
return c;c=$0.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';break;case Number:json=isFinite(obj)?String(obj):"<not_finite>";break;case Boolean:json=String(obj);break;}
if(json===null)
return"<unknown_constructor "+obj.constructor.toString()+">";return json;}
var PolylineEncoder=function(numLevels,zoomFactor,verySmall,forceEndpoints){var i;if(!numLevels){numLevels=18;}
if(!zoomFactor){zoomFactor=2;}
if(!verySmall){verySmall=0.00001;}
if(!forceEndpoints){forceEndpoints=true;}
this.numLevels=numLevels;this.zoomFactor=zoomFactor;this.verySmall=verySmall;this.forceEndpoints=forceEndpoints;this.zoomLevelBreaks=new Array(numLevels);for(i=0;i<numLevels;i++){this.zoomLevelBreaks[i]=verySmall*Math.pow(zoomFactor,numLevels-i-1);}}
PolylineEncoder.prototype.dpEncode=function(points){var absMaxDist=0;var stack=[];var dists=new Array(points.length);var maxDist,maxLoc,temp,first,last,current;var i,encodedPoints,encodedLevels;var segmentLength;if(points.length>2){stack.push([0,points.length-1]);while(stack.length>0){current=stack.pop();maxDist=0;segmentLength=Math.pow(points[current[1]].lat()-points[current[0]].lat(),2)+
Math.pow(points[current[1]].lng()-points[current[0]].lng(),2);for(i=current[0]+1;i<current[1];i++){temp=this.distance(points[i],points[current[0]],points[current[1]],segmentLength);if(temp>maxDist){maxDist=temp;maxLoc=i;if(maxDist>absMaxDist){absMaxDist=maxDist;}}}
if(maxDist>this.verySmall){dists[maxLoc]=maxDist;stack.push([current[0],maxLoc]);stack.push([maxLoc,current[1]]);}}}
encodedPoints=this.createEncodings(points,dists);encodedLevels=this.encodeLevels(points,dists,absMaxDist);return{encodedPoints:encodedPoints,encodedLevels:encodedLevels,encodedPointsLiteral:encodedPoints.replace(/\\/g,"\\\\")}}
PolylineEncoder.prototype.dpEncodeToJSON=function(points,color,weight,opacity){var result;if(!opacity){opacity=0.9;}
if(!weight){weight=3;}
if(!color){color="#0000ff";}
result=this.dpEncode(points);return{color:color,weight:weight,opacity:opacity,points:result.encodedPoints,levels:result.encodedLevels,numLevels:this.numLevels,zoomFactor:this.zoomFactor}}
PolylineEncoder.prototype.dpEncodeToGPolyline=function(points,color,weight,opacity){if(!opacity){opacity=0.9;}
if(!weight){weight=3;}
if(!color){color="#0000ff";}
return new GPolyline.fromEncoded(this.dpEncodeToJSON(points,color,weight,opacity));}
PolylineEncoder.prototype.dpEncodeToGPolygon=function(pointsArray,boundaryColor,boundaryWeight,boundaryOpacity,fillColor,fillOpacity,fill,outline){var i,boundaries;if(!boundaryColor){boundaryColor="#0000ff";}
if(!boundaryWeight){boundaryWeight=3;}
if(!boundaryOpacity){boundaryOpacity=0.9;}
if(!fillColor){fillColor=boundaryColor;}
if(!fillOpacity){fillOpacity=boundaryOpacity/3;}
if(fill==undefined){fill=true;}
if(outline==undefined){outline=true;}
boundaries=new Array(0);for(i=0;i<pointsArray.length;i++){boundaries.push(this.dpEncodeToJSON(pointsArray[i],boundaryColor,boundaryWeight,boundaryOpacity));}
return new GPolygon.fromEncoded({polylines:boundaries,color:fillColor,opacity:fillOpacity,fill:fill,outline:outline});}
PolylineEncoder.prototype.distance=function(p0,p1,p2,segLength){var u,out;if(p1.lat()===p2.lat()&&p1.lng()===p2.lng()){out=Math.sqrt(Math.pow(p2.lat()-p0.lat(),2)+Math.pow(p2.lng()-p0.lng(),2));}
else{u=((p0.lat()-p1.lat())*(p2.lat()-p1.lat())+(p0.lng()-p1.lng())*(p2.lng()-p1.lng()))/segLength;if(u<=0){out=Math.sqrt(Math.pow(p0.lat()-p1.lat(),2)+Math.pow(p0.lng()-p1.lng(),2));}
if(u>=1){out=Math.sqrt(Math.pow(p0.lat()-p2.lat(),2)+Math.pow(p0.lng()-p2.lng(),2));}
if(0<u&&u<1){out=Math.sqrt(Math.pow(p0.lat()-p1.lat()-u*(p2.lat()-p1.lat()),2)+
Math.pow(p0.lng()-p1.lng()-u*(p2.lng()-p1.lng()),2));}}
return out;}
PolylineEncoder.prototype.createEncodings=function(points,dists){var i,dlat,dlng;var plat=0;var plng=0;var encoded_points="";for(i=0;i<points.length;i++){if(dists[i]!=undefined||i==0||i==points.length-1){var point=points[i];var lat=point.lat();var lng=point.lng();var late5=Math.floor(lat*1e5);var lnge5=Math.floor(lng*1e5);dlat=late5-plat;dlng=lnge5-plng;plat=late5;plng=lnge5;encoded_points+=this.encodeSignedNumber(dlat)+
this.encodeSignedNumber(dlng);}}
return encoded_points;}
PolylineEncoder.prototype.computeLevel=function(dd){var lev;lev=0;while(dd<this.zoomLevelBreaks[lev]){lev++;}
return lev;}
PolylineEncoder.prototype.encodeLevels=function(points,dists,absMaxDist){var i;var encoded_levels="";for(i=0;i<points.length;i++){if(i==0||i==points.length-1){encoded_levels+=this.encodeNumber(this.numLevels-1);}else if(dists[i]!=undefined){encoded_levels+=this.encodeNumber(this.numLevels-this.computeLevel(dists[i])-1);}}
return encoded_levels;}
PolylineEncoder.prototype.encodeNumber=function(num){var encodeString="";var nextValue,finalValue;while(num>=0x20){nextValue=(0x20|(num&0x1f))+63;encodeString+=(String.fromCharCode(nextValue));num>>=5;}
finalValue=num+63;encodeString+=(String.fromCharCode(finalValue));return encodeString;}
PolylineEncoder.prototype.encodeSignedNumber=function(num){var sgn_num=num<<1;if(num<0){sgn_num=~(sgn_num);}
return(this.encodeNumber(sgn_num));}
function map(func,list){var len=list.length;var r=new Array(len);for(var i=0;i<len;i++){r[i]=func(list[i]);}
return r;}
function reduce(unity,func,list){var r=unity;for(var i=0;i<list.length;i++){r=func(r,list[i]);}
return r;}
function popup(link,windowname,w,h){if(!window.focus)
return true;var href;if(typeof(link)=='string')
href=link;else
href=link.href;window.open(href,windowname,'width='+w+',height='+h+',resizable=1');return false;}
var n=0;var maps={};var attrfix=function(){var e=document.createElement('div');e.className='foo';if(!e.getAttribute('class')){return{'acceptcharset':'acceptCharset','accesskey':'accessKey','allowtransparency':'allowTransparency','bgcolor':'bgColor','cellpadding':'cellPadding','cellspacing':'cellSpacing','checked':undefined,'class':'className','colspan':'colSpan','defaultchecked':'defaultChecked','defaultselected':'defaultSelected','defaultvalue':'defaultValue','for':'htmlFor','frameborder':'frameBorder','hspace':'hSpace','longdesc':'longDesc','maxlength':'maxLength','marginwidth':'marginWidth','marginheight':'marginHeight','noresize':'noResize','noshade':'noShade','readonly':'readOnly','rowspan':'rowSpan','style':undefined,'tabindex':'tabIndex','valign':'vAlign','vspace':'vSpace','enctype':'encoding'};}else{return{};}}();function velt(name,args){var e=document.createElement(name);for(var i=0;i<args.length;i++){if(typeof args[i]=='string'){var attr=args[i];attr=attrfix[attr]||attr;e.setAttribute(attr,args[i+1]);i++;}else{e.appendChild(args[i]);}}
return e;}
function text(s){return document.createTextNode(s);}
function make_elt(name){return function(){return velt(name,arguments);}}
var elts=['a','br','center','div','form','h1','h2','iframe','img','input','li','p','span','table','tbody','td','th','thead','tr','textarea','ul'];for(var i in elts){var name=elts[i];this[name]=make_elt(name);}
function hidden(name,value){return input('type','hidden','name',name,'value',value);}
function button(label,action){var r=input('type','button','value',label);if(action)
r.onclick=action;return r;}
function button_wrap(elt,buttons){return p(table('class','buttonwrapper',tbody(tr(td('class','bwleft',elt),td('class','bwright',buttons)))));}
function c_any(myid,elt,inner){return button_wrap(inner,div(edit_button(myid),br(),delete_button(myid)));}
function e_any(myid,elt,inner){return button_wrap(inner,div(save_button(myid),br(),cancel_button(myid)));}
function c_buttons(myid,edit_label){return div('class','editbuttons',edit_button(myid,edit_label),delete_button(myid));}
function e_buttons(myid){return div('class','editbuttons',save_button(myid),cancel_button(myid));}
function caption_wrap(content,caption,buttons){return p(vtable(['class','captionwrapper'],[['class','cwmain',content],[htable(['class','cwsub'],[['class','cwleft',caption],['class','cwright',buttons]])]]));}
function i_text(elt){elt.value='';}
function c_text(myid,elt){return c_any(myid,elt,div('id','text_'+myid,text(elt['value'])));}
function e_text(myid,elt){return e_any(myid,elt,bloute.defer_focus(textarea('id','value_'+myid,'rows',8,text(elt['value']))));}
function i_heading(elt){elt.value='';}
function c_heading(myid,elt){return c_any(myid,elt,h2(text(elt.value)));}
function save_on_enter(entry,myid){bloute.bind_entry(entry,function(){save_section(myid);});return entry;}
function e_heading(myid,elt){return e_any(myid,elt,save_on_enter(bloute.defer_focus(input('id','value_'+myid,'type','text','size','60','value',elt.value)),myid));}
function i_photo(elt){elt['caption']='';}
function c_photo(myid,elt){if(!elt['hash'])
return e_photo(myid,elt);return caption_wrap(photo_img(data.trip_id,elt,640),div('class','caption',text(elt.caption)),c_buttons(myid,elt.caption==''?'Add\u00A0caption':'Edit'));}
function trip_file_upload_form(myid,type,label,extra_rows,extra_buttons,callback){var target_name=myid+"_target";var uploading;var target_span;var f=form('action','/trip/'+data.trip_id+'/upload/','method','POST','enctype','multipart/form-data','target',target_name,div('id',myid+'_ready',cram_right(table(velt('tbody',[tr(td(label),td(input('name','file','type','file')))].concat(extra_rows))),velt('abut_h',[input('type','submit','name','start','value','Start upload')].concat(extra_buttons)))),uploading=div('id',myid+'_uploading','class','status_inprogress',text('Uploading...')),target_span=span(text("")),hidden('type',type),hidden('id',myid),hidden('xsrf_token',data.xsrf_token));target_span.innerHTML='<iframe class="uploadtarget" name="'+target_name+'" width="1" height="1" src="/blank/"></iframe>';f.onsubmit=function(){trip_file_upload_form_setstate(myid,'uploading');}
uploading.style.display='none';bloute.uploads[myid]=callback;return f;}
function trip_file_upload_form_setstate(id,state){var states=['ready','uploading'];for(var i=0;i<states.length;i++){var s=states[i];getbyid(id+"_"+s).style.display=(state==s)?'block':'none';}}
function uploaded(s){var retdata=eval('('+s+')');if(retdata.err){alert("Upload failed: "+retdata.err);}
if(retdata.id){var func=bloute.uploads[retdata.id];if(func)
func(retdata);else
alert("internal error: missing callback for id "+retdata.id);}}
function photo_uploaded(retdata){if(retdata.err){if(retdata.id)
set_section_mode(retdata.id,'ctor');}else{var elt=retdata.elt;bloute.edit.eltbyid[elt.id]=elt;set_section_mode(elt.id,'ctor');for(var id in maps){if(maps.hasOwnProperty(id)){bloute.photos.add_photo_to_map(maps[id],elt,data.trip_id,undefined);}}}}
function e_photo(myid,elt){var hash=elt['hash'];var caption=elt['caption'];if(hash)
return caption_wrap(photo_img(data.trip_id,elt,640),save_on_enter(bloute.defer_focus(input('id','caption_'+myid,'type','text','size','40','value',caption)),myid),e_buttons(myid));else
return div('class','upload',trip_file_upload_form(myid,'photo',text('Upload photo: '),[tr(td(text('Photo caption: ')),td(input('name','caption','type',text)))],[button('Cancel',function(){delete_section(myid);})],photo_uploaded));}
function i_map(elt){elt.caption='';elt.bounds=data.bounds;}
function make_map_section(myid,elt,caption,buttons){var mapdiv;r=caption_wrap(mapdiv=div('id','m_'+myid),caption,buttons);mapdiv.className='map';return r;}
function c_map(myid,elt){return make_map_section(myid,elt,div('class','caption',text(elt.caption)),c_buttons(myid,'Edit'));}
function e_map(myid,elt){return make_map_section(myid,elt,save_on_enter(bloute.defer_focus(input('id','caption_'+myid,'type','text','size','40','value',elt.caption)),myid),e_buttons(myid));}
function map_onetime_warning(id){if(!bloute.edit.being_edited[id]&&!bloute.edit.have_warned){alert("This map is not being edited, so panning or zooming will not permanently change it.  If you wish to save your changes, click the Edit link at the lower right corner of the map, pan / zoom to the desired map view, and then click Save when done.");bloute.edit.have_warned=true;}}
function postinsert_map(elt){var m=bloute.setup_map_4('m_'+elt.id,elt['map_type'],bounds_from_list(elt['bounds']),{},elt['static_url']);maps[elt.id]=m;for(var i=0;i<3;i++){var ev=['moveend','zoomend','maptypechanged'][i];GEvent.addListener(m,ev,function(){map_onetime_warning(elt.id);});}}
function c_null(myid,elt){return div();}
function getbyid(id){var e=document.getElementById(id)
if(!e)
alert('could not find element with id '+id);return e;}
function bounds_to_list(bounds){var sw=bounds.getSouthWest();var ne=bounds.getNorthEast();return[sw.lat(),sw.lng(),ne.lat(),ne.lng()];}
function s_map(elt){var gmap=maps[elt.id];elt.bounds=bounds_to_list(gmap.getBounds());elt.map_type=gmap.getCurrentMapType().getUrlArg();return elt;}
function tag2ctor(tag){if(tag=='text')
return c_text;alert('bad type tag '+tag)
return'';}
function s_photo(p){return bloute.photos.clean(p);}
var g_types={'text':{ior:i_text,ctor:c_text,etor:e_text},'heading':{ior:i_heading,ctor:c_heading,etor:e_heading},'photo':{ior:i_photo,ctor:c_photo,etor:e_photo,save:s_photo},'map':{ior:i_map,ctor:c_map,etor:e_map,save:s_map,postinsert:postinsert_map},'null':{ctor:c_null}};function make_link(label,func){var s=a('href','#',text(label))
s.onclick=func;return s;}
function gen_id(){return(new Date()).getTime().toString();}
function add_section_link(id,tag,label){return make_link(label,function(){var elt={'type':tag,'id':gen_id()};var ior=g_types[tag].ior;if(ior)
ior(elt);bloute.ajaj.perform({'type':'insert','before':id,'data':elt});insert_section_before(id,elt,'etor');bloute.edit.eltstate[elt.id]='newly_created';return false;});}
function insertion_bar(id){return p('class','insertionbar',text('\u2014 insert here: '),add_section_link(id,'text','text'),text(' / '),add_section_link(id,'heading','section heading'),text(' / '),add_section_link(id,'photo','photo'),text(' / '),add_section_link(id,'map','map'),text(' \u2014'));}
function make_button(text,func){return make_link('['+text+']',func);}
function delete_button(myid,text){return make_button('Delete',function(){delete_section(myid);return false;});}
function edit_button(myid,edit_label){return make_button(edit_label||'Edit',function(){set_section_mode(myid,'etor');return false;});}
function save_button(myid,text){return make_button('Save',function(){save_section(myid);return false;});}
function cancel_button(myid,text){return make_button('Cancel',function(){cancel_section(myid);return false;});}
function title_edit_button(){return make_button('Edit\u00A0title',edit_title);}
function title_save_button(){return make_button('Save',save_title);}
function show_title(){var t=getbyid('title');remove_children(t);t.appendChild(button_wrap(h1(text(data.trip_title)),title_edit_button()));delete bloute.edit.being_edited['title'];}
function save_title_on_enter(entry){bloute.bind_entry(entry,save_title);return entry;}
function edit_title(){var t=getbyid('title');remove_children(t);var inp;t.appendChild(button_wrap(save_title_on_enter(inp=input('type','text','class','title','id','title_input','size','40','value',data.trip_title)),title_save_button()));inp.focus();bloute.edit.being_edited['title']=true;}
function save_title(){var v=getbyid('title_input').value;data.trip_title=v;bloute.ajaj.perform({type:'set_title',data:v});show_title();}
function bounds_from_list(c){return new GLatLngBounds(new GLatLng(c[0],c[1]),new GLatLng(c[2],c[3]));}
function decode_bounds(value){return bounds_from_list(value.split(','))}
function insert_section_before(nextid,elt,mode){var id=elt.id;bloute.edit.eltbyid[id]=elt;var newsection=div('id',id);var nextelt=getbyid(nextid);nextelt.parentNode.insertBefore(newsection,nextelt);set_section_mode(id,mode);}
function set_section_mode(id,mode){var e=getbyid(id);remove_children(e);e.appendChild(insertion_bar(id));var elt=bloute.edit.eltbyid[id];var tor=g_types[elt.type][mode];e.appendChild(tor(id,elt));var func=g_types[elt.type]['postinsert'];if(func)
func(elt);bloute.run_deferred();if(mode=='etor')
bloute.edit.being_edited[id]=true;else
delete bloute.edit.being_edited[id];}
function save_section(id){var elt=bloute.edit.eltbyid[id];for(var attr in elt){if(elt.hasOwnProperty(attr)&&attr!='id'){var fieldid=attr+'_'+id;docelt=document.getElementById(fieldid);if(docelt){elt[attr]=docelt.value;}}}
savefunc=g_types[elt.type]['save'];if(savefunc)
elt=savefunc(elt);bloute.ajaj.perform({type:'update',data:elt});delete bloute.edit.eltstate[id];set_section_mode(id,'ctor');}
function cancel_section(id){if(bloute.edit.eltstate[id]=='newly_created')
delete_section(id);else
set_section_mode(id,'ctor');}
function delete_section(id){var elt=bloute.edit.eltbyid[id];if(!elt){alert("Already deleted? "+id)
return;}
getbyid(id).style.display='none';delete bloute.edit.being_edited[id];bloute.ajaj.perform({type:'delete',data:elt});}
function map_type_from_urlarg(m,u){var types=m.getMapTypes();for(var i=0;i<types.length;i++){var t=types[i];if(u==t.getUrlArg())
return t;}
alert("unsupported map type "+u);return'';}
function remove_node(node){node.parentNode.removeChild(node);}
function remove_children(node){while(node.hasChildNodes())
node.removeChild(node.childNodes[0]);}
function set_node_contents(node,contents){remove_children(node);node.appendChild(contents);}
function set_ui(contents,helptext){set_node_contents(getbyid('ui'),contents);set_node_contents(getbyid('mode_help'),helptext);}
function replace_node(o,n){o.parentNode.replaceChild(n,o);}
function track_gtoj(track){return map(function(pt){return{lat:pt.lat(),lng:pt.lng()}},track);}
function polyline2glatlngarray(pl){var n=pl.getVertexCount();var pts=new Array(n);for(var i=0;i<n;i++){pts[i]=pl.getVertex(i);}
return pts;}
function point_jtog(jp){return new GLatLng(jp.lat,jp.lng);}
function point_gtoj(gp){return{lat:gp.lat(),lng:gp.lng()};}
function lz(i){var s=i.toString();if(s.length<2)
s='0'+s;return s;}
function format_utc_dateonly(d){var s=d.getUTCFullYear().toString()+'-'+
lz(d.getUTCMonth()+1)+'-'+
lz(d.getUTCDate());return s;}
function format_utc_timeonly(d){var s=lz(d.getUTCHours())+':'+
lz(d.getUTCMinutes())+':'+
lz(d.getUTCSeconds());return s;}
function format_utc_time(d){return format_utc_dateonly(d)+' '+format_utc_timeonly(d);}
function format_time_as_td(t){if(!t)
return td('align','center',text('\u2014'));var d=new Date(t*1000);return td('align','center',text(format_utc_dateonly(d)),br(),text(format_utc_timeonly(d)));}
function view_also(gmap,point){var bounds=gmap.getBounds();if(!bounds.contains(point)){bounds.extend(point);gmap.setCenter(bounds.getCenter(),gmap.getBoundsZoomLevel(bounds));}}
function _geocode(gmap,entry,callback){var value=entry.value;var gc=new GClientGeocoder();gc.setViewport(gmap.getBounds());gc.getLatLng(value,function(point){if(!point){alert("Sorry, I don't know where that is");return;}
view_also(gmap,point);callback(point,value);});}
function enter_point(gmap,ui_node,callback){var click_listener;var cleanup=function(){enter_point_cancel(click_listener);};click_listener=GEvent.addListener(gmap,'click',function(overlay,point,overlaypoint){if(!point)
point=overlaypoint;if(!point){alert("sorry, clicking there doesn't work");return;}
cleanup();callback(point);});var address_entry;var find_button;set_node_contents(ui_node,span(text('Click on the map or enter an address: '),address_entry=input('type','text','size',40),text('\u00A0'),find_button=button('Find')));address_entry.focus();var geocode_callback=function(){cleanup();_geocode(gmap,address_entry,callback);};bloute.bind_entry_with_button(address_entry,find_button,geocode_callback);return click_listener;}
function enter_point_cancel(listener){GEvent.removeListener(listener);}
function scaled_size(size,bounds){var sf=map(function(dim){return bounds[dim]/size[dim];},[0,1]);var sfmin=Math.min.apply(this,sf);return map(function(dim){return Math.floor(size[dim]*sfmin+0.5);},[0,1]);}
function photo_res_url_rel(photo,res){return'photo/'+res.toString()+'/'+photo.hash+'.jpg';}
function photo_res_url(trip_id,photo,res){return data.photo_urlprefix+'/trip/'+trip_id+'/'+photo_res_url_rel(photo,res);}
function photo_popup_url(trip_id,photo){return'/trip/'+trip_id+'/photo_popup/'+photo.hash+'/';}
function photo_img(trip_id,photo,res){var url=photo_res_url(trip_id,photo,res);var size=scaled_size(photo.size,[res,res]);return img('src',url,'width',size[0].toString(),'height',size[1].toString());}
function nullnote(s){return div('class','nullnote',text(s));}
function htable(attrs,tds){return table.apply(this,attrs.concat([tbody(tr.apply(this,map(function(t){return td.apply(this,t)},tds)))]));}
function vtable(attrs,tds){return table.apply(this,attrs.concat([tbody.apply(this,map(function(t){return tr(td.apply(this,t))},tds))]));}
function abut_h(){return table('class','abut',tbody(velt('tr',map(function(e){return td(e)},arguments))));}
function abut_v(){return velt('div',arguments);}
function cram_right(a,b){return table('class','abut',tbody(tr(td('width','100%',a),td('width','1',b))));}
function copy_attrs(to,from){for(var i in from){to[i]=from[i];}}
var bloute=new function(){copy_attrs(this,{uploads:{},bind_entry:function(entry,callback){entry.onkeypress=function(ev){var key;if(window.event)
key=window.event.keyCode;else
key=ev.which
if(key==13)
callback();};},bind_entry_with_button:function(entry,button,callback){bloute.bind_entry(entry,callback);button.onclick=callback;},new_id:function(elts){var r=0;for(var i=0;i<elts.length;i++){var elt=elts[i];r=Math.max(r,elt.i)}
return r+1;},format_coord:function(obj,type){if(!obj.coords)
return'';var val=(obj.coords[type]+0.0).toFixed(6);var i=(type=='lat'?0:2);i+=(val>=0);return val+'\u00B0\u00A0'+['S','N','W','E'][i];},format_coords_as_td:function(obj){return td('align','right',text(bloute.format_coord(obj,'lat')),br(),text(bloute.format_coord(obj,'lng')));},setup_map_3:function(id,type,bounds,options,static_url){options=options||{};var divelt=getbyid(id);if(GBrowserIsCompatible()){var gmap=new GMap2(divelt,options);gmap.addControl(new GLargeMapControl());gmap.addControl(new GMapTypeControl());gmap.addControl(new GScaleControl());gmap.setCenter(bounds.getCenter(),gmap.getBoundsZoomLevel(bounds));if(type)
gmap.setMapType(map_type_from_urlarg(gmap,type));return gmap;}else{if(static_url){set_node_contents(divelt,img(src(static_url)));}else{set_node_contents(divelt,center(p(text('Sorry, no maps - your browser is not compatible with Google Maps'))));}
return undefined;}},setup_map_4:function(id,type,bounds,options,static_url,cbopts){cbopts=cbopts||{};var m=bloute.setup_map_3(id,type,bounds,options,static_url);if(!m)
return undefined;for(var i=0;i<data.tracks.length;i++){var t=data.tracks[i];var pl=new GPolyline.fromEncoded(t.encoded,{clickable:cbopts.tracks_clickable||false});m.addOverlay(pl);t.polyline=pl;}
for(var i=0;i<data.waypoints.length;i++){bloute.waypoints.add_waypoint_to_map(m,data.waypoints[i],data.trip_id,cbopts.waypoint_moved);}
bloute.photos.add_photos_to_map(m,data.photos,data.trip_id,cbopts.photo_moved);return m;},selected_items:function(items){var selected=[];for(var i=0;i<items.length;i++){var id=items[i].i;var box=getbyid('select_'+id);if(box.checked)
selected.push(i);}
return selected;},clone:function(obj){var r={};for(var k in obj){if(obj.hasOwnProperty(k)){r[k]=obj[k];}}
return r;},deferred:[],defer:function(f){bloute.deferred.push(f);},run_deferred:function(){for(var i=0;i<bloute.deferred.length;i++){var f=bloute.deferred[i];f();}},defer_focus:function(e){bloute.defer(function(){e.focus();});return e;}});}();bloute.trip={load:function(){for(var id in data.maps){if(data.maps.hasOwnProperty(id)){var elt=data.maps[id];bloute.setup_map_4('m_'+id,elt['map_type'],bounds_from_list(elt['bounds']),{},elt['static_url']);}}},unload:function(){GUnload()}};bloute.edit={dirty:false,eltbyid:{},eltstate:{},being_edited:{},confirm_exit:function(){dirty=undefined;for(var id in bloute.edit.being_edited)
if(bloute.edit.being_edited.hasOwnProperty(id))
dirty=id;if(dirty){var dirty_div=getbyid(dirty);dirty_div.scrollIntoView(true);dirty_div.lastChild.className='unsaved';return"You have unsaved changes.  If you want to save them, "+"click Cancel to stay on the current page, "+"and then click the [Save] link next to each unsaved item.";}else
return undefined;},addcontent:function(json){for(var i=0;i<json.length;i++){var elt=json[i];if(elt.type=='null')
continue;insert_section_before('end',elt,'ctor');}},load:function(){var maindiv=getbyid('main');var title_p=p('id','title');maindiv.appendChild(title_p);show_title();var end_p=p('id','end');end_p.appendChild(insertion_bar('end'));maindiv.appendChild(end_p);bloute.edit.addcontent(data.initial_content);window.onbeforeunload=bloute.edit.confirm_exit;},unload:function(){GUnload()}};bloute.withmap=new function(){copy_attrs(this,{add_worp_to_map:function(gmap,worp,trip_id,drag_callback,cls){var attrs={title:cls.tooltip(worp)};if(drag_callback)
attrs.draggable=true;var marker=new GMarker(new GLatLng(worp.coords.lat,worp.coords.lng),attrs);GEvent.addListener(marker,'click',function(marker,worp,trip_id){return function(){cls.open_info_window(marker,worp,trip_id);}}(marker,worp,trip_id));if(drag_callback)
GEvent.addListener(marker,'dragend',function(){drag_callback(worp,marker);});gmap.addOverlay(marker);worp.marker=marker;},load:function(cbopts){cbopts=cbopts||{};var main=getbyid('main');var list_part=div('class','scrollablelist','id','list');var ui_part=div('id','uiwrapper','class','uiwrapper',div('id','mode_help'),div('id','ui'));main.appendChild(abut_v(abut_h(list_part,div('id','m_0','class','mgmtmap')),table('class','abut','width','100%',tbody(tr(td(ui_part),td('width','1','valign','bottom',button('Done',function(){location.href='../';})))))));the_map=bloute.setup_map_4('m_0',undefined,bounds_from_list(data.bounds),{draggableCursor:'crosshair',draggingCursor:'pointer'},undefined,cbopts);},unload:function(){GUnload();}});}();bloute.photos=new function(){copy_attrs(this,{tooltip:function(photo){if(photo.caption)
return'Photo: '+photo.caption;else
return'Photo';},open_info_window:function(marker,photo,trip_id){var thumbres=160;var fullres=640;var disp_url=photo_res_url(trip_id,photo,fullres);var popup_url=photo_popup_url(trip_id,photo);var caption=photo.caption||'';var image;var node=div(a('href',disp_url,image=photo_img(trip_id,photo,thumbres)),br(),text(caption));marker.openInfoWindow(node);var popup_size=scaled_size(photo.size,[fullres,fullres]);image.onclick=function(){return popup(popup_url,'photo',popup_size[0],popup_size[1]);}},add_photo_to_map:function(gmap,photo,trip_id,drag_callback){if(!photo.coords)
return;bloute.withmap.add_worp_to_map(gmap,photo,trip_id,drag_callback,bloute.photos);},add_photos_to_map:function(gmap,photos,trip_id,drag_callback){for(var i=0;i<photos.length;i++){bloute.photos.add_photo_to_map(gmap,photos[i],trip_id,drag_callback);}},clean:function(photo){var r=bloute.clone(photo);delete r.marker;delete r.row;return r;},move_photo_to:function(photo,point){photo.coords=point_gtoj(point);bloute.ajaj.perform({type:'update',data:bloute.photos.clean(photo)});bloute.photos.update_list();},moved_marker:function(photo,marker){bloute.photos.move_photo_to(photo,marker.getLatLng());},place_photo:function(photo){var enter_point_node;var handle;function cleanup(){enter_point_cancel(handle);bloute.photos.update_list();bloute.photos.ground_state();}
set_ui(div(div(text('Enter photo location')),enter_point_node=span(),text('\u00A0'),button('Cancel',cleanup)),text(''));handle=enter_point(the_map,enter_point_node,function(point){bloute.photos.move_photo_to(photo,point);bloute.photos.add_photo_to_map(the_map,photo,data.trip_id,bloute.photos.moved_marker);bloute.photos.ground_state();});},highlight:function(t,source){if(t.marker)
t.marker.setImage('/site_media/yellow-marker.png');if(t.row){t.row.className='highlight';if(source!='list')
t.row.scrollIntoView(false);}},lowlight:function(t){if(t.marker)
t.marker.setImage('http://maps.google.com/intl/en_ALL/mapfiles/marker.png');if(t.row)
t.row.className='lowlight';},center_on:function(t){if(t.coords)
the_map.setCenter(new GLatLng(t.coords.lat,t.coords.lng));},update_list:function(){var elt=getbyid('list');remove_children(elt);if(data.photos.length==0){elt.appendChild(nullnote("This trip has no photos yet."));}else{elt.appendChild(table(thead(velt('tr',map(function(t){return th(text(t));},['Preview','Time','Location','Filename']))),velt('tbody',map(function(t){var coords_td;if(t.coords){coords_td=bloute.format_coords_as_td(t);}else{var place_button=button('Place on map',function(){replace_node(place_button,text("..."));bloute.photos.place_photo(t);});coords_td=td('align','center',place_button);}
var row=tr(td('align','center',photo_img(data.trip_id,t,120)),format_time_as_td(t.camera_time),coords_td,td('align','center',text(t.filename||'')));row.onmouseover=function(){bloute.photos.highlight(t,'list');};row.onmouseout=function(){bloute.photos.lowlight(t);};row.ondblclick=function(){bloute.photos.center_on(t);};t.row=row;return row;},data.photos))));}},ground_state:function(){set_ui(text(''),text(''));},add_callbacks:function(t){if(!t.marker)
return;GEvent.addListener(t.marker,'mouseover',function(){bloute.photos.highlight(t,'map');});GEvent.addListener(t.marker,'mouseout',function(){bloute.photos.lowlight(t);});},load:function(){bloute.withmap.load({photo_moved:bloute.photos.moved_marker});for(var i=0;i<data.photos.length;i++){var t=data.photos[i];bloute.photos.add_callbacks(t);}
getbyid('uiwrapper').appendChild(p(text('To upload more photos, use the "insert here ... photo" links on the '),a('href','../edit/',text('Edit')),text(' page')));this.update_list();this.ground_state();},unload:function(){bloute.withmap.unload();}});}();bloute.tracks=new function(){copy_attrs(this,{playback:function(je){if(je.type=='add_track'){var t=je.track
data.tracks.push(t);the_map.addOverlay(t.polyline);bloute.tracks.add_callbacks(t);bloute.tracks.update_list();if(t.row)
t.row.scrollIntoView(false);}else if(je.type=='delete_track'){var t=data.tracks[je.index];data.tracks.splice(je.index,1);the_map.removeOverlay(t.polyline);bloute.tracks.update_list();}},highlight:function(t,source){if(t.encoded){var hl=t.encoded;hl.color='#0000FF';hl.opacity=0.5;hl.weight=10;t.hili_poly=new GPolyline.fromEncoded(hl,{clickable:false});the_map.addOverlay(t.hili_poly);}
if(t.row){t.row.className='highlight';if(source!='list')
t.row.scrollIntoView(false);}},lowlight:function(t){if(t.hili_poly)
the_map.removeOverlay(t.hili_poly);if(t.row)
t.row.className='lowlight';},zoom_trackseg:function(t){var bounds=t.polyline.getBounds();the_map.setCenter(bounds.getCenter(),the_map.getBoundsZoomLevel(bounds));},update_list:function(){var elt=getbyid('list');remove_children(elt);if(data.tracks.length==0){elt.appendChild(nullnote("This trip has no tracks yet."));}else{elt.appendChild(table(thead(velt('tr',map(function(t){return th(text(t));},['No','Points','Begin','End','Time','Distance','']))),velt('tbody',map(function(t){var row=tr('class','lowlight',td(text(t.i+1)),td('align','right',text(t.npoints)),format_time_as_td(t.btime),format_time_as_td(t.etime),td('align','right',text(t.duration_fmt||'\u2014')),td('align','right',text(t.distance_fmt||'TBD')),td(input('type','checkbox','id','select_'+t.i)));row.onmouseover=function(){bloute.tracks.highlight(t,'list');};row.onmouseout=function(){bloute.tracks.lowlight(t);};row.ondblclick=function(){bloute.tracks.zoom_trackseg(t);};t.row=row;return row;},data.tracks))));}},show_track:function(){},ground_state:function(){set_ui(div(button('Add straight-line track',bloute.tracks.add_track),text('\u00A0'),button('Add road track',bloute.tracks.add_drive),text('\u00A0'),button('Delete selected tracks',bloute.tracks.delete_selected)),text(''));},track_gtoj:function(track){return map(function(pt){return{lat:pt.lat(),lng:pt.lng()}},track);},clean_journal_elt:function(elt){if(elt.type=='add_track'){return{type:'add_track',track:elt.track.unencoded};}else{return elt;}},record_track:function(latlng_array,glatlng_array,polyline){var enc=new PolylineEncoder();var encoded=enc.dpEncodeToJSON(glatlng_array);var new_track={i:bloute.new_id(data.tracks),polyline:polyline,unencoded:latlng_array,encoded:encoded,npoints:latlng_array.length};var je={type:'add_track',track:new_track};bloute.tracks.playback(je);bloute.ajaj.perform(bloute.tracks.clean_journal_elt(je));},add_drive:function(){var start_point_div;var markers=[];function add_marker(point){var marker=new GMarker(point);the_map.addOverlay(marker);markers.push(marker);}
function cleanup(){for(var i=0;i<markers.length;i++){the_map.removeOverlay(markers[i]);}}
set_ui(start_point_div=div(text('')),text('Set the start point of the drive'));var handle=enter_point(the_map,start_point_div,function(start_point){var end_point_div;add_marker(start_point);set_ui(end_point_div=div(text('')),text('Set the end point of the drive'));var handle2=enter_point(the_map,end_point_div,function(end_point){add_marker(end_point);set_ui(div(text('')),text('Please wait while Google Maps calculates driving directions...'));var gd=new GDirections();var load_listener=GEvent.addListener(gd,'load',function(){var polyline=gd.getPolyline();var glarray=polyline2glatlngarray(polyline);bloute.tracks.record_track(bloute.tracks.track_gtoj(glarray),glarray,polyline);finish();});var error_listener=GEvent.addListener(gd,'error',function(){alert('Unable to obtain driving directions between selected points');finish();});function finish(){GEvent.removeListener(load_listener);GEvent.removeListener(error_listener);cleanup();bloute.tracks.ground_state();}
gd.loadFromWaypoints([start_point,end_point],{getPolyline:true});})})},add_track:function(){var point_div;var point_listener;var markers=[];var current_track=[];var overlay;var finish_button;var undo_button;var update=function(){if(overlay){the_map.removeOverlay(overlay);overlay=undefined;}
if(current_track.length>=2){overlay=new GPolyline(current_track,'#0000FF',4,0.8,{clickable:true});the_map.addOverlay(overlay);}
finish_button.disabled=(current_track.length<2);undo_button.disabled=(current_track.length==0);};var cleanup=function(){enter_point_cancel(point_listener);for(var i=0;i<markers.length;i++){the_map.removeOverlay(markers[i]);}
if(overlay)
the_map.removeOverlay(overlay);bloute.tracks.ground_state();};set_ui(div(point_div=div(text('')),undo_button=button('Undo last point',function(){if(current_track.length>0){current_track.pop();the_map.removeOverlay(markers.pop());update();}}),text('\u00A0'),button('Cancel track',cleanup),text('\u00A0'),finish_button=button('Finish track',function(){if(current_track.length<1){alert("Empty tracks are not allowed");}else{var polyline=new GPolyline(current_track,'#0000FF',4,0.8,{clickable:true});bloute.tracks.record_track(bloute.tracks.track_gtoj(current_track),current_track,polyline);}
cleanup();})),text('Add points to the track'));update();var add_track_loop;add_track_loop=function(){point_listener=enter_point(the_map,point_div,function(point){var marker=new GMarker(point);the_map.addOverlay(marker);markers.push(marker);current_track.push(point);update();add_track_loop();});};add_track_loop();},delete_selected:function(){var selected=bloute.selected_items(data.tracks);for(var i=selected.length-1;i>=0;i--){var je={type:'delete_track',index:selected[i]};bloute.tracks.playback(je);bloute.ajaj.enqueue(je);}
bloute.ajaj.start();},add_callbacks:function(t){GEvent.addListener(t.polyline,'mouseover',function(){bloute.tracks.highlight(t,'map');});GEvent.addListener(t.polyline,'mouseout',function(){bloute.tracks.lowlight(t);});},load:function(){bloute.withmap.load({tracks_clickable:true});bloute.tracks.update_list();for(var i=0;i<data.tracks.length;i++){var t=data.tracks[i];bloute.tracks.add_callbacks(t);}
bloute.tracks.ground_state();},unload:function(){bloute.withmap.unload();}});}();bloute.waypoints=new function(){copy_attrs(this,{open_info_window:function(marker,w,trip_id){var node=div(text(w.name));marker.openInfoWindow(node);},add_waypoint_to_map:function(gmap,w,trip_id,drag_callback){return bloute.withmap.add_worp_to_map(gmap,w,trip_id,drag_callback,bloute.waypoints);},remove_waypoint_from_map:function(gmap,w){gmap.removeOverlay(w.marker);delete w.marker;},tooltip:function(waypoint){if(waypoint.name)
return'Waypoint: '+waypoint.name;else
return'Waypoint';},playback:function(je){if(je.type=='add_waypoint'){var w=je.waypoint;data.waypoints.push(w);bloute.waypoints.add_waypoint_to_map(the_map,w,data.trip_id,bloute.waypoints.moved_marker);bloute.waypoints.add_callbacks(w);bloute.waypoints.update_list();}else if(je.type=='delete_waypoint'){var w=data.waypoints[je.index];data.waypoints.splice(je.index,1);bloute.waypoints.remove_waypoint_from_map(the_map,w);bloute.waypoints.update_list();}},highlight:function(t,source){t.marker.setImage('/site_media/yellow-marker.png');if(t.row){t.row.className='highlight';if(source!='list')
t.row.scrollIntoView(false);}},lowlight:function(t){t.marker.setImage('http://maps.google.com/intl/en_ALL/mapfiles/marker.png');if(t.row)
t.row.className='lowlight';},center_on:function(t){the_map.setCenter(new GLatLng(t.coords.lat,t.coords.lng));return true;},update_list:function(){var elt=getbyid('list');remove_children(elt);if(data.waypoints.length==0){elt.appendChild(nullnote("This trip has no waypoints yet."))}else{elt.appendChild(table(thead(velt('tr',map(function(t){return th(text(t));},['No','Name','Location','']))),velt('tbody',map(function(t){var row=tr(td('align','left',text(t.i+1)),td('align','left',text(t.name)),bloute.format_coords_as_td(t),td(input('type','checkbox','id','select_'+t.i)));row.onmouseover=function(){bloute.waypoints.highlight(t,'list');};row.onmouseout=function(){bloute.waypoints.lowlight(t);};row.ondblclick=function(){bloute.waypoints.center_on(t);};t.row=row;return row;},data.waypoints))));}},clean:function(wpt){return{coords:wpt.coords,name:wpt.name}},clean_journal_elt:function(elt){if(elt.type=='add_waypoint'){return{type:'add_waypoint',waypoint:bloute.waypoints.clean(elt.waypoint)};}else{return elt;}},create:function(point,name){var wp={coords:point_gtoj(point),name:name,i:bloute.new_id(data.waypoints)};var je={type:'add_waypoint',waypoint:wp};bloute.waypoints.playback(je);bloute.ajaj.perform(bloute.waypoints.clean_journal_elt(je));getbyid('list').lastChild.scrollIntoView(false);},move_waypoint_to:function(wpt,point){wpt.coords=point_gtoj(point);bloute.ajaj.perform({type:'update_waypoint',index:wpt.i,waypoint:bloute.waypoints.clean(wpt)});bloute.waypoints.update_list();},moved_marker:function(wpt,marker){bloute.waypoints.move_waypoint_to(wpt,marker.getLatLng());},add_waypoint:function(){var enter_point_node;var handle;function cleanup1(){enter_point_cancel(handle);bloute.waypoints.ground_state();}
set_ui(div(div(text('Enter waypoint location')),enter_point_node=span(),text('\u00A0'),button('Cancel',cleanup1)),text(''));handle=enter_point(the_map,enter_point_node,function(point,opt_addr){var temp_marker=new GMarker(point);the_map.addOverlay(temp_marker);temp_marker.setImage('/site_media/yellow-marker.png');function cleanup2(){the_map.removeOverlay(temp_marker);bloute.waypoints.ground_state();}
var name_entry;var cont_button;set_ui(div(text('Enter a name for the waypoint: '),name_entry=input('type','text','size',40),text('\u00A0'),cont_button=button('Create waypoint'),text('\u00A0'),button('Cancel',cleanup2)),text(''));if(opt_addr)
name_entry.value=opt_addr;name_entry.focus();bloute.bind_entry_with_button(name_entry,cont_button,function(){var name=name_entry.value;bloute.waypoints.create(point,name);cleanup2();});});},ground_state:function(){set_ui(div(button('Add a new waypoint',bloute.waypoints.add_waypoint),text('\u00A0'),button('Delete selected waypoints',bloute.waypoints.delete_selected)),text(''));},delete_selected:function(){var selected=bloute.selected_items(data.waypoints);for(var i=selected.length-1;i>=0;i--){var je={type:'delete_waypoint',index:selected[i]};bloute.waypoints.playback(je);bloute.ajaj.enqueue(je);}
bloute.ajaj.start();},add_callbacks:function(t){GEvent.addListener(t.marker,'mouseover',function(){bloute.waypoints.highlight(t,'map');});GEvent.addListener(t.marker,'mouseout',function(){bloute.waypoints.lowlight(t);});},load:function(){bloute.withmap.load({waypoint_moved:bloute.waypoints.moved_marker});for(var i=0;i<data.waypoints.length;i++){var t=data.waypoints[i];bloute.waypoints.add_callbacks(t);}
bloute.waypoints.ground_state();bloute.waypoints.update_list();},unload:function(){bloute.withmap.unload();}});}();bloute.photo_popup={load:function(){var ns=navigator.appName=='Netscape';iWidth=ns?window.innerWidth:document.body.clientWidth;iHeight=ns?window.innerHeight:document.body.clientHeight;iWidth=document.images[0].width-iWidth;iHeight=document.images[0].height-iHeight;window.resizeBy(iWidth,iHeight);},unload:function(){}};bloute.timezone={format_time:function(d){var s=d.getFullYear().toString()+'-'+
lz(d.getMonth()+1)+'-'+
lz(d.getDate())+' '+
lz(d.getHours())+':'+
lz(d.getMinutes())+':'+
lz(d.getSeconds());return s;},load:function(){var ct=getbyid("id_camera_time");ct.value=bloute.timezone.format_time(new Date());var tz=getbyid("id_tz_offset");var sign=getbyid("id_tz_sign");var tzo_minutes=-(new Date().getTimezoneOffset());if(tzo_minutes>=0){sign.value="east";}else{sign.value="west";tzo_minutes=-tzo_minutes;}
tz.value=tzo_minutes/60;},unload:function(){}};bloute.gps={n:0,load:function(){var maindiv=getbyid('main');var upload_div;function add_upload_field(){bloute.gps.n++;var id='gpx_'+bloute.gps.n;upload_div.appendChild(p('id',id,trip_file_upload_form(id,'gpx',text('GPX file: '),[],[],function(retdata){if(retdata.id){set_node_contents(getbyid(retdata.id),retdata.err?p('class','status_bad',text('Upload failed')):p('class','status_ok',text('Upload complete')));var b=button('Upload more files');upload_div.appendChild(b);b.onclick=function(){remove_node(b);add_upload_field();}}})));}
maindiv.appendChild(p(text('If you have saved tracks or waypoints from a GPS unit, you can upload them here. They must be in the GPX file format.  If you have no GPX files to upload, just press Continue.')));maindiv.appendChild(upload_div=div('class','upload'));add_upload_field();var next_url='/trip/'+data.trip_id+'/next/';maindiv.appendChild(p(form('method','GET','action',next_url,input('type','submit','value','Continue'))));},unload:function(){}};bloute.ajaj={unsent:[],being_sent:[],send:function(payload,url,callback){var msg={xsrf_token:data.xsrf_token,data:payload};GDownloadUrl(url,callback,toJSON(msg),'application/json');},enqueue:function(item){bloute.ajaj.unsent.push(item);},start:function(){if(bloute.ajaj.being_sent.length!=0){alert("send already in progress");return;}
if(bloute.ajaj.unsent.length==0)
return;function done(text,resultcode){if(resultcode!=200){alert('Could not save changes (result code '+resultcode+')');bloute.ajaj.unsent=bloute.ajaj.being_sent.slice(1).concat(bloute.ajaj.unsent);bloute.ajaj.being_sent=[];}else{bloute.ajaj.being_sent=[];}
bloute.ajaj.start();}
bloute.ajaj.being_sent=bloute.ajaj.unsent;bloute.ajaj.unsent=[];bloute.ajaj.send(bloute.ajaj.being_sent,data.save_url,done);},perform:function(item){bloute.ajaj.enqueue(item);bloute.ajaj.start();}};
