Misc formatting fixes like only show iOS stuff on those devices, don't show letters on nearby when have no nearby stuff
Misc formatting fixes like only show iOS stuff on those devices, don't show letters on nearby when have no nearby stuff

--- a/common-geo.inc.php
+++ b/common-geo.inc.php
@@ -51,7 +51,7 @@
 	if ($collapsible) $output.= '</div>';
 	return $output;
 }
-function distance($lat1, $lng1, $lat2, $lng2)
+function distance($lat1, $lng1, $lat2, $lng2, $roundLargeValues = false)
 {
 	$pi80 = M_PI / 180;
 	$lat1*= $pi80;
@@ -64,7 +64,10 @@
 	$a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2);
 	$c = 2 * atan2(sqrt($a) , sqrt(1 - $a));
 	$km = $r * $c;
-	return $km * 1000;
+	if ($roundLargeValues) {
+	  if ($km < 1) return floor($km * 1000);
+	  else return round($km,2)."k";
+	} else return floor($km * 1000);
 }
 function decodePolylineToArray($encoded)
 {

--- a/common-template.inc.php
+++ b/common-template.inc.php
@@ -20,7 +20,7 @@
 		});	
 	</script> 
 	<script src="js/jQuery.ui.datepicker.js"></script>';
-echo '<style type="text/css">
+	echo '<style type="text/css">
      .ui-navbar {
      width: 100%;
      }
@@ -44,11 +44,13 @@
     body {
         background-color: #F0F0F0;
     }
-</style>
-<meta name="apple-mobile-web-app-capable" content="yes" />
+</style>';
+	if (strstr($_SERVER['HTTP_USER_AGENT'], 'iPhone') || strstr($_SERVER['HTTP_USER_AGENT'], 'iPod')) {
+		echo '<meta name="apple-mobile-web-app-capable" content="yes" />
  <meta name="apple-mobile-web-app-status-bar-style" content="black" />
  <link rel="apple-touch-startup-image" href="startup.png" />
  <link rel="apple-touch-icon" href="apple-touch-icon.png" />';
+	}
 	if ($geolocate) {
 		echo "<script>
 
@@ -63,7 +65,12 @@
 }
 
 if (navigator.geolocation) {
-  navigator.geolocation.getCurrentPosition(success, error);
+var options = {
+      enableHighAccuracy: false,
+      timeout: 60000,
+      maximumAge: 10000
+}
+  navigator.geolocation.getCurrentPosition(success, error, options);
 }
 
 </script> ";
@@ -109,7 +116,7 @@
         or enter an address/co-ordinates in the box below.</div>';
 	}
 	echo '<div data-role="collapsible" data-collapsed="' . !$geoerror . '">
-        <h3>Change Time/Place (' . (isset($_SESSION['time']) ? $_SESSION['time'] : "Current Time,") . ' '.ucwords(service_period()).')...</h3>
+        <h3>Change Time/Place (' . (isset($_SESSION['time']) ? $_SESSION['time'] : "Current Time,") . ' ' . ucwords(service_period()) . ')...</h3>
         <form action="" method="post">
         <div class="ui-body"> 
 		<div data-role="fieldcontain">

--- a/common.inc.php
+++ b/common.inc.php
@@ -25,31 +25,31 @@
 	$_SESSION['time'] = filter_var($_REQUEST['time'], FILTER_SANITIZE_STRING);
 }
 if (isset($_REQUEST['geolocate'])) {
-   
 	$geocoded = false;
 	if (isset($_REQUEST['lat']) && isset($_REQUEST['lon'])) {
 		$_SESSION['lat'] = trim(filter_var($_REQUEST['lat'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
 		$_SESSION['lon'] = trim(filter_var($_REQUEST['lon'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
 	}
 	else {
-	 $geolocate = filter_var($_REQUEST['geolocate'], FILTER_SANITIZE_URL);
-	 echo $_REQUEST['geolocate'];
-   	 if (startsWith($geolocate, "-")) {
-		  $locateparts = explode(",",$geolocate);
-		  $_SESSION['lat'] = $locateparts[0];
-			$_SESSION['lon'] =$locateparts[1];
-		} else {
-		$contents = geocode($geolocate, true);
-		print_r($contents);
-		if (isset($contents[0]->centroid)) {
-			$geocoded = true;
-			$_SESSION['lat'] = $contents[0]->centroid->coordinates[0];
-			$_SESSION['lon'] = $contents[0]->centroid->coordinates[1];
+		$geolocate = filter_var($_REQUEST['geolocate'], FILTER_SANITIZE_URL);
+		echo $_REQUEST['geolocate'];
+		if (startsWith($geolocate, "-")) {
+			$locateparts = explode(",", $geolocate);
+			$_SESSION['lat'] = $locateparts[0];
+			$_SESSION['lon'] = $locateparts[1];
 		}
 		else {
-			$_SESSION['lat'] = "";
-			$_SESSION['lon'] = "";
-		}
+			$contents = geocode($geolocate, true);
+			print_r($contents);
+			if (isset($contents[0]->centroid)) {
+				$geocoded = true;
+				$_SESSION['lat'] = $contents[0]->centroid->coordinates[0];
+				$_SESSION['lon'] = $contents[0]->centroid->coordinates[1];
+			}
+			else {
+				$_SESSION['lat'] = "";
+				$_SESSION['lon'] = "";
+			}
 		}
 	}
 }
@@ -66,6 +66,31 @@
 function debug($msg, $debugReason = "other")
 {
 	if (isDebug($debugReason)) echo "\n<!-- " . date(DATE_RFC822) . "\n $msg -->\n";
+}
+function isJQueryMobileDevice()
+{
+   // http://forum.jquery.com/topic/what-is-the-best-way-to-detect-all-useragents-which-can-handle-jquery-mobile#14737000002087897
+	$user_agent = $_SERVER['HTTP_USER_AGENT'];   
+	return preg_match('/iphone/i', $user_agent)
+	|| preg_match('/android/i', $user_agent)
+	|| preg_match('/webos/i', $user_agent)
+	|| preg_match('/ios/i', $user_agent)
+	|| preg_match('/bada/i', $user_agent)
+	|| preg_match('/maemo/i', $user_agent)
+	|| preg_match('/meego/i', $user_agent)
+	|| preg_match('/fennec/i', $user_agent)
+	|| (preg_match('/symbian/i', $user_agent)
+	    && preg_match('/s60/i', $user_agent)
+	    && $browser['majorver'] >= 5)
+	|| (preg_match('/symbian/i', $user_agent)
+	    && preg_match('/platform/i', $user_agent)
+	    && $browser['majorver'] >= 3)
+	|| (preg_match('/blackberry/i', $user_agent)
+	    && $browser['majorver'] >= 5)
+	|| (preg_match('/opera mobile/i', $user_agent)
+	    && $browser['majorver'] >= 10)
+	|| (preg_match('/opera mini/i', $user_agent)
+	    && $browser['majorver'] >= 5);
 }
 function isFastDevice()
 {
@@ -129,5 +154,27 @@
 {
 	return str_replace(")", "</small>", str_replace("(", "<br><small>", $input));
 }
+function sksort(&$array, $subkey = "id", $sort_ascending = false)
+{
+	if (count($array)) $temp_array[key($array) ] = array_shift($array);
+	foreach ($array as $key => $val) {
+		$offset = 0;
+		$found = false;
+		foreach ($temp_array as $tmp_key => $tmp_val) {
+			if (!$found and strtolower($val[$subkey]) > strtolower($tmp_val[$subkey])) {
+				$temp_array = array_merge((array)array_slice($temp_array, 0, $offset) , array(
+					$key => $val
+				) , array_slice($temp_array, $offset));
+				$found = true;
+			}
+			$offset++;
+		}
+		if (!$found) $temp_array = array_merge($temp_array, array(
+			$key => $val
+		));
+	}
+	if ($sort_ascending) $array = array_reverse($temp_array);
+	else $array = $temp_array;
+}
 ?>
 

file:a/index.php -> file:b/index.php
--- a/index.php
+++ b/index.php
@@ -19,6 +19,7 @@
                 <li data-role="list-divider">Timetables - Routes</li>
                 <li><a href="routeList.php">Routes By Final Destination</a></li>
 		<li><a href="routeList.php?bynumber=yes">Routes By Number</a></li>
+		<li><a href="routeList.php?bysuburb=yes">Stops By Suburb</a></li>
 		<li><a class="nearby" href="routeList.php?nearby=yes">Nearby Routes</a></li>
             </ul>
 <?php

--- a/routeList.php
+++ b/routeList.php
@@ -1,7 +1,8 @@
 <?php
 include ('common.inc.php');
-include_header("Routes", "routeList");
-echo '
+function navbar()
+{
+	echo '
 		<div data-role="navbar"> 
 			<ul> 
 				<li><a href="routeList.php">By Final Destination...</a></li> 
@@ -11,16 +12,57 @@
 			</ul>
                 </div>
 	';
-echo '  <ul data-role="listview"  data-inset="true">';
-$url = $APIurl . "/json/routes";
-$contents = json_decode(getPage($url));
-function printRoutes($routes)
-{
+}
+if ($_REQUEST['bysuburb']) {
+	include_header("Routes by Suburb", "routeList");
+	navbar();
+	echo '  <ul data-role="listview" data-filter="true" data-inset="true" >';
+	if (!isset($_REQUEST['firstLetter'])) {
+		foreach (range('A', 'Z') as $letter) {
+			echo "<li><a href=\"routeList.php?firstLetter=$letter&bysuburb=yes\">$letter...</a></li>\n";
+		}
+	}
+	else {
+		foreach ($suburbs as $suburb) {
+			if (startsWith($suburb, $_REQUEST['firstLetter'])) {
+				echo '<li><a href="routeList.php?suburb=' . urlencode($suburb) . '">' . $suburb . '</a></li>';
+			}
+		}
+	}
+	echo '</ul>';
+}
+else if ($_REQUEST['nearby'] || $_REQUEST['suburb']) {
+	if ($_REQUEST['suburb']) {
+		$suburb = filter_var($_REQUEST['suburb'], FILTER_SANITIZE_STRING);
+		$url = $APIurl . "/json/stopzonesearch?q=" . $suburb;
+		include_header("Routes by Suburb", "routeList");
+	}
+	if ($_REQUEST['nearby']) {
+		$url = $APIurl . "/json/neareststops?lat={$_SESSION['lat']}&lon={$_SESSION['lon']}&limit=15";
+		include_header("Routes Nearby", "routeList");
+	}
+	$stops = json_decode(getPage($url));
+	$routes = Array();
+	foreach ($stops as $stop) {
+		$url = $APIurl . "/json/stoproutes?stop=" . $stop[0];
+		$stoproutes = json_decode(getPage($url));
+		foreach ($stoproutes as $route) {
+			if (!isset($routes[$route[0]])) $routes[$route[0]] = $route;
+		}
+	}
+	navbar();
+	echo '  <ul data-role="listview" data-filter="true" data-inset="true" >';
+	sksort($routes, 1, true);
 	foreach ($routes as $row) {
-		echo '<li>' . $row[1] . ' <a href="trip.php?routeid=' . $row[0] . '">' . $row[2] . " (" . ucwords($row[3]) . ")</a></li>\n";
+		echo '<li>' . $row[1] . ' <a href="trip.php?routeid=' . $row[0] . '">' . $row[2] . " (" . ucwords($row[4]) . ")</a></li>\n";
 	}
 }
-if ($_REQUEST['bynumber']) {
+else if ($_REQUEST['bynumber']) {
+	include_header("Routes by Number", "routeList");
+	navbar();
+	echo ' <ul data-role="listview"  data-inset="true">';
+	$url = $APIurl . "/json/routes";
+	$contents = json_decode(getPage($url));
 	$routeSeries = Array();
 	$seriesRange = Array();
 	foreach ($contents as $key => $row) {
@@ -54,11 +96,19 @@
 		echo '<a name="' . $series . '"></a>';
 		if ($series <= 9) echo '<li>' . $series . "<ul>\n";
 		else echo "<li>{$seriesRange[$series]['min']}-{$seriesRange[$series]['max']}<ul>\n";
-		printRoutes($routes);
+		foreach ($routes as $row) {
+			echo '<li>' . $row[1] . ' <a href="trip.php?routeid=' . $row[0] . '">' . $row[2] . " (" . ucwords($row[3]) . ")</a></li>\n";
+		}
 		echo "</ul></li>\n";
 	}
 }
 else {
+	include_header("Routes by Destination", "routeList");
+	navbar();
+	echo ' <ul data-role="listview"  data-inset="true">';
+	$url = $APIurl . "/json/routes";
+	$contents = json_decode(getPage($url));
+	// by destination!
 	foreach ($contents as $key => $row) {
 		$routeDestinations[$row[2]][] = $row;
 	}
@@ -73,7 +123,9 @@
 	foreach ($routeDestinations as $destination => $routes) {
 		echo '<a name="' . $destination . '"></a>';
 		echo '<li>' . $destination . "... <ul>\n";
-		printRoutes($routes);
+		foreach ($routes as $row) {
+			echo '<li>' . $row[1] . ' <a href="trip.php?routeid=' . $row[0] . '">' . $row[2] . " (" . ucwords($row[3]) . ")</a></li>\n";
+		}
 		echo "</ul></li>\n";
 	}
 }

--- a/schedule_viewer.py
+++ b/schedule_viewer.py
@@ -281,6 +281,23 @@
       result.append( (r.route_id, r.route_short_name, r.route_long_name, servicep.service_id) )
     result.sort(key = lambda x: x[1:3])
     return result
+
+  def handle_json_GET_routesearch(self, params):
+    """Return a list of routes with matching short name."""
+    schedule = self.server.schedule
+    routeshortname = params.get('routeshortname', None)
+    result = []
+    for r in schedule.GetRouteList():
+      if r.route_short_name == routeshortname:
+        servicep = None
+        for t in schedule.GetTripList():
+          if t.route_id == r.route_id:
+            servicep = t.service_period
+            break
+        result.append( (r.route_id, r.route_short_name, r.route_long_name, servicep.service_id) )
+    result.sort(key = lambda x: x[1:3])
+    return result
+
 
   def handle_json_GET_routerow(self, params):
     schedule = self.server.schedule
@@ -477,8 +494,8 @@
     result = {}
     for trip in trips:
       route = schedule.GetRoute(trip.route_id)
-      if not trip.route_short_name+route.route_long_name in result:
-        result[trip.route_short_name+route.route_long_name] = (route.route_id, route.route_short_name, route.route_long_name, trip.trip_id)
+      if not route.route_short_name+route.route_long_name+trip.service_id in result:
+        result[route.route_short_name+route.route_long_name+trip.service_id] = (route.route_id, route.route_short_name, route.route_long_name, trip.trip_id, trip.service_id)
     return result
     
   def handle_json_GET_stopalltrips(self, params):
@@ -509,6 +526,8 @@
       if service_period == None or trip.service_id == service_period:
         result.append((time, (trip.trip_id, trip_name, trip.service_id), tp))
     return result
+  
+
 
   def handle_json_GET_stoptrips(self, params):
     """Given a stop_id and time in seconds since midnight return the next

--- a/stopList.php
+++ b/stopList.php
@@ -1,7 +1,8 @@
 <?php
 include ('common.inc.php');
-function filterByFirstLetter($var) {
-   return $var[1][0] == $_REQUEST['firstLetter'];
+function filterByFirstLetter($var)
+{
+	return $var[1][0] == $_REQUEST['firstLetter'];
 }
 function navbar()
 {
@@ -21,14 +22,16 @@
 	include_header("Stops by Suburb", "stopList");
 	navbar();
 	echo '  <ul data-role="listview" data-filter="true" data-inset="true" >';
-	foreach ($suburbs as $suburb) {
-		if (!isset($_REQUEST['firstLetter'])) {
-			foreach (range('A', 'Z') as $letter) {
-				echo "<li><a href=\"stopList.php?firstLetter=$letter&suburbs=yes\">$letter...</a></li>\n";
+	if (!isset($_REQUEST['firstLetter'])) {
+		foreach (range('A', 'Z') as $letter) {
+			echo "<li><a href=\"stopList.php?firstLetter=$letter&suburbs=yes\">$letter...</a></li>\n";
+		}
+	}
+	else {
+		foreach ($suburbs as $suburb) {
+			if (startsWith($suburb, $_REQUEST['firstLetter'])) {
+				echo '<li><a href="stopList.php?suburb=' . urlencode($suburb) . '">' . $suburb . '</a></li>';
 			}
-		}
-		else if (startsWith($suburb, $_REQUEST['firstLetter'])) {
-			echo '<li><a href="stopList.php?suburb=' . urlencode($suburb) . '">' . $suburb . '</a></li>';
 		}
 	}
 	echo '</ul>';
@@ -48,6 +51,10 @@
 		include_header("Nearby Stops", "stopList");
 		navbar();
 		timePlaceSettings(true);
+		if (!isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == "") {
+			include_footer();
+			die();
+		}
 	}
 	else if ($_REQUEST['suburb']) {
 		$suburb = filter_var($_REQUEST['suburb'], FILTER_SANITIZE_STRING);
@@ -63,7 +70,7 @@
 		timePlaceSettings();
 	}
 	echo '  <ul data-role="listview" data-filter="true" data-inset="true" >';
-	if (!isset($_REQUEST['firstLetter']) && !$_REQUEST['suburb']) {
+	if (!isset($_REQUEST['firstLetter']) && !$_REQUEST['suburb'] && !$_REQUEST['nearby']) {
 		foreach (range('A', 'Z') as $letter) {
 			echo "<li><a href=\"stopList.php?firstLetter=$letter&$listType\">$letter...</a></li>\n";
 		}
@@ -75,48 +82,47 @@
 		}
 		// Sort the stops by name
 		array_multisort($stopName, SORT_ASC, $stops);
-		if (!isset($_REQUEST['suburb'])){
-		  $stops = array_filter($stops, "filterByFirstLetter");
+		if (!isset($_REQUEST['suburb']) && !isset($_REQUEST['nearby'])) {
+			$stops = array_filter($stops, "filterByFirstLetter");
 		}
 		$stopsGrouped = Array();
 		foreach ($stops as $key => $row) {
-				if ((trim(preg_replace("/\(Platform.*/","",$stops[$key][1])) != trim(preg_replace("/\(Platform.*/","",$stops[$key + 1][1]))) || $key + 1 >= sizeof($stops)) {
-					if (sizeof($stopsGrouped) > 0) {
-						// print and empty grouped stops
-						// subsequent duplicates
-						$stopsGrouped["stop_ids"][] = $row[0];
-						echo '<li>';
-						
-						if (!startsWith($stopsGrouped['stop_codes'][0], "Wj")) echo '<img src="css/images/time.png" alt="Timing Point" class="ui-li-icon">';
-						echo '<a href="stop.php?stopids=' . implode(",", $stopsGrouped['stop_ids']) . '">';
-						if (isset($_SESSION['lat']) && isset($_SESSION['lon'])) {
-							echo '<span class="ui-li-count">' . floor(distance($row[2], $row[3], $_SESSION['lat'], $_SESSION['lon'])) . 'm away</span>';
-						}
-						echo bracketsMeanNewLine(trim(preg_replace("/\(Platform.*/","",$row[1])) . '(' . sizeof($stopsGrouped["stop_ids"]) . ' stops)');
-						echo "</a></li>\n";
-						$stopsGrouped = Array();
+			if ((trim(preg_replace("/\(Platform.*/", "", $stops[$key][1])) != trim(preg_replace("/\(Platform.*/", "", $stops[$key + 1][1]))) || $key + 1 >= sizeof($stops)) {
+				if (sizeof($stopsGrouped) > 0) {
+					// print and empty grouped stops
+					// subsequent duplicates
+					$stopsGrouped["stop_ids"][] = $row[0];
+					echo '<li>';
+					if (!startsWith($stopsGrouped['stop_codes'][0], "Wj")) echo '<img src="css/images/time.png" alt="Timing Point: " class="ui-li-icon">';
+					echo '<a href="stop.php?stopids=' . implode(",", $stopsGrouped['stop_ids']) . '">';
+					if (isset($_SESSION['lat']) && isset($_SESSION['lon'])) {
+						echo '<span class="ui-li-count">' . distance($row[2], $row[3], $_SESSION['lat'], $_SESSION['lon'], true) . 'm away</span>';
 					}
-					else {
-						// just a normal stop
-						echo '<li>';
-						if (!startsWith($row[5], "Wj")) echo '<img src="css/images/time.png" alt="Timing Point" class="ui-li-icon">';
-						echo '<a href="stop.php?stopid=' . $row[0] . (startsWith($row[5], "Wj") ? '&stopcode=' . $row[5] : "") . '">';
-						if (isset($_SESSION['lat']) && isset($_SESSION['lon'])) {
-							echo '<span class="ui-li-count">' . floor(distance($row[2], $row[3], $_SESSION['lat'], $_SESSION['lon'])) . 'm away</span>';
-						}
-						echo bracketsMeanNewLine($row[1]);
-						echo "</a></li>\n";
+					echo bracketsMeanNewLine(trim(preg_replace("/\(Platform.*/", "", $row[1])) . '(' . sizeof($stopsGrouped["stop_ids"]) . ' stops)');
+					echo "</a></li>\n";
+					$stopsGrouped = Array();
+				}
+				else {
+					// just a normal stop
+					echo '<li>';
+					if (!startsWith($row[5], "Wj")) echo '<img src="css/images/time.png" alt="Timing Point" class="ui-li-icon">';
+					echo '<a href="stop.php?stopid=' . $row[0] . (startsWith($row[5], "Wj") ? '&stopcode=' . $row[5] : "") . '">';
+					if (isset($_SESSION['lat']) && isset($_SESSION['lon'])) {
+						echo '<span class="ui-li-count">' . distance($row[2], $row[3], $_SESSION['lat'], $_SESSION['lon'], true) . 'm away</span>';
 					}
-				
-			} else {
+					echo bracketsMeanNewLine($row[1]);
+					echo "</a></li>\n";
+				}
+			}
+			else {
 				// this is a duplicated line item
-				if ($key - 1 <= 0 || (trim(preg_replace("/\(Platform.*/","",$stops[$key][1])) != trim(preg_replace("/\(Platform.*/","",$stops[$key - 1][1])))) {
+				if ($key - 1 <= 0 || (trim(preg_replace("/\(Platform.*/", "", $stops[$key][1])) != trim(preg_replace("/\(Platform.*/", "", $stops[$key - 1][1])))) {
 					// first duplicate
 					$stopsGrouped = Array(
-						"name" => trim(preg_replace("/\(Platform.*/","",$row[1])),
+						"name" => trim(preg_replace("/\(Platform.*/", "", $row[1])) ,
 						"stop_ids" => Array(
 							$row[0]
-						),
+						) ,
 						"stop_codes" => Array(
 							$row[5]
 						)
@@ -127,11 +133,9 @@
 					$stopsGrouped["stop_ids"][] = $row[0];
 				}
 			}
-		
-	       }
+		}
 	}
 	echo '</ul>';
-	var_dump ($stopsGrouped);
 }
 include_footer();
 ?>

file:a/trip.php -> file:b/trip.php
--- a/trip.php
+++ b/trip.php
@@ -4,16 +4,17 @@
 $stopid = filter_var($_REQUEST['stopid'], FILTER_SANITIZE_NUMBER_INT);
 $routeid = filter_var($_REQUEST['routeid'], FILTER_SANITIZE_NUMBER_INT);
 $routetrips = Array();
-if ($_REQUEST['routeid']) {
+if ($_REQUEST['routeid'] && !$_REQUEST['tripid']) {
+	$tripid = 0;
 	$url = $APIurl . "/json/routetrips?route_id=" . $routeid;
 	$routetrips = json_decode(getPage($url));
 	foreach ($routetrips as $trip) {
-		if ($trip[0] < midnight_seconds()) {
+		if ($trip[0] > midnight_seconds()) {
 			$tripid = $trip[1];
 			break;
 		}
 	}
-	if (!($tripid > 0)) $tripid = $routetrip[0][1];
+	if ($tripid == 0) $tripid = $routetrips[0][1];
 }
 $url = $APIurl . "/json/triprows?trip=" . $tripid;
 $trips = array_flatten(json_decode(getPage($url)));
@@ -23,18 +24,29 @@
 	$routetrips = json_decode(getPage($url));
 }
 include_header("Stops on " . $trips[1]->route_short_name . ' ' . $trips[1]->route_long_name, "trip");
-timePlaceSettings();
+$url = $APIurl . "/json/tripstoptimes?trip=" . $tripid;
+$json = json_decode(getPage($url));
+$stops = $json[0];
+$times = $json[1];
+$viaPoints = Array();
+foreach ($stops as $stop) {
+	if (!startsWith($stop[5], "Wj")) {
+		$viaPoints[] = $stop[1];
+	}
+}
+echo 'Via: ' . implode(", ", $viaPoints) . '</small>';
 echo '<p> Other Trips: ';
 foreach ($routetrips as $othertrip) {
 	echo '<a href="trip.php?tripid=' . $othertrip[1] . "&routeid=" . $routeid . '">' . midnight_seconds_to_time($othertrip[0]) . '</a> ';
 }
 echo '</p> Other directions/timing periods: ';
+$url = $APIurl . "/json/routesearch?routeshortname=" . $trips[1]->route_short_name;
+$json = json_decode(getPage($url));
+foreach ($json as $row) {
+	if ($row[0] != $routeid) echo '<a href="trip.php?routeid=' . $row[0] . '">' . $row[2] . ' (' . ucwords($row[3]) . ')</a> ';
+}
 echo '  <ul data-role="listview"  data-inset="true">';
-$url = $APIurl . "/json/tripstoptimes?trip=" . $tripid;
-$json = json_decode(getPage($url));
-$stops = $json[0];
-$times = $json[1];
-echo '<li data-role="list-divider">' . midnight_seconds_to_time($times[0]) . '-' . midnight_seconds_to_time($times[sizeof($times) - 1]) . '</li>';
+echo '<li data-role="list-divider">' . midnight_seconds_to_time($times[0]) . '-' . midnight_seconds_to_time($times[sizeof($times) - 1]) . ' ' . $trips[1]->route_long_name . '</li>';
 $stopsGrouped = Array();
 foreach ($stops as $key => $row) {
 	if (($stops[$key][1] != $stops[$key + 1][1]) || $key + 1 >= sizeof($stops)) {
@@ -45,7 +57,7 @@
 			// subsequent duplicates
 			$stopsGrouped["stop_ids"][] = $row[0];
 			$stopsGrouped["endTime"] = $times[$key];
-			echo '<a href="stop.php?stopids=' . implode(",",$stopsGrouped['stop_ids']) . '">';
+			echo '<a href="stop.php?stopids=' . implode(",", $stopsGrouped['stop_ids']) . '">';
 			echo '<p class="ui-li-aside">' . midnight_seconds_to_time($stopsGrouped['startTime']) . ' to ' . midnight_seconds_to_time($stopsGrouped['endTime']) . '</p>';
 			echo bracketsMeanNewLine($row[1]);
 			echo '</a></li>';

--- a/tripPlanner.php
+++ b/tripPlanner.php
@@ -5,7 +5,10 @@
 $to = (isset($_REQUEST['to']) ? filter_var($_REQUEST['to'], FILTER_SANITIZE_STRING) : "Barry");
 $date = (isset($_REQUEST['date']) ? filter_var($_REQUEST['date'], FILTER_SANITIZE_STRING) : date("m/d/Y"));
 $time = (isset($_REQUEST['time']) ? filter_var($_REQUEST['time'], FILTER_SANITIZE_STRING) : date("H:i"));
-// todo: convert date from form to h:ia?
+function formatTime($timeString) {
+  $timeParts = explode("T",$timeString);
+  return str_replace("Z","",$timeParts[1]);
+}
 function tripPlanForm($errorMessage = "")
 {
 	global $date, $time, $from, $to;
@@ -40,7 +43,7 @@
 }
 function processItinerary($itineraryNumber, $itinerary)
 {
-	echo '<div data-role="collapsible" ' . ($itineraryNumber > 0 ? 'data-collapsed="true"' : "") . '> <h3> Option #' . ($itineraryNumber + 1) . ": " . floor($itinerary->duration / 60000) . " minutes ({$itinerary->startTime} to {$itinerary->endTime})</h3><p>";
+	echo '<div data-role="collapsible" ' . ($itineraryNumber > 0 ? 'data-collapsed="true"' : "") . '> <h3> Option #' . ($itineraryNumber + 1) . ": " . floor($itinerary->duration / 60000) . " minutes (".formatTime($itinerary->startTime)." to ".formatTime($itinerary->endTime).")</h3><p>";
 	echo "Walking time: " . floor($itinerary->walkTime / 60000) . " minutes (" . floor($itinerary->walkDistance) . " meters)<br>\n";
 	echo "Transit time: " . floor($itinerary->transitTime / 60000) . " minutes<br>\n";
 	echo "Waiting time: " . floor($itinerary->waitingTime / 60000) . " minutes<br>\n";
@@ -119,7 +122,7 @@
 			$tripplan = json_decode($page);
 			debug(print_r($triplan, true));
 			echo "<h1> From: {$tripplan->plan->from->name} To: {$tripplan->plan->to->name} </h1>";
-			echo "<h1> At: {$tripplan->plan->date} </h1>";
+			echo "<h1> At: ".formatTime($tripplan->plan->date)." </h1>";
 			if (is_array($tripplan->plan->itineraries->itinerary)) {
 				echo '<div data-role="collapsible-set">';
 				foreach ($tripplan->plan->itineraries->itinerary as $itineraryNumber => $itinerary) {