// config related
var LOADMAP = true;
var makeLocation = function(x) { return "http://spartanburg.placeaware.com/"+x; };
var makeAJAXLocation = function(x) { return makeLocation('ajax/'+x); };
var makeImageLocation = function(x) { return makeLocation('images/spartanburg/'+x); };
var makeMarkerImageLocation = function(x) { return makeImageLocation('markers/'+x); };
var remoteCall = partial(callRemote, makeAJAXLocation('remoteCall.php'));
// environment setup
var BUTTER = new ButterLib();
Butterlate.setTextDomain("messages", makeLocation("langs"));
var B = createDOMFunc("B");
// global variables
var MAP = null;
var USER_EMAIL = "unknown";
var STARTING_POINT = null;
var PLACE_TYPES = new Array();
//var PLACES = new Array();
var PLACE_MARKERS = new Array();
var TRIP_LIST = new TripList();
var MAP_LIST = new MapList();
var MINI_MSG_SHOWING = false;
var TRIP_LINE = null;
var TRIP_POINTS = new Array();
// objects
function PlaceType(id,name) {
this.id = id;
this.name = name;
this.places = new Array();
this.addPlace = function(x) { this.places.push(x); };
this.hasVisibleMarkers = function() {
return (PLACE_MARKERS.get(this.id).length > 0);
};
this.hideMarkers = function() {
var id = this.id;
PLACE_MARKERS = PLACE_MARKERS.getWithFunction(function(type_id) { return (type_id!=id); });
redrawMarkers();
};
this.refreshMarkerList = function() {
var request = doSimpleXMLHttpRequest(makeAJAXLocation('places.php'), {'type_id': this.id});
request.addCallback(setupPlaceMenu, this.id);
request.addCallback(this._showMarkers, this.id);
};
this.showMarkers = function() {
if(this.places.length==0) this.refreshMarkerList();
else this._showMarkers(this.id, null);
};
this._showMarkers = function(id, request) {
PLACE_MARKERS.push(id);
redrawMarkers();
};
}
function Map(name) {
this.name = name;
this.id = BUTTER.getID();
this.toXml = function() {
return "";
};
this.toJSON = function() {
return "{'name': \""+JSONEscape(this.name)+"\"}";
};
}
function MapList() {
this.current = null;
this.maps = new Array();
this.setCurrent = function(name) {
this.current = name;
this._addMap(name);
this.refresh();
};
this.addMap = function() {
var number = this.maps.length + 1;
var name = prompt("Enter a name for your new map:", "Day "+number);
if(name) {
name = name.maxLength(10);
if(this.maps.getWithFunction(function (m) {return m.name==name;}).length > 0) {
alert("\""+name+"\" has already been used.");
MAP_LIST.addMap();
} else {
this._addMap(name);
this.current = name;
this.refresh();
TRIP_LIST.loadTrip(this.current);
}
};
};
this._addMap = function(name) {
if(this.maps.getWithFunction(function(map) { return map.name==name; }).length == 0) {
this.maps.push(new Map(name));
}
};
this.changeName = function() {
var number = this.maps.length + 1;
var name = prompt("Enter a new name for the map \""+unescapeHTML(this.current)+"\":", "Day "+number);
if(name) {
name = name.maxLength(10);
if(this.maps.getWithFunction(function (m) {return m.name==name;}).length > 0) {
alert("\""+name+"\" has already been used.");
MAP_LIST.changeName();
} else {
doSimpleXMLHttpRequest(makeAJAXLocation('trip.php'), {'action': 'delete', 'name': MAP_LIST.current});
var index = this.maps.getIndexWithFunction(function (x) { return x.name==MAP_LIST.current; });
this.maps[index].name = name;
this.current = name;
MAP_LIST.refresh();
TRIP_LIST.save();
}
};
};
this.deleteCurrentMap = function() {
if (confirm("All trips in the \""+unescapeHTML(this.current)+"\" itenerary will be deleted. Are you sure?")) {
doSimpleXMLHttpRequest(makeAJAXLocation('trip.php'), {'action': 'delete', 'name': this.current});
this.maps = this.maps.getWithFunction(function (x) { return x.name!=MAP_LIST.current });
this.current = this.maps[0].name;
this.refresh();
TRIP_LIST.loadTrip(this.current);
}
};
this.loadList = function() {
var handleList = function(request) {
if(request.responseText=="") {
MAP_LIST.setCurrent("Day 1");
return;
}
MAP_LIST.maps = new Array();
var makeMap = function (x) { return new Map(unescapeHTML(x.name)); };
var maps = forEachJSONElement(request, makeMap);
forEach(maps, function(map) { MAP_LIST.maps.push(map); });
MAP_LIST.current = MAP_LIST.maps[0].name;
MAP_LIST.refresh();
TRIP_LIST.loadTrip(MAP_LIST.current);
};
var request = doSimpleXMLHttpRequest(makeAJAXLocation('map_list.php'));
request.addCallback(handleList);
};
this.refresh = function() {
if(this.maps.length ==1) addElementClass($("delete_current_map"), "hidden_block");
else removeElementClass($("delete_current_map"), "hidden_block");
var maplist = new Array();
forEach(this.maps, function (map) {
var elem_class = (map.name==MAP_LIST.current) ? "selected_map" : "unselected_map";
maplist.push(toHTML(SPAN({'class': elem_class, 'id': map.id}, SPAN({'class': "tab"}, map.name))));
});
$("map_list").innerHTML = "".join(maplist);
var tmp_maplist = new Array();
forEach(this.maps, function (map) {
onMouseOverClass(map.id, "map_name_hover");
connect(map.id, 'onclick', function() {
MAP_LIST.setCurrent(map.name);
TRIP_LIST.loadTrip(map.name);
});
tmp_maplist.push(map.toJSON());
});
var xml = "(["+','.join(tmp_maplist)+"])";
doSimpleXMLHttpRequest(makeAJAXLocation('map_list.php'), {'map_list': xml});
};
}
function TripList() {
this.places = new Array();
this.hasPlace = function(id) {
var existing = this.places.getWithFunction( function(x) { return x.id==id; });
return (existing.length > 0);
};
this.addStartPoint = function(pladdy) {
// accepts place or addy
if(TRIP_LIST.places.length > 0 && TRIP_LIST.places[0].id==pladdy.id) return;
//this.places = this.places.frontPush(pladdy);
var narray = new Array();
narray.push(pladdy);
this.places.each(function (i) { narray.push(i); });
this.places = narray;
};
this.addPlace = function (place) {
//if(this.hasPlace(place.id)) { alert(_("Place already exists in trip.")); return; }
this.places.push(place);
this.refresh();
};
this.addAddy = function(addy) {
//if(this.hasPlace(addy.id)) { alert(_("Place already exists in trip.")); return; }
this.places.push(addy);
this.refresh();
};
this.move_up = function(index) {
//var index = this.places.getIndexWithFunction( function(x) {return x.id==place_id;} );
if(index > 0) {
this.places.swap(index, index-1);
this.refresh();
}
};
this.move_down = function(index) {
//var index = this.places.getIndexWithFunction( function(x) {return x.id==place_id;} );
if(index < (this.places.length-1)) {
this.places.swap(index, index+1);
this.refresh();
}
};
this.remove = function(index) {
var id = this.places[index].id+'.'+index;
dropOut('trip_place.'+id, {afterFinish: function () { TRIP_LIST._remove(index); }});
};
this._remove = function(index) {
//this.places = this.places.getWithFunction(function(x) {return x.id!=place_id;});
this.places = this.places.getByIndexFunction(function(x) {return x!=index;});
this.refresh();
};
this.hasPoint = function(point) {
return this.places.getWithFunction(function (p) { return p.point.equals(point); }).length > 0;
};
this.refresh = function() {
var d = document.createElement('div');
if(TRIP_LIST.places.length < 1) {
var menu = DIV({'class': 'trip_place_menu'},H1({'id': 'empty'},"You have no trips in today's itinerary."));
var html = DIV({'class': 'trip_place_info'}, menu, DIV({'class': 'trip_empty'}, H1({}, "Click on the Places menu on the left to start adding trips.")));
d.appendChild(html);
}
else {
var html = this.places.cmap(function(x, index) {
return makeTripHTML(x, index, TRIP_LIST.places.length);
});
html.each(function(o) { d.appendChild(o); });
}
swapDOM($("trip").firstChild, d);
var points = new Array();
cforEach(this.places, function(info, index) {
var id = info.id+'.'+index;
var remove_link = 'trip_remove.'+id;
onMouseOverClass(remove_link, "span_link_hover");
connect(remove_link, 'onclick', function() { TRIP_LIST.remove(index); });
// must do this so IE doesn't feck up
if(index!=0) {
var mup_link = 'trip_mup.'+id;
onMouseOverClass(mup_link, "span_link_hover");
connect(mup_link, 'onclick', function() { TRIP_LIST.move_up(index); });
}
// must do this so IE doesn't feck up
if(index!=(TRIP_LIST.places.length-1)) {
var mdown_link = 'trip_mdown.'+id;
onMouseOverClass(mdown_link, "span_link_hover");
connect(mdown_link, 'onclick', function() { TRIP_LIST.move_down(index); });
}
var notes_link = 'notes_visible.'+id;
onMouseOverClass(notes_link, "span_link_hover");
var edit_link = SPAN({'id': 'edit_link_'+id, 'class': 'button'}, "Edit Notes");
var save_link = SPAN({'id': 'save_link_'+id, 'class': 'button'}, "Save Notes");
$(notes_link).appendChild(edit_link);
connect(edit_link, 'onclick', function() {
swapDOM($(edit_link), $(save_link));
var notes = toggleDivText('notes.'+id, 10, 100);
// only save if user finished editing
if(notes != info.notes) {
info.notes = notes;
TRIP_LIST.save();
}
});
connect(save_link, 'onclick', function() {
swapDOM($(save_link), $(edit_link));
var notes = toggleDivText('notes.'+id, 10, 100);
// only save if user finished editing
if(notes != info.notes) {
info.notes = notes;
TRIP_LIST.save();
}
});
points.push(new GLatLng(info.point.lat, info.point.lon));
});
this.save();
if(this.places.length > 1) {
TRIP_POINTS = new Array();
TRIP_LIST.getDirections(0);
// don't need to call redrawMarkers here because it will be called as we get directions
} else {
TRIP_LINE = null;
redrawMarkers();
}
};
this.save = function() {
trip_json_array = new Array();
forEach(this.places, function(info) {
var json = info.toJSON();
trip_json_array.push(json);
});
var trip_xml = "({'map_name': \""+escapeHTML(MAP_LIST.current)+"\", 'places': [" + ','.join(trip_json_array) + "]})";
doSimpleXMLHttpRequest(makeAJAXLocation('trip.php'), {'trip': trip_xml, 'name': MAP_LIST.current});
};
this.loadTrip = function(trip_name) {
var handleTrip = function(request) {
TRIP_LIST.places = new Array();
if(request.responseText != "") {
var makePlace = function (x) {
if(x.type == "place") {
x.point = new BPoint(x.lat, x.lon);
x.toXml = function() {
return "";
};
x.toJSON = function () {
return "{'type': \"place\",'id': \""+this.id+"\",'notes': \""+JSONEscape(this.notes)+"\"}";
};
// resecape the notes in case they aren't changed, they will be posted as escaped HTML
// x.notes = escapeHTML(x.notes);
} else {
notes = x.notes;
x = new Addy(x.addy, new BPoint(x.lat, x.lon));
// resecape the notes in case they aren't changed, they will be posted as escaped HTML
x.notes = notes; //escapeHTML(notes);
}
return x;
};
//alert(request.responseText);
var root = eval(request.responseText);
MAP_LIST.setCurrent(unescapeHTML(root.map_name));
var places = map(makePlace, root.places);
forEach(places, function(place) { TRIP_LIST.places.push(place); });
if(STARTING_POINT) TRIP_LIST.addStartPoint(STARTING_POINT);
} else if(STARTING_POINT) TRIP_LIST.addStartPoint(STARTING_POINT);
TRIP_LIST.refresh();
};
// seems weird - but the xml we sent eariler w/ the trip had been escaped this way, so we must escape
// when we request by name as well
// trip_name = HTMLToXML(escapeHTML(trip_name));
var request = doSimpleXMLHttpRequest(makeAJAXLocation('trip.php'), {'name': trip_name});
request.addCallback(handleTrip);
};
this.setDirectionText = function(index, text) {
$("directions."+index).innerHTML = text;
};
this.getDirections = function(index) {
if((index+1) >= this.places.length) return;
var fr_place = this.places[index];
var fr_type = fr_place.type;
var fr = (fr_type=="addy") ? fr_place.addy : fr_place.id;
var fraddy = (fr_type == "addy") ? fr_place.addy : fr_place.address;
var to_place = this.places[index+1];
var to_type = to_place.type;
var to = (to_type=="addy") ? to_place.addy : to_place.id;
var toaddy = (to_type == "addy") ? to_place.addy : to_place.address;
var handleSearchResults = function (request) {
if(request.responseText == "NOT_FOUND") {
var d = new GDirections(FAKEMAP);
d.load("from: " + fraddy + " to: " + toaddy, {getSteps: true});
GEvent.addListener(d, "load", function() {
if(d.getNumRoutes() == 0) {
showBriefMiniMessage("Directions from place "+(index+1)+" could not be found");
TRIP_LIST.setDirectionText(index, "Directions not found.");
} else {
var xml = '';
var route = d.getRoute(0);
for(var i=0; i" + escapeHTML(step.getDescriptionHtml()) + "";
}
xml += "";
var poly = d.getPolyline();
for(var i=0; i";
}
xml += "";
var params = queryString({'key': fraddy+toaddy, 'value': xml});
var request = doXHR(makeAJAXLocation('storage.php'), {method: 'POST', sendContent: params, headers: {"Content-Type":"application/x-www-form-urlencoded"}});
request.addCallback(TRIP_LIST.getDirections(index));
}
TRIP_LIST.getDirections(index+1);
});
GEvent.addListener(d, "error", function() {
showBriefMiniMessage("Directions from place "+(index+1)+" could not be found");
TRIP_LIST.setDirectionText(index, "Directions not found.");
TRIP_LIST.getDirections(index+1);
});
} else {
var pdata = rootToObject(request);
var makeStep = function (x) { return x.inner_text; };
var steps = forEachElement(request, "step", makeStep);
var dtext = "Distance: "+pdata.distance+"
"+"
".join(steps);
TRIP_LIST.setDirectionText(index, dtext);
var points = forEachElement(request, "point", function (x) { return new GLatLng(x.lat, x.lon) });
points.unshiftArray(TRIP_POINTS);
TRIP_POINTS = points;
TRIP_LINE = new GPolyline(points); //, "#FF0000", 2);
var bounds = new GLatLngBounds();
forEach(points, function(x) { bounds.extend(x); });
var newzoom = MAP.getBoundsZoomLevel(bounds);
MAP.setCenter(bounds.getCenter(), newzoom);
TRIP_LIST.getDirections(index+1);
redrawMarkers();
}
};
var params = {'key': fraddy+toaddy};
var request = doSimpleXMLHttpRequest(makeAJAXLocation('storage.php'), params);
request.addCallback(handleSearchResults);
};
}
function Place(id, name, type_id, point) {
this.type = "place";
this.id = id;
this.name = name;
this.type_id = type_id;
this.point = point;
this.toJSON = function () {
return "{'type': \"place\",'id': \""+this.id+"\",'notes': \""+JSONEscape(this.notes)+"\"}";
};
this.toXml = function() {
return "";
};
this.notes = null;
}
// smaller than a GPoint
function BPoint(lat,lon) {
this.lat = lat;
this.lon = lon;
this.toGLatLng = function() { return new GLatLng(lat, lon); };
this.equals = function(bp) { return (bp.lat == this.lat && bp.lon == this.lon); };
}
// address object
function Addy(addy, point) {
this.type = "addy";
this.id = BUTTER.getID();
this.addy = addy;
this.point = point;
this.toXml = function() {
return "";
};
this.toJSON = function() {
return "{'notes': \""+JSONEscape(this.notes)+"\",'type': \"addy\",'addy': \""+this.addy+"\",'lat': \""+this.point.lat+"\",'lon': \""+this.point.lon+"\"}";
};
this.notes = null;
}
// small GIcon
function SmallPin() {
var icon = new GIcon();
icon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
icon.iconSize = new GSize(12, 20);
icon.shadowSize = new GSize(22, 20);
icon.iconAnchor = new GPoint(6, 20);
icon.infoWindowAnchor = new GPoint(5, 1);
return icon;
}
// Extending mochikit functions
function onMouseOverClass(elementName, className) {
connect(elementName, 'onmouseover', function() { addElementClass(elementName, className); });
connect(elementName, 'onmouseout', function() { removeElementClass(elementName, className); });
}
function onEnter(id, fnc) {
connect(id, 'onkeydown', function(e) {if(e.key().code==13) fnc();});
}
function toggleDivText(id, rows, cols) {
var src = null;
var dest = $(id);
var result = "";
if(dest.nodeName.toLowerCase()=="div") {
src = document.createElement("textarea");
src.setAttribute('rows', rows);
src.setAttribute('cols', cols);
result = src.value = unescapeHTML(dest.innerHTML);
}
else {
src = document.createElement("div");
result = src.innerHTML = escapeHTML(dest.value);
}
src.setAttribute('id', id);
swapDOM(dest,src);
return result;
}
function XMLToHTML(s) {
if(s==null) return "";
return s.replace("&","&");
}
function JSONEscape(s) {
if(s==null) return "";
return s.replace("\"","\\\"");
}
function HTMLToXML(s) {
if(s==null) return "";
s = s.replace(">",">");
return s.replace("<","<");
}
function escapeHTML(s) {
if(s==null) return "";
s = s.replace("&","&");
s = s.replace("<","<");
s = s.replace(">",">");
return s;
}
function unescapeHTML(s) {
s = s.replace("<","<");
s = s.replace(">",">");
s = s.replace("&","&");
return s;
}
//functions
function loadMap() {
if(!LOADMAP) return;
var isFirstLoad = (MAP==null);
if(isFirstLoad) {
if (!GBrowserIsCompatible()) {
alert(_("Your browser is not compatable with this map."));
return;
}
FAKEMAP = new GMap2($("fakemap"));
MAP = new GMap2($("map"));
MAP.setCenter(new GLatLng(34.949444, -81.932222), 13);
MAP.addControl(new GLargeMapControl());
MAP.addControl(new GOverviewMapControl());
MAP.addControl(new GMapTypeControl());
GEvent.addListener(MAP, "click", function(overlay, point) {
if (point) {
//MAP.showMapBlowup(point);
}
});
//$("search_box").value = "Type addy or place name here.";
//connect("search_box", 'onfocus', function() { $("search_box").value = ""; });
// if someone types something and hits enter, run a search
onEnter("search_box", function() { doSearch($("search_box").value); });
// login hit enter on password
onEnter("password", login);
// create account hit enter on password
onEnter("create_reenter_password", createAccount);
function makeDiv(id) {
var d = document.createElement('div');
d.id = id;
$("map").appendChild(d);
setOpacity(id, 0.9);
hideElement(id);
}
makeDiv("map_message");
makeDiv("mini_map_message");
setOpacity("darken", 0.7);
showLoginoutLink();
}
getPlaceTypes();
// this will call TRIP_LIST.loadTrip(); when finished
MAP_LIST.loadList();
showLoginoutLink();
// roundElement("type_menu_wrapper", null);
// add empty message to itinerary
var menu = DIV({'class': 'trip_place_menu'},H1({'id': 'empty'},"You have no trips in today's itinerary."));
var html = DIV({'class': 'trip_place_info'}, menu, DIV({'class': 'trip_empty'}, H1({}, "Click on the Places menu on the left to start adding trips.")));
appendChildNodes($("trip"), html);
// set default start point if we need to
if(getQueryParam("default")!=null) {
var handleCall = function(request) {
var makePlace = function (x) {
var place = new Place(x.id, x.name, x.type_id, new BPoint(x.lat, x.lon));
place.address = x.address;
place.website = x.website;
place.description = x.description;
place.phone = x.phone;
return place;
};
var places = forEachJSONElement(request, makePlace);
STARTING_POINT = places[0];
TRIP_LIST.addStartPoint(STARTING_POINT);
TRIP_LIST.refresh();
MAP.setCenter(new GLatLng(places[0].point.lat, places[0].point.lon), 13);
};
var request = doSimpleXMLHttpRequest(makeAJAXLocation('places.php'), {'default_id': getQueryParam("default")});
request.addCallback(handleCall);
}
}
function showLoginoutLink() {
var handleCall = function(request) {
if(request.responseText=='0') showLoginLink();
else showLogoutLink();
};
var request = doSimpleXMLHttpRequest(makeAJAXLocation('user.php'), {'action': 'check_login'});
request.addCallback(handleCall);
}
function clearFormFields() {
var f = new Array("create_email", "email", "create_password", "password", "create_reenter_password");
f.each(function (id) { $(id).value=""; });
}
function logout() {
clearFormFields();
var request = doSimpleXMLHttpRequest(makeAJAXLocation('user.php'), {'action': 'logout'});
request.addCallback(function (request) {
showLoginoutLink();
MAP_LIST = new MapList();
TRIP_LIST = new TripList();
TRIP_LIST.refresh();
MAP_LIST.loadList();
showBriefMiniMessage("You've been logged out.");
});
}
function login() {
var email = USER_EMAIL = $("email").value;
var password = $("password").value;
if(email=="" || password=="") {
alert("You must specify both a username and password.");
return;
}
var handleLogin = function(request) {
if(request.responseText=='1') {
hideLogin();
showLogoutLink();
clearFormFields();
MAP_LIST.loadList();
} else alert("Incorrect username or password.");
};
var params = {'action': 'login', 'email': email, 'password': password};
var request = doSimpleXMLHttpRequest(makeAJAXLocation('user.php'), params);
request.addCallback(handleLogin);
}
function createAccount() {
var email = $("create_email").value;
var password = $("create_password").value;
var preenter = $("create_reenter_password").value;
if(password=="" || preenter=="" || email=="") {
alert("No field can be left blank");
return;
} else if (!isValidEmailAddy(email)) {
alert("The email address you entered is invalid.");
return;
}
if(password != preenter) {
alert("The password you entered the second time doesn't match the first");
return;
}
var handleCreate = function(request) {
if(request.responseText == '1') {
hideLogin();
showLogoutLink();
showBriefMiniMessage("User created.");
clearFormFields();
//MAP_LIST.refresh();
TRIP_LIST.save();
} else if(request.responseText == '2') {
alert("Email address has already been used.");
}
};
var params = {'action': 'create', 'email': email, 'password': password};
var request = doSimpleXMLHttpRequest(makeAJAXLocation('user.php'), params);
request.addCallback(handleCreate);
}
function showLoginLink() {
hideElement("logout");
hideElement("email_itinerary");
showElement("login");
showElement("create_account");
}
function doLogin() {
if(!confirm("If you log in all of your current settings will be lost. Continue?")) return;
showElement("darken");
showElement("login_box");
$("email").focus();
}
function doCreate() {
showElement("darken");
showElement("create_login_box");
$("create_email").focus();
};
function showLogoutLink() {
hideElement("login");
hideElement("create_account");
showElement("logout");
showElement("email_itinerary");
}
function hideLogin() {
hideElement("darken");
hideElement("login_box");
hideElement("create_login_box");
}
function showMapMessage(html) {
//var closeButton = function(x) { return INPUT({'id': 'map_msg_close.'+x, 'type': 'button', 'value': 'Close Window'}); };
var closeButton = function(x) { return SPAN({'id': 'map_msg_close.'+x, 'class': 'span_link'}, 'Close Window'); };
var map_message = $('map_message');
map_message.innerHTML = "";
appendChildNodes(map_message, DIV({}, closeButton(1), BR(), html, BR(), closeButton(2)));
var closeFunction = function(x) {
connect('map_msg_close.'+x, 'onclick', function () { shrink("map_message"); });
onMouseOverClass('map_msg_close.'+x, 'span_link_hover');
};
forEach([1,2], closeFunction);
appear(map_message);
}
function hideMapMessage() { shrink("map_message"); }
function showMiniMessage(msg) {
$('mini_map_message').innerHTML = msg;
if (MINI_MSG_SHOWING) shake('mini_map_message');
else {
appear('mini_map_message', {afterFinish: function () { MINI_MSG_SHOWING = true; }});
}
}
function showBriefMiniMessage(msg) { showMiniMessage(msg); callLater(5, hideMiniMessage); }
function hideMiniMessage() { fade('mini_map_message'); MINI_MSG_SHOWING = false; }
function doSearch(txt) {
//var txt = $("search_box").value;
if(txt=="") return;
showMiniMessage("Searching...");
//hideMapMessage();
var handleSearchResults = function(request) {
var makePlace = function (x) { return x; };
var places = forEachElement(request, "place", makePlace);
// if no results
if(places.length==0) {
showBriefMiniMessage("Sorry, no results were found.");
return;
}
hideMiniMessage();
var items = [{}];
var sr = 0;
forEach(places, function(x) {
var name = (x.type=="addy") ? x.addy : x.name;
items.push(LI({}, SPAN({'class': 'span_link', 'id': 'search_result.'+sr}, name)));
sr++;
});
sr = 0;
showMapMessage(UL.apply(null, items));
forEach(places, function(x) {
onMouseOverClass('search_result.'+sr, "span_link_hover");
connect('search_result.'+sr, 'onclick', function() {
if(x.type=="addy") {
var addy = new Addy(x.addy, new BPoint(x.lat, x.lon));
var marker = makeAddyMarker(addy);
openAddyInfoWindow(addy);
} else {
var place = new Place(x.id, x.name, x.type_id, new BPoint(x.lat, x.lon));
var marker = makeMarker(place);
openMarkerInfoWindow(place);
}
MAP.addOverlay(marker);
hideMapMessage();
});
sr++;
});
};
var request = doSimpleXMLHttpRequest(makeAJAXLocation('search.php'), {'query': txt});
request.addCallback(handleSearchResults);
}
function getPlaceTypes() {
var request = doSimpleXMLHttpRequest(makeAJAXLocation('placeTypes.php'));
request.addCallback(setupTypeMenu);
}
function redrawMarkers() {
MAP.clearOverlays();
forEach(PLACE_MARKERS, function(type_id) {
var place_type = getLocalPlaceType(type_id);
forEach(place_type.places, function(place) {
// If this place is not on the trip list
if(!TRIP_LIST.hasPoint(place.point)) {
var marker = makeMarker(place);
MAP.addOverlay(marker);
}
});
});
if(TRIP_LINE!=null) MAP.addOverlay(TRIP_LINE);
TRIP_LIST.places.ceach(function(place, index) { MAP.addOverlay(makeTripMarker(place, index, TRIP_LIST.places.length)); });
}
function makeTripMarker(place, number, max) {
var point = place.point.toGLatLng();
var makeIcon = function () {
var baseIcon = new GIcon();
baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
baseIcon.iconSize = new GSize(20, 34);
baseIcon.shadowSize = new GSize(37, 34);
baseIcon.iconAnchor = new GPoint(9, 34);
baseIcon.infoWindowAnchor = new GPoint(9, 2);
baseIcon.infoShadowAnchor = new GPoint(18, 25);
return baseIcon;
};
var icon = new GIcon(makeIcon());
if(number == 0) icon.image = makeMarkerImageLocation('start.png');
else if(number == (max-1)) icon.image = icon.image = makeMarkerImageLocation('stop.png');
else icon.image = makeMarkerImageLocation('marker'+(number+1)+'.png');
var marker = new GMarker(point, icon);
GEvent.addListener(marker, 'click', function() {
if(place.type=="place") openMarkerInfoWindow(place);
else openAddyInfoWindow(place);
});
return marker;
}
function setupTypeMenu(request) {
var makePlaceType = function (x) { return new PlaceType(x.id, x.name); };
PLACE_TYPES = forEachJSONElement(request, makePlaceType);
var divs = map(function (place) {
var div = toHTML(DIV({'class': 'typeHeading'}, DIV({'id': 'typeHeading.'+place.id},place.name)));
return div+toHTML(DIV({'class': 'typeContents', 'id': 'typeContents.'+place.id}, _("loading...")));
}, PLACE_TYPES);
$("type_menu").innerHTML = "".join(divs);
forEach(PLACE_TYPES, function (place_type) {
toggle($('typeContents.'+place_type.id), "blind");
onMouseOverClass('typeHeading.'+place_type.id, "typeHeading_hover");
connect('typeHeading.'+place_type.id, 'onclick', function() {
toggle($('typeContents.'+place_type.id), "blind");
// Already being shown - hide it!
if(place_type.hasVisibleMarkers()) {
place_type.hideMarkers();
}
else {
place_type.showMarkers();
}
});
});
}
function setupPlaceMenu(type_id, request) {
var makePlace = function (x) { return new Place(x.id, x.name, x.type_id, new BPoint(x.lat, x.lon)); };
var places = forEachJSONElement(request, makePlace);
var placeType = getLocalPlaceType(type_id);
// add each place to it's proper place type, and make menu
var contents = new Array();
forEach(places, function(place) {
placeType.addPlace(place);
var html = toHTML(LI({'class': 'place_link', 'id': 'place_link.'+place.id}, place.name));
contents.push(html);
//var marker = makeMarker(place);
//MAP.addOverlay(marker);
});
var list = "
";
$('typeContents.'+type_id).innerHTML = (contents.length!=0) ? list : _("No places for this type.");
forEach(places, function(place) {
onMouseOverClass('place_link.'+place.id, "place_link_hover");
connect('place_link.'+place.id, 'onclick', function() {
openMarkerInfoWindow(place);
});
});
}
function makeAddyMarker(addy) {
var point = new GLatLng(addy.point.lat, addy.point.lon);
var marker = new GMarker(point, SmallPin());
GEvent.addListener(marker, 'click', function() {
openAddyInfoWindow(addy);
});
return marker;
}
function openAddyInfoWindow(addy) {
var point = new GLatLng(addy.point.lat, addy.point.lon);
MAP.setCenter(point);
MAP.openInfoWindowHtml(point, makeAddyHTML(addy));
connect('addLink.'+addy.id, 'onclick', function() { TRIP_LIST.addAddy(addy); });
connect('makeDefaultStart.'+addy.id, 'onclick', function() { addStartingPoint(addy); });
onMouseOverClass('addLink.'+addy.id, "span_link_hover");
onMouseOverClass('makeDefaultStart.'+addy.id, "span_link_hover");
}
function makeAddyHTML(addy) {
var addToTrip = SPAN({'id': 'addLink.'+addy.id, 'class': 'span_link'}, _("Add To Trip"));
var makeDefaultStart = SPAN({'id': 'makeDefaultStart.'+addy.id, 'class': 'span_link'}, _("Make Default Starting Point"));
var html = DIV({'class': 'marker_place_info'}, addToTrip, BR(), makeDefaultStart, BR(), B({}, addy.addy), BR(), BR());
return toHTML(html);
}
function makeMarker(place) {
var point = new GLatLng(place.point.lat, place.point.lon);
var marker = new GMarker(point, SmallPin());
GEvent.addListener(marker, 'click', function() {
openMarkerInfoWindow(place);
});
return marker;
}
function openMarkerInfoWindow(place) {
var openWindow = function(lat, lon, request) {
// This next array will have one element that is an object formed from the XML "place"
// element that contains extended information about the place, such as description, website, etc.
//var place_info_list = forEachElement(request, "place", function(x) { return x; });
var place_info_list = forEachJSONElement(request, function(x) {
// we're going to return something that isn't really a "place" type,
// but an "extended" place, w/ description, etc, no lat/lon
x.type = "place";
x.point = new BPoint(x.lat, x.lon);
x.toXml = function() {
return "";
};
x.toJSON = function() {
return "{'type': \"place\",'id': \""+this.id+"\",'notes': \""+JSONEscape(this.notes)+"\"}";
};
return x;
});
var point = new GLatLng(lat, lon);
MAP.setCenter(point);
MAP.openInfoWindow(point, makeMarkerHTML(place_info_list[0]));
connect('addLink.'+place_info_list[0].id, 'onclick', function() { TRIP_LIST.addPlace(place_info_list[0]); });
connect('makeDefaultStart.'+place_info_list[0].id, 'onclick', function() { addStartingPoint(place_info_list[0]); });
onMouseOverClass('addLink.'+place_info_list[0].id, "span_link_hover");
onMouseOverClass('makeDefaultStart.'+place_info_list[0].id, "span_link_hover");
};
var request = doSimpleXMLHttpRequest(makeAJAXLocation('places.php'), {'id': place.id, 'clicked': '1'});
request.addCallback(openWindow, place.point.lat, place.point.lon);
}
// This function takes an info object that contains extended information
// about the place, such as description, website, etc.
function makeMarkerHTML(info) {
var addToTrip = SPAN({'id': 'addLink.'+info.id, 'class': 'span_link'}, _("Add To Trip"));
var makeDefaultStart = SPAN({'id': 'makeDefaultStart.'+info.id, 'class': 'span_link'}, _("Make Default Starting Point"));
var link = (info.website) ? makeRedirectLink(info.id, info.website) : _("No website.");
var name = H1({}, info.name);
// The description must be handled differently in IE because it sucks
var description = null;
description = DIV({'class': 'description'}, info.description);
var phone = info.phone;
var address = info.address;
var html = DIV({'class': 'marker_place_info'}, addToTrip, BR(), makeDefaultStart, name, description, UL({}, LI({}, _("Phone: "), phone), LI({}, _("Address: "), address), LI({}, _("Website: "), link)));
return html;
}
function makeRedirectLink(place_id, website) {
var link = makeLocation("redirect.php?place_id="+place_id+"&to=http://"+website);
return A({'href': link, 'target': '_BLANK'}, website);
}
function makeTripHTML(info, number, trip_size) {
var id = info.id+'.'+number;
var remove_link = SPAN({'id': 'trip_remove.'+id, 'class': 'span_link'}, IMG({'src': makeImageLocation('list-remove.gif')}), _("Remove from trip"));
var move_up = (number==0) ? null : SPAN({'id': 'trip_mup.'+id, 'class': 'span_link'}, IMG({'src': makeImageLocation('go-up.gif')}), _("Move Up"));
var move_down = (number==(trip_size-1)) ? null : SPAN({'id': 'trip_mdown.'+id, 'class': 'span_link'}, IMG({'src': makeImageLocation('go-down.gif')}), _("Move Down"));
var menu = DIV({'class': 'trip_place_menu'}, remove_link, " ", move_up, " ", move_down);
var directions = (number==(trip_size-1)) ? BR() : DIV({'id': 'directions.'+number, 'class': 'directions'}, "Fetching directions");
var notes_text = (info.notes=="No notes."||info.notes==null||info.notes==""||info.notes=="undefined") ? "No notes." : unescapeHTML(info.notes);
var notes = DIV({'class': 'note'}, DIV({'id': 'notes.'+id}, notes_text));
var notes_link = SPAN({'id': 'notes_visible.'+id, 'class': 'span_link'}," ");
if(info.type=="place") {
var link = (info.website) ? makeRedirectLink(info.id, info.website) : _("No website.");
var name = H1({}, (number+1)+'. '+info.name);
// IE is the suck!
var description = null;
description = DIV({'class': 'description'}, info.description);
var phone = info.phone;
var address = info.address;
var html = DIV({'class': 'trip_place_info', 'id': 'trip_place.'+id}, menu, DIV({'class': 'trip_details'}, name, description, UL({},LI(_("Phone: "), phone), LI(_("Address: "), address), LI(_("Website: "), link)), directions, notes_link, notes));
} else {
// addy
var name = H1({}, (number+1)+'. '+info.addy);
var html = DIV({'class': 'trip_place_info', 'id': 'trip_place.'+id}, menu, DIV({'class': 'trip_details'}, name, directions, notes_link, notes));
}
return html;
}
function getLocalPlaceType(id) {
var place_type = null;
forEach(PLACE_TYPES, function(x) {
if(x.id==id) { place_type = x; return; }
});
return place_type;
}
function addStartingPoint(addy) {
STARTING_POINT = addy;
var location = (addy.type == "addy") ? addy.addy : addy.name;
if(confirm("Add staring point of \""+location+"\" to front of each trip?")) {
TRIP_LIST.addStartPoint(addy);
TRIP_LIST.refresh();
}
}
// email trips to user
function email() {
if(!confirm("Send an email containing your trip information?")) return;
var r = doSimpleXMLHttpRequest(makeAJAXLocation('email.php'));
r.addCallback(function() { alert("Email sent. You should receive it shortly."); });
}
// check for a valid email addy
function isValidEmailAddy(email) {
var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
return filter.test(email);
}
function help() {
showElement("darken");
showElement('help_box');
}
function hideHelp() {
hideElement("darken");
hideElement('help_box');
}
function setMyAddress() {
var addy = prompt("Specify your starting address:");
if (addy) doSearch(addy);
}