<?php | |
/* | |
* GeoPo Encode in PHP | |
* @author : Shintaro Inagaki | |
* @param $location (Array) | |
* @return $geopo (String) | |
*/ | |
function geopoEncode($lat, $lng) | |
{ | |
// 64characters (number + big and small letter + hyphen + underscore) | |
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"; | |
$geopo = ""; | |
$scale = 7; | |
// Change a degree measure to a decimal number | |
$lat = ($lat + 90) / 180 * pow(8, 10); | |
$lng = ($lng + 180) / 360 * pow(8, 10); | |
// Compute a GeoPo code from head and concatenate | |
for ($i = 0; $i < $scale; $i++) { | |
$geopo .= substr($chars, floor($lat / pow(8, 9 - $i) % 8) + floor($lng / pow(8, 9 - $i) % 8) * 8, 1); | |
} | |
return $geopo; | |
} | |
/* | |
* GeoPo Decode in PHP | |
* @author : Shintaro Inagaki | |
* @param $geopo (String) | |
* @return $location (Array) | |
*/ | |
function geopoDecode($geopo) | |
{ | |
// 64characters (number + big and small letter + hyphen + underscore) | |
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"; | |
// Array for geolocation | |
$location = array(); | |
for ($i = 0; $i < strlen($geopo); $i++) { | |
// What number of character that equal to a GeoPo code (0-63) | |
$order = strpos($chars, substr($geopo, $i, 1)); | |
// Lat/Lng plus geolocation value of scale | |
$location['lat'] = $location['lat'] + floor($order % 8) * pow(8, 9 - $i); | |
$location['lng'] = $location['lng'] + floor($order / 8) * pow(8, 9 - $i); | |
} | |
// Change a decimal number to a degree measure, and plus revised value that shift center of area | |
$location['lat'] = $location['lat'] * 180 / pow(8, 10) + 180 / pow(8, strlen($geopo)) / 2 - 90; | |
$location['lng'] = $location['lng'] * 360 / pow(8, 10) + 360 / pow(8, strlen($geopo)) / 2 - 180; | |
$location['scale'] = strlen($geopo); | |
return $location; | |
} | |
$conn = pg_connect("dbname=bus user=postgres password=snmc"); | |
if (!$conn) { | |
echo "An error occured.\n"; | |
exit; | |
} | |
if ($_REQUEST['newlatlng']) { | |
$latlng = explode(";", $_REQUEST['newlatlng']); | |
$lat = (float)$latlng[0]; | |
$lng = (float)$latlng[1]; | |
$geoPo = geopoEncode($lat, $lng); | |
$nodelat = (int)($lat * 10000000); | |
$nodelon = (int)($lng * 10000000); | |
echo($nodelat . "," . $nodelon . "=$geoPo<br>"); | |
$sql = "UPDATE stops SET geohash='$geoPo', lat='$nodelat', lng='$nodelon' WHERE geohash = '{$_REQUEST['oldgeopo']}'"; | |
$result = pg_query($conn, $sql); | |
if (!$result) { | |
echo("Error in SQL query: " . pg_last_error() . "<br>\n"); | |
} else { | |
echo $_REQUEST['oldgeopo'] . " replaced with $geoPo <br>"; | |
$updatedroutes = 0; | |
$result_outdatedroutes = pg_query($conn, "Select * FROM between_stops where points LIKE '%" . $_REQUEST['oldgeopo'] . ";%'"); | |
while ($outdatedroute = pg_fetch_assoc($result_outdatedroutes)) { | |
$newpoints = str_replace($_REQUEST['oldgeopo'], $geoPo, $outdatedroute['points']); | |
$sql = "UPDATE between_stops set points='$newpoints' where fromlocation = '{$outdatedroute['fromlocation']}' AND tolocation = '{$outdatedroute['tolocation']}' "; | |
$result = pg_query($conn, $sql); | |
if (!$result) { | |
echo("Error in SQL query: " . pg_last_error() . "<br>\n"); | |
} | |
$updatedroutes++; | |
} | |
echo "updated $updatedroutes routes<br>"; | |
} | |
} | |
flush(); | |
?> |
<html xmlns="http://www.w3.org/1999/xhtml"> | <html xmlns="http://www.w3.org/1999/xhtml"> |
<head> | <head> |
<script src="openlayers/OpenLayers.js"></script> | <script src="openlayers/OpenLayers.js"></script> |
<SCRIPT TYPE="text/javascript" SRC="OpenStreetMap.js"></SCRIPT> | <SCRIPT TYPE="text/javascript" SRC="OpenStreetMap.js"></SCRIPT> |
<script type="text/javascript" src="jquery.1.3.2.min.js"></script> | <script type="text/javascript" src="jquery.1.3.2.min.js"></script> |
<script type="text/javascript"> | <script type="text/javascript"> |
function init() | function init() |
{ | { |
// create the ol map object | // create the ol map object |
var map = new OpenLayers.Map('map'); | var map = new OpenLayers.Map('map'); |
var osmtiles = new OpenLayers.Layer.OSM("local", "http://127.0.0.1/tiles/${z}/${x}/${y}.png") | var osmtiles = new OpenLayers.Layer.OSM("local", "http://10.0.1.154/tiles/${z}/${x}/${y}.png") |
// use http://open.atlas.free.fr/GMapsTransparenciesImgOver.php and http://code.google.com/p/googletilecutter/ to make tiles | // use http://open.atlas.free.fr/GMapsTransparenciesImgOver.php and http://code.google.com/p/googletilecutter/ to make tiles |
markers = new OpenLayers.Layer.Markers("Between Stop Markers"); | markers = new OpenLayers.Layer.Markers("Between Stop Markers"); |
//hanlde mousedown on regions that are not points by reporting latlng | |
OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, { | |
defaultHandlerOptions: { | |
'single': true, | |
'double': false, | |
'pixelTolerance': 0, | |
'stopSingle': false, | |
'stopDouble': false | |
}, | |
initialize: function(options) { | |
this.handlerOptions = OpenLayers.Util.extend( | |
{}, this.defaultHandlerOptions | |
); | |
OpenLayers.Control.prototype.initialize.apply( | |
this, arguments | |
); | |
this.handler = new OpenLayers.Handler.Click( | |
this, { | |
'click': this.trigger | |
}, this.handlerOptions | |
); | |
}, | |
trigger: function(e) { | |
var lonlat = map.getLonLatFromViewPortPx(e.xy).transform( | |
new OpenLayers.Projection("EPSG:900913"), | |
new OpenLayers.Projection("EPSG:4326") | |
); | |
$('form input[name="newlatlng"]').val(lonlat.lat + ";" + lonlat.lon ); | |
} | |
}); | |
var click = new OpenLayers.Control.Click(); | |
map.addControl(click); | |
click.activate(); | |
<?php | <?php |
$conn = pg_connect("dbname=bus user=postgres password=snmc"); | $conn = pg_connect("dbname=bus user=postgres password=snmc"); |
if (!$conn) { | if (!$conn) { |
echo "An error occured.\n"; | echo "An error occured.\n"; |
exit; | exit; |
} | } |
$result_stops = pg_query($conn, "Select * FROM stops"); | $result_stops = pg_query($conn, "Select * FROM stops"); |
while ($stop = pg_fetch_assoc($result_stops)) { | while ($stop = pg_fetch_assoc($result_stops)) { |
echo 'marker = new OpenLayers.Marker(new OpenLayers.LonLat(' . ($stop['lng'] / 10000000) . "," . ($stop['lat'] / 10000000) . ') | echo 'marker = new OpenLayers.Marker(new OpenLayers.LonLat(' . ($stop['lng'] / 10000000) . "," . ($stop['lat'] / 10000000) . ') |
.transform( | .transform( |
new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984 | new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984 |
new OpenLayers.Projection("EPSG:900913") // to Spherical Mercator Projection | new OpenLayers.Projection("EPSG:900913") // to Spherical Mercator Projection |
));'; | ));'; |
echo ' | echo ' |
marker.id="' . $stop['geohash'] . '"; | marker.id="' . $stop['geohash'] . '"; |
markers.addMarker(marker); | markers.addMarker(marker); |
marker.events.register("mousedown", marker, function() { | marker.events.register("mousedown", marker, function() { |
document.getElementById("between_points").innerHTML += this.id+";"; | document.getElementById("between_points").innerHTML += this.id+";"; |
$(\'form input[name="oldgeopo"]\').val(this.id); | |
}); | }); |
'; | '; |
} | } |
?> | ?> |
var timeicon = new OpenLayers.Icon("http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png",new OpenLayers.Size(32,32)); | var timeicon = new OpenLayers.Icon("http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png",new OpenLayers.Size(32,32)); |
var timepoints = new OpenLayers.Layer.GeoRSS("Timing Points", "displaytimepoints.georss.php", { icon: timeicon }); | var timepoints = new OpenLayers.Layer.GeoRSS("Timing Points", "displaytimepoints.georss.php", { icon: timeicon }); |
map.addLayers([osmtiles, markers,timepoints]); | map.addLayers([osmtiles, markers,timepoints]); |
map.addControl(new OpenLayers.Control.LayerSwitcher()); | map.addControl(new OpenLayers.Control.LayerSwitcher()); |
map.zoomToExtent(markers.getDataExtent()); | map.zoomToExtent(markers.getDataExtent()); |
} | } |
</script> | </script> |
<script type="text/javascript"> | <script type="text/javascript"> |
function submitBetween () { | function submitBetween () { |
$.post("betweenpoint.submit.php", $("#inputform").serialize(), function(html){ | $.post("betweenpoint.submit.php", $("#inputform").serialize(), function(html){ |
$("#response").html(html); | $("#response").html(html); |
//clearForms(); | //clearForms(); |
return false; | return false; |
}); | }); |
}; | }; |
function submitMove () { | |
$.post("betweenpoint.move.php", $("#moveform").serialize(), function(html){ | |
$("#response").html(html); | |
return false; | |
}); | |
}; | |
function OnChange(dropdown) | function OnChange(dropdown) |
{ | { |
var myindex = dropdown.selectedIndex | var myindex = dropdown.selectedIndex |
var selValue = dropdown.options[myindex].value; | var selValue = dropdown.options[myindex].value; |
$("#routes").val(selValue.split(":",2)[0]); | $("#routes").val(selValue.split(":",2)[0]); |
fromto = selValue.split(":",2)[1]; | fromto = selValue.split(":",2)[1]; |
$("#from").val(fromto.split("->",2)[0]); | $("#from").val(fromto.split("->",2)[0]); |
$("#to").val(fromto.split("->",2)[1]); | $("#to").val(fromto.split("->",2)[1]); |
document.getElementById("between_points").innerHTML = ""; | document.getElementById("between_points").innerHTML = ""; |
return true; | return true; |
} | } |
// function will clear input elements on each form | // function will clear input elements on each form |
function clearForms(){ | function clearForms(){ |
document.getElementById("between_points").innerHTML = ""; | document.getElementById("between_points").innerHTML = ""; |
// declare element type | // declare element type |
var type = null; | var type = null; |
// loop through forms on HTML page | // loop through forms on HTML page |
for (var x=0; x<document.forms.length; x++){ | for (var x=0; x<document.forms.length; x++){ |
// loop through each element on form | // loop through each element on form |
for (var y=0; y<document.forms[x].elements.length; y++){ | for (var y=0; y<document.forms[x].elements.length; y++){ |
// define element type | // define element type |
type = document.forms[x].elements[y].type | type = document.forms[x].elements[y].type |
// alert before erasing form element | // alert before erasing form element |
//alert('form='+x+' element='+y+' type='+type); | //alert('form='+x+' element='+y+' type='+type); |
// switch on element type | // switch on element type |
switch(type){ | switch(type){ |
case "text": | case "text": |
case "textarea": | case "textarea": |
case "password": | case "password": |
//case "hidden": | //case "hidden": |
document.forms[x].elements[y].value = ""; | document.forms[x].elements[y].value = ""; |
break; | break; |
case "radio": | case "radio": |
case "checkbox": | case "checkbox": |
document.forms[x].elements[y].checked = true; | document.forms[x].elements[y].checked = true; |
break; | break; |
case "select-one": | case "select-one": |
document.forms[x].elements[y].options[0].selected = true; | document.forms[x].elements[y].options[0].selected = true; |
break; | break; |
case "select-multiple": | case "select-multiple": |
for (z=0; z<document.forms[x].elements[y].options.length; z++){ | for (z=0; z<document.forms[x].elements[y].options.length; z++){ |
document.forms[x].elements[y].options[z].selected = false; | document.forms[x].elements[y].options[z].selected = false; |
} | } |
break; | break; |
} | } |
} | } |
} | } |
} | } |
</script> | </script> |
</head> | </head> |
<body onload="init()"> | <body onload="init()"> |
<div id="inputpane"><form id="inputform"> | <div id="inputpane"><form id="inputform"> |
<select name=selectPair onchange='OnChange(this.form.selectPair);'> | <select name=selectPair onchange='OnChange(this.form.selectPair);'> |
<option>Select a from/to pair...</option> | <option>Select a from/to pair...</option> |
<?php | <?php |
include('spyc/spyc.php'); | include('spyc/spyc.php'); |
//$timetable = Spyc::YAMLLoad('../spyc.yaml'); | //$timetable = Spyc::YAMLLoad('../spyc.yaml'); |
$path = "maxious-canberra-transit-feed/output/"; | $path = "maxious-canberra-transit-feed/output/"; |
$dhandle = opendir("maxious-canberra-transit-feed/output/"); | $dhandle = opendir("maxious-canberra-transit-feed/output/"); |
// define an array to hold the files | // define an array to hold the files |
$files = array(); | $files = array(); |
$paths = array(); | $paths = array(); |
if ($dhandle) { | if ($dhandle) { |
// loop through all of the files | // loop through all of the files |
while (false !== ($fname = readdir($dhandle))) { | while (false !== ($fname = readdir($dhandle))) { |
if (($fname != '.') && ($fname != '..')) { | if (($fname != '.') && ($fname != '..')) { |
$timetable = Spyc::YAMLLoad("maxious-canberra-transit-feed/output/" . $fname); | $timetable = Spyc::YAMLLoad("maxious-canberra-transit-feed/output/" . $fname); |
// Strip off individual platforms because it usually doesn't matter for routes | // Strip off individual platforms because it usually doesn't matter for routes |
$timetable["time_points"] = preg_replace("/\(Platform.*/","",$timetable["time_points"]); | $timetable["time_points"] = preg_replace("/\(Platform.*/","",$timetable["time_points"]); |
for ($i = 0; $i < sizeof($timetable["time_points"]) - 1; $i++) { | for ($i = 0; $i < sizeof($timetable["time_points"]) - 1; $i++) { |
$key = trim($timetable["time_points"][$i]) . "->" . trim($timetable["time_points"][$i + 1]); | $key = trim($timetable["time_points"][$i]) . "->" . trim($timetable["time_points"][$i + 1]); |
if (strstr($paths[$key],";" . $timetable["short_name"] . ";") === false) | if (strstr($paths[$key],";" . $timetable["short_name"] . ";") === false) |
@$paths[$key] .= $timetable["short_name"] . ";"; | @$paths[$key] .= $timetable["short_name"] . ";"; |
} | } |
} | } |
} | } |
} | } |
ksort($paths); | ksort($paths); |
$completedPaths = array(); | $completedPaths = array(); |
$result_betweenstops = pg_query($conn, "Select * FROM between_stops"); | $result_betweenstops = pg_query($conn, "Select * FROM between_stops"); |
while ($path = pg_fetch_assoc($result_betweenstops)) { | while ($path = pg_fetch_assoc($result_betweenstops)) { |
$key = trim($path['fromlocation']) . "->" . trim($path['tolocation']); | $key = trim($path['fromlocation']) . "->" . trim($path['tolocation']); |
$completedPaths[$key].= trim($path['routes']); | $completedPaths[$key].= trim($path['routes']); |
} | } |
foreach ($paths as $path => $routes) { | foreach ($paths as $path => $routes) { |
if (!in_array($path, array_keys($completedPaths))) { | if (!in_array($path, array_keys($completedPaths))) { |
echo "<option value=\"$routes:$path\">" . sizeof(explode(";", $routes)) . " $path</option>\n"; | echo "<option value=\"$routes:$path\">" . sizeof(explode(";", $routes)) . " $path</option>\n"; |
} else { | } else { |
$completedRoutes = explode(";", $completedPaths[$path]); | $completedRoutes = explode(";", $completedPaths[$path]); |
$incompleteRoutes = ""; | $incompleteRoutes = ""; |
foreach (explode(";", $routes) as $route) { | foreach (explode(";", $routes) as $route) { |
if (!in_array($route,$completedRoutes) && strstr($incompleteRoutes,';'.$route.';') === false) { | if (!in_array($route,$completedRoutes) && strstr($incompleteRoutes,';'.$route.';') === false) { |
$incompleteRoutes .= $route.';'; | $incompleteRoutes .= $route.';'; |
} | } |
} | } |
if ($incompleteRoutes != "") { | if ($incompleteRoutes != "") { |
echo "<option value=\"$incompleteRoutes:$path\">" . sizeof(explode(";", $incompleteRoutes)) . " $path</option>\n"; | echo "<option value=\"$incompleteRoutes:$path\">" . sizeof(explode(";", $incompleteRoutes)) . " $path</option>\n"; |
} | } |
} | } |
} | } |
?> | ?> |
</select> | </select> |
from <input type="text" name="from" id="from"/> | from <input type="text" name="from" id="from"/> |
to <input type="text" name="to" id="to"/> | to <input type="text" name="to" id="to"/> |
<br> | <br> |
on routes <input type="text" name="routes" id="routes"/> | on routes <input type="text" name="routes" id="routes"/> |
Reverse? <input type="checkbox" name="reverse" id="reverse" checked="true"/> | Reverse? <input type="checkbox" name="reverse" id="reverse" checked="true"/> |
<input type="button" onclick="javascript:submitBetween()" value="Submit!"> | <input type="button" onclick="javascript:submitBetween()" value="Submit!"> |
<input type="button" value="Clear" onclick="javascript:clearForms()" title="Start clearForms() JavaScript function"> | <input type="button" value="Clear" onclick="javascript:clearForms()" title="Start clearForms() JavaScript function"> |
<br> | <br> |
<textarea name="between_points" id="between_points" rows="1" cols="120"></textarea> | <textarea name="between_points" id="between_points" rows="1" cols="120"></textarea> |
</form> | </form> |
<form id="moveform"> | |
oldgeopo <input type="text" name="oldgeopo" id="oldgeopo"/> | |
newlatlng <input type="text" name="newlatlng" id="newlatlng" size="60"/> | |
<input type="button" onclick="javascript:submitMove()" value="Move!"> | |
</form> | |
<div id="response"> | <div id="response"> |
<!-- Our message will be echoed out here --> | <!-- Our message will be echoed out here --> |
</div> | </div> |
</div> | </div> |
<div id="map" width="100%" height="100%"></div> | <div id="map" width="100%" height="100%"></div> |
</body> | </body> |
</html> | </html> |
<?php | <?php |
$conn = pg_connect("dbname=bus user=postgres password=snmc"); | $conn = pg_connect("dbname=bus user=postgres password=snmc"); |
if (!$conn) { | if (!$conn) { |
echo "An error occured.\n"; | echo "An error occured.\n"; |
exit; | exit; |
} | } |
print_r($_REQUEST); | print_r($_REQUEST); |
$reverse=$_REQUEST["reverse"]; | $reverse=$_REQUEST["reverse"]; |
$from=$_REQUEST["from"]; | $from=pg_escape_string($_REQUEST["from"]); |
$to=$_REQUEST["to"]; | $to=pg_escape_string($_REQUEST["to"]); |
$routes=$_REQUEST["routes"] ; | $routes=$_REQUEST["routes"] ; |
$points=$_REQUEST["between_points"]; | $points=$_REQUEST["between_points"]; |
$sql = "INSERT INTO between_stops (fromLocation, toLocation, points, routes) VALUES('$from','$to','$points','$routes')"; | $sql = "INSERT INTO between_stops (fromLocation, toLocation, points, routes) VALUES('$from','$to','$points','$routes')"; |
$result = pg_query($conn, $sql); | $result = pg_query($conn, $sql); |
if (!$result) { | if (!$result) { |
echo("Error in SQL query: " . pg_last_error() ."<br>\n"); | echo("Error in SQL query: " . pg_last_error() ."<br>\n"); |
} | } |
if ($reverse === "on") { | if ($reverse === "on") { |
$ep = explode(";",$points); | $ep = explode(";",$points); |
$epr = array_reverse($ep); | $epr = array_reverse($ep); |
$p = implode(";",$epr).";"; | $p = implode(";",$epr).";"; |
$pointsString = substr($p,1); | $pointsString = substr($p,1); |
$sql = "INSERT INTO between_stops ( toLocation, fromLocation, points, routes) VALUES('$from','$to','$pointsString','$routes')"; | $sql = "INSERT INTO between_stops ( toLocation, fromLocation, points, routes) VALUES('$from','$to','$pointsString','$routes')"; |
$result = pg_query($conn, $sql); | $result = pg_query($conn, $sql); |
if (!$result) { | if (!$result) { |
echo("Error in SQL query: " . pg_last_error() ."<br>\n"); | echo("Error in SQL query: " . pg_last_error() ."<br>\n"); |
} | } |
} | } |
flush(); | flush(); |
?> | ?> |
<?php | <?php |
date_default_timezone_set('Australia/ACT'); | date_default_timezone_set('Australia/ACT'); |
$APIurl = "http://localhost:8765"; | $APIurl = "http://localhost:8765"; |
error_reporting(E_ALL ^ E_NOTICE); | error_reporting(E_ALL ^ E_NOTICE); |
// you have to open the session to be able to modify or remove it | |
session_start(); | |
function isDebug() | function isDebug() |
{ | { |
return true; | return $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1" || !$_SERVER['SERVER_NAME']; |
} | } |
function debug($msg) { | |
if (isDebug()) echo "<!-- $msg -->"; | |
} | |
function isFastDevice() { | function isFastDevice() { |
return true; | return true; |
} | } |
function include_header($pageTitle, $opendiv = true, $geolocate = false) { | function include_header($pageTitle, $opendiv = true, $geolocate = false) { |
// this starts the session | |
session_start(); | |
// if (isDebug()) // set php error level high | // if (isDebug()) // set php error level high |
echo ' | echo ' |
<!DOCTYPE html> | <!DOCTYPE html> |
<html> | <html> |
<head> | <head> |
<title>bus.lambdacomplex.org - '.$pageTitle.'</title> | <title>bus.lambdacomplex.org - '.$pageTitle.'</title> |
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.css" /> | '; |
<script src="http://code.jquery.com/jquery-1.4.3.min.js"></script><script type="text/javascript" | if (isDebug()) echo '<link rel="stylesheet" href="jquery-mobile-1.0a2.css" /> |
src="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.js"></script> | <script type="text/javascript" src="jquery-mobile-1.0a2.js"></script>'; |
<script type="text/javascript" src="docs/docs.js"></script> | else echo '<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.css" /> |
<meta name="apple-mobile-web-app-capable" content="yes" /> | <script type="text/javascript" src="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.js"></script>'; |
echo ' | |
<style type="text/css"> | |
.ui-navbar { | |
padding-bottom: 18px; | |
width: 100%; | |
} | |
</style> | |
<meta name="apple-mobile-web-app-capable" content="yes" /> | |
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> | <meta name="apple-mobile-web-app-status-bar-style" content="black" /> |
<link rel="apple-touch-startup-image" href="startup.png" /> | <link rel="apple-touch-startup-image" href="startup.png" /> |
<link rel="apple-touch-icon" href="apple-touch-icon.png" /> | <link rel="apple-touch-icon" href="apple-touch-icon.png" />'; |
</head> | if ($geolocate) { |
echo "<script> | |
function setCookie(c_name,value,expiredays) | |
{ | |
var exdate=new Date(); | |
exdate.setDate(exdate.getDate()+expiredays); | |
document.cookie=c_name+ \"=\" +escape(value)+ | |
((expiredays==null) ? \"\" : \";expires=\"+exdate.toUTCString()); | |
} | |
function getCookie(c_name) | |
{ | |
if (document.cookie.length>0) | |
{ | |
c_start=document.cookie.indexOf(c_name + \"=\"); | |
if (c_start!=-1) | |
{ | |
c_start=c_start + c_name.length+1; | |
c_end=document.cookie.indexOf(\";\",c_start); | |
if (c_end==-1) c_end=document.cookie.length; | |
return unescape(document.cookie.substring(c_start,c_end)); | |
} | |
} | |
return \"\"; | |
} | |
function success(position) { | |
$('#geolocate').val(position.coords.latitude+','+position.coords.longitude); | |
setCookie('geolocate',position.coords.latitude+','+position.coords.longitude,1); | |
} | |
function error(msg) { | |
console.log(msg); | |
} | |
if (navigator.geolocation) { | |
navigator.geolocation.getCurrentPosition(success, error); | |
} | |
</script> "; | |
} | |
echo '</head> | |
<body> | <body> |
'; | '; |
if ($opendiv) echo '<div data-role="page"> | if ($opendiv) echo '<div data-role="page"> |
<div data-role="header"> | <div data-role="header"> |
<h1>'.$pageTitle.'</h1> | <h1>'.$pageTitle.'</h1> |
<a href="index.php" data-icon="back" class="ui-btn-right">Home</a> | |
</div><!-- /header --> | </div><!-- /header --> |
<div data-role="content"> '; | <div data-role="content"> '; |
} | } |
function include_footer() | function include_footer() |
{ | { |
echo '</div>'; | echo '</div>'; |
} | } |
$service_periods = Array ('sunday','saturday','weekday'); | |
function service_period() | function service_period() |
{ | { |
if (isset($_SESSION['service_period'])) return $_SESSION['service_period']; | |
switch (date('w')){ | switch (date('w')){ |
case 0: | case 0: |
return 'sunday'; | return 'sunday'; |
case 6: | case 6: |
return 'saturday'; | return 'saturday'; |
default: | default: |
return 'weekday'; | return 'weekday'; |
} | } |
} | } |
function remove_spaces($string) | |
{ | |
return str_replace(' ','',$string); | |
} | |
function midnight_seconds() | function midnight_seconds() |
{ | { |
// from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html | // from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html |
$secs = (date("G") * 3600) + (date("i") * 60) + date("s"); | if (isset($_SESSION['time'])) { |
return $secs; | $time = mkdate($_SESSION['time']); |
return (date("G",$time) * 3600) + (date("i",$time) * 60) + date("s",$time); | |
} | |
return (date("G") * 3600) + (date("i") * 60) + date("s"); | |
} | } |
function midnight_seconds_to_time($seconds) | function midnight_seconds_to_time($seconds) |
{ | { |
$midnight = mktime (0, 0, 0, date("n"), date("j"), date("Y")); | $midnight = mktime (0, 0, 0, date("n"), date("j"), date("Y")); |
return date("h:ia",$midnight+$seconds); | return date("h:ia",$midnight+$seconds); |
} | } |
function getPage($url) | function getPage($url) |
{ | { |
$ch = curl_init($url); | $ch = curl_init($url); |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); | curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); |
curl_setopt( $ch, CURLOPT_HEADER, 0 ); | curl_setopt( $ch, CURLOPT_HEADER, 0 ); |
$page = curl_exec($ch); | $page = curl_exec($ch); |
curl_close($ch); | curl_close($ch); |
return $page; | return $page; |
} | } |
function array_flatten($a,$f=array()){ | function array_flatten($a,$f=array()){ |
if(!$a||!is_array($a))return ''; | if(!$a||!is_array($a))return ''; |
foreach($a as $k=>$v){ | foreach($a as $k=>$v){ |
if(is_array($v))$f=array_flatten($v,$f); | if(is_array($v))$f=array_flatten($v,$f); |
else $f[$k]=$v; | else $f[$k]=$v; |
} | } |
return $f; | return $f; |
} | } |
function staticmap($mapPoints) | function staticmap($mapPoints, $zoom = 0, $markerImage = "iconb") |
{ | { |
$width = 300; | $width = 300; |
$height = 300; | $height = 300; |
$zoom = 0; | $metersperpixel[9]=305.492*$width; |
$metersperpixel[10]=152.746*$width; | |
$metersperpixel[11]=76.373*$width; | |
$metersperpixel[12]=38.187*$width; | |
$metersperpixel[13]=19.093*$width; | |
$metersperpixel[14]=9.547*$width; | |
$metersperpixel[15]=4.773*$width; | |
$metersperpixel[16]=2.387*$width; | |
// $metersperpixel[17]=1.193*$width; | |
$center = ""; | $center = ""; |
$markers = ""; | $markers = ""; |
$minlat = 999; | |
if (sizeof($mapPoints) < 1) return ""; | $minlon = 999; |
$maxlat = 0; | |
$maxlon = 0; | |
if (sizeof($mapPoints) < 1) return "map error"; | |
if (sizeof($mapPoints) === 1) { | if (sizeof($mapPoints) === 1) { |
$zoom = 14; | if ($zoom == 0) $zoom = 14; |
$markers .= $mapPoint[0].",".$mapPoint[1].",ol-marker"; | $markers .= "{$mapPoints[0][0]},{$mapPoints[0][1]},$markerimage"; |
$center = "{$mapPoints[0][0]},{$mapPoints[0][1]}"; | $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}"; |
} else { | } else { |
foreach ($mapPoints as $index => $mapPoint) { | foreach ($mapPoints as $index => $mapPoint) { |
$markers .= $mapPoint[0].",".$mapPoint[1].",lightblue".($index+1); | $markers .= $mapPoint[0].",".$mapPoint[1].",".$markerImage.($index+1); |
if ($index+1 != sizeof($mapPoints)) $markers .= "|"; | if ($index+1 != sizeof($mapPoints)) $markers .= "|"; |
if ($mapPoint[0] < $minlat) $minlat = $mapPoint[0]; | |
if ($mapPoint[0] > $maxlat) $maxlat = $mapPoint[0]; | |
if ($mapPoint[1] < $minlon) $minlon = $mapPoint[1]; | |
if ($mapPoint[1] > $maxlon) $maxlon = $mapPoint[1]; | |
$totalLat += $mapPoint[0]; | $totalLat += $mapPoint[0]; |
$totalLon += $mapPoint[1]; | $totalLon += $mapPoint[1]; |
} | } |
$zoom = 11; | if ($zoom == 0) { |
$mapwidthinmeters = distance($minlat,$minlon,$minlat,$maxlon); | |
foreach (array_reverse($metersperpixel,true) as $zoomLevel => $maxdistance) | |
{ | |
if ($zoom == 0 && $mapwidthinmeters < ($maxdistance + 50)) $zoom = $zoomLevel; | |
} | |
} | |
$center = $totalLat/sizeof($mapPoints).",".$totalLon/sizeof($mapPoints); | $center = $totalLat/sizeof($mapPoints).",".$totalLon/sizeof($mapPoints); |
} | } |
return '<img src="staticmaplite/staticmap.php?center='.$center.'&zoom='.$zoom.'&size='.$width.'x'.$height.'&maptype=mapnik&markers='.$markers.'" width='.$width.' height='.$height.'>'; | return '<img src="staticmaplite/staticmap.php?center='.$center.'&zoom='.$zoom.'&size='.$width.'x'.$height.'&maptype=mapnik&markers='.$markers.'" width='.$width.' height='.$height.'>'; |
} | |
function distance($lat1, $lng1, $lat2, $lng2) | |
{ | |
$pi80 = M_PI / 180; | |
$lat1 *= $pi80; | |
$lng1 *= $pi80; | |
$lat2 *= $pi80; | |
$lng2 *= $pi80; | |
$r = 6372.797; // mean radius of Earth in km | |
$dlat = $lat2 - $lat1; | |
$dlng = $lng2 - $lng1; | |
$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; | |
} | } |
function decodePolylineToArray($encoded) | function decodePolylineToArray($encoded) |
{ | { |
// source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5 | // source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5 |
$length = strlen($encoded); | $length = strlen($encoded); |
$index = 0; | $index = 0; |
$points = array(); | $points = array(); |
$lat = 0; | $lat = 0; |
$lng = 0; | $lng = 0; |
while ($index < $length) | while ($index < $length) |
{ | { |
// Temporary variable to hold each ASCII byte. | // Temporary variable to hold each ASCII byte. |
$b = 0; | $b = 0; |
// The encoded polyline consists of a latitude value followed by a | // The encoded polyline consists of a latitude value followed by a |
// longitude value. They should always come in pairs. Read the | // longitude value. They should always come in pairs. Read the |
// latitude value first. | // latitude value first. |
$shift = 0; | $shift = 0; |
$result = 0; | $result = 0; |
do | do |
{ | { |
// The `ord(substr($encoded, $index++))` statement returns the ASCII | // The `ord(substr($encoded, $index++))` statement returns the ASCII |
// code for the character at $index. Subtract 63 to get the original | // code for the character at $index. Subtract 63 to get the original |
// value. (63 was added to ensure proper ASCII characters are displayed | // value. (63 was added to ensure proper ASCII characters are displayed |
// in the encoded polyline string, which is `human` readable) | // in the encoded polyline string, which is `human` readable) |
$b = ord(substr($encoded, $index++)) - 63; | $b = ord(substr($encoded, $index++)) - 63; |
// AND the bits of the byte with 0x1f to get the original 5-bit `chunk. | // AND the bits of the byte with 0x1f to get the original 5-bit `chunk. |
// Then left shift the bits by the required amount, which increases | // Then left shift the bits by the required amount, which increases |
// by 5 bits each time. | // by 5 bits each time. |
// OR the value into $results, which sums up the individual 5-bit chunks | // OR the value into $results, which sums up the individual 5-bit chunks |
// into the original value. Since the 5-bit chunks were reversed in | // into the original value. Since the 5-bit chunks were reversed in |
// order during encoding, reading them in this way ensures proper | // order during encoding, reading them in this way ensures proper |
// summation. | // summation. |
$result |= ($b & 0x1f) << $shift; | $result |= ($b & 0x1f) << $shift; |
$shift += 5; | $shift += 5; |
} | } |
// Continue while the read byte is >= 0x20 since the last `chunk` | // Continue while the read byte is >= 0x20 since the last `chunk` |
// was not OR'd with 0x20 during the conversion process. (Signals the end) | // was not OR'd with 0x20 during the conversion process. (Signals the end) |
while ($b >= 0x20); | while ($b >= 0x20); |
// Check if negative, and convert. (All negative values have the last bit | // Check if negative, and convert. (All negative values have the last bit |
// set) | // set) |
$dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1)); | $dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1)); |
// Compute actual latitude since value is offset from previous value. | // Compute actual latitude since value is offset from previous value. |
$lat += $dlat; | $lat += $dlat; |
// The next values will correspond to the longitude for this point. | // The next values will correspond to the longitude for this point. |
$shift = 0; | $shift = 0; |
$result = 0; | $result = 0; |
do | do |
{ | { |
$b = ord(substr($encoded, $index++)) - 63; | $b = ord(substr($encoded, $index++)) - 63; |
$result |= ($b & 0x1f) << $shift; | $result |= ($b & 0x1f) << $shift; |
$shift += 5; | $shift += 5; |
} | } |
while ($b >= 0x20); | while ($b >= 0x20); |
$dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1)); | $dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1)); |
$lng += $dlng; | $lng += $dlng; |
// The actual latitude and longitude values were multiplied by | // The actual latitude and longitude values were multiplied by |
// 1e5 before encoding so that they could be converted to a 32-bit | // 1e5 before encoding so that they could be converted to a 32-bit |
// integer representation. (With a decimal accuracy of 5 places) | // integer representation. (With a decimal accuracy of 5 places) |
// Convert back to original values. | // Convert back to original values. |
$points[] = array($lat * 1e-5, $lng * 1e-5); | $points[] = array($lat * 1e-5, $lng * 1e-5); |
} | } |
return $points; | return $points; |
} | } |
function object2array($object) { | function object2array($object) { |
if (is_object($object)) { | if (is_object($object)) { |
foreach ($object as $key => $value) { | foreach ($object as $key => $value) { |
$array[$key] = $value; | $array[$key] = $value; |
} | } |
} | } |
else { | else { |
$array = $object; | $array = $object; |
} | } |
return $array; | return $array; |
} | } |
function geocode($query, $giveOptions) { | function geocode($query, $giveOptions) { |
$url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?query=".$query."&bbox=-35.5,149.00,-35.15,149.1930&return_location=true&bbox_only=true"; | $url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?query=".$query."&bbox=-35.5,149.00,-35.15,149.1930&return_location=true&bbox_only=true"; |
$contents = json_decode(getPage($url)); | $contents = json_decode(getPage($url)); |
if ($giveOptions) return $contents->features; | if ($giveOptions) return $contents->features; |
else return $contents->features[0]->centroid->coordinates[0].",".$contents->features[0]->centroid->coordinates[1]; | elseif (isset($contents->features[0]->centroid)) return $contents->features[0]->centroid->coordinates[0].",".$contents->features[0]->centroid->coordinates[1]; |
else return ""; | |
} | } |
function reverseGeocode($lat,$lng) { | function reverseGeocode($lat,$lng) { |
$url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?around=".$lat.",".$lng."&distance=closest&object_type=road"; | $url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?around=".$lat.",".$lng."&distance=closest&object_type=road"; |
$contents = json_decode(getPage($url)); | $contents = json_decode(getPage($url)); |
return $contents->features[0]->properties->name; | return $contents->features[0]->properties->name; |
} | } |
function startsWith($haystack,$needle,$case=true) { | |
if($case){return (strcmp(substr($haystack, 0, strlen($needle)),$needle)===0);} | |
return (strcasecmp(substr($haystack, 0, strlen($needle)),$needle)===0); | |
} | |
function endsWith($haystack,$needle,$case=true) { | |
if($case){return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0);} | |
return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0); | |
} | |
?> | ?> |
<?php | <?php |
include('common.inc.php'); | include('common.inc.php'); |
include_header("bus.lambdacomplex.org",false) | // remove all the variable in the session |
session_unset(); | |
//destroy the session | |
session_destroy(); | |
if (isset($_REQUEST['service_period'])) $_SESSION['service_period'] = $_REQUEST['service_period']; | |
if (isset($_REQUEST['time'])) $_SESSION['time'] = $_REQUEST['time']; | |
// todo take in cellids and crossreference with http://realtimeblog.free.fr/latest/cellular/processed/sqlite/505_sqlite_zones.zip to estimate location | |
include_header("bus.lambdacomplex.org",false, true) | |
?> | ?> |
<div data-role="page" data-theme="b" id="jqm-home" class="ui-page ui-body-b ui-page-active"> | <div data-role="page" data-theme="b" id="jqm-home" class="ui-page ui-body-b ui-page-active"> |
<div id="jqm-homeheader"> | <div id="jqm-homeheader"> |
<center><h1 id="jqm-logo"><img src="apple-touch-icon.png" alt="jQuery Mobile Framework" width="64" height="64" /> | <center><h1 id="jqm-logo"><img src="apple-touch-icon.png" alt="logo" width="64" height="64" /><br> |
bus.lambdacomplex.org</h1></center> | bus.lambdacomplex.org</h1></center> |
</div> | </div> |
<div data-role="content"> | <div data-role="content"> |
<a href="tripPlanner.php" data-role="button">Launch Trip Planner...</a> | |
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"> | <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"> |
<li data-role="list-divider">Stops</li> | <li data-role="list-divider">Timetables - Stops</li> |
<li><a href="stopList.php">All stops List</a></li> | <li><a href="stopList.php">Major (Timing Point) Stops</a></li> |
<li class="nearby"><a href="stopList.php?nearby=yes">Nearby List</a></li> | <li><a href="stopList.php">All Stops</a></li> |
<li><a href="stopList.php?favourites=yes">Favourites List</a></li> | <li><a href="stopList.php?nearbyfavs=yes">Nearby/Favourite Stops</a></li> |
</ul> | </ul> |
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"> | <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"> |
<li data-role="list-divider">Routes</li> | <li data-role="list-divider">Timetables - Routes</li> |
<li><a href="routeList.php">All Routes List</a></li> | <li><a href="routeList.php">Routes By Final Destination</a></li> |
<li class="nearby"><a href="routeList.php?nearby=yes">Nearby List</a></li> | <li><a href="routeList.php?bynumber=yes">Routes By Number</a></li> |
<li><a href="routeList.php?favourites=yes">Favourites List</a></li> | <li><a href="routeList.php?nearbyfavs=yes">Nearby/Favourites Routes</a></li> |
</ul> | </ul> |
<div class="ui-body ui-body-c info"> | <div class="ui-body ui-body-c"> |
<p class="latlng"></p> | <h3>Time/Place Settings</h3> |
Time: <?php echo date("H:m"); ?> <br> | <div data-role="fieldcontain"> |
Service Period: <?php echo ucwords(service_period()); ?> | <label for="geolocate"> Current Location: </label> |
<input type="text" id="geolocate" name="geolocate"/> <a href="#" style="display:none" name="here" id="here"/>Here?</a> | |
</div> | |
<div data-role="fieldcontain"> | |
<label for="time"> Time: </label> | |
<input type="time" value="<?php echo date("H:m"); ?>"/> <a href="#" style="display:none" name="currentTime" id="currentTime"/>Current Time?</a> | |
</div> | |
<div data-role="fieldcontain"> | |
<label for="service_period"> Service Period: </label> | |
<select name="service_period"> | |
<?php | |
foreach ($service_periods as $service_period) { | |
echo "<option value=\"$service_period\"".(service_period() === $service_period ? "SELECTED" : "").'>'.ucwords($service_period).'</option>'; | |
}?> | |
</select> | |
<a href="#" style="display:none" name="currentPeriod" id="currentPeriod"/>Current Period?</a> | |
</div> | |
<input type="submit" value="Update"/> | |
</div> | </div> |
<script> | |
$('#here').click(function(event) { $('#geolocate').val(getCookie('geolocate')); return false;}); | |
$('#here').show(); | |
</script> | |
</div> | </div> |
</div> | </div> |
</body> | </body> |
</html> | </html> |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. | |
* Note: Code is in draft form and is subject to change | |
*/ | |
/* theme bar,body,btn containers | |
----------------------------------*/ | |
.ui-bar-a { border: 1px solid #2A2A2A; background: #111111; color: #fff; font-weight: bold; text-shadow: 0 -1px 1px #000; background-image: -moz-linear-gradient(top, #3c3c3c, #111111); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #3c3c3c),color-stop(1, #111111)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#3c3c3c', EndColorStr='#111111')"; } | |
.ui-bar-a, .ui-bar-a input, .ui-bar-a select, .ui-bar-a textarea, .ui-bar-a button { font-family: Helvetica, Arial, sans-serif; } | |
.ui-bar-a .ui-link-inherit { color: #fff; } | |
.ui-bar-a .ui-link { color: #7cc4e7; font-weight: bold; } | |
.ui-body-a { border: 1px solid #2A2A2A; background: #222222; color: #fff; text-shadow: 0 1px 0 #000; font-weight: normal; background-image: -moz-linear-gradient(top, #666666, #222222); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #666666),color-stop(1, #222222)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#666666', EndColorStr='#222222)')"; } | |
.ui-body-a, .ui-body-a input, .ui-body-a select, .ui-body-a textarea, .ui-body-a button { font-family: Helvetica, Arial, sans-serif; } | |
.ui-body-a .ui-link-inherit { color: #fff; } | |
.ui-body-a .ui-link { color: #2489CE; font-weight: bold; } | |
.ui-br { border-bottom: 1px solid rgba(130,130,130,.3); } | |
.ui-btn-up-a { border: 1px solid #222; background: #333333; font-weight: bold; color: #fff; cursor: pointer; text-shadow: 0 -1px 1px #000; text-decoration: none; background-image: -moz-linear-gradient(top, #555555, #333333); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #555555),color-stop(1, #333333)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#555555', EndColorStr='#333333')"; } | |
.ui-btn-up-a a.ui-link-inherit { color: #fff; } | |
.ui-btn-hover-a { border: 1px solid #000; background: #444444; font-weight: bold; color: #fff; text-shadow: 0 -1px 1px #000; text-decoration: none; background-image: -moz-linear-gradient(top, #666666, #444444); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #666666),color-stop(1, #444444)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#666666', EndColorStr='#444444')"; } | |
.ui-btn-hover-a a.ui-link-inherit { color: #fff; } | |
.ui-btn-down-a { border: 1px solid #000; background: #3d3d3d; font-weight: bold; color: #fff; text-shadow: 0 -1px 1px #000; background-image: -moz-linear-gradient(top, #333333, #5a5a5a); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #333333),color-stop(1, #5a5a5a)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#333333', EndColorStr='#5a5a5a')"; } | |
.ui-btn-down-a a.ui-link-inherit { color: #fff; } | |
.ui-btn-up-a, .ui-btn-hover-a, .ui-btn-down-a { font-family: Helvetica, Arial, sans-serif; } | |
.ui-bar-b { border: 1px solid #456f9a; background: #5e87b0; color: #fff; font-weight: bold; text-shadow: 0 -1px 1px #254f7a; background-image: -moz-linear-gradient(top, #81a8ce, #5e87b0); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #81a8ce),color-stop(1, #5e87b0)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#81a8ce', EndColorStr='#5e87b0')"; } | |
.ui-bar-b, .ui-bar-b input, .ui-bar-b select, .ui-bar-b textarea, .ui-bar-b button { font-family: Helvetica, Arial, sans-serif; } | |
.ui-bar-b .ui-link-inherit { color: #fff; } | |
.ui-bar-b .ui-link { color: #7cc4e7; font-weight: bold; } | |
.ui-body-b { border: 1px solid #C6C6C6; background: #cccccc; color: #333333; text-shadow: 0 1px 0 #fff; font-weight: normal; background-image: -moz-linear-gradient(top, #e6e6e6, #cccccc); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #e6e6e6),color-stop(1, #cccccc)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#e6e6e6', EndColorStr='#cccccc')"; } | |
.ui-body-b, .ui-body-b input, .ui-body-b select, .ui-body-b textarea, .ui-body-b button { font-family: Helvetica, Arial, sans-serif; } | |
.ui-body-b .ui-link-inherit { color: #333333; } | |
.ui-body-b .ui-link { color: #2489CE; font-weight: bold; } | |
.ui-btn-up-b { border: 1px solid #145072; background: #2567ab; font-weight: bold; color: #fff; cursor: pointer; text-shadow: 0 -1px 1px #145072; text-decoration: none; background-image: -moz-linear-gradient(top, #4e89c5, #2567ab); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #5f9cc5),color-stop(1, #396b9e)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#4e89c5', EndColorStr='#2567ab')"; } | |
.ui-btn-up-b a.ui-link-inherit { color: #fff; } | |
.ui-btn-hover-b { border: 1px solid #00516e; background: #4b88b6; font-weight: bold; color: #fff; text-shadow: 0 -1px 1px #014D68; background-image: -moz-linear-gradient(top, #72b0d4, #4b88b6); text-decoration: none; background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #72b0d4),color-stop(1, #4b88b6)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#72b0d4', EndColorStr='#4b88b6')"; } | |
.ui-btn-hover-b a.ui-link-inherit { color: #fff; } | |
.ui-btn-down-b { border: 1px solid #225377; background: #4e89c5; font-weight: bold; color: #fff; text-shadow: 0 -1px 1px #225377; background-image: -moz-linear-gradient(top, #396b9e, #4e89c5); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #396b9e),color-stop(1, #4e89c5)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#396b9e', EndColorStr='#4e89c5')"; } | |
.ui-btn-down-b a.ui-link-inherit { color: #fff; } | |
.ui-btn-up-b, .ui-btn-hover-b, .ui-btn-down-b { font-family: Helvetica, Arial, sans-serif; } | |
.ui-bar-c { border: 1px solid #B3B3B3; background: #e9eaeb; color: #3E3E3E; font-weight: bold; text-shadow: 0 1px 1px #fff; background-image: -moz-linear-gradient(top, #f0f0f0, #e9eaeb); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #f0f0f0),color-stop(1, #e9eaeb)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#f0f0f0', EndColorStr='#e9eaeb')"; } | |
.ui-bar-c, .ui-bar-c input, .ui-bar-c select, .ui-bar-c textarea, .ui-bar-c button { font-family: Helvetica, Arial, sans-serif; } | |
.ui-body-c { border: 1px solid #B3B3B3; color: #333333; text-shadow: 0 1px 0 #fff; background: #f0f0f0; background-image: -moz-linear-gradient(top, #fff, #f0f0f0); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #fff),color-stop(1, #f0f0f0)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#f0f0f0')"; } | |
.ui-body-c, .ui-body-c input, .ui-body-c select, .ui-body-c textarea, .ui-body-c button { font-family: Helvetica, Arial, sans-serif; } | |
.ui-body-c .ui-link-inherit { color: #333333; } | |
.ui-body-c .ui-link { color: #2489CE; font-weight: bold; } | |
.ui-btn-up-c { border: 1px solid #ccc; background: #eee; font-weight: bold; color: #444; cursor: pointer; text-shadow: 0 1px 1px #f6f6f6; text-decoration: none; background-image: -moz-linear-gradient(top, #fdfdfd, #eeeeee); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #fdfdfd),color-stop(1, #eeeeee)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fdfdfd', EndColorStr='#eeeeee')"; } | |
.ui-btn-up-c a.ui-link-inherit { color: #2F3E46; } | |
.ui-btn-hover-c { border: 1px solid #aaa; background: #f5f5f5; font-weight: bold; color: #111111; text-decoration: none; text-shadow: 0 1px 1px #fff; background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #ffffff),color-stop(1, #f5f5f5)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#f5f5f5')"; } | |
.ui-btn-hover-c a.ui-link-inherit { color: #2F3E46; } | |
.ui-btn-down-c { border: 1px solid #808080; background: #fdfdfd; font-weight: bold; color: #111111; text-shadow: 0 1px 1px #ffffff; background-image: -moz-linear-gradient(top, #eeeeee, #fdfdfd); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #eeeeee),color-stop(1, #fdfdfd)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#fdfdfd')"; } | |
.ui-btn-down-c a.ui-link-inherit { color: #2F3E46; } | |
.ui-btn-up-c, .ui-btn-hover-c, .ui-btn-down-c { font-family: Helvetica, Arial, sans-serif; } | |
.ui-bar-d { border: 1px solid #ccc; background: #bbb; color: #333; text-shadow: 0 1px 0 #eee; background-image: -moz-linear-gradient(top, #ddd, #bbb); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #ddd),color-stop(1, #bbb)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ddd', EndColorStr='#bbb')"; } | |
.ui-bar-d, .ui-bar-d input, .ui-bar-d select, .ui-bar-d textarea, .ui-bar-d button { font-family: Helvetica, Arial, sans-serif; } | |
.ui-bar-d .ui-link-inherit { color: #333; } | |
.ui-bar-d .ui-link { color: #2489CE; font-weight: bold; } | |
.ui-body-d { border: 1px solid #ccc; color: #333333; text-shadow: 0 1px 0 #fff; background: #ffffff; } | |
.ui-body-d, .ui-body-d input, .ui-body-d select, .ui-body-d textarea, .ui-body-d button { font-family: Helvetica, Arial, sans-serif; } | |
.ui-body-d .ui-link-inherit { color: #333333; } | |
.ui-body-d .ui-link { color: #2489CE; font-weight: bold; } | |
.ui-btn-up-d { border: 1px solid #ccc; background: #fff; font-weight: bold; color: #444; text-decoration: none; text-shadow: 0 1px 1px #fff; } | |
.ui-btn-up-d a.ui-link-inherit { color: #333; } | |
.ui-btn-hover-d { border: 1px solid #aaa; background: #eeeeee; font-weight: bold; color: #222; cursor: pointer; text-shadow: 0 1px 1px #fff; text-decoration: none; background-image: -moz-linear-gradient(top, #fdfdfd, #eeeeee); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #fdfdfd),color-stop(1, #eeeeee)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fdfdfd', EndColorStr='#eeeeee')"; } | |
.ui-btn-hover-d a.ui-link-inherit { color: #222; } | |
.ui-btn-down-d { border: 1px solid #aaaaaa; background: #ffffff; font-weight: bold; color: #111; text-shadow: 0 1px 1px #ffffff; background-image: -moz-linear-gradient(top, #eeeeee, #ffffff); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #eeeeee),color-stop(1, #ffffff)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#ffffff')"; } | |
.ui-btn-down-d a.ui-link-inherit { border: 1px solid #808080; background: #ced0d2; font-weight: bold; color: #111; text-shadow: none; background-image: -moz-linear-gradient(top, #cccccc, #eeeeee); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #cccccc),color-stop(1, #eeeeee)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#cccccc', EndColorStr='#eeeeee')"; } | |
.ui-btn-up-d, .ui-btn-hover-d, .ui-btn-down-d { font-family: Helvetica, Arial, sans-serif; } | |
.ui-bar-e { border: 1px solid #F7C942; background: #fadb4e; color: #333; text-shadow: 0 1px 0 #fff; background-image: -moz-linear-gradient(top, #fceda7, #fadb4e); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #fceda7),color-stop(1, #fadb4e)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fceda7', EndColorStr='#fadb4e')"; } | |
.ui-bar-e, .ui-bar-e input, .ui-bar-e select, .ui-bar-e textarea, .ui-bar-d button { font-family: Helvetica, Arial, sans-serif; } | |
.ui-bar-e .ui-link-inherit { color: #333; } | |
.ui-bar-e .ui-link { color: #2489CE; font-weight: bold; } | |
.ui-body-e { border: 1px solid #F7C942; color: #333333; text-shadow: 0 1px 0 #fff; background: #faeb9e; background-image: -moz-linear-gradient(top, #fff, #faeb9e); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #fff),color-stop(1, #faeb9e)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#faeb9e')"; } | |
.ui-body-e, .ui-body-e input, .ui-body-e select, .ui-body-e textarea, .ui-body-e button { font-family: Helvetica, Arial, sans-serif; } | |
.ui-body-e .ui-link-inherit { color: #333333; } | |
.ui-body-e .ui-link { color: #2489CE; font-weight: bold; } | |
.ui-btn-up-e { border: 1px solid #F7C942; background: #fadb4e; font-weight: bold; color: #333; cursor: pointer; text-shadow: 0 1px 1px #fe3; text-decoration: none; text-shadow: 0 1px 0 #fff; background-image: -moz-linear-gradient(top, #fceda7, #fadb4e); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #fceda7),color-stop(1, #fadb4e)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fceda7', EndColorStr='#fadb4e')"; } | |
.ui-btn-up-e a.ui-link-inherit { color: #333; } | |
.ui-btn-hover-e { border: 1px solid #e79952; background: #fbe26f; font-weight: bold; color: #111; text-decoration: none; text-shadow: 0 1px 1px #fff; background-image: -moz-linear-gradient(top, #fcf0b5, #fbe26f); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #fcf0b5),color-stop(1, #fbe26f)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fcf0b5', EndColorStr='#fbe26f')"; } | |
.ui-btn-hover-e a.ui-link-inherit { color: #333; } | |
.ui-btn-down-e { border: 1px solid #F7C942; background: #fceda7; font-weight: bold; color: #111; text-shadow: 0 1px 1px #ffffff; background-image: -moz-linear-gradient(top, #fadb4e, #fceda7); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #fadb4e),color-stop(1, #fceda7)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fadb4e', EndColorStr='#fceda7')"; } | |
.ui-btn-down-e a.ui-link-inherit { color: #333; } | |
.ui-btn-up-e, .ui-btn-hover-e, .ui-btn-down-e { font-family: Helvetica, Arial, sans-serif; } | |
/* links within "buttons" */ | |
a.ui-link-inherit { text-decoration: none !important; } | |
/* Active class used as the "on" state across all themes */ | |
.ui-btn-active { border: 1px solid #155678; background: #4596ce; font-weight: bold; color: #fff; cursor: pointer; text-shadow: 0 -1px 1px #145072; text-decoration: none; background-image: -moz-linear-gradient(top, #85bae4, #5393c5); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #85bae4),color-stop(1, #5393c5)); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#85bae4', EndColorStr='#5393c5')"; } | |
.ui-btn-active a.ui-link-inherit { color: #fff; } | |
/* button inner top highlight */ | |
.ui-btn-inner { border-top: 1px solid #fff; border-color: rgba(255,255,255,.3); } | |
/* Container Corner radius */ | |
.ui-corner-tl { -moz-border-radius-topleft: .6em; -webkit-border-top-left-radius: .6em; border-top-left-radius: .6em; } | |
.ui-corner-tr { -moz-border-radius-topright: .6em; -webkit-border-top-right-radius: .6em; border-top-right-radius: .6em; } | |
.ui-corner-bl { -moz-border-radius-bottomleft: .6em; -webkit-border-bottom-left-radius: .6em; border-bottom-left-radius: .6em; } | |
.ui-corner-br { -moz-border-radius-bottomright: .6em; -webkit-border-bottom-right-radius: .6em; border-bottom-right-radius: .6em; } | |
.ui-corner-top { -moz-border-radius-topleft: .6em; -webkit-border-top-left-radius: .6em; border-top-left-radius: .6em; -moz-border-radius-topright: .6em; -webkit-border-top-right-radius: .6em; border-top-right-radius: .6em; } | |
.ui-corner-bottom { -moz-border-radius-bottomleft: .6em; -webkit-border-bottom-left-radius: .6em; border-bottom-left-radius: .6em; -moz-border-radius-bottomright: .6em; -webkit-border-bottom-right-radius: .6em; border-bottom-right-radius: .6em; } | |
.ui-corner-right { -moz-border-radius-topright: .6em; -webkit-border-top-right-radius: .6em; border-top-right-radius: .6em; -moz-border-radius-bottomright: .6em; -webkit-border-bottom-right-radius: .6em; border-bottom-right-radius: .6em; } | |
.ui-corner-left { -moz-border-radius-topleft: .6em; -webkit-border-top-left-radius: .6em; border-top-left-radius: .6em; -moz-border-radius-bottomleft: .6em; -webkit-border-bottom-left-radius: .6em; border-bottom-left-radius: .6em; } | |
.ui-corner-all { -moz-border-radius: .6em; -webkit-border-radius: .6em; border-radius: .6em; } | |
/* Interaction Cues | |
----------------------------------*/ | |
.ui-disabled { cursor: default !important; opacity: .3; } | |
/* Icons | |
----------------------------------*/ | |
/* .ui-icon { background-position: 50% 50%; background-repeat: no-repeat; background-color: #fff; background-color: rgba(0,0,0,.4); -moz-border-radius: 9px; -webkit-border-radius: 9px; border-radius: 9px; } */ | |
.ui-icon { background-image: url(images/icons-18-white.png); background-repeat: no-repeat; background-color: #666; background-color: rgba(0,0,0,.4); -moz-border-radius: 9px; -webkit-border-radius: 9px; border-radius: 9px; } | |
.ui-icon-disc { background-color: #666; background-color: rgba(0,0,0,.3); -moz-border-radius: 9px; -webkit-border-radius: 9px; border-radius: 9px; } | |
/* alt color */ | |
.ui-icon-black { background-image: url(images/icons-18-black.png); } | |
.ui-icon-black-disc { background-color: #fff; background-color: rgba(255,255,255,.3); -moz-border-radius: 9px; -webkit-border-radius: 9px; border-radius: 9px; } | |
/* retina */ | |
@media screen and (-webkit-min-device-pixel-ratio: 2), screen and (max--moz-device-pixel-ratio: 2) { | |
.ui-icon { background-image: url(images/icons-36-white.png); background-size: 558px 18px; } | |
.ui-icon-black { background-image: url(images/icons-36-black.png); } | |
} | |
/*plus minus*/ | |
.ui-icon-plus { background-position: -0 0; } | |
.ui-icon-minus { background-position: -36px 0; } | |
/* delete/close */ | |
.ui-icon-delete { background-position: -72px 0; } | |
/*arrows*/ | |
.ui-icon-arrow-r { background-position: -108px 0; } | |
.ui-icon-arrow-l { background-position: -144px 0; } | |
.ui-icon-arrow-u { background-position: -180px 0; } | |
.ui-icon-arrow-d { background-position: -216px 0; } | |
.ui-icon-check { background-position: -252px 0; } | |
.ui-icon-gear { background-position: -288px 0; } | |
.ui-icon-refresh { background-position: -324px 0; } | |
.ui-icon-forward { background-position: -360px 0; } | |
.ui-icon-back { background-position: -396px 0; } | |
.ui-icon-grid { background-position: -432px 0; } | |
.ui-icon-star { background-position: -468px 0; } | |
.ui-icon-alert { background-position: -504px 0; } | |
.ui-icon-info { background-position: -540px 0; } | |
/*checks,radios*/ | |
.ui-icon-checkbox-off, | |
.ui-icon-checkbox-on, | |
.ui-icon-radio-off, | |
.ui-icon-radio-on { background-color: transparent; -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; background-size: 20px 20px; } | |
.ui-icon-checkbox-off { background-image: url(images/form-check-off.png); } | |
.ui-icon-checkbox-on { background-image: url(images/form-check-on.png); } | |
.ui-icon-radio-off { background-image: url(images/form-radio-off.png);} | |
.ui-icon-radio-on { background-image: url(images/form-radio-on.png); } | |
.ui-icon-search { background-image: url(images/icon-search-black.png); background-size: 16px 16px; } | |
/* loading icon */ | |
.ui-icon-loading { background-image: url(images/ajax-loader.png); width: 40px; height: 40px; -moz-border-radius: 20px; -webkit-border-radius: 20px; border-radius: 20px; background-size: 35px 35px; } | |
/* btn Corner radius */ | |
.ui-btn-corner-tl { -moz-border-radius-topleft: 1em; -webkit-border-top-left-radius: 1em; border-top-left-radius: 1em; } | |
.ui-btn-corner-tr { -moz-border-radius-topright: 1em; -webkit-border-top-right-radius: 1em; border-top-right-radius: 1em; } | |
.ui-btn-corner-bl { -moz-border-radius-bottomleft: 1em; -webkit-border-bottom-left-radius: 1em; border-bottom-left-radius: 1em; } | |
.ui-btn-corner-br { -moz-border-radius-bottomright: 1em; -webkit-border-bottom-right-radius: 1em; border-bottom-right-radius: 1em; } | |
.ui-btn-corner-top { -moz-border-radius-topleft: 1em; -webkit-border-top-left-radius: 1em; border-top-left-radius: 1em; -moz-border-radius-topright: 1em; -webkit-border-top-right-radius: 1em; border-top-right-radius: 1em; } | |
.ui-btn-corner-bottom { -moz-border-radius-bottomleft: 1em; -webkit-border-bottom-left-radius: 1em; border-bottom-left-radius: 1em; -moz-border-radius-bottomright: 1em; -webkit-border-bottom-right-radius: 1em; border-bottom-right-radius: 1em; } | |
.ui-btn-corner-right { -moz-border-radius-topright: 1em; -webkit-border-top-right-radius: 1em; border-top-right-radius: 1em; -moz-border-radius-bottomright: 1em; -webkit-border-bottom-right-radius: 1em; border-bottom-right-radius: 1em; } | |
.ui-btn-corner-left { -moz-border-radius-topleft: 1em; -webkit-border-top-left-radius: 1em; border-top-left-radius: 1em; -moz-border-radius-bottomleft: 1em; -webkit-border-bottom-left-radius: 1em; border-bottom-left-radius: 1em; } | |
.ui-btn-corner-all { -moz-border-radius: 1em; -webkit-border-radius: 1em; border-radius: 1em;} | |
/* radius clip */ | |
.ui-corner-tl, .ui-corner-tr, .ui-corner-bl, | |
.ui-corner-br, .ui-corner-top, .ui-corner-bottom, | |
.ui-corner-right, .ui-corner-left, .ui-corner-all, | |
.ui-btn-corner-tl, .ui-btn-corner-tr, .ui-btn-corner-bl, | |
.ui-btn-corner-br, .ui-btn-corner-top, .ui-btn-corner-bottom, | |
.ui-btn-corner-right, .ui-btn-corner-left, .ui-btn-corner-all { | |
-webkit-background-clip: padding-box; | |
-moz-background-clip: padding-box; | |
background-clip: padding-box; | |
} | |
/* Overlays */ | |
.ui-overlay { background: #666; opacity: .5; filter:Alpha(Opacity=50); position: absolute; width: 100%; height: 100%; } | |
.ui-overlay-shadow { -moz-box-shadow: 0px 0px 12px rgba(0,0,0,.6); -webkit-box-shadow: 0px 0px 12px rgba(0,0,0,.6); box-shadow: 0px 0px 12px rgba(0,0,0,.6); } | |
.ui-shadow { -moz-box-shadow: 0px 1px 4px rgba(0,0,0,.3); -webkit-box-shadow: 0px 1px 4px rgba(0,0,0,.3); box-shadow: 0px 1px 4px rgba(0,0,0,.3); } | |
.ui-bar-a .ui-shadow, .ui-bar-b .ui-shadow , .ui-bar-c .ui-shadow { -moz-box-shadow: 0px 1px 0 rgba(255,255,255,.3); -webkit-box-shadow: 0px 1px 0 rgba(255,255,255,.3); box-shadow: 0px 1px 0 rgba(255,255,255,.3); } | |
.ui-shadow-inset { -moz-box-shadow: inset 0px 1px 4px rgba(0,0,0,.2); -webkit-box-shadow: inset 0px 1px 4px rgba(0,0,0,.2); box-shadow: inset 0px 1px 4px rgba(0,0,0,.2); } | |
.ui-icon-shadow { -moz-box-shadow: 0px 1px 0 rgba(255,255,255,.4); -webkit-box-shadow: 0px 1px 0 rgba(255,255,255,.4); box-shadow: 0px 1px 0 rgba(255,255,255,.4); } | |
/* set focus state last */ | |
.ui-focus { outline-width: 0; -moz-box-shadow: 0px 0px 12px #387bbe; -webkit-box-shadow: 0px 0px 12px #387bbe; box-shadow: 0px 0px 12px #387bbe; } | |
/* unset box shadow in browsers that don't do it right */ | |
.ui-mobile-nosupport-boxshadow * { -moz-box-shadow: none !important; -webkit-box-shadow: none !important; box-shadow: none !important; } | |
.ui-mobile-nosupport-boxshadow .ui-focus { outline-width: 2px; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. | |
* Note: Code is in draft form and is subject to change | |
*/ | |
/* some unsets - more probably needed */ | |
.ui-mobile fieldset, .ui-page { padding: 0; margin: 0; } | |
.ui-mobile a img, .ui-mobile fieldset { border: 0; } | |
/* responsive page widths */ | |
.ui-mobile-viewport { margin: 0; overflow-x: hidden; -webkit-text-size-adjust: none; -ms-text-size-adjust:none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } | |
/*orientations from js are available */ | |
.portrait { } | |
.landscape { } | |
/* "page" containers - full-screen views, one should always be in view post-pageload */ | |
.ui-page { top: 0; left: 0; width: 100%; min-height: 100%; position: absolute; display: none; border: 0; } | |
.ui-page-active { display: block; overflow: visible; min-height: 100%; } | |
/* loading screen */ | |
.ui-loading .ui-mobile-viewport { overflow: hidden !important; } | |
.ui-loading .ui-loader { display: block; } | |
.ui-loading .ui-page { overflow: hidden; } | |
.ui-loader { display: none; position: absolute; opacity: .85; z-index: 10; top: 75px; left: 50%; width: 200px; margin-left: -130px; padding: 20px 30px; } | |
.ui-loader h1 { font-size: 15px; text-align: center; } | |
.ui-loader .ui-icon { position: static; display: block; opacity: .9; margin: 0 auto; width: 35px; height: 35px; background-color: transparent; } | |
/*fouc*/ | |
.ui-mobile-rendering > * { visibility: hidden; } | |
/*headers, content panels*/ | |
.ui-bar, .ui-body { position: relative; padding: .4em 15px; overflow: hidden; display: block; clear:both; } | |
.ui-bar { font-size: 16px; margin: 0; } | |
.ui-bar h1, .ui-bar h2, .ui-bar h3, .ui-bar h4, .ui-bar h5, .ui-bar h6 { margin: 0; padding: 0; font-size: 16px; display: inline-block; } | |
.ui-header, .ui-footer { display: block; } | |
.ui-page .ui-header, .ui-page .ui-footer { position: relative; } | |
.ui-header .ui-btn-left { position: absolute; left: 10px; top: .4em; } | |
.ui-header .ui-title, .ui-footer .ui-title { text-align: center; font-size: 16px; display: block; margin: .6em 90px .8em; padding: 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; outline: 0 !important; } | |
.ui-header .ui-btn-right { position: absolute; right: 10px; top: .4em; } | |
/*content area*/ | |
.ui-content { border-width: 0; overflow: visible; overflow-x: hidden; padding: 15px; } | |
.ui-page-fullscreen .ui-content { padding:0; } | |
/* icons sizing */ | |
.ui-icon { width: 18px; height: 18px; } | |
/* fullscreen class on ui-content div */ | |
.ui-fullscreen { } | |
.ui-fullscreen img { max-width: 100%; } | |
/* non-js content hiding */ | |
.ui-nojs { position: absolute; left: -9999px; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
.spin { | |
-webkit-transform: rotate(360deg); | |
-webkit-animation-name: spin; | |
-webkit-animation-duration: 1s; | |
-webkit-animation-iteration-count: infinite; | |
} | |
@-webkit-keyframes spin { | |
from {-webkit-transform: rotate(0deg);} | |
to {-webkit-transform: rotate(360deg);} | |
} | |
/* Transitions from jQtouch (with small modifications): http://www.jqtouch.com/ | |
Built by David Kaneda and maintained by Jonathan Stark. | |
*/ | |
.in, .out { | |
-webkit-animation-timing-function: ease-in-out; | |
-webkit-animation-duration: 350ms; | |
} | |
.slide.in { | |
-webkit-transform: translateX(0); | |
-webkit-animation-name: slideinfromright; | |
} | |
.slide.out { | |
-webkit-transform: translateX(-100%); | |
-webkit-animation-name: slideouttoleft; | |
} | |
.slide.in.reverse { | |
-webkit-transform: translateX(0); | |
-webkit-animation-name: slideinfromleft; | |
} | |
.slide.out.reverse { | |
-webkit-transform: translateX(100%); | |
-webkit-animation-name: slideouttoright; | |
} | |
.slideup.in { | |
-webkit-transform: translateY(0); | |
-webkit-animation-name: slideinfrombottom; | |
z-index: 10; | |
} | |
.slideup.out { | |
-webkit-animation-name: dontmove; | |
z-index: 0; | |
} | |
.slideup.out.reverse { | |
-webkit-transform: translateY(100%); | |
z-index: 10; | |
-webkit-animation-name: slideouttobottom; | |
} | |
.slideup.in.reverse { | |
z-index: 0; | |
-webkit-animation-name: dontmove; | |
} | |
.slidedown.in { | |
-webkit-transform: translateY(0); | |
-webkit-animation-name: slideinfromtop; | |
z-index: 10; | |
} | |
.slidedown.out { | |
-webkit-animation-name: dontmove; | |
z-index: 0; | |
} | |
.slidedown.out.reverse { | |
-webkit-transform: translateY(-100%); | |
z-index: 10; | |
-webkit-animation-name: slideouttotop; | |
} | |
.slidedown.in.reverse { | |
z-index: 0; | |
-webkit-animation-name: dontmove; | |
} | |
@-webkit-keyframes slideinfromright { | |
from { -webkit-transform: translateX(100%); } | |
to { -webkit-transform: translateX(0); } | |
} | |
@-webkit-keyframes slideinfromleft { | |
from { -webkit-transform: translateX(-100%); } | |
to { -webkit-transform: translateX(0); } | |
} | |
@-webkit-keyframes slideouttoleft { | |
from { -webkit-transform: translateX(0); } | |
to { -webkit-transform: translateX(-100%); } | |
} | |
@-webkit-keyframes slideouttoright { | |
from { -webkit-transform: translateX(0); } | |
to { -webkit-transform: translateX(100%); } | |
} | |
@-webkit-keyframes slideinfromtop { | |
from { -webkit-transform: translateY(-100%); } | |
to { -webkit-transform: translateY(0); } | |
} | |
@-webkit-keyframes slideinfrombottom { | |
from { -webkit-transform: translateY(100%); } | |
to { -webkit-transform: translateY(0); } | |
} | |
@-webkit-keyframes slideouttobottom { | |
from { -webkit-transform: translateY(0); } | |
to { -webkit-transform: translateY(100%); } | |
} | |
@-webkit-keyframes slideouttotop { | |
from { -webkit-transform: translateY(0); } | |
to { -webkit-transform: translateY(-100%); } | |
} | |
@-webkit-keyframes fadein { | |
from { opacity: 0; } | |
to { opacity: 1; } | |
} | |
@-webkit-keyframes fadeout { | |
from { opacity: 1; } | |
to { opacity: 0; } | |
} | |
.fade.in { | |
opacity: 1; | |
z-index: 10; | |
-webkit-animation-name: fadein; | |
} | |
.fade.out { | |
z-index: 0; | |
} | |
/* The properties in this body rule are only necessary for the 'flip' transition. | |
* We need specify the perspective to create a projection matrix. This will add | |
* some depth as the element flips. The depth number represents the distance of | |
* the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate | |
* value. | |
*/ | |
.ui-mobile-viewport-transitioning { | |
-webkit-perspective: 1000; | |
position: absolute; | |
} | |
.ui-mobile-viewport-transitioning, | |
.ui-mobile-viewport-transitioning .ui-page { | |
width: 100%; | |
height: 100%; | |
overflow: hidden; | |
} | |
.flip { | |
-webkit-animation-duration: .65s; | |
-webkit-backface-visibility:hidden; | |
-webkit-transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */ | |
} | |
.flip.in { | |
-webkit-transform: rotateY(0) scale(1); | |
-webkit-animation-name: flipinfromleft; | |
} | |
.flip.out { | |
-webkit-transform: rotateY(-180deg) scale(.8); | |
-webkit-animation-name: flipouttoleft; | |
} | |
/* Shake it all about */ | |
.flip.in.reverse { | |
-webkit-transform: rotateY(0) scale(1); | |
-webkit-animation-name: flipinfromright; | |
} | |
.flip.out.reverse { | |
-webkit-transform: rotateY(180deg) scale(.8); | |
-webkit-animation-name: flipouttoright; | |
} | |
@-webkit-keyframes flipinfromright { | |
from { -webkit-transform: rotateY(-180deg) scale(.8); } | |
to { -webkit-transform: rotateY(0) scale(1); } | |
} | |
@-webkit-keyframes flipinfromleft { | |
from { -webkit-transform: rotateY(180deg) scale(.8); } | |
to { -webkit-transform: rotateY(0) scale(1); } | |
} | |
@-webkit-keyframes flipouttoleft { | |
from { -webkit-transform: rotateY(0) scale(1); } | |
to { -webkit-transform: rotateY(-180deg) scale(.8); } | |
} | |
@-webkit-keyframes flipouttoright { | |
from { -webkit-transform: rotateY(0) scale(1); } | |
to { -webkit-transform: rotateY(180deg) scale(.8); } | |
} | |
/* Hackish, but reliable. */ | |
@-webkit-keyframes dontmove { | |
from { opacity: 1; } | |
to { opacity: 1; } | |
} | |
.pop { | |
-webkit-transform-origin: 50% 50%; | |
} | |
.pop.in { | |
-webkit-transform: scale(1); | |
opacity: 1; | |
-webkit-animation-name: popin; | |
z-index: 10; | |
} | |
.pop.out.reverse { | |
-webkit-transform: scale(.2); | |
opacity: 0; | |
-webkit-animation-name: popout; | |
z-index: 10; | |
} | |
.pop.in.reverse { | |
z-index: 0; | |
-webkit-animation-name: dontmove; | |
} | |
@-webkit-keyframes popin { | |
from { | |
-webkit-transform: scale(.2); | |
opacity: 0; | |
} | |
to { | |
-webkit-transform: scale(1); | |
opacity: 1; | |
} | |
} | |
@-webkit-keyframes popout { | |
from { | |
-webkit-transform: scale(1); | |
opacity: 1; | |
} | |
to { | |
-webkit-transform: scale(.2); | |
opacity: 0; | |
} | |
} | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
/* content configurations. */ | |
.ui-grid-a, .ui-grid-b, .ui-grid-c, .ui-grid-d { overflow: hidden; } | |
.ui-block-a, .ui-block-b, .ui-block-c, .ui-block-d, .ui-block-e { margin: 0; padding: 0; border: 0; float: left; } | |
/* grid a: 50/50 */ | |
.ui-grid-a .ui-block-a, .ui-grid-a .ui-block-b { width: 50%; } | |
.ui-grid-a .ui-block-a { clear: left; } | |
/* grid b: 33/33/33 */ | |
.ui-grid-b .ui-block-a, .ui-grid-b .ui-block-b, .ui-grid-b .ui-block-c { width: 33.333%; } | |
.ui-grid-b .ui-block-a { clear: left; } | |
/* grid c: 25/25/25/25 */ | |
.ui-grid-c .ui-block-a, .ui-grid-c .ui-block-b, .ui-grid-c .ui-block-c, .ui-grid-c .ui-block-d { width: 25%; } | |
.ui-grid-c .ui-block-a { clear: left; } | |
/* grid d: 20/20/20/20/20 */ | |
.ui-grid-d .ui-block-a, .ui-grid-d .ui-block-b, .ui-grid-d .ui-block-c, .ui-grid-d .ui-block-d, .ui-grid-d .ui-block-e { width: 20%; } | |
.ui-grid-d .ui-block-a { clear: left; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
/* fixed page header & footer configuration */ | |
.ui-header, .ui-footer, .ui-page-fullscreen .ui-header, .ui-page-fullscreen .ui-footer { position: absolute; overflow: hidden; width: 100%; border-left-width: 0; border-right-width: 0; } | |
.ui-header-fixed, .ui-footer-fixed { | |
z-index: 1000; | |
-webkit-transform: translateZ(0); /* Force header/footer rendering to go through the same rendering pipeline as native page scrolling. */ | |
} | |
.ui-footer-duplicate, .ui-page-fullscreen .ui-fixed-inline { display: none; } | |
.ui-page-fullscreen .ui-header, .ui-page-fullscreen .ui-footer { opacity: .9; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
.ui-navbar { overflow: hidden; } | |
.ui-navbar ul, .ui-navbar-expanded ul { list-style:none; padding: 0; margin: 0; position: relative; display: block; border: 0;} | |
.ui-navbar-collapsed ul { float: left; width: 75%; margin-right: -2px; } | |
.ui-navbar-collapsed .ui-navbar-toggle { float: left; width: 25%; } | |
.ui-navbar li.ui-navbar-truncate { position: absolute; left: -99999px; top: -99999px; } | |
.ui-navbar li .ui-btn, .ui-navbar .ui-navbar-toggle .ui-btn { display: block; font-size: 12px; text-align: center; margin: 0; outline: none; border-right-width: 0; } | |
.ui-navbar li .ui-btn { margin-right: -1px; } | |
.ui-navbar li .ui-btn:last-child { margin-right: 0; } | |
.ui-header .ui-navbar li .ui-btn, .ui-header .ui-navbar .ui-navbar-toggle .ui-btn, | |
.ui-footer .ui-navbar li .ui-btn, .ui-footer .ui-navbar .ui-navbar-toggle .ui-btn { border-top-width: 0; border-bottom-width: 0; } | |
.ui-navbar .ui-btn-inner { padding-left: 2px; padding-right: 2px; } | |
.ui-navbar-noicons li .ui-btn .ui-btn-inner, .ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner { padding-top: .8em; padding-bottom: .9em; } | |
/*expanded page styles*/ | |
.ui-navbar-expanded .ui-btn { margin: 0; font-size: 14px; } | |
.ui-navbar-expanded .ui-btn-inner { padding-left: 5px; padding-right: 5px; } | |
.ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner { padding: 45px 5px 15px; text-align: center; } | |
.ui-navbar-expanded .ui-btn-icon-top .ui-icon { top: 15px; } | |
.ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner { padding: 15px 5px 45px; text-align: center; } | |
.ui-navbar-expanded .ui-btn-icon-bottom .ui-icon { bottom: 15px; } | |
.ui-navbar-expanded li .ui-btn .ui-btn-inner { min-height: 2.5em; } | |
.ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner { padding-top: 1.8em; padding-bottom: 1.9em; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
.ui-btn { display: block; text-align: center; cursor:pointer; position: relative; margin: .5em 5px; padding: 0; } | |
.ui-btn:focus, .ui-btn a:focus { outline: none; } | |
.ui-header .ui-btn, .ui-footer .ui-btn, .ui-bar .ui-btn { display: inline-block; font-size: 13px; margin: 0; } | |
.ui-btn-inline { display: inline-block; } | |
.ui-btn-inner { padding: .6em 25px; display: block; height: 100%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; position: relative; } | |
.ui-header .ui-btn-inner, .ui-footer .ui-btn-inner, .ui-bar .ui-btn-inner { padding: .4em 8px .5em; } | |
.ui-btn-icon-notext { display: inline-block; width: 20px; height: 20px; padding: 1px 0px 1px 2px; text-indent: -9999px; } | |
.ui-btn-icon-notext .ui-btn-inner { padding: 0; } | |
.ui-btn-icon-notext .ui-btn-text { position: absolute; left: -999px; } | |
.ui-btn-icon-left .ui-btn-inner { padding-left: 33px; } | |
.ui-header .ui-btn-icon-left .ui-btn-inner, | |
.ui-footer .ui-btn-icon-left .ui-btn-inner, | |
.ui-bar .ui-btn-icon-left .ui-btn-inner { padding-left: 27px; } | |
.ui-btn-icon-right .ui-btn-inner { padding-right: 33px; } | |
.ui-header .ui-btn-icon-right .ui-btn-inner, | |
.ui-footer .ui-btn-icon-right .ui-btn-inner, | |
.ui-bar .ui-btn-icon-right .ui-btn-inner { padding-right: 27px; } | |
.ui-btn-icon-top .ui-btn-inner { padding-top: 33px; } | |
.ui-header .ui-btn-icon-top .ui-btn-inner, | |
.ui-footer .ui-btn-icon-top .ui-btn-inner, | |
.ui-bar .ui-btn-icon-top .ui-btn-inner { padding-top: 27px; } | |
.ui-btn-icon-bottom .ui-btn-inner { padding-bottom: 33px; } | |
.ui-header .ui-btn-icon-bottom .ui-btn-inner, | |
.ui-footer .ui-btn-icon-bottom .ui-btn-inner, | |
.ui-bar .ui-btn-icon-bottom .ui-btn-inner { padding-bottom: 27px; } | |
/*btn icon positioning*/ | |
.ui-btn-icon-notext .ui-icon { display: block; } | |
.ui-btn-icon-left .ui-icon, .ui-btn-icon-right .ui-icon { position: absolute; top: 50%; margin-top: -9px; } | |
.ui-btn-icon-top .ui-icon, .ui-btn-icon-bottom .ui-icon { position: absolute; left: 50%; margin-left: -9px; } | |
.ui-btn-icon-left .ui-icon { left: 10px; } | |
.ui-btn-icon-right .ui-icon {right: 10px; } | |
.ui-header .ui-btn-icon-left .ui-icon, | |
.ui-footer .ui-btn-icon-left .ui-icon, | |
.ui-bar .ui-btn-icon-left .ui-icon { left: 4px; } | |
.ui-header .ui-btn-icon-right .ui-icon, | |
.ui-footer .ui-btn-icon-right .ui-icon, | |
.ui-bar .ui-btn-icon-right .ui-icon { right: 4px; } | |
.ui-header .ui-btn-icon-top .ui-icon, | |
.ui-footer .ui-btn-icon-top .ui-icon, | |
.ui-bar .ui-btn-icon-top .ui-icon { top: 4px; } | |
.ui-header .ui-btn-icon-bottom .ui-icon, | |
.ui-footer .ui-btn-icon-bottom .ui-icon, | |
.ui-bar .ui-btn-icon-bottom .ui-icon { bottom: 4px; } | |
.ui-btn-icon-top .ui-icon { top: 5px; } | |
.ui-btn-icon-bottom .ui-icon { bottom: 5px; } | |
/*hiding native button,inputs */ | |
.ui-btn-hidden { position: absolute; left: -9999px; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
.ui-collapsible-contain { margin: .5em 0; } | |
.ui-collapsible-heading { font-size: 16px; display: block; margin: 0 -8px; padding: 0; border-width: 0 0 1px 0; position: relative; } | |
.ui-collapsible-heading a { text-align: left; margin: 0; } | |
.ui-collapsible-heading a .ui-btn-inner { padding-left: 40px; } | |
.ui-collapsible-heading a span.ui-btn { position: absolute; left: 6px; top: 50%; margin: -12px 0 0 0; width: 20px; height: 20px; padding: 1px 0px 1px 2px; text-indent: -9999px; } | |
.ui-collapsible-heading a span.ui-btn .ui-btn-inner { padding: 0; } | |
.ui-collapsible-heading a span.ui-btn .ui-icon { left: 0; margin-top: -10px; } | |
.ui-collapsible-heading-status { position:absolute; left:-99999px; } | |
.ui-collapsible-content { display: block; padding: 10px 0 10px 8px; } | |
.ui-collapsible-content-collapsed { display: none; } | |
.ui-collapsible-set { margin: .5em 0; } | |
.ui-collapsible-set .ui-collapsible-contain { margin: -1px 0 0; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
.ui-controlgroup, fieldset.ui-controlgroup { padding: 0; margin: .5em 0 1em; } | |
.ui-bar .ui-controlgroup { margin: 0 .3em; } | |
.ui-controlgroup-label { font-size: 16px; line-height: 1.4; font-weight: normal; margin: 0 0 .3em; } | |
.ui-controlgroup-controls { display: block; width: 95%;} | |
.ui-controlgroup li { list-style: none; } | |
.ui-controlgroup-vertical .ui-btn, | |
.ui-controlgroup-vertical .ui-checkbox, .ui-controlgroup-vertical .ui-radio { margin: 0; border-bottom-width: 0; } | |
.ui-controlgroup-vertical .ui-controlgroup-last { border-bottom-width: 1px; } | |
.ui-controlgroup-horizontal { padding: 0; } | |
.ui-controlgroup-horizontal .ui-btn, | |
.ui-controlgroup-horizontal .ui-checkbox, .ui-controlgroup-horizontal .ui-radio { margin: 0 -5px 0 0; display: inline-block; } | |
.ui-controlgroup-horizontal .ui-checkbox .ui-btn, .ui-controlgroup-horizontal .ui-radio .ui-btn, | |
.ui-controlgroup-horizontal .ui-checkbox:last-child, .ui-controlgroup-horizontal .ui-radio:last-child { margin-right: 0; } | |
.ui-controlgroup-horizontal .ui-controlgroup-last { margin-right: 0; } | |
.ui-controlgroup .ui-checkbox label, .ui-controlgroup .ui-radio label { font-size: 16px; } | |
/* conflicts with listview.. | |
.ui-controlgroup .ui-btn-icon-notext { width: 30px; height: 30px; text-indent: -9999px; } | |
.ui-controlgroup .ui-btn-icon-notext .ui-btn-inner { padding: 5px 6px 5px 5px; } | |
*/ | |
.min-width-480px .ui-controlgroup-label { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0; } | |
.min-width-480px .ui-controlgroup-controls { width: 60%; display: inline-block; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
.ui-dialog .ui-header, .ui-dialog .ui-content, .ui-dialog .ui-footer { margin: 15px; position: relative; } | |
.ui-dialog .ui-header, .ui-dialog .ui-footer { z-index: 10; width: auto; } | |
.ui-dialog .ui-content, .ui-dialog .ui-footer { margin-top: -15px; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
.ui-checkbox, .ui-radio { position:relative; margin: .2em 0 .5em; z-index: 1; } | |
.ui-checkbox .ui-btn, .ui-radio .ui-btn { margin: 0; text-align: left; z-index: 2; } | |
.ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner { padding-left: 45px; } | |
.ui-checkbox .ui-btn-icon-right .ui-btn-inner, .ui-radio .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; } | |
.ui-checkbox .ui-btn-icon-left .ui-icon, .ui-radio .ui-btn-icon-left .ui-icon {left: 15px; } | |
.ui-checkbox .ui-btn-icon-right .ui-icon, .ui-radio .ui-btn-icon-right .ui-icon {right: 15px; } | |
/* input, label positioning */ | |
.ui-checkbox input,.ui-radio input { position:absolute; left:20px; top:50%; width: 10px; height: 10px; margin:-5px 0 0 0; outline: 0 !important; z-index: 1; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
.ui-field-contain { background: none; padding: 1.5em 0; margin: 0; border-bottom-width: 1px; overflow: visible; } | |
.ui-field-contain:first-child { border-top-width: 0; } | |
@media screen and (max-width: 480px){ | |
.ui-field-contain { border-width: 0; padding: 0; margin: 1em 0; } | |
} | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
.ui-select { display: block; } | |
.ui-select select { position: absolute; left: -99999px; } | |
.ui-select .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; } | |
.ui-select .ui-btn-icon-right .ui-icon { right: 15px; } | |
/* labels */ | |
label.ui-select { font-size: 16px; line-height: 1.4; font-weight: normal; margin: 0 0 .3em; display: block; } | |
/*listbox*/ | |
.ui-selectmenu { position: absolute; padding: 0; z-index: 100 !important; width: 80%; max-width: 350px; padding: 6px; } | |
.ui-selectmenu .ui-listview { margin: 0; | |
} | |
.ui-selectmenu-hidden { top: -999999px; left: -99999px; } | |
.ui-selectmenu-screen { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 99; } | |
.ui-screen-hidden, .ui-selectmenu-list .ui-li .ui-icon { display: none; } | |
.ui-selectmenu-list .ui-btn-active .ui-icon { display: block; } | |
.min-width-480px label.ui-select { display: inline-block; width: 20%; margin: 0 2% 0 0; } | |
.min-width-480px .ui-select { width: 60%; display: inline-block; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
label.ui-input-text { font-size: 16px; line-height: 1.4; display: block; font-weight: normal; margin: 0 0 .3em; } | |
input.ui-input-text, textarea.ui-input-text { background-image: none; padding: .4em; line-height: 1.4; font-size: 16px; display: block; width: 95%; } | |
input.ui-input-text { -webkit-appearance: none; } | |
textarea.ui-input-text { height: 50px; -webkit-transition: height 200ms linear; -moz-transition: height 200ms linear; -o-transition: height 200ms linear; transition: height 200ms linear; } | |
.ui-input-search { padding: 0 30px; width: 77%; background-position: 8px 50%; background-repeat: no-repeat; position: relative; } | |
.ui-input-search input.ui-input-text { border: none; width: 98%; padding: .4em 0; margin: 0; display: block; background: transparent none; outline: 0 !important; } | |
.ui-input-search .ui-input-clear { position: absolute; right: 2px; top: 50%; margin-top: -12px; } | |
.ui-input-search .ui-input-clear-hidden { display: none; } | |
/* orientation adjustments - incomplete!*/ | |
.min-width-480px label.ui-input-text { vertical-align: top; } | |
.min-width-480px label.ui-input-text { display: inline-block; width: 20%; margin: 0 2% 0 0; } | |
.min-width-480px input.ui-input-text, | |
.min-width-480px textarea.ui-input-text, | |
.min-width-480px .ui-input-search { width: 60%; display: inline-block; } | |
.min-width-480px .ui-input-search { width: 50%; } | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
.ui-listview { margin: 0; counter-reset: listnumbering; } | |
.ui-content .ui-listview { margin: -15px; } | |
.ui-content .ui-listview-inset { margin: 1em 0; } | |
.ui-listview, .ui-li { list-style:none; padding:0; zoom: 1; } | |
.ui-li { display: block; margin:0; position: relative; overflow: hidden; text-align: left; border-width: 0; border-top-width: 1px; } | |
.ui-li .ui-btn-text { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } | |
.ui-li-divider, .ui-li-static { padding: .5em 15px; font-size: 14px; font-weight: bold; counter-reset: listnumbering; } | |
ol.ui-listview .ui-link-inherit:before, .ui-li-dec { font-size: .8em; display: inline-block; padding-right: .3em; font-weight: normal;counter-increment: listnumbering; content: counter(listnumbering) ". "; } | |
ol.ui-listview .ui-li-jsnumbering:before { content: "" !important; } /* to avoid chance of duplication */ | |
.ui-listview-inset .ui-li { border-right-width: 1px; border-left-width: 1px; } | |
.ui-li:last-child { border-bottom-width: 1px; } | |
.ui-li .ui-btn-inner { display: block; position: relative; padding: .7em 75px .7em 15px; } | |
.ui-li-has-thumb .ui-btn-inner { min-height: 60px; padding-left: 100px; } | |
.ui-li-has-icon .ui-btn-inner { min-height: 20px; padding-left: 40px; } | |
.ui-li-heading { font-size: 16px; font-weight: bold; display: block; margin: .6em 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } | |
.ui-li-desc { font-size: 12px; font-weight: normal; display: block; margin: -.5em 0 .6em; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } | |
.ui-li-thumb, .ui-li-icon { position: absolute; left: 1px; top: 0; max-height: 80px; max-width: 80px; } | |
.ui-li-icon { max-height: 40px; max-width: 40px; left: 10px; top: .9em; } | |
.ui-li-thumb, .ui-li-icon, .ui-li-content { float: left; margin-right: 10px; } | |
.ui-li-aside { float: right; width: 50%; text-align: right; margin: .3em 0; } | |
.min-width-480px .ui-li-aside { width: 45%; } | |
.ui-li-has-alt .ui-btn-inner { padding-right: 95px; } | |
.ui-li-count { position: absolute; font-size: 11px; font-weight: bold; padding: .2em .5em; top: 50%; margin-top: -.9em; right: 38px; } | |
.ui-li-divider .ui-li-count { right: 10px; } | |
.ui-li-has-alt .ui-li-count { right: 55px; } | |
.ui-li-link-alt { position: absolute; width: 40px; height: 100%; border-width: 0; border-left-width: 1px; top: 0; right: 0; margin: 0; padding: 0; } | |
.ui-li-link-alt .ui-btn { overflow: hidden; position: absolute; right: 8px; top: 50%; margin: -11px 0 0 0; border-bottom-width: 1px; } | |
.ui-li-link-alt .ui-btn-inner { padding: 0; position: static; } | |
.ui-li-link-alt .ui-btn .ui-icon { right: 50%; margin-right: -9px; } | |
.ui-listview-filter { border-width: 0; overflow: hidden; margin: -15px -15px 15px -15px } | |
.ui-listview-filter .ui-input-search { margin: 5px; width: auto; display: block; } | |
/* Odd iPad positioning issue. */ | |
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) { | |
.ui-li .ui-btn-text { overflow: visible; } | |
} | |
/* | |
* jQuery Mobile Framework | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses. | |
*/ | |
label.ui-slider { display: block; } | |
input.ui-slider-input, .min-width-480px input.ui-slider-input { display: inline-block; width: 50px; } | |
select.ui-slider-switch { display: none; } | |
div.ui-slider { position: relative; display: inline-block; overflow: visible; height: 15px; padding: 0; margin: 0 2% 0 20px; top: 4px; width: 66%; } | |
a.ui-slider-handle { position: absolute; z-index: 10; top: 50%; width: 28px; height: 28px; margin-top: -15px; margin-left: -15px; } | |
a.ui-slider-handle .ui-btn-inner { padding-left: 0; padding-right: 0; } | |
.min-width-480px label.ui-slider { display: inline-block; width: 20%; margin: 0 2% 0 0; } | |
.min-width-480px div.ui-slider { width: 45%; } | |
div.ui-slider-switch { height: 32px; overflow: hidden; margin-left: 0; } | |
div.ui-slider-inneroffset { margin-left: 50%; position: absolute; top: 1px; height: 100%; width: 50%; } | |
div.ui-slider-handle-snapping { -webkit-transition: left 100ms linear; } | |
div.ui-slider-labelbg { position: absolute; top:0; margin: 0; border-width: 0; } | |
div.ui-slider-switch div.ui-slider-labelbg-a { width: 60%; height: 100%; left: 0; } | |
div.ui-slider-switch div.ui-slider-labelbg-b { width: 60%; height: 100%; right: 0; } | |
.ui-slider-switch-a div.ui-slider-labelbg-a, .ui-slider-switch-b div.ui-slider-labelbg-b { z-index: 1; } | |
.ui-slider-switch-a div.ui-slider-labelbg-b, .ui-slider-switch-b div.ui-slider-labelbg-a { z-index: 10; } | |
div.ui-slider-switch a.ui-slider-handle { z-index: 20; width: 101%; height: 32px; margin-top: -18px; margin-left: -101%; } | |
span.ui-slider-label { width: 100%; position: absolute;height: 32px; font-size: 16px; text-align: center; line-height: 2; background: none; border-color: transparent; } | |
span.ui-slider-label-a { left: -100%; margin-right: -1px } | |
span.ui-slider-label-b { right: -100%; margin-left: -1px } | |
/*! | |
* jQuery JavaScript Library v1.4.4 | |
* http://jquery.com/ | |
* | |
* Copyright 2010, John Resig | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
* | |
* Includes Sizzle.js | |
* http://sizzlejs.com/ | |
* Copyright 2010, The Dojo Foundation | |
* Released under the MIT, BSD, and GPL Licenses. | |
* | |
* Date: Thu Nov 11 19:04:53 2010 -0500 | |
*/ | |
(function( window, undefined ) { | |
// Use the correct document accordingly with window argument (sandbox) | |
var document = window.document; | |
var jQuery = (function() { | |
// Define a local copy of jQuery | |
var jQuery = function( selector, context ) { | |
// The jQuery object is actually just the init constructor 'enhanced' | |
return new jQuery.fn.init( selector, context ); | |
}, | |
// Map over jQuery in case of overwrite | |
_jQuery = window.jQuery, | |
// Map over the $ in case of overwrite | |
_$ = window.$, | |
// A central reference to the root jQuery(document) | |
rootjQuery, | |
// A simple way to check for HTML strings or ID strings | |
// (both of which we optimize for) | |
quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, | |
// Is it a simple selector | |
isSimple = /^.[^:#\[\.,]*$/, | |
// Check if a string has a non-whitespace character in it | |
rnotwhite = /\S/, | |
rwhite = /\s/, | |
// Used for trimming whitespace | |
trimLeft = /^\s+/, | |
trimRight = /\s+$/, | |
// Check for non-word characters | |
rnonword = /\W/, | |
// Check for digits | |
rdigit = /\d/, | |
// Match a standalone tag | |
rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, | |
// JSON RegExp | |
rvalidchars = /^[\],:{}\s]*$/, | |
rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, | |
rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, | |
rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, | |
// Useragent RegExp | |
rwebkit = /(webkit)[ \/]([\w.]+)/, | |
ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, | |
rmsie = /(msie) ([\w.]+)/, | |
rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, | |
// Keep a UserAgent string for use with jQuery.browser | |
userAgent = navigator.userAgent, | |
// For matching the engine and version of the browser | |
browserMatch, | |
// Has the ready events already been bound? | |
readyBound = false, | |
// The functions to execute on DOM ready | |
readyList = [], | |
// The ready event handler | |
DOMContentLoaded, | |
// Save a reference to some core methods | |
toString = Object.prototype.toString, | |
hasOwn = Object.prototype.hasOwnProperty, | |
push = Array.prototype.push, | |
slice = Array.prototype.slice, | |
trim = String.prototype.trim, | |
indexOf = Array.prototype.indexOf, | |
// [[Class]] -> type pairs | |
class2type = {}; | |
jQuery.fn = jQuery.prototype = { | |
init: function( selector, context ) { | |
var match, elem, ret, doc; | |
// Handle $(""), $(null), or $(undefined) | |
if ( !selector ) { | |
return this; | |
} | |
// Handle $(DOMElement) | |
if ( selector.nodeType ) { | |
this.context = this[0] = selector; | |
this.length = 1; | |
return this; | |
} | |
// The body element only exists once, optimize finding it | |
if ( selector === "body" && !context && document.body ) { | |
this.context = document; | |
this[0] = document.body; | |
this.selector = "body"; | |
this.length = 1; | |
return this; | |
} | |
// Handle HTML strings | |
if ( typeof selector === "string" ) { | |
// Are we dealing with HTML string or an ID? | |
match = quickExpr.exec( selector ); | |
// Verify a match, and that no context was specified for #id | |
if ( match && (match[1] || !context) ) { | |
// HANDLE: $(html) -> $(array) | |
if ( match[1] ) { | |
doc = (context ? context.ownerDocument || context : document); | |
// If a single string is passed in and it's a single tag | |
// just do a createElement and skip the rest | |
ret = rsingleTag.exec( selector ); | |
if ( ret ) { | |
if ( jQuery.isPlainObject( context ) ) { | |
selector = [ document.createElement( ret[1] ) ]; | |
jQuery.fn.attr.call( selector, context, true ); | |
} else { | |
selector = [ doc.createElement( ret[1] ) ]; | |
} | |
} else { | |
ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); | |
selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; | |
} | |
return jQuery.merge( this, selector ); | |
// HANDLE: $("#id") | |
} else { | |
elem = document.getElementById( match[2] ); | |
// Check parentNode to catch when Blackberry 4.6 returns | |
// nodes that are no longer in the document #6963 | |
if ( elem && elem.parentNode ) { | |
// Handle the case where IE and Opera return items | |
// by name instead of ID | |
if ( elem.id !== match[2] ) { | |
return rootjQuery.find( selector ); | |
} | |
// Otherwise, we inject the element directly into the jQuery object | |
this.length = 1; | |
this[0] = elem; | |
} | |
this.context = document; | |
this.selector = selector; | |
return this; | |
} | |
// HANDLE: $("TAG") | |
} else if ( !context && !rnonword.test( selector ) ) { | |
this.selector = selector; | |
this.context = document; | |
selector = document.getElementsByTagName( selector ); | |
return jQuery.merge( this, selector ); | |
// HANDLE: $(expr, $(...)) | |
} else if ( !context || context.jquery ) { | |
return (context || rootjQuery).find( selector ); | |
// HANDLE: $(expr, context) | |
// (which is just equivalent to: $(context).find(expr) | |
} else { | |
return jQuery( context ).find( selector ); | |
} | |
// HANDLE: $(function) | |
// Shortcut for document ready | |
} else if ( jQuery.isFunction( selector ) ) { | |
return rootjQuery.ready( selector ); | |
} | |
if (selector.selector !== undefined) { | |
this.selector = selector.selector; | |
this.context = selector.context; | |
} | |
return jQuery.makeArray( selector, this ); | |
}, | |
// Start with an empty selector | |
selector: "", | |
// The current version of jQuery being used | |
jquery: "1.4.4", | |
// The default length of a jQuery object is 0 | |
length: 0, | |
// The number of elements contained in the matched element set | |
size: function() { | |
return this.length; | |
}, | |
toArray: function() { | |
return slice.call( this, 0 ); | |
}, | |
// Get the Nth element in the matched element set OR | |
// Get the whole matched element set as a clean array | |
get: function( num ) { | |
return num == null ? | |
// Return a 'clean' array | |
this.toArray() : | |
// Return just the object | |
( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); | |
}, | |
// Take an array of elements and push it onto the stack | |
// (returning the new matched element set) | |
pushStack: function( elems, name, selector ) { | |
// Build a new jQuery matched element set | |
var ret = jQuery(); | |
if ( jQuery.isArray( elems ) ) { | |
push.apply( ret, elems ); | |
} else { | |
jQuery.merge( ret, elems ); | |
} | |
// Add the old object onto the stack (as a reference) | |
ret.prevObject = this; | |
ret.context = this.context; | |
if ( name === "find" ) { | |
ret.selector = this.selector + (this.selector ? " " : "") + selector; | |
} else if ( name ) { | |
ret.selector = this.selector + "." + name + "(" + selector + ")"; | |
} | |
// Return the newly-formed element set | |
return ret; | |
}, | |
// Execute a callback for every element in the matched set. | |
// (You can seed the arguments with an array of args, but this is | |
// only used internally.) | |
each: function( callback, args ) { | |
return jQuery.each( this, callback, args ); | |
}, | |
ready: function( fn ) { | |
// Attach the listeners | |
jQuery.bindReady(); | |
// If the DOM is already ready | |
if ( jQuery.isReady ) { | |
// Execute the function immediately | |
fn.call( document, jQuery ); | |
// Otherwise, remember the function for later | |
} else if ( readyList ) { | |
// Add the function to the wait list | |
readyList.push( fn ); | |
} | |
return this; | |
}, | |
eq: function( i ) { | |
return i === -1 ? | |
this.slice( i ) : | |
this.slice( i, +i + 1 ); | |
}, | |
first: function() { | |
return this.eq( 0 ); | |
}, | |
last: function() { | |
return this.eq( -1 ); | |
}, | |
slice: function() { | |
return this.pushStack( slice.apply( this, arguments ), | |
"slice", slice.call(arguments).join(",") ); | |
}, | |
map: function( callback ) { | |
return this.pushStack( jQuery.map(this, function( elem, i ) { | |
return callback.call( elem, i, elem ); | |
})); | |
}, | |
end: function() { | |
return this.prevObject || jQuery(null); | |
}, | |
// For internal use only. | |
// Behaves like an Array's method, not like a jQuery method. | |
push: push, | |
sort: [].sort, | |
splice: [].splice | |
}; | |
// Give the init function the jQuery prototype for later instantiation | |
jQuery.fn.init.prototype = jQuery.fn; | |
jQuery.extend = jQuery.fn.extend = function() { | |
var options, name, src, copy, copyIsArray, clone, | |
target = arguments[0] || {}, | |
i = 1, | |
length = arguments.length, | |
deep = false; | |
// Handle a deep copy situation | |
if ( typeof target === "boolean" ) { | |
deep = target; | |
target = arguments[1] || {}; | |
// skip the boolean and the target | |
i = 2; | |
} | |
// Handle case when target is a string or something (possible in deep copy) | |
if ( typeof target !== "object" && !jQuery.isFunction(target) ) { | |
target = {}; | |
} | |
// extend jQuery itself if only one argument is passed | |
if ( length === i ) { | |
target = this; | |
--i; | |
} | |
for ( ; i < length; i++ ) { | |
// Only deal with non-null/undefined values | |
if ( (options = arguments[ i ]) != null ) { | |
// Extend the base object | |
for ( name in options ) { | |
src = target[ name ]; | |
copy = options[ name ]; | |
// Prevent never-ending loop | |
if ( target === copy ) { | |
continue; | |
} | |
// Recurse if we're merging plain objects or arrays | |
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { | |
if ( copyIsArray ) { | |
copyIsArray = false; | |
clone = src && jQuery.isArray(src) ? src : []; | |
} else { | |
clone = src && jQuery.isPlainObject(src) ? src : {}; | |
} | |
// Never move original objects, clone them | |
target[ name ] = jQuery.extend( deep, clone, copy ); | |
// Don't bring in undefined values | |
} else if ( copy !== undefined ) { | |
target[ name ] = copy; | |
} | |
} | |
} | |
} | |
// Return the modified object | |
return target; | |
}; | |
jQuery.extend({ | |
noConflict: function( deep ) { | |
window.$ = _$; | |
if ( deep ) { | |
window.jQuery = _jQuery; | |
} | |
return jQuery; | |
}, | |
// Is the DOM ready to be used? Set to true once it occurs. | |
isReady: false, | |
// A counter to track how many items to wait for before | |
// the ready event fires. See #6781 | |
readyWait: 1, | |
// Handle when the DOM is ready | |
ready: function( wait ) { | |
// A third-party is pushing the ready event forwards | |
if ( wait === true ) { | |
jQuery.readyWait--; | |
} | |
// Make sure that the DOM is not already loaded | |
if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { | |
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). | |
if ( !document.body ) { | |
return setTimeout( jQuery.ready, 1 ); | |
} | |
// Remember that the DOM is ready | |
jQuery.isReady = true; | |
// If a normal DOM Ready event fired, decrement, and wait if need be | |
if ( wait !== true && --jQuery.readyWait > 0 ) { | |
return; | |
} | |
// If there are functions bound, to execute | |
if ( readyList ) { | |
// Execute all of them | |
var fn, | |
i = 0, | |
ready = readyList; | |
// Reset the list of functions | |
readyList = null; | |
while ( (fn = ready[ i++ ]) ) { | |
fn.call( document, jQuery ); | |
} | |
// Trigger any bound ready events | |
if ( jQuery.fn.trigger ) { | |
jQuery( document ).trigger( "ready" ).unbind( "ready" ); | |
} | |
} | |
} | |
}, | |
bindReady: function() { | |
if ( readyBound ) { | |
return; | |
} | |
readyBound = true; | |
// Catch cases where $(document).ready() is called after the | |
// browser event has already occurred. | |
if ( document.readyState === "complete" ) { | |
// Handle it asynchronously to allow scripts the opportunity to delay ready | |
return setTimeout( jQuery.ready, 1 ); | |
} | |
// Mozilla, Opera and webkit nightlies currently support this event | |
if ( document.addEventListener ) { | |
// Use the handy event callback | |
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); | |
// A fallback to window.onload, that will always work | |
window.addEventListener( "load", jQuery.ready, false ); | |
// If IE event model is used | |
} else if ( document.attachEvent ) { | |
// ensure firing before onload, | |
// maybe late but safe also for iframes | |
document.attachEvent("onreadystatechange", DOMContentLoaded); | |
// A fallback to window.onload, that will always work | |
window.attachEvent( "onload", jQuery.ready ); | |
// If IE and not a frame | |
// continually check to see if the document is ready | |
var toplevel = false; | |
try { | |
toplevel = window.frameElement == null; | |
} catch(e) {} | |
if ( document.documentElement.doScroll && toplevel ) { | |
doScrollCheck(); | |
} | |
} | |
}, | |
// See test/unit/core.js for details concerning isFunction. | |
// Since version 1.3, DOM methods and functions like alert | |
// aren't supported. They return false on IE (#2968). | |
isFunction: function( obj ) { | |
return jQuery.type(obj) === "function"; | |
}, | |
isArray: Array.isArray || function( obj ) { | |
return jQuery.type(obj) === "array"; | |
}, | |
// A crude way of determining if an object is a window | |
isWindow: function( obj ) { | |
return obj && typeof obj === "object" && "setInterval" in obj; | |
}, | |
isNaN: function( obj ) { | |
return obj == null || !rdigit.test( obj ) || isNaN( obj ); | |
}, | |
type: function( obj ) { | |
return obj == null ? | |
String( obj ) : | |
class2type[ toString.call(obj) ] || "object"; | |
}, | |
isPlainObject: function( obj ) { | |
// Must be an Object. | |
// Because of IE, we also have to check the presence of the constructor property. | |
// Make sure that DOM nodes and window objects don't pass through, as well | |
if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { | |
return false; | |
} | |
// Not own constructor property must be Object | |
if ( obj.constructor && | |
!hasOwn.call(obj, "constructor") && | |
!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { | |
return false; | |
} | |
// Own properties are enumerated firstly, so to speed up, | |
// if last one is own, then all properties are own. | |
var key; | |
for ( key in obj ) {} | |
return key === undefined || hasOwn.call( obj, key ); | |
}, | |
isEmptyObject: function( obj ) { | |
for ( var name in obj ) { | |
return false; | |
} | |
return true; | |
}, | |
error: function( msg ) { | |
throw msg; | |
}, | |
parseJSON: function( data ) { | |
if ( typeof data !== "string" || !data ) { | |
return null; | |
} | |
// Make sure leading/trailing whitespace is removed (IE can't handle it) | |
data = jQuery.trim( data ); | |
// Make sure the incoming data is actual JSON | |
// Logic borrowed from http://json.org/json2.js | |
if ( rvalidchars.test(data.replace(rvalidescape, "@") | |
.replace(rvalidtokens, "]") | |
.replace(rvalidbraces, "")) ) { | |
// Try to use the native JSON parser first | |
return window.JSON && window.JSON.parse ? | |
window.JSON.parse( data ) : | |
(new Function("return " + data))(); | |
} else { | |
jQuery.error( "Invalid JSON: " + data ); | |
} | |
}, | |
noop: function() {}, | |
// Evalulates a script in a global context | |
globalEval: function( data ) { | |
if ( data && rnotwhite.test(data) ) { | |
// Inspired by code by Andrea Giammarchi | |
// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html | |
var head = document.getElementsByTagName("head")[0] || document.documentElement, | |
script = document.createElement("script"); | |
script.type = "text/javascript"; | |
if ( jQuery.support.scriptEval ) { | |
script.appendChild( document.createTextNode( data ) ); | |
} else { | |
script.text = data; | |
} | |
// Use insertBefore instead of appendChild to circumvent an IE6 bug. | |
// This arises when a base node is used (#2709). | |
head.insertBefore( script, head.firstChild ); | |
head.removeChild( script ); | |
} | |
}, | |
nodeName: function( elem, name ) { | |
return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); | |
}, | |
// args is for internal usage only | |
each: function( object, callback, args ) { | |
var name, i = 0, | |
length = object.length, | |
isObj = length === undefined || jQuery.isFunction(object); | |
if ( args ) { | |
if ( isObj ) { | |
for ( name in object ) { | |
if ( callback.apply( object[ name ], args ) === false ) { | |
break; | |
} | |
} | |
} else { | |
for ( ; i < length; ) { | |
if ( callback.apply( object[ i++ ], args ) === false ) { | |
break; | |
} | |
} | |
} | |
// A special, fast, case for the most common use of each | |
} else { | |
if ( isObj ) { | |
for ( name in object ) { | |
if ( callback.call( object[ name ], name, object[ name ] ) === false ) { | |
break; | |
} | |
} | |
} else { | |
for ( var value = object[0]; | |
i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} | |
} | |
} | |
return object; | |
}, | |
// Use native String.trim function wherever possible | |
trim: trim ? | |
function( text ) { | |
return text == null ? | |
"" : | |
trim.call( text ); | |
} : | |
// Otherwise use our own trimming functionality | |
function( text ) { | |
return text == null ? | |
"" : | |
text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); | |
}, | |
// results is for internal usage only | |
makeArray: function( array, results ) { | |
var ret = results || []; | |
if ( array != null ) { | |
// The window, strings (and functions) also have 'length' | |
// The extra typeof function check is to prevent crashes | |
// in Safari 2 (See: #3039) | |
// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 | |
var type = jQuery.type(array); | |
if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { | |
push.call( ret, array ); | |
} else { | |
jQuery.merge( ret, array ); | |
} | |
} | |
return ret; | |
}, | |
inArray: function( elem, array ) { | |
if ( array.indexOf ) { | |
return array.indexOf( elem ); | |
} | |
for ( var i = 0, length = array.length; i < length; i++ ) { | |
if ( array[ i ] === elem ) { | |
return i; | |
} | |
} | |
return -1; | |
}, | |
merge: function( first, second ) { | |
var i = first.length, | |
j = 0; | |
if ( typeof second.length === "number" ) { | |
for ( var l = second.length; j < l; j++ ) { | |
first[ i++ ] = second[ j ]; | |
} | |
} else { | |
while ( second[j] !== undefined ) { | |
first[ i++ ] = second[ j++ ]; | |
} | |
} | |
first.length = i; | |
return first; | |
}, | |
grep: function( elems, callback, inv ) { | |
var ret = [], retVal; | |
inv = !!inv; | |
// Go through the array, only saving the items | |
// that pass the validator function | |
for ( var i = 0, length = elems.length; i < length; i++ ) { | |
retVal = !!callback( elems[ i ], i ); | |
if ( inv !== retVal ) { | |
ret.push( elems[ i ] ); | |
} | |
} | |
return ret; | |
}, | |
// arg is for internal usage only | |
map: function( elems, callback, arg ) { | |
var ret = [], value; | |
// Go through the array, translating each of the items to their | |
// new value (or values). | |
for ( var i = 0, length = elems.length; i < length; i++ ) { | |
value = callback( elems[ i ], i, arg ); | |
if ( value != null ) { | |
ret[ ret.length ] = value; | |
} | |
} | |
return ret.concat.apply( [], ret ); | |
}, | |
// A global GUID counter for objects | |
guid: 1, | |
proxy: function( fn, proxy, thisObject ) { | |
if ( arguments.length === 2 ) { | |
if ( typeof proxy === "string" ) { | |
thisObject = fn; | |
fn = thisObject[ proxy ]; | |
proxy = undefined; | |
} else if ( proxy && !jQuery.isFunction( proxy ) ) { | |
thisObject = proxy; | |
proxy = undefined; | |
} | |
} | |
if ( !proxy && fn ) { | |
proxy = function() { | |
return fn.apply( thisObject || this, arguments ); | |
}; | |
} | |
// Set the guid of unique handler to the same of original handler, so it can be removed | |
if ( fn ) { | |
proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; | |
} | |
// So proxy can be declared as an argument | |
return proxy; | |
}, | |
// Mutifunctional method to get and set values to a collection | |
// The value/s can be optionally by executed if its a function | |
access: function( elems, key, value, exec, fn, pass ) { | |
var length = elems.length; | |
// Setting many attributes | |
if ( typeof key === "object" ) { | |
for ( var k in key ) { | |
jQuery.access( elems, k, key[k], exec, fn, value ); | |
} | |
return elems; | |
} | |
// Setting one attribute | |
if ( value !== undefined ) { | |
// Optionally, function values get executed if exec is true | |
exec = !pass && exec && jQuery.isFunction(value); | |
for ( var i = 0; i < length; i++ ) { | |
fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); | |
} | |
return elems; | |
} | |
// Getting an attribute | |
return length ? fn( elems[0], key ) : undefined; | |
}, | |
now: function() { | |
return (new Date()).getTime(); | |
}, | |
// Use of jQuery.browser is frowned upon. | |
// More details: http://docs.jquery.com/Utilities/jQuery.browser | |
uaMatch: function( ua ) { | |
ua = ua.toLowerCase(); | |
var match = rwebkit.exec( ua ) || | |
ropera.exec( ua ) || | |
rmsie.exec( ua ) || | |
ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || | |
[]; | |
return { browser: match[1] || "", version: match[2] || "0" }; | |
}, | |
browser: {} | |
}); | |
// Populate the class2type map | |
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { | |
class2type[ "[object " + name + "]" ] = name.toLowerCase(); | |
}); | |
browserMatch = jQuery.uaMatch( userAgent ); | |
if ( browserMatch.browser ) { | |
jQuery.browser[ browserMatch.browser ] = true; | |
jQuery.browser.version = browserMatch.version; | |
} | |
// Deprecated, use jQuery.browser.webkit instead | |
if ( jQuery.browser.webkit ) { | |
jQuery.browser.safari = true; | |
} | |
if ( indexOf ) { | |
jQuery.inArray = function( elem, array ) { | |
return indexOf.call( array, elem ); | |
}; | |
} | |
// Verify that \s matches non-breaking spaces | |
// (IE fails on this test) | |
if ( !rwhite.test( "\xA0" ) ) { | |
trimLeft = /^[\s\xA0]+/; | |
trimRight = /[\s\xA0]+$/; | |
} | |
// All jQuery objects should point back to these | |
rootjQuery = jQuery(document); | |
// Cleanup functions for the document ready method | |
if ( document.addEventListener ) { | |
DOMContentLoaded = function() { | |
document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); | |
jQuery.ready(); | |
}; | |
} else if ( document.attachEvent ) { | |
DOMContentLoaded = function() { | |
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). | |
if ( document.readyState === "complete" ) { | |
document.detachEvent( "onreadystatechange", DOMContentLoaded ); | |
jQuery.ready(); | |
} | |
}; | |
} | |
// The DOM ready check for Internet Explorer | |
function doScrollCheck() { | |
if ( jQuery.isReady ) { | |
return; | |
} | |
try { | |
// If IE is used, use the trick by Diego Perini | |
// http://javascript.nwbox.com/IEContentLoaded/ | |
document.documentElement.doScroll("left"); | |
} catch(e) { | |
setTimeout( doScrollCheck, 1 ); | |
return; | |
} | |
// and execute any waiting functions | |
jQuery.ready(); | |
} | |
// Expose jQuery to the global object | |
return (window.jQuery = window.$ = jQuery); | |
})(); | |
(function() { | |
jQuery.support = {}; | |
var root = document.documentElement, | |
script = document.createElement("script"), | |
div = document.createElement("div"), | |
id = "script" + jQuery.now(); | |
div.style.display = "none"; | |
div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; | |
var all = div.getElementsByTagName("*"), | |
a = div.getElementsByTagName("a")[0], | |
select = document.createElement("select"), | |
opt = select.appendChild( document.createElement("option") ); | |
// Can't get basic test support | |
if ( !all || !all.length || !a ) { | |
return; | |
} | |
jQuery.support = { | |
// IE strips leading whitespace when .innerHTML is used | |
leadingWhitespace: div.firstChild.nodeType === 3, | |
// Make sure that tbody elements aren't automatically inserted | |
// IE will insert them into empty tables | |
tbody: !div.getElementsByTagName("tbody").length, | |
// Make sure that link elements get serialized correctly by innerHTML | |
// This requires a wrapper element in IE | |
htmlSerialize: !!div.getElementsByTagName("link").length, | |
// Get the style information from getAttribute | |
// (IE uses .cssText insted) | |
style: /red/.test( a.getAttribute("style") ), | |
// Make sure that URLs aren't manipulated | |
// (IE normalizes it by default) | |
hrefNormalized: a.getAttribute("href") === "/a", | |
// Make sure that element opacity exists | |
// (IE uses filter instead) | |
// Use a regex to work around a WebKit issue. See #5145 | |
opacity: /^0.55$/.test( a.style.opacity ), | |
// Verify style float existence | |
// (IE uses styleFloat instead of cssFloat) | |
cssFloat: !!a.style.cssFloat, | |
// Make sure that if no value is specified for a checkbox | |
// that it defaults to "on". | |
// (WebKit defaults to "" instead) | |
checkOn: div.getElementsByTagName("input")[0].value === "on", | |
// Make sure that a selected-by-default option has a working selected property. | |
// (WebKit defaults to false instead of true, IE too, if it's in an optgroup) | |
optSelected: opt.selected, | |
// Will be defined later | |
deleteExpando: true, | |
optDisabled: false, | |
checkClone: false, | |
scriptEval: false, | |
noCloneEvent: true, | |
boxModel: null, | |
inlineBlockNeedsLayout: false, | |
shrinkWrapBlocks: false, | |
reliableHiddenOffsets: true | |
}; | |
// Make sure that the options inside disabled selects aren't marked as disabled | |
// (WebKit marks them as diabled) | |
select.disabled = true; | |
jQuery.support.optDisabled = !opt.disabled; | |
script.type = "text/javascript"; | |
try { | |
script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); | |
} catch(e) {} | |
root.insertBefore( script, root.firstChild ); | |
// Make sure that the execution of code works by injecting a script | |
// tag with appendChild/createTextNode | |
// (IE doesn't support this, fails, and uses .text instead) | |
if ( window[ id ] ) { | |
jQuery.support.scriptEval = true; | |
delete window[ id ]; | |
} | |
// Test to see if it's possible to delete an expando from an element | |
// Fails in Internet Explorer | |
try { | |
delete script.test; | |
} catch(e) { | |
jQuery.support.deleteExpando = false; | |
} | |
root.removeChild( script ); | |
if ( div.attachEvent && div.fireEvent ) { | |
div.attachEvent("onclick", function click() { | |
// Cloning a node shouldn't copy over any | |
// bound event handlers (IE does this) | |
jQuery.support.noCloneEvent = false; | |
div.detachEvent("onclick", click); | |
}); | |
div.cloneNode(true).fireEvent("onclick"); | |
} | |
div = document.createElement("div"); | |
div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>"; | |
var fragment = document.createDocumentFragment(); | |
fragment.appendChild( div.firstChild ); | |
// WebKit doesn't clone checked state correctly in fragments | |
jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; | |
// Figure out if the W3C box model works as expected | |
// document.body must exist before we can do this | |
jQuery(function() { | |
var div = document.createElement("div"); | |
div.style.width = div.style.paddingLeft = "1px"; | |
document.body.appendChild( div ); | |
jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; | |
if ( "zoom" in div.style ) { | |
// Check if natively block-level elements act like inline-block | |
// elements when setting their display to 'inline' and giving | |
// them layout | |
// (IE < 8 does this) | |
div.style.display = "inline"; | |
div.style.zoom = 1; | |
jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; | |
// Check if elements with layout shrink-wrap their children | |
// (IE 6 does this) | |
div.style.display = ""; | |
div.innerHTML = "<div style='width:4px;'></div>"; | |
jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; | |
} | |
div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>"; | |
var tds = div.getElementsByTagName("td"); | |
// Check if table cells still have offsetWidth/Height when they are set | |
// to display:none and there are still other visible table cells in a | |
// table row; if so, offsetWidth/Height are not reliable for use when | |
// determining if an element has been hidden directly using | |
// display:none (it is still safe to use offsets if a parent element is | |
// hidden; don safety goggles and see bug #4512 for more information). | |
// (only IE 8 fails this test) | |
jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; | |
tds[0].style.display = ""; | |
tds[1].style.display = "none"; | |
// Check if empty table cells still have offsetWidth/Height | |
// (IE < 8 fail this test) | |
jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; | |
div.innerHTML = ""; | |
document.body.removeChild( div ).style.display = "none"; | |
div = tds = null; | |
}); | |
// Technique from Juriy Zaytsev | |
// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ | |
var eventSupported = function( eventName ) { | |
var el = document.createElement("div"); | |
eventName = "on" + eventName; | |
var isSupported = (eventName in el); | |
if ( !isSupported ) { | |
el.setAttribute(eventName, "return;"); | |
isSupported = typeof el[eventName] === "function"; | |
} | |
el = null; | |
return isSupported; | |
}; | |
jQuery.support.submitBubbles = eventSupported("submit"); | |
jQuery.support.changeBubbles = eventSupported("change"); | |
// release memory in IE | |
root = script = div = all = a = null; | |
})(); | |
var windowData = {}, | |
rbrace = /^(?:\{.*\}|\[.*\])$/; | |
jQuery.extend({ | |
cache: {}, | |
// Please use with caution | |
uuid: 0, | |
// Unique for each copy of jQuery on the page | |
expando: "jQuery" + jQuery.now(), | |
// The following elements throw uncatchable exceptions if you | |
// attempt to add expando properties to them. | |
noData: { | |
"embed": true, | |
// Ban all objects except for Flash (which handle expandos) | |
"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", | |
"applet": true | |
}, | |
data: function( elem, name, data ) { | |
if ( !jQuery.acceptData( elem ) ) { | |
return; | |
} | |
elem = elem == window ? | |
windowData : | |
elem; | |
var isNode = elem.nodeType, | |
id = isNode ? elem[ jQuery.expando ] : null, | |
cache = jQuery.cache, thisCache; | |
if ( isNode && !id && typeof name === "string" && data === undefined ) { | |
return; | |
} | |
// Get the data from the object directly | |
if ( !isNode ) { | |
cache = elem; | |
// Compute a unique ID for the element | |
} else if ( !id ) { | |
elem[ jQuery.expando ] = id = ++jQuery.uuid; | |
} | |
// Avoid generating a new cache unless none exists and we | |
// want to manipulate it. | |
if ( typeof name === "object" ) { | |
if ( isNode ) { | |
cache[ id ] = jQuery.extend(cache[ id ], name); | |
} else { | |
jQuery.extend( cache, name ); | |
} | |
} else if ( isNode && !cache[ id ] ) { | |
cache[ id ] = {}; | |
} | |
thisCache = isNode ? cache[ id ] : cache; | |
// Prevent overriding the named cache with undefined values | |
if ( data !== undefined ) { | |
thisCache[ name ] = data; | |
} | |
return typeof name === "string" ? thisCache[ name ] : thisCache; | |
}, | |
removeData: function( elem, name ) { | |
if ( !jQuery.acceptData( elem ) ) { | |
return; | |
} | |
elem = elem == window ? | |
windowData : | |
elem; | |
var isNode = elem.nodeType, | |
id = isNode ? elem[ jQuery.expando ] : elem, | |
cache = jQuery.cache, | |
thisCache = isNode ? cache[ id ] : id; | |
// If we want to remove a specific section of the element's data | |
if ( name ) { | |
if ( thisCache ) { | |
// Remove the section of cache data | |
delete thisCache[ name ]; | |
// If we've removed all the data, remove the element's cache | |
if ( isNode && jQuery.isEmptyObject(thisCache) ) { | |
jQuery.removeData( elem ); | |
} | |
} | |
// Otherwise, we want to remove all of the element's data | |
} else { | |
if ( isNode && jQuery.support.deleteExpando ) { | |
delete elem[ jQuery.expando ]; | |
} else if ( elem.removeAttribute ) { | |
elem.removeAttribute( jQuery.expando ); | |
// Completely remove the data cache | |
} else if ( isNode ) { | |
delete cache[ id ]; | |
// Remove all fields from the object | |
} else { | |
for ( var n in elem ) { | |
delete elem[ n ]; | |
} | |
} | |
} | |
}, | |
// A method for determining if a DOM node can handle the data expando | |
acceptData: function( elem ) { | |
if ( elem.nodeName ) { | |
var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; | |
if ( match ) { | |
return !(match === true || elem.getAttribute("classid") !== match); | |
} | |
} | |
return true; | |
} | |
}); | |
jQuery.fn.extend({ | |
data: function( key, value ) { | |
var data = null; | |
if ( typeof key === "undefined" ) { | |
if ( this.length ) { | |
var attr = this[0].attributes, name; | |
data = jQuery.data( this[0] ); | |
for ( var i = 0, l = attr.length; i < l; i++ ) { | |
name = attr[i].name; | |
if ( name.indexOf( "data-" ) === 0 ) { | |
name = name.substr( 5 ); | |
dataAttr( this[0], name, data[ name ] ); | |
} | |
} | |
} | |
return data; | |
} else if ( typeof key === "object" ) { | |
return this.each(function() { | |
jQuery.data( this, key ); | |
}); | |
} | |
var parts = key.split("."); | |
parts[1] = parts[1] ? "." + parts[1] : ""; | |
if ( value === undefined ) { | |
data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); | |
// Try to fetch any internally stored data first | |
if ( data === undefined && this.length ) { | |
data = jQuery.data( this[0], key ); | |
data = dataAttr( this[0], key, data ); | |
} | |
return data === undefined && parts[1] ? | |
this.data( parts[0] ) : | |
data; | |
} else { | |
return this.each(function() { | |
var $this = jQuery( this ), | |
args = [ parts[0], value ]; | |
$this.triggerHandler( "setData" + parts[1] + "!", args ); | |
jQuery.data( this, key, value ); | |
$this.triggerHandler( "changeData" + parts[1] + "!", args ); | |
}); | |
} | |
}, | |
removeData: function( key ) { | |
return this.each(function() { | |
jQuery.removeData( this, key ); | |
}); | |
} | |
}); | |
function dataAttr( elem, key, data ) { | |
// If nothing was found internally, try to fetch any | |
// data from the HTML5 data-* attribute | |
if ( data === undefined && elem.nodeType === 1 ) { | |
data = elem.getAttribute( "data-" + key ); | |
if ( typeof data === "string" ) { | |
try { | |
data = data === "true" ? true : | |
data === "false" ? false : | |
data === "null" ? null : | |
!jQuery.isNaN( data ) ? parseFloat( data ) : | |
rbrace.test( data ) ? jQuery.parseJSON( data ) : | |
data; | |
} catch( e ) {} | |
// Make sure we set the data so it isn't changed later | |
jQuery.data( elem, key, data ); | |
} else { | |
data = undefined; | |
} | |
} | |
return data; | |
} | |
jQuery.extend({ | |
queue: function( elem, type, data ) { | |
if ( !elem ) { | |
return; | |
} | |
type = (type || "fx") + "queue"; | |
var q = jQuery.data( elem, type ); | |
// Speed up dequeue by getting out quickly if this is just a lookup | |
if ( !data ) { | |
return q || []; | |
} | |
if ( !q || jQuery.isArray(data) ) { | |
q = jQuery.data( elem, type, jQuery.makeArray(data) ); | |
} else { | |
q.push( data ); | |
} | |
return q; | |
}, | |
dequeue: function( elem, type ) { | |
type = type || "fx"; | |
var queue = jQuery.queue( elem, type ), | |
fn = queue.shift(); | |
// If the fx queue is dequeued, always remove the progress sentinel | |
if ( fn === "inprogress" ) { | |
fn = queue.shift(); | |
} | |
if ( fn ) { | |
// Add a progress sentinel to prevent the fx queue from being | |
// automatically dequeued | |
if ( type === "fx" ) { | |
queue.unshift("inprogress"); | |
} | |
fn.call(elem, function() { | |
jQuery.dequeue(elem, type); | |
}); | |
} | |
} | |
}); | |
jQuery.fn.extend({ | |
queue: function( type, data ) { | |
if ( typeof type !== "string" ) { | |
data = type; | |
type = "fx"; | |
} | |
if ( data === undefined ) { | |
return jQuery.queue( this[0], type ); | |
} | |
return this.each(function( i ) { | |
var queue = jQuery.queue( this, type, data ); | |
if ( type === "fx" && queue[0] !== "inprogress" ) { | |
jQuery.dequeue( this, type ); | |
} | |
}); | |
}, | |
dequeue: function( type ) { | |
return this.each(function() { | |
jQuery.dequeue( this, type ); | |
}); | |
}, | |
// Based off of the plugin by Clint Helfers, with permission. | |
// http://blindsignals.com/index.php/2009/07/jquery-delay/ | |
delay: function( time, type ) { | |
time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; | |
type = type || "fx"; | |
return this.queue( type, function() { | |
var elem = this; | |
setTimeout(function() { | |
jQuery.dequeue( elem, type ); | |
}, time ); | |
}); | |
}, | |
clearQueue: function( type ) { | |
return this.queue( type || "fx", [] ); | |
} | |
}); | |
var rclass = /[\n\t]/g, | |
rspaces = /\s+/, | |
rreturn = /\r/g, | |
rspecialurl = /^(?:href|src|style)$/, | |
rtype = /^(?:button|input)$/i, | |
rfocusable = /^(?:button|input|object|select|textarea)$/i, | |
rclickable = /^a(?:rea)?$/i, | |
rradiocheck = /^(?:radio|checkbox)$/i; | |
jQuery.props = { | |
"for": "htmlFor", | |
"class": "className", | |
readonly: "readOnly", | |
maxlength: "maxLength", | |
cellspacing: "cellSpacing", | |
rowspan: "rowSpan", | |
colspan: "colSpan", | |
tabindex: "tabIndex", | |
usemap: "useMap", | |
frameborder: "frameBorder" | |
}; | |
jQuery.fn.extend({ | |
attr: function( name, value ) { | |
return jQuery.access( this, name, value, true, jQuery.attr ); | |
}, | |
removeAttr: function( name, fn ) { | |
return this.each(function(){ | |
jQuery.attr( this, name, "" ); | |
if ( this.nodeType === 1 ) { | |
this.removeAttribute( name ); | |
} | |
}); | |
}, | |
addClass: function( value ) { | |
if ( jQuery.isFunction(value) ) { | |
return this.each(function(i) { | |
var self = jQuery(this); | |
self.addClass( value.call(this, i, self.attr("class")) ); | |
}); | |
} | |
if ( value && typeof value === "string" ) { | |
var classNames = (value || "").split( rspaces ); | |
for ( var i = 0, l = this.length; i < l; i++ ) { | |
var elem = this[i]; | |
if ( elem.nodeType === 1 ) { | |
if ( !elem.className ) { | |
elem.className = value; | |
} else { | |
var className = " " + elem.className + " ", | |
setClass = elem.className; | |
for ( var c = 0, cl = classNames.length; c < cl; c++ ) { | |
if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { | |
setClass += " " + classNames[c]; | |
} | |
} | |
elem.className = jQuery.trim( setClass ); | |
} | |
} | |
} | |
} | |
return this; | |
}, | |
removeClass: function( value ) { | |
if ( jQuery.isFunction(value) ) { | |
return this.each(function(i) { | |
var self = jQuery(this); | |
self.removeClass( value.call(this, i, self.attr("class")) ); | |
}); | |
} | |
if ( (value && typeof value === "string") || value === undefined ) { | |
var classNames = (value || "").split( rspaces ); | |
for ( var i = 0, l = this.length; i < l; i++ ) { | |
var elem = this[i]; | |
if ( elem.nodeType === 1 && elem.className ) { | |
if ( value ) { | |
var className = (" " + elem.className + " ").replace(rclass, " "); | |
for ( var c = 0, cl = classNames.length; c < cl; c++ ) { | |
className = className.replace(" " + classNames[c] + " ", " "); | |
} | |
elem.className = jQuery.trim( className ); | |
} else { | |
elem.className = ""; | |
} | |
} | |
} | |
} | |
return this; | |
}, | |
toggleClass: function( value, stateVal ) { | |
var type = typeof value, | |
isBool = typeof stateVal === "boolean"; | |
if ( jQuery.isFunction( value ) ) { | |
return this.each(function(i) { | |
var self = jQuery(this); | |
self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); | |
}); | |
} | |
return this.each(function() { | |
if ( type === "string" ) { | |
// toggle individual class names | |
var className, | |
i = 0, | |
self = jQuery( this ), | |
state = stateVal, | |
classNames = value.split( rspaces ); | |
while ( (className = classNames[ i++ ]) ) { | |
// check each className given, space seperated list | |
state = isBool ? state : !self.hasClass( className ); | |
self[ state ? "addClass" : "removeClass" ]( className ); | |
} | |
} else if ( type === "undefined" || type === "boolean" ) { | |
if ( this.className ) { | |
// store className if set | |
jQuery.data( this, "__className__", this.className ); | |
} | |
// toggle whole className | |
this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; | |
} | |
}); | |
}, | |
hasClass: function( selector ) { | |
var className = " " + selector + " "; | |
for ( var i = 0, l = this.length; i < l; i++ ) { | |
if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { | |
return true; | |
} | |
} | |
return false; | |
}, | |
val: function( value ) { | |
if ( !arguments.length ) { | |
var elem = this[0]; | |
if ( elem ) { | |
if ( jQuery.nodeName( elem, "option" ) ) { | |
// attributes.value is undefined in Blackberry 4.7 but | |
// uses .value. See #6932 | |
var val = elem.attributes.value; | |
return !val || val.specified ? elem.value : elem.text; | |
} | |
// We need to handle select boxes special | |
if ( jQuery.nodeName( elem, "select" ) ) { | |
var index = elem.selectedIndex, | |
values = [], | |
options = elem.options, | |
one = elem.type === "select-one"; | |
// Nothing was selected | |
if ( index < 0 ) { | |
return null; | |
} | |
// Loop through all the selected options | |
for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { | |
var option = options[ i ]; | |
// Don't return options that are disabled or in a disabled optgroup | |
if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && | |
(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { | |
// Get the specific value for the option | |
value = jQuery(option).val(); | |
// We don't need an array for one selects | |
if ( one ) { | |
return value; | |
} | |
// Multi-Selects return an array | |
values.push( value ); | |
} | |
} | |
return values; | |
} | |
// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified | |
if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { | |
return elem.getAttribute("value") === null ? "on" : elem.value; | |
} | |
// Everything else, we just grab the value | |
return (elem.value || "").replace(rreturn, ""); | |
} | |
return undefined; | |
} | |
var isFunction = jQuery.isFunction(value); | |
return this.each(function(i) { | |
var self = jQuery(this), val = value; | |
if ( this.nodeType !== 1 ) { | |
return; | |
} | |
if ( isFunction ) { | |
val = value.call(this, i, self.val()); | |
} | |
// Treat null/undefined as ""; convert numbers to string | |
if ( val == null ) { | |
val = ""; | |
} else if ( typeof val === "number" ) { | |
val += ""; | |
} else if ( jQuery.isArray(val) ) { | |
val = jQuery.map(val, function (value) { | |
return value == null ? "" : value + ""; | |
}); | |
} | |
if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { | |
this.checked = jQuery.inArray( self.val(), val ) >= 0; | |
} else if ( jQuery.nodeName( this, "select" ) ) { | |
var values = jQuery.makeArray(val); | |
jQuery( "option", this ).each(function() { | |
this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; | |
}); | |
if ( !values.length ) { | |
this.selectedIndex = -1; | |
} | |
} else { | |
this.value = val; | |
} | |
}); | |
} | |
}); | |
jQuery.extend({ | |
attrFn: { | |
val: true, | |
css: true, | |
html: true, | |
text: true, | |
data: true, | |
width: true, | |
height: true, | |
offset: true | |
}, | |
attr: function( elem, name, value, pass ) { | |
// don't set attributes on text and comment nodes | |
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { | |
return undefined; | |
} | |
if ( pass && name in jQuery.attrFn ) { | |
return jQuery(elem)[name](value); | |
} | |
var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), | |
// Whether we are setting (or getting) | |
set = value !== undefined; | |
// Try to normalize/fix the name | |
name = notxml && jQuery.props[ name ] || name; | |
// These attributes require special treatment | |
var special = rspecialurl.test( name ); | |
// Safari mis-reports the default selected property of an option | |
// Accessing the parent's selectedIndex property fixes it | |
if ( name === "selected" && !jQuery.support.optSelected ) { | |
var parent = elem.parentNode; | |
if ( parent ) { | |
parent.selectedIndex; | |
// Make sure that it also works with optgroups, see #5701 | |
if ( parent.parentNode ) { | |
parent.parentNode.selectedIndex; | |
} | |
} | |
} | |
// If applicable, access the attribute via the DOM 0 way | |
// 'in' checks fail in Blackberry 4.7 #6931 | |
if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { | |
if ( set ) { | |
// We can't allow the type property to be changed (since it causes problems in IE) | |
if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { | |
jQuery.error( "type property can't be changed" ); | |
} | |
if ( value === null ) { | |
if ( elem.nodeType === 1 ) { | |
elem.removeAttribute( name ); | |
} | |
} else { | |
elem[ name ] = value; | |
} | |
} | |
// browsers index elements by id/name on forms, give priority to attributes. | |
if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { | |
return elem.getAttributeNode( name ).nodeValue; | |
} | |
// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set | |
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ | |
if ( name === "tabIndex" ) { | |
var attributeNode = elem.getAttributeNode( "tabIndex" ); | |
return attributeNode && attributeNode.specified ? | |
attributeNode.value : | |
rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? | |
0 : | |
undefined; | |
} | |
return elem[ name ]; | |
} | |
if ( !jQuery.support.style && notxml && name === "style" ) { | |
if ( set ) { | |
elem.style.cssText = "" + value; | |
} | |
return elem.style.cssText; | |
} | |
if ( set ) { | |
// convert the value to a string (all browsers do this but IE) see #1070 | |
elem.setAttribute( name, "" + value ); | |
} | |
// Ensure that missing attributes return undefined | |
// Blackberry 4.7 returns "" from getAttribute #6938 | |
if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { | |
return undefined; | |
} | |
var attr = !jQuery.support.hrefNormalized && notxml && special ? | |
// Some attributes require a special call on IE | |
elem.getAttribute( name, 2 ) : | |
elem.getAttribute( name ); | |
// Non-existent attributes return null, we normalize to undefined | |
return attr === null ? undefined : attr; | |
} | |
}); | |
var rnamespaces = /\.(.*)$/, | |
rformElems = /^(?:textarea|input|select)$/i, | |
rperiod = /\./g, | |
rspace = / /g, | |
rescape = /[^\w\s.|`]/g, | |
fcleanup = function( nm ) { | |
return nm.replace(rescape, "\\$&"); | |
}, | |
focusCounts = { focusin: 0, focusout: 0 }; | |
/* | |
* A number of helper functions used for managing events. | |
* Many of the ideas behind this code originated from | |
* Dean Edwards' addEvent library. | |
*/ | |
jQuery.event = { | |
// Bind an event to an element | |
// Original by Dean Edwards | |
add: function( elem, types, handler, data ) { | |
if ( elem.nodeType === 3 || elem.nodeType === 8 ) { | |
return; | |
} | |
// For whatever reason, IE has trouble passing the window object | |
// around, causing it to be cloned in the process | |
if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { | |
elem = window; | |
} | |
if ( handler === false ) { | |
handler = returnFalse; | |
} else if ( !handler ) { | |
// Fixes bug #7229. Fix recommended by jdalton | |
return; | |
} | |
var handleObjIn, handleObj; | |
if ( handler.handler ) { | |
handleObjIn = handler; | |
handler = handleObjIn.handler; | |
} | |
// Make sure that the function being executed has a unique ID | |
if ( !handler.guid ) { | |
handler.guid = jQuery.guid++; | |
} | |
// Init the element's event structure | |
var elemData = jQuery.data( elem ); | |
// If no elemData is found then we must be trying to bind to one of the | |
// banned noData elements | |
if ( !elemData ) { | |
return; | |
} | |
// Use a key less likely to result in collisions for plain JS objects. | |
// Fixes bug #7150. | |
var eventKey = elem.nodeType ? "events" : "__events__", | |
events = elemData[ eventKey ], | |
eventHandle = elemData.handle; | |
if ( typeof events === "function" ) { | |
// On plain objects events is a fn that holds the the data | |
// which prevents this data from being JSON serialized | |
// the function does not need to be called, it just contains the data | |
eventHandle = events.handle; | |
events = events.events; | |
} else if ( !events ) { | |
if ( !elem.nodeType ) { | |
// On plain objects, create a fn that acts as the holder | |
// of the values to avoid JSON serialization of event data | |
elemData[ eventKey ] = elemData = function(){}; | |
} | |
elemData.events = events = {}; | |
} | |
if ( !eventHandle ) { | |
elemData.handle = eventHandle = function() { | |
// Handle the second event of a trigger and when | |
// an event is called after a page has unloaded | |
return typeof jQuery !== "undefined" && !jQuery.event.triggered ? | |
jQuery.event.handle.apply( eventHandle.elem, arguments ) : | |
undefined; | |
}; | |
} | |
// Add elem as a property of the handle function | |
// This is to prevent a memory leak with non-native events in IE. | |
eventHandle.elem = elem; | |
// Handle multiple events separated by a space | |
// jQuery(...).bind("mouseover mouseout", fn); | |
types = types.split(" "); | |
var type, i = 0, namespaces; | |
while ( (type = types[ i++ ]) ) { | |
handleObj = handleObjIn ? | |
jQuery.extend({}, handleObjIn) : | |
{ handler: handler, data: data }; | |
// Namespaced event handlers | |
if ( type.indexOf(".") > -1 ) { | |
namespaces = type.split("."); | |
type = namespaces.shift(); | |
handleObj.namespace = namespaces.slice(0).sort().join("."); | |
} else { | |
namespaces = []; | |
handleObj.namespace = ""; | |
} | |
handleObj.type = type; | |
if ( !handleObj.guid ) { | |
handleObj.guid = handler.guid; | |
} | |
// Get the current list of functions bound to this event | |
var handlers = events[ type ], | |
special = jQuery.event.special[ type ] || {}; | |
// Init the event handler queue | |
if ( !handlers ) { | |
handlers = events[ type ] = []; | |
// Check for a special event handler | |
// Only use addEventListener/attachEvent if the special | |
// events handler returns false | |
if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { | |
// Bind the global event handler to the element | |
if ( elem.addEventListener ) { | |
elem.addEventListener( type, eventHandle, false ); | |
} else if ( elem.attachEvent ) { | |
elem.attachEvent( "on" + type, eventHandle ); | |
} | |
} | |
} | |
if ( special.add ) { | |
special.add.call( elem, handleObj ); | |
if ( !handleObj.handler.guid ) { | |
handleObj.handler.guid = handler.guid; | |
} | |
} | |
// Add the function to the element's handler list | |
handlers.push( handleObj ); | |
// Keep track of which events have been used, for global triggering | |
jQuery.event.global[ type ] = true; | |
} | |
// Nullify elem to prevent memory leaks in IE | |
elem = null; | |
}, | |
global: {}, | |
// Detach an event or set of events from an element | |
remove: function( elem, types, handler, pos ) { | |
// don't do events on text and comment nodes | |
if ( elem.nodeType === 3 || elem.nodeType === 8 ) { | |
return; | |
} | |
if ( handler === false ) { | |
handler = returnFalse; | |
} | |
var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, | |
eventKey = elem.nodeType ? "events" : "__events__", | |
elemData = jQuery.data( elem ), | |
events = elemData && elemData[ eventKey ]; | |
if ( !elemData || !events ) { | |
return; | |
} | |
if ( typeof events === "function" ) { | |
elemData = events; | |
events = events.events; | |
} | |
// types is actually an event object here | |
if ( types && types.type ) { | |
handler = types.handler; | |
types = types.type; | |
} | |
// Unbind all events for the element | |
if ( !types || typeof types === "string" && types.charAt(0) === "." ) { | |
types = types || ""; | |
for ( type in events ) { | |
jQuery.event.remove( elem, type + types ); | |
} | |
return; | |
} | |
// Handle multiple events separated by a space | |
// jQuery(...).unbind("mouseover mouseout", fn); | |
types = types.split(" "); | |
while ( (type = types[ i++ ]) ) { | |
origType = type; | |
handleObj = null; | |
all = type.indexOf(".") < 0; | |
namespaces = []; | |
if ( !all ) { | |
// Namespaced event handlers | |
namespaces = type.split("."); | |
type = namespaces.shift(); | |
namespace = new RegExp("(^|\\.)" + | |
jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); | |
} | |
eventType = events[ type ]; | |
if ( !eventType ) { | |
continue; | |
} | |
if ( !handler ) { | |
for ( j = 0; j < eventType.length; j++ ) { | |
handleObj = eventType[ j ]; | |
if ( all || namespace.test( handleObj.namespace ) ) { | |
jQuery.event.remove( elem, origType, handleObj.handler, j ); | |
eventType.splice( j--, 1 ); | |
} | |
} | |
continue; | |
} | |
special = jQuery.event.special[ type ] || {}; | |
for ( j = pos || 0; j < eventType.length; j++ ) { | |
handleObj = eventType[ j ]; | |
if ( handler.guid === handleObj.guid ) { | |
// remove the given handler for the given type | |
if ( all || namespace.test( handleObj.namespace ) ) { | |
if ( pos == null ) { | |
eventType.splice( j--, 1 ); | |
} | |
if ( special.remove ) { | |
special.remove.call( elem, handleObj ); | |
} | |
} | |
if ( pos != null ) { | |
break; | |
} | |
} | |
} | |
// remove generic event handler if no more handlers exist | |
if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { | |
if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { | |
jQuery.removeEvent( elem, type, elemData.handle ); | |
} | |
ret = null; | |
delete events[ type ]; | |
} | |
} | |
// Remove the expando if it's no longer used | |
if ( jQuery.isEmptyObject( events ) ) { | |
var handle = elemData.handle; | |
if ( handle ) { | |
handle.elem = null; | |
} | |
delete elemData.events; | |
delete elemData.handle; | |
if ( typeof elemData === "function" ) { | |
jQuery.removeData( elem, eventKey ); | |
} else if ( jQuery.isEmptyObject( elemData ) ) { | |
jQuery.removeData( elem ); | |
} | |
} | |
}, | |
// bubbling is internal | |
trigger: function( event, data, elem /*, bubbling */ ) { | |
// Event object or event type | |
var type = event.type || event, | |
bubbling = arguments[3]; | |
if ( !bubbling ) { | |
event = typeof event === "object" ? | |
// jQuery.Event object | |
event[ jQuery.expando ] ? event : | |
// Object literal | |
jQuery.extend( jQuery.Event(type), event ) : | |
// Just the event type (string) | |
jQuery.Event(type); | |
if ( type.indexOf("!") >= 0 ) { | |
event.type = type = type.slice(0, -1); | |
event.exclusive = true; | |
} | |
// Handle a global trigger | |
if ( !elem ) { | |
// Don't bubble custom events when global (to avoid too much overhead) | |
event.stopPropagation(); | |
// Only trigger if we've ever bound an event for it | |
if ( jQuery.event.global[ type ] ) { | |
jQuery.each( jQuery.cache, function() { | |
if ( this.events && this.events[type] ) { | |
jQuery.event.trigger( event, data, this.handle.elem ); | |
} | |
}); | |
} | |
} | |
// Handle triggering a single element | |
// don't do events on text and comment nodes | |
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { | |
return undefined; | |
} | |
// Clean up in case it is reused | |
event.result = undefined; | |
event.target = elem; | |
// Clone the incoming data, if any | |
data = jQuery.makeArray( data ); | |
data.unshift( event ); | |
} | |
event.currentTarget = elem; | |
// Trigger the event, it is assumed that "handle" is a function | |
var handle = elem.nodeType ? | |
jQuery.data( elem, "handle" ) : | |
(jQuery.data( elem, "__events__" ) || {}).handle; | |
if ( handle ) { | |
handle.apply( elem, data ); | |
} | |
var parent = elem.parentNode || elem.ownerDocument; | |
// Trigger an inline bound script | |
try { | |
if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { | |
if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { | |
event.result = false; | |
event.preventDefault(); | |
} | |
} | |
// prevent IE from throwing an error for some elements with some event types, see #3533 | |
} catch (inlineError) {} | |
if ( !event.isPropagationStopped() && parent ) { | |
jQuery.event.trigger( event, data, parent, true ); | |
} else if ( !event.isDefaultPrevented() ) { | |
var old, | |
target = event.target, | |
targetType = type.replace( rnamespaces, "" ), | |
isClick = jQuery.nodeName( target, "a" ) && targetType === "click", | |
special = jQuery.event.special[ targetType ] || {}; | |
if ( (!special._default || special._default.call( elem, event ) === false) && | |
!isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { | |
try { | |
if ( target[ targetType ] ) { | |
// Make sure that we don't accidentally re-trigger the onFOO events | |
old = target[ "on" + targetType ]; | |
if ( old ) { | |
target[ "on" + targetType ] = null; | |
} | |
jQuery.event.triggered = true; | |
target[ targetType ](); | |
} | |
// prevent IE from throwing an error for some elements with some event types, see #3533 | |
} catch (triggerError) {} | |
if ( old ) { | |
target[ "on" + targetType ] = old; | |
} | |
jQuery.event.triggered = false; | |
} | |
} | |
}, | |
handle: function( event ) { | |
var all, handlers, namespaces, namespace_re, events, | |
namespace_sort = [], | |
args = jQuery.makeArray( arguments ); | |
event = args[0] = jQuery.event.fix( event || window.event ); | |
event.currentTarget = this; | |
// Namespaced event handlers | |
all = event.type.indexOf(".") < 0 && !event.exclusive; | |
if ( !all ) { | |
namespaces = event.type.split("."); | |
event.type = namespaces.shift(); | |
namespace_sort = namespaces.slice(0).sort(); | |
namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)"); | |
} | |
event.namespace = event.namespace || namespace_sort.join("."); | |
events = jQuery.data(this, this.nodeType ? "events" : "__events__"); | |
if ( typeof events === "function" ) { | |
events = events.events; | |
} | |
handlers = (events || {})[ event.type ]; | |
if ( events && handlers ) { | |
// Clone the handlers to prevent manipulation | |
handlers = handlers.slice(0); | |
for ( var j = 0, l = handlers.length; j < l; j++ ) { | |
var handleObj = handlers[ j ]; | |
// Filter the functions by class | |
if ( all || namespace_re.test( handleObj.namespace ) ) { | |
// Pass in a reference to the handler function itself | |
// So that we can later remove it | |
event.handler = handleObj.handler; | |
event.data = handleObj.data; | |
event.handleObj = handleObj; | |
var ret = handleObj.handler.apply( this, args ); | |
if ( ret !== undefined ) { | |
event.result = ret; | |
if ( ret === false ) { | |
event.preventDefault(); | |
event.stopPropagation(); | |
} | |
} | |
if ( event.isImmediatePropagationStopped() ) { | |
break; | |
} | |
} | |
} | |
} | |
return event.result; | |
}, | |
props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), | |
fix: function( event ) { | |
if ( event[ jQuery.expando ] ) { | |
return event; | |
} | |
// store a copy of the original event object | |
// and "clone" to set read-only properties | |
var originalEvent = event; | |
event = jQuery.Event( originalEvent ); | |
for ( var i = this.props.length, prop; i; ) { | |
prop = this.props[ --i ]; | |
event[ prop ] = originalEvent[ prop ]; | |
} | |
// Fix target property, if necessary | |
if ( !event.target ) { | |
// Fixes #1925 where srcElement might not be defined either | |
event.target = event.srcElement || document; | |
} | |
// check if target is a textnode (safari) | |
if ( event.target.nodeType === 3 ) { | |
event.target = event.target.parentNode; | |
} | |
// Add relatedTarget, if necessary | |
if ( !event.relatedTarget && event.fromElement ) { | |
event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; | |
} | |
// Calculate pageX/Y if missing and clientX/Y available | |
if ( event.pageX == null && event.clientX != null ) { | |
var doc = document.documentElement, | |
body = document.body; | |
event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); | |
event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); | |
} | |
// Add which for key events | |
if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { | |
event.which = event.charCode != null ? event.charCode : event.keyCode; | |
} | |
// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) | |
if ( !event.metaKey && event.ctrlKey ) { | |
event.metaKey = event.ctrlKey; | |
} | |
// Add which for click: 1 === left; 2 === middle; 3 === right | |
// Note: button is not normalized, so don't use it | |
if ( !event.which && event.button !== undefined ) { | |
event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); | |
} | |
return event; | |
}, | |
// Deprecated, use jQuery.guid instead | |
guid: 1E8, | |
// Deprecated, use jQuery.proxy instead | |
proxy: jQuery.proxy, | |
special: { | |
ready: { | |
// Make sure the ready event is setup | |
setup: jQuery.bindReady, | |
teardown: jQuery.noop | |
}, | |
live: { | |
add: function( handleObj ) { | |
jQuery.event.add( this, | |
liveConvert( handleObj.origType, handleObj.selector ), | |
jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); | |
}, | |
remove: function( handleObj ) { | |
jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); | |
} | |
}, | |
beforeunload: { | |
setup: function( data, namespaces, eventHandle ) { | |
// We only want to do this special case on windows | |
if ( jQuery.isWindow( this ) ) { | |
this.onbeforeunload = eventHandle; | |
} | |
}, | |
teardown: function( namespaces, eventHandle ) { | |
if ( this.onbeforeunload === eventHandle ) { | |
this.onbeforeunload = null; | |
} | |
} | |
} | |
} | |
}; | |
jQuery.removeEvent = document.removeEventListener ? | |
function( elem, type, handle ) { | |
if ( elem.removeEventListener ) { | |
elem.removeEventListener( type, handle, false ); | |
} | |
} : | |
function( elem, type, handle ) { | |
if ( elem.detachEvent ) { | |
elem.detachEvent( "on" + type, handle ); | |
} | |
}; | |
jQuery.Event = function( src ) { | |
// Allow instantiation without the 'new' keyword | |
if ( !this.preventDefault ) { | |
return new jQuery.Event( src ); | |
} | |
// Event object | |
if ( src && src.type ) { | |
this.originalEvent = src; | |
this.type = src.type; | |
// Event type | |
} else { | |
this.type = src; | |
} | |
// timeStamp is buggy for some events on Firefox(#3843) | |
// So we won't rely on the native value | |
this.timeStamp = jQuery.now(); | |
// Mark it as fixed | |
this[ jQuery.expando ] = true; | |
}; | |
function returnFalse() { | |
return false; | |
} | |
function returnTrue() { | |
return true; | |
} | |
// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding | |
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html | |
jQuery.Event.prototype = { | |
preventDefault: function() { | |
this.isDefaultPrevented = returnTrue; | |
var e = this.originalEvent; | |
if ( !e ) { | |
return; | |
} | |
// if preventDefault exists run it on the original event | |
if ( e.preventDefault ) { | |
e.preventDefault(); | |
// otherwise set the returnValue property of the original event to false (IE) | |
} else { | |
e.returnValue = false; | |
} | |
}, | |
stopPropagation: function() { | |
this.isPropagationStopped = returnTrue; | |
var e = this.originalEvent; | |
if ( !e ) { | |
return; | |
} | |
// if stopPropagation exists run it on the original event | |
if ( e.stopPropagation ) { | |
e.stopPropagation(); | |
} | |
// otherwise set the cancelBubble property of the original event to true (IE) | |
e.cancelBubble = true; | |
}, | |
stopImmediatePropagation: function() { | |
this.isImmediatePropagationStopped = returnTrue; | |
this.stopPropagation(); | |
}, | |
isDefaultPrevented: returnFalse, | |
isPropagationStopped: returnFalse, | |
isImmediatePropagationStopped: returnFalse | |
}; | |
// Checks if an event happened on an element within another element | |
// Used in jQuery.event.special.mouseenter and mouseleave handlers | |
var withinElement = function( event ) { | |
// Check if mouse(over|out) are still within the same parent element | |
var parent = event.relatedTarget; | |
// Firefox sometimes assigns relatedTarget a XUL element | |
// which we cannot access the parentNode property of | |
try { | |
// Traverse up the tree | |
while ( parent && parent !== this ) { | |
parent = parent.parentNode; | |
} | |
if ( parent !== this ) { | |
// set the correct event type | |
event.type = event.data; | |
// handle event if we actually just moused on to a non sub-element | |
jQuery.event.handle.apply( this, arguments ); | |
} | |
// assuming we've left the element since we most likely mousedover a xul element | |
} catch(e) { } | |
}, | |
// In case of event delegation, we only need to rename the event.type, | |
// liveHandler will take care of the rest. | |
delegate = function( event ) { | |
event.type = event.data; | |
jQuery.event.handle.apply( this, arguments ); | |
}; | |
// Create mouseenter and mouseleave events | |
jQuery.each({ | |
mouseenter: "mouseover", | |
mouseleave: "mouseout" | |
}, function( orig, fix ) { | |
jQuery.event.special[ orig ] = { | |
setup: function( data ) { | |
jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); | |
}, | |
teardown: function( data ) { | |
jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); | |
} | |
}; | |
}); | |
// submit delegation | |
if ( !jQuery.support.submitBubbles ) { | |
jQuery.event.special.submit = { | |
setup: function( data, namespaces ) { | |
if ( this.nodeName.toLowerCase() !== "form" ) { | |
jQuery.event.add(this, "click.specialSubmit", function( e ) { | |
var elem = e.target, | |
type = elem.type; | |
if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { | |
e.liveFired = undefined; | |
return trigger( "submit", this, arguments ); | |
} | |
}); | |
jQuery.event.add(this, "keypress.specialSubmit", function( e ) { | |
var elem = e.target, | |
type = elem.type; | |
if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { | |
e.liveFired = undefined; | |
return trigger( "submit", this, arguments ); | |
} | |
}); | |
} else { | |
return false; | |
} | |
}, | |
teardown: function( namespaces ) { | |
jQuery.event.remove( this, ".specialSubmit" ); | |
} | |
}; | |
} | |
// change delegation, happens here so we have bind. | |
if ( !jQuery.support.changeBubbles ) { | |
var changeFilters, | |
getVal = function( elem ) { | |
var type = elem.type, val = elem.value; | |
if ( type === "radio" || type === "checkbox" ) { | |
val = elem.checked; | |
} else if ( type === "select-multiple" ) { | |
val = elem.selectedIndex > -1 ? | |
jQuery.map( elem.options, function( elem ) { | |
return elem.selected; | |
}).join("-") : | |
""; | |
} else if ( elem.nodeName.toLowerCase() === "select" ) { | |
val = elem.selectedIndex; | |
} | |
return val; | |
}, | |
testChange = function testChange( e ) { | |
var elem = e.target, data, val; | |
if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { | |
return; | |
} | |
data = jQuery.data( elem, "_change_data" ); | |
val = getVal(elem); | |
// the current data will be also retrieved by beforeactivate | |
if ( e.type !== "focusout" || elem.type !== "radio" ) { | |
jQuery.data( elem, "_change_data", val ); | |
} | |
if ( data === undefined || val === data ) { | |
return; | |
} | |
if ( data != null || val ) { | |
e.type = "change"; | |
e.liveFired = undefined; | |
return jQuery.event.trigger( e, arguments[1], elem ); | |
} | |
}; | |
jQuery.event.special.change = { | |
filters: { | |
focusout: testChange, | |
beforedeactivate: testChange, | |
click: function( e ) { | |
var elem = e.target, type = elem.type; | |
if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { | |
return testChange.call( this, e ); | |
} | |
}, | |
// Change has to be called before submit | |
// Keydown will be called before keypress, which is used in submit-event delegation | |
keydown: function( e ) { | |
var elem = e.target, type = elem.type; | |
if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || | |
(e.keyCode === 32 && (type === "checkbox" || type === "radio")) || | |
type === "select-multiple" ) { | |
return testChange.call( this, e ); | |
} | |
}, | |
// Beforeactivate happens also before the previous element is blurred | |
// with this event you can't trigger a change event, but you can store | |
// information | |
beforeactivate: function( e ) { | |
var elem = e.target; | |
jQuery.data( elem, "_change_data", getVal(elem) ); | |
} | |
}, | |
setup: function( data, namespaces ) { | |
if ( this.type === "file" ) { | |
return false; | |
} | |
for ( var type in changeFilters ) { | |
jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); | |
} | |
return rformElems.test( this.nodeName ); | |
}, | |
teardown: function( namespaces ) { | |
jQuery.event.remove( this, ".specialChange" ); | |
return rformElems.test( this.nodeName ); | |
} | |
}; | |
changeFilters = jQuery.event.special.change.filters; | |
// Handle when the input is .focus()'d | |
changeFilters.focus = changeFilters.beforeactivate; | |
} | |
function trigger( type, elem, args ) { | |
args[0].type = type; | |
return jQuery.event.handle.apply( elem, args ); | |
} | |
// Create "bubbling" focus and blur events | |
if ( document.addEventListener ) { | |
jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { | |
jQuery.event.special[ fix ] = { | |
setup: function() { | |
if ( focusCounts[fix]++ === 0 ) { | |
document.addEventListener( orig, handler, true ); | |
} | |
}, | |
teardown: function() { | |
if ( --focusCounts[fix] === 0 ) { | |
document.removeEventListener( orig, handler, true ); | |
} | |
} | |
}; | |
function handler( e ) { | |
e = jQuery.event.fix( e ); | |
e.type = fix; | |
return jQuery.event.trigger( e, null, e.target ); | |
} | |
}); | |
} | |
jQuery.each(["bind", "one"], function( i, name ) { | |
jQuery.fn[ name ] = function( type, data, fn ) { | |
// Handle object literals | |
if ( typeof type === "object" ) { | |
for ( var key in type ) { | |
this[ name ](key, data, type[key], fn); | |
} | |
return this; | |
} | |
if ( jQuery.isFunction( data ) || data === false ) { | |
fn = data; | |
data = undefined; | |
} | |
var handler = name === "one" ? jQuery.proxy( fn, function( event ) { | |
jQuery( this ).unbind( event, handler ); | |
return fn.apply( this, arguments ); | |
}) : fn; | |
if ( type === "unload" && name !== "one" ) { | |
this.one( type, data, fn ); | |
} else { | |
for ( var i = 0, l = this.length; i < l; i++ ) { | |
jQuery.event.add( this[i], type, handler, data ); | |
} | |
} | |
return this; | |
}; | |
}); | |
jQuery.fn.extend({ | |
unbind: function( type, fn ) { | |
// Handle object literals | |
if ( typeof type === "object" && !type.preventDefault ) { | |
for ( var key in type ) { | |
this.unbind(key, type[key]); | |
} | |
} else { | |
for ( var i = 0, l = this.length; i < l; i++ ) { | |
jQuery.event.remove( this[i], type, fn ); | |
} | |
} | |
return this; | |
}, | |
delegate: function( selector, types, data, fn ) { | |
return this.live( types, data, fn, selector ); | |
}, | |
undelegate: function( selector, types, fn ) { | |
if ( arguments.length === 0 ) { | |
return this.unbind( "live" ); | |
} else { | |
return this.die( types, null, fn, selector ); | |
} | |
}, | |
trigger: function( type, data ) { | |
return this.each(function() { | |
jQuery.event.trigger( type, data, this ); | |
}); | |
}, | |
triggerHandler: function( type, data ) { | |
if ( this[0] ) { | |
var event = jQuery.Event( type ); | |
event.preventDefault(); | |
event.stopPropagation(); | |
jQuery.event.trigger( event, data, this[0] ); | |
return event.result; | |
} | |
}, | |
toggle: function( fn ) { | |
// Save reference to arguments for access in closure | |
var args = arguments, | |
i = 1; | |
// link all the functions, so any of them can unbind this click handler | |
while ( i < args.length ) { | |
jQuery.proxy( fn, args[ i++ ] ); | |
} | |
return this.click( jQuery.proxy( fn, function( event ) { | |
// Figure out which function to execute | |
var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; | |
jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); | |
// Make sure that clicks stop | |
event.preventDefault(); | |
// and execute the function | |
return args[ lastToggle ].apply( this, arguments ) || false; | |
})); | |
}, | |
hover: function( fnOver, fnOut ) { | |
return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); | |
} | |
}); | |
var liveMap = { | |
focus: "focusin", | |
blur: "focusout", | |
mouseenter: "mouseover", | |
mouseleave: "mouseout" | |
}; | |
jQuery.each(["live", "die"], function( i, name ) { | |
jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { | |
var type, i = 0, match, namespaces, preType, | |
selector = origSelector || this.selector, | |
context = origSelector ? this : jQuery( this.context ); | |
if ( typeof types === "object" && !types.preventDefault ) { | |
for ( var key in types ) { | |
context[ name ]( key, data, types[key], selector ); | |
} | |
return this; | |
} | |
if ( jQuery.isFunction( data ) ) { | |
fn = data; | |
data = undefined; | |
} | |
types = (types || "").split(" "); | |
while ( (type = types[ i++ ]) != null ) { | |
match = rnamespaces.exec( type ); | |
namespaces = ""; | |
if ( match ) { | |
namespaces = match[0]; | |
type = type.replace( rnamespaces, "" ); | |
} | |
if ( type === "hover" ) { | |
types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); | |
continue; | |
} | |
preType = type; | |
if ( type === "focus" || type === "blur" ) { | |
types.push( liveMap[ type ] + namespaces ); | |
type = type + namespaces; | |
} else { | |
type = (liveMap[ type ] || type) + namespaces; | |
} | |
if ( name === "live" ) { | |
// bind live handler | |
for ( var j = 0, l = context.length; j < l; j++ ) { | |
jQuery.event.add( context[j], "live." + liveConvert( type, selector ), | |
{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); | |
} | |
} else { | |
// unbind live handler | |
context.unbind( "live." + liveConvert( type, selector ), fn ); | |
} | |
} | |
return this; | |
}; | |
}); | |
function liveHandler( event ) { | |
var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, | |
elems = [], | |
selectors = [], | |
events = jQuery.data( this, this.nodeType ? "events" : "__events__" ); | |
if ( typeof events === "function" ) { | |
events = events.events; | |
} | |
// Make sure we avoid non-left-click bubbling in Firefox (#3861) | |
if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) { | |
return; | |
} | |
if ( event.namespace ) { | |
namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); | |
} | |
event.liveFired = this; | |
var live = events.live.slice(0); | |
for ( j = 0; j < live.length; j++ ) { | |
handleObj = live[j]; | |
if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { | |
selectors.push( handleObj.selector ); | |
} else { | |
live.splice( j--, 1 ); | |
} | |
} | |
match = jQuery( event.target ).closest( selectors, event.currentTarget ); | |
for ( i = 0, l = match.length; i < l; i++ ) { | |
close = match[i]; | |
for ( j = 0; j < live.length; j++ ) { | |
handleObj = live[j]; | |
if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) { | |
elem = close.elem; | |
related = null; | |
// Those two events require additional checking | |
if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { | |
event.type = handleObj.preType; | |
related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; | |
} | |
if ( !related || related !== elem ) { | |
elems.push({ elem: elem, handleObj: handleObj, level: close.level }); | |
} | |
} | |
} | |
} | |
for ( i = 0, l = elems.length; i < l; i++ ) { | |
match = elems[i]; | |
if ( maxLevel && match.level > maxLevel ) { | |
break; | |
} | |
event.currentTarget = match.elem; | |
event.data = match.handleObj.data; | |
event.handleObj = match.handleObj; | |
ret = match.handleObj.origHandler.apply( match.elem, arguments ); | |
if ( ret === false || event.isPropagationStopped() ) { | |
maxLevel = match.level; | |
if ( ret === false ) { | |
stop = false; | |
} | |
if ( event.isImmediatePropagationStopped() ) { | |
break; | |
} | |
} | |
} | |
return stop; | |
} | |
function liveConvert( type, selector ) { | |
return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&"); | |
} | |
jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + | |
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + | |
"change select submit keydown keypress keyup error").split(" "), function( i, name ) { | |
// Handle event binding | |
jQuery.fn[ name ] = function( data, fn ) { | |
if ( fn == null ) { | |
fn = data; | |
data = null; | |
} | |
return arguments.length > 0 ? | |
this.bind( name, data, fn ) : | |
this.trigger( name ); | |
}; | |
if ( jQuery.attrFn ) { | |
jQuery.attrFn[ name ] = true; | |
} | |
}); | |
// Prevent memory leaks in IE | |
// Window isn't included so as not to unbind existing unload events | |
// More info: | |
// - http://isaacschlueter.com/2006/10/msie-memory-leaks/ | |
if ( window.attachEvent && !window.addEventListener ) { | |
jQuery(window).bind("unload", function() { | |
for ( var id in jQuery.cache ) { | |
if ( jQuery.cache[ id ].handle ) { | |
// Try/Catch is to handle iframes being unloaded, see #4280 | |
try { | |
jQuery.event.remove( jQuery.cache[ id ].handle.elem ); | |
} catch(e) {} | |
} | |
} | |
}); | |
} | |
/*! | |
* Sizzle CSS Selector Engine - v1.0 | |
* Copyright 2009, The Dojo Foundation | |
* Released under the MIT, BSD, and GPL Licenses. | |
* More information: http://sizzlejs.com/ | |
*/ | |
(function(){ | |
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, | |
done = 0, | |
toString = Object.prototype.toString, | |
hasDuplicate = false, | |
baseHasDuplicate = true; | |
// Here we check if the JavaScript engine is using some sort of | |
// optimization where it does not always call our comparision | |
// function. If that is the case, discard the hasDuplicate value. | |
// Thus far that includes Google Chrome. | |
[0, 0].sort(function() { | |
baseHasDuplicate = false; | |
return 0; | |
}); | |
var Sizzle = function( selector, context, results, seed ) { | |
results = results || []; | |
context = context || document; | |
var origContext = context; | |
if ( context.nodeType !== 1 && context.nodeType !== 9 ) { | |
return []; | |
} | |
if ( !selector || typeof selector !== "string" ) { | |
return results; | |
} | |
var m, set, checkSet, extra, ret, cur, pop, i, | |
prune = true, | |
contextXML = Sizzle.isXML( context ), | |
parts = [], | |
soFar = selector; | |
// Reset the position of the chunker regexp (start from head) | |
do { | |
chunker.exec( "" ); | |
m = chunker.exec( soFar ); | |
if ( m ) { | |
soFar = m[3]; | |
parts.push( m[1] ); | |
if ( m[2] ) { | |
extra = m[3]; | |
break; | |
} | |
} | |
} while ( m ); | |
if ( parts.length > 1 && origPOS.exec( selector ) ) { | |
if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { | |
set = posProcess( parts[0] + parts[1], context ); | |
} else { | |
set = Expr.relative[ parts[0] ] ? | |
[ context ] : | |
Sizzle( parts.shift(), context ); | |
while ( parts.length ) { | |
selector = parts.shift(); | |
if ( Expr.relative[ selector ] ) { | |
selector += parts.shift(); | |
} | |
set = posProcess( selector, set ); | |
} | |
} | |
} else { | |
// Take a shortcut and set the context if the root selector is an ID | |
// (but not if it'll be faster if the inner selector is an ID) | |
if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && | |
Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { | |
ret = Sizzle.find( parts.shift(), context, contextXML ); | |
context = ret.expr ? | |
Sizzle.filter( ret.expr, ret.set )[0] : | |
ret.set[0]; | |
} | |
if ( context ) { | |
ret = seed ? | |
{ expr: parts.pop(), set: makeArray(seed) } : | |
Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); | |
set = ret.expr ? | |
Sizzle.filter( ret.expr, ret.set ) : | |
ret.set; | |
if ( parts.length > 0 ) { | |
checkSet = makeArray( set ); | |
} else { | |
prune = false; | |
} | |
while ( parts.length ) { | |
cur = parts.pop(); | |
pop = cur; | |
if ( !Expr.relative[ cur ] ) { | |
cur = ""; | |
} else { | |
pop = parts.pop(); | |
} | |
if ( pop == null ) { | |
pop = context; | |
} | |
Expr.relative[ cur ]( checkSet, pop, contextXML ); | |
} | |
} else { | |
checkSet = parts = []; | |
} | |
} | |
if ( !checkSet ) { | |
checkSet = set; | |
} | |
if ( !checkSet ) { | |
Sizzle.error( cur || selector ); | |
} | |
if ( toString.call(checkSet) === "[object Array]" ) { | |
if ( !prune ) { | |
results.push.apply( results, checkSet ); | |
} else if ( context && context.nodeType === 1 ) { | |
for ( i = 0; checkSet[i] != null; i++ ) { | |
if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { | |
results.push( set[i] ); | |
} | |
} | |
} else { | |
for ( i = 0; checkSet[i] != null; i++ ) { | |
if ( checkSet[i] && checkSet[i].nodeType === 1 ) { | |
results.push( set[i] ); | |
} | |
} | |
} | |
} else { | |
makeArray( checkSet, results ); | |
} | |
if ( extra ) { | |
Sizzle( extra, origContext, results, seed ); | |
Sizzle.uniqueSort( results ); | |
} | |
return results; | |
}; | |
Sizzle.uniqueSort = function( results ) { | |
if ( sortOrder ) { | |
hasDuplicate = baseHasDuplicate; | |
results.sort( sortOrder ); | |
if ( hasDuplicate ) { | |
for ( var i = 1; i < results.length; i++ ) { | |
if ( results[i] === results[ i - 1 ] ) { | |
results.splice( i--, 1 ); | |
} | |
} | |
} | |
} | |
return results; | |
}; | |
Sizzle.matches = function( expr, set ) { | |
return Sizzle( expr, null, null, set ); | |
}; | |
Sizzle.matchesSelector = function( node, expr ) { | |
return Sizzle( expr, null, null, [node] ).length > 0; | |
}; | |
Sizzle.find = function( expr, context, isXML ) { | |
var set; | |
if ( !expr ) { | |
return []; | |
} | |
for ( var i = 0, l = Expr.order.length; i < l; i++ ) { | |
var match, | |
type = Expr.order[i]; | |
if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { | |
var left = match[1]; | |
match.splice( 1, 1 ); | |
if ( left.substr( left.length - 1 ) !== "\\" ) { | |
match[1] = (match[1] || "").replace(/\\/g, ""); | |
set = Expr.find[ type ]( match, context, isXML ); | |
if ( set != null ) { | |
expr = expr.replace( Expr.match[ type ], "" ); | |
break; | |
} | |
} | |
} | |
} | |
if ( !set ) { | |
set = context.getElementsByTagName( "*" ); | |
} | |
return { set: set, expr: expr }; | |
}; | |
Sizzle.filter = function( expr, set, inplace, not ) { | |
var match, anyFound, | |
old = expr, | |
result = [], | |
curLoop = set, | |
isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); | |
while ( expr && set.length ) { | |
for ( var type in Expr.filter ) { | |
if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { | |
var found, item, | |
filter = Expr.filter[ type ], | |
left = match[1]; | |
anyFound = false; | |
match.splice(1,1); | |
if ( left.substr( left.length - 1 ) === "\\" ) { | |
continue; | |
} | |
if ( curLoop === result ) { | |
result = []; | |
} | |
if ( Expr.preFilter[ type ] ) { | |
match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); | |
if ( !match ) { | |
anyFound = found = true; | |
} else if ( match === true ) { | |
continue; | |
} | |
} | |
if ( match ) { | |
for ( var i = 0; (item = curLoop[i]) != null; i++ ) { | |
if ( item ) { | |
found = filter( item, match, i, curLoop ); | |
var pass = not ^ !!found; | |
if ( inplace && found != null ) { | |
if ( pass ) { | |
anyFound = true; | |
} else { | |
curLoop[i] = false; | |
} | |
} else if ( pass ) { | |
result.push( item ); | |
anyFound = true; | |
} | |
} | |
} | |
} | |
if ( found !== undefined ) { | |
if ( !inplace ) { | |
curLoop = result; | |
} | |
expr = expr.replace( Expr.match[ type ], "" ); | |
if ( !anyFound ) { | |
return []; | |
} | |
break; | |
} | |
} | |
} | |
// Improper expression | |
if ( expr === old ) { | |
if ( anyFound == null ) { | |
Sizzle.error( expr ); | |
} else { | |
break; | |
} | |
} | |
old = expr; | |
} | |
return curLoop; | |
}; | |
Sizzle.error = function( msg ) { | |
throw "Syntax error, unrecognized expression: " + msg; | |
}; | |
var Expr = Sizzle.selectors = { | |
order: [ "ID", "NAME", "TAG" ], | |
match: { | |
ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, | |
CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, | |
NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, | |
ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, | |
TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, | |
CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/, | |
POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, | |
PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ | |
}, | |
leftMatch: {}, | |
attrMap: { | |
"class": "className", | |
"for": "htmlFor" | |
}, | |
attrHandle: { | |
href: function( elem ) { | |
return elem.getAttribute( "href" ); | |
} | |
}, | |
relative: { | |
"+": function(checkSet, part){ | |
var isPartStr = typeof part === "string", | |
isTag = isPartStr && !/\W/.test( part ), | |
isPartStrNotTag = isPartStr && !isTag; | |
if ( isTag ) { | |
part = part.toLowerCase(); | |
} | |
for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { | |
if ( (elem = checkSet[i]) ) { | |
while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} | |
checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? | |
elem || false : | |
elem === part; | |
} | |
} | |
if ( isPartStrNotTag ) { | |
Sizzle.filter( part, checkSet, true ); | |
} | |
}, | |
">": function( checkSet, part ) { | |
var elem, | |
isPartStr = typeof part === "string", | |
i = 0, | |
l = checkSet.length; | |
if ( isPartStr && !/\W/.test( part ) ) { | |
part = part.toLowerCase(); | |
for ( ; i < l; i++ ) { | |
elem = checkSet[i]; | |
if ( elem ) { | |
var parent = elem.parentNode; | |
checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; | |
} | |
} | |
} else { | |
for ( ; i < l; i++ ) { | |
elem = checkSet[i]; | |
if ( elem ) { | |
checkSet[i] = isPartStr ? | |
elem.parentNode : | |
elem.parentNode === part; | |
} | |
} | |
if ( isPartStr ) { | |
Sizzle.filter( part, checkSet, true ); | |
} | |
} | |
}, | |
"": function(checkSet, part, isXML){ | |
var nodeCheck, | |
doneName = done++, | |
checkFn = dirCheck; | |
if ( typeof part === "string" && !/\W/.test(part) ) { | |
part = part.toLowerCase(); | |
nodeCheck = part; | |
checkFn = dirNodeCheck; | |
} | |
checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); | |
}, | |
"~": function( checkSet, part, isXML ) { | |
var nodeCheck, | |
doneName = done++, | |
checkFn = dirCheck; | |
if ( typeof part === "string" && !/\W/.test( part ) ) { | |
part = part.toLowerCase(); | |
nodeCheck = part; | |
checkFn = dirNodeCheck; | |
} | |
checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); | |
} | |
}, | |
find: { | |
ID: function( match, context, isXML ) { | |
if ( typeof context.getElementById !== "undefined" && !isXML ) { | |
var m = context.getElementById(match[1]); | |
// Check parentNode to catch when Blackberry 4.6 returns | |
// nodes that are no longer in the document #6963 | |
return m && m.parentNode ? [m] : []; | |
} | |
}, | |
NAME: function( match, context ) { | |
if ( typeof context.getElementsByName !== "undefined" ) { | |
var ret = [], | |
results = context.getElementsByName( match[1] ); | |
for ( var i = 0, l = results.length; i < l; i++ ) { | |
if ( results[i].getAttribute("name") === match[1] ) { | |
ret.push( results[i] ); | |
} | |
} | |
return ret.length === 0 ? null : ret; | |
} | |
}, | |
TAG: function( match, context ) { | |
return context.getElementsByTagName( match[1] ); | |
} | |
}, | |
preFilter: { | |
CLASS: function( match, curLoop, inplace, result, not, isXML ) { | |
match = " " + match[1].replace(/\\/g, "") + " "; | |
if ( isXML ) { | |
return match; | |
} | |
for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { | |
if ( elem ) { | |
if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { | |
if ( !inplace ) { | |
result.push( elem ); | |
} | |
} else if ( inplace ) { | |
curLoop[i] = false; | |
} | |
} | |
} | |
return false; | |
}, | |
ID: function( match ) { | |
return match[1].replace(/\\/g, ""); | |
}, | |
TAG: function( match, curLoop ) { | |
return match[1].toLowerCase(); | |
}, | |
CHILD: function( match ) { | |
if ( match[1] === "nth" ) { | |
// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' | |
var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( | |
match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || | |
!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); | |
// calculate the numbers (first)n+(last) including if they are negative | |
match[2] = (test[1] + (test[2] || 1)) - 0; | |
match[3] = test[3] - 0; | |
} | |
// TODO: Move to normal caching system | |
match[0] = done++; | |
return match; | |
}, | |
ATTR: function( match, curLoop, inplace, result, not, isXML ) { | |
var name = match[1].replace(/\\/g, ""); | |
if ( !isXML && Expr.attrMap[name] ) { | |
match[1] = Expr.attrMap[name]; | |
} | |
if ( match[2] === "~=" ) { | |
match[4] = " " + match[4] + " "; | |
} | |
return match; | |
}, | |
PSEUDO: function( match, curLoop, inplace, result, not ) { | |
if ( match[1] === "not" ) { | |
// If we're dealing with a complex expression, or a simple one | |
if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { | |
match[3] = Sizzle(match[3], null, null, curLoop); | |
} else { | |
var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); | |
if ( !inplace ) { | |
result.push.apply( result, ret ); | |
} | |
return false; | |
} | |
} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { | |
return true; | |
} | |
return match; | |
}, | |
POS: function( match ) { | |
match.unshift( true ); | |
return match; | |
} | |
}, | |
filters: { | |
enabled: function( elem ) { | |
return elem.disabled === false && elem.type !== "hidden"; | |
}, | |
disabled: function( elem ) { | |
return elem.disabled === true; | |
}, | |
checked: function( elem ) { | |
return elem.checked === true; | |
}, | |
selected: function( elem ) { | |
// Accessing this property makes selected-by-default | |
// options in Safari work properly | |
elem.parentNode.selectedIndex; | |
return elem.selected === true; | |
}, | |
parent: function( elem ) { | |
return !!elem.firstChild; | |
}, | |
empty: function( elem ) { | |
return !elem.firstChild; | |
}, | |
has: function( elem, i, match ) { | |
return !!Sizzle( match[3], elem ).length; | |
}, | |
header: function( elem ) { | |
return (/h\d/i).test( elem.nodeName ); | |
}, | |
text: function( elem ) { | |
return "text" === elem.type; | |
}, | |
radio: function( elem ) { | |
return "radio" === elem.type; | |
}, | |
checkbox: function( elem ) { | |
return "checkbox" === elem.type; | |
}, | |
file: function( elem ) { | |
return "file" === elem.type; | |
}, | |
password: function( elem ) { | |
return "password" === elem.type; | |
}, | |
submit: function( elem ) { | |
return "submit" === elem.type; | |
}, | |
image: function( elem ) { | |
return "image" === elem.type; | |
}, | |
reset: function( elem ) { | |
return "reset" === elem.type; | |
}, | |
button: function( elem ) { | |
return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; | |
}, | |
input: function( elem ) { | |
return (/input|select|textarea|button/i).test( elem.nodeName ); | |
} | |
}, | |
setFilters: { | |
first: function( elem, i ) { | |
return i === 0; | |
}, | |
last: function( elem, i, match, array ) { | |
return i === array.length - 1; | |
}, | |
even: function( elem, i ) { | |
return i % 2 === 0; | |
}, | |
odd: function( elem, i ) { | |
return i % 2 === 1; | |
}, | |
lt: function( elem, i, match ) { | |
return i < match[3] - 0; | |
}, | |
gt: function( elem, i, match ) { | |
return i > match[3] - 0; | |
}, | |
nth: function( elem, i, match ) { | |
return match[3] - 0 === i; | |
}, | |
eq: function( elem, i, match ) { | |
return match[3] - 0 === i; | |
} | |
}, | |
filter: { | |
PSEUDO: function( elem, match, i, array ) { | |
var name = match[1], | |
filter = Expr.filters[ name ]; | |
if ( filter ) { | |
return filter( elem, i, match, array ); | |
} else if ( name === "contains" ) { | |
return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; | |
} else if ( name === "not" ) { | |
var not = match[3]; | |
for ( var j = 0, l = not.length; j < l; j++ ) { | |
if ( not[j] === elem ) { | |
return false; | |
} | |
} | |
return true; | |
} else { | |
Sizzle.error( "Syntax error, unrecognized expression: " + name ); | |
} | |
}, | |
CHILD: function( elem, match ) { | |
var type = match[1], | |
node = elem; | |
switch ( type ) { | |
case "only": | |
case "first": | |
while ( (node = node.previousSibling) ) { | |
if ( node.nodeType === 1 ) { | |
return false; | |
} | |
} | |
if ( type === "first" ) { | |
return true; | |
} | |
node = elem; | |
case "last": | |
while ( (node = node.nextSibling) ) { | |
if ( node.nodeType === 1 ) { | |
return false; | |
} | |
} | |
return true; | |
case "nth": | |
var first = match[2], | |
last = match[3]; | |
if ( first === 1 && last === 0 ) { | |
return true; | |
} | |
var doneName = match[0], | |
parent = elem.parentNode; | |
if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { | |
var count = 0; | |
for ( node = parent.firstChild; node; node = node.nextSibling ) { | |
if ( node.nodeType === 1 ) { | |
node.nodeIndex = ++count; | |
} | |
} | |
parent.sizcache = doneName; | |
} | |
var diff = elem.nodeIndex - last; | |
if ( first === 0 ) { | |
return diff === 0; | |
} else { | |
return ( diff % first === 0 && diff / first >= 0 ); | |
} | |
} | |
}, | |
ID: function( elem, match ) { | |
return elem.nodeType === 1 && elem.getAttribute("id") === match; | |
}, | |
TAG: function( elem, match ) { | |
return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; | |
}, | |
CLASS: function( elem, match ) { | |
return (" " + (elem.className || elem.getAttribute("class")) + " ") | |
.indexOf( match ) > -1; | |
}, | |
ATTR: function( elem, match ) { | |
var name = match[1], | |
result = Expr.attrHandle[ name ] ? | |
Expr.attrHandle[ name ]( elem ) : | |
elem[ name ] != null ? | |
elem[ name ] : | |
elem.getAttribute( name ), | |
value = result + "", | |
type = match[2], | |
check = match[4]; | |
return result == null ? | |
type === "!=" : | |
type === "=" ? | |
value === check : | |
type === "*=" ? | |
value.indexOf(check) >= 0 : | |
type === "~=" ? | |
(" " + value + " ").indexOf(check) >= 0 : | |
!check ? | |
value && result !== false : | |
type === "!=" ? | |
value !== check : | |
type === "^=" ? | |
value.indexOf(check) === 0 : | |
type === "$=" ? | |
value.substr(value.length - check.length) === check : | |
type === "|=" ? | |
value === check || value.substr(0, check.length + 1) === check + "-" : | |
false; | |
}, | |
POS: function( elem, match, i, array ) { | |
var name = match[2], | |
filter = Expr.setFilters[ name ]; | |
if ( filter ) { | |
return filter( elem, i, match, array ); | |
} | |
} | |
} | |
}; | |
var origPOS = Expr.match.POS, | |
fescape = function(all, num){ | |
return "\\" + (num - 0 + 1); | |
}; | |
for ( var type in Expr.match ) { | |
Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); | |
Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); | |
} | |
var makeArray = function( array, results ) { | |
array = Array.prototype.slice.call( array, 0 ); | |
if ( results ) { | |
results.push.apply( results, array ); | |
return results; | |
} | |
return array; | |
}; | |
// Perform a simple check to determine if the browser is capable of | |
// converting a NodeList to an array using builtin methods. | |
// Also verifies that the returned array holds DOM nodes | |
// (which is not the case in the Blackberry browser) | |
try { | |
Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; | |
// Provide a fallback method if it does not work | |
} catch( e ) { | |
makeArray = function( array, results ) { | |
var i = 0, | |
ret = results || []; | |
if ( toString.call(array) === "[object Array]" ) { | |
Array.prototype.push.apply( ret, array ); | |
} else { | |
if ( typeof array.length === "number" ) { | |
for ( var l = array.length; i < l; i++ ) { | |
ret.push( array[i] ); | |
} | |
} else { | |
for ( ; array[i]; i++ ) { | |
ret.push( array[i] ); | |
} | |
} | |
} | |
return ret; | |
}; | |
} | |
var sortOrder, siblingCheck; | |
if ( document.documentElement.compareDocumentPosition ) { | |
sortOrder = function( a, b ) { | |
if ( a === b ) { | |
hasDuplicate = true; | |
return 0; | |
} | |
if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { | |
return a.compareDocumentPosition ? -1 : 1; | |
} | |
return a.compareDocumentPosition(b) & 4 ? -1 : 1; | |
}; | |
} else { | |
sortOrder = function( a, b ) { | |
var al, bl, | |
ap = [], | |
bp = [], | |
aup = a.parentNode, | |
bup = b.parentNode, | |
cur = aup; | |
// The nodes are identical, we can exit early | |
if ( a === b ) { | |
hasDuplicate = true; | |
return 0; | |
// If the nodes are siblings (or identical) we can do a quick check | |
} else if ( aup === bup ) { | |
return siblingCheck( a, b ); | |
// If no parents were found then the nodes are disconnected | |
} else if ( !aup ) { | |
return -1; | |
} else if ( !bup ) { | |
return 1; | |
} | |
// Otherwise they're somewhere else in the tree so we need | |
// to build up a full list of the parentNodes for comparison | |
while ( cur ) { | |
ap.unshift( cur ); | |
cur = cur.parentNode; | |
} | |
cur = bup; | |
while ( cur ) { | |
bp.unshift( cur ); | |
cur = cur.parentNode; | |
} | |
al = ap.length; | |
bl = bp.length; | |
// Start walking down the tree looking for a discrepancy | |
for ( var i = 0; i < al && i < bl; i++ ) { | |
if ( ap[i] !== bp[i] ) { | |
return siblingCheck( ap[i], bp[i] ); | |
} | |
} | |
// We ended someplace up the tree so do a sibling check | |
return i === al ? | |
siblingCheck( a, bp[i], -1 ) : | |
siblingCheck( ap[i], b, 1 ); | |
}; | |
siblingCheck = function( a, b, ret ) { | |
if ( a === b ) { | |
return ret; | |
} | |
var cur = a.nextSibling; | |
while ( cur ) { | |
if ( cur === b ) { | |
return -1; | |
} | |
cur = cur.nextSibling; | |
} | |
return 1; | |
}; | |
} | |
// Utility function for retreiving the text value of an array of DOM nodes | |
Sizzle.getText = function( elems ) { | |
var ret = "", elem; | |
for ( var i = 0; elems[i]; i++ ) { | |
elem = elems[i]; | |
// Get the text from text nodes and CDATA nodes | |
if ( elem.nodeType === 3 || elem.nodeType === 4 ) { | |
ret += elem.nodeValue; | |
// Traverse everything else, except comment nodes | |
} else if ( elem.nodeType !== 8 ) { | |
ret += Sizzle.getText( elem.childNodes ); | |
} | |
} | |
return ret; | |
}; | |
// Check to see if the browser returns elements by name when | |
// querying by getElementById (and provide a workaround) | |
(function(){ | |
// We're going to inject a fake input element with a specified name | |
var form = document.createElement("div"), | |
id = "script" + (new Date()).getTime(), | |
root = document.documentElement; | |
form.innerHTML = "<a name='" + id + "'/>"; | |
// Inject it into the root element, check its status, and remove it quickly | |
root.insertBefore( form, root.firstChild ); | |
// The workaround has to do additional checks after a getElementById | |
// Which slows things down for other browsers (hence the branching) | |
if ( document.getElementById( id ) ) { | |
Expr.find.ID = function( match, context, isXML ) { | |
if ( typeof context.getElementById !== "undefined" && !isXML ) { | |
var m = context.getElementById(match[1]); | |
return m ? | |
m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? | |
[m] : | |
undefined : | |
[]; | |
} | |
}; | |
Expr.filter.ID = function( elem, match ) { | |
var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); | |
return elem.nodeType === 1 && node && node.nodeValue === match; | |
}; | |
} | |
root.removeChild( form ); | |
// release memory in IE | |
root = form = null; | |
})(); | |
(function(){ | |
// Check to see if the browser returns only elements | |
// when doing getElementsByTagName("*") | |
// Create a fake element | |
var div = document.createElement("div"); | |
div.appendChild( document.createComment("") ); | |
// Make sure no comments are found | |
if ( div.getElementsByTagName("*").length > 0 ) { | |
Expr.find.TAG = function( match, context ) { | |
var results = context.getElementsByTagName( match[1] ); | |
// Filter out possible comments | |
if ( match[1] === "*" ) { | |
var tmp = []; | |
for ( var i = 0; results[i]; i++ ) { | |
if ( results[i].nodeType === 1 ) { | |
tmp.push( results[i] ); | |
} | |
} | |
results = tmp; | |
} | |
return results; | |
}; | |
} | |
// Check to see if an attribute returns normalized href attributes | |
div.innerHTML = "<a href='#'></a>"; | |
if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && | |
div.firstChild.getAttribute("href") !== "#" ) { | |
Expr.attrHandle.href = function( elem ) { | |
return elem.getAttribute( "href", 2 ); | |
}; | |
} | |
// release memory in IE | |
div = null; | |
})(); | |
if ( document.querySelectorAll ) { | |
(function(){ | |
var oldSizzle = Sizzle, | |
div = document.createElement("div"), | |
id = "__sizzle__"; | |
div.innerHTML = "<p class='TEST'></p>"; | |
// Safari can't handle uppercase or unicode characters when | |
// in quirks mode. | |
if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { | |
return; | |
} | |
Sizzle = function( query, context, extra, seed ) { | |
context = context || document; | |
// Make sure that attribute selectors are quoted | |
query = query.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); | |
// Only use querySelectorAll on non-XML documents | |
// (ID selectors don't work in non-HTML documents) | |
if ( !seed && !Sizzle.isXML(context) ) { | |
if ( context.nodeType === 9 ) { | |
try { | |
return makeArray( context.querySelectorAll(query), extra ); | |
} catch(qsaError) {} | |
// qSA works strangely on Element-rooted queries | |
// We can work around this by specifying an extra ID on the root | |
// and working up from there (Thanks to Andrew Dupont for the technique) | |
// IE 8 doesn't work on object elements | |
} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { | |
var old = context.getAttribute( "id" ), | |
nid = old || id; | |
if ( !old ) { | |
context.setAttribute( "id", nid ); | |
} | |
try { | |
return makeArray( context.querySelectorAll( "#" + nid + " " + query ), extra ); | |
} catch(pseudoError) { | |
} finally { | |
if ( !old ) { | |
context.removeAttribute( "id" ); | |
} | |
} | |
} | |
} | |
return oldSizzle(query, context, extra, seed); | |
}; | |
for ( var prop in oldSizzle ) { | |
Sizzle[ prop ] = oldSizzle[ prop ]; | |
} | |
// release memory in IE | |
div = null; | |
})(); | |
} | |
(function(){ | |
var html = document.documentElement, | |
matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector, | |
pseudoWorks = false; | |
try { | |
// This should fail with an exception | |
// Gecko does not error, returns false instead | |
matches.call( document.documentElement, "[test!='']:sizzle" ); | |
} catch( pseudoError ) { | |
pseudoWorks = true; | |
} | |
if ( matches ) { | |
Sizzle.matchesSelector = function( node, expr ) { | |
// Make sure that attribute selectors are quoted | |
expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); | |
if ( !Sizzle.isXML( node ) ) { | |
try { | |
if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { | |
return matches.call( node, expr ); | |
} | |
} catch(e) {} | |
} | |
return Sizzle(expr, null, null, [node]).length > 0; | |
}; | |
} | |
})(); | |
(function(){ | |
var div = document.createElement("div"); | |
div.innerHTML = "<div class='test e'></div><div class='test'></div>"; | |
// Opera can't find a second classname (in 9.6) | |
// Also, make sure that getElementsByClassName actually exists | |
if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { | |
return; | |
} | |
// Safari caches class attributes, doesn't catch changes (in 3.2) | |
div.lastChild.className = "e"; | |
if ( div.getElementsByClassName("e").length === 1 ) { | |
return; | |
} | |
Expr.order.splice(1, 0, "CLASS"); | |
Expr.find.CLASS = function( match, context, isXML ) { | |
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { | |
return context.getElementsByClassName(match[1]); | |
} | |
}; | |
// release memory in IE | |
div = null; | |
})(); | |
function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { | |
for ( var i = 0, l = checkSet.length; i < l; i++ ) { | |
var elem = checkSet[i]; | |
if ( elem ) { | |
var match = false; | |
elem = elem[dir]; | |
while ( elem ) { | |
if ( elem.sizcache === doneName ) { | |
match = checkSet[elem.sizset]; | |
break; | |
} | |
if ( elem.nodeType === 1 && !isXML ){ | |
elem.sizcache = doneName; | |
elem.sizset = i; | |
} | |
if ( elem.nodeName.toLowerCase() === cur ) { | |
match = elem; | |
break; | |
} | |
elem = elem[dir]; | |
} | |
checkSet[i] = match; | |
} | |
} | |
} | |
function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { | |
for ( var i = 0, l = checkSet.length; i < l; i++ ) { | |
var elem = checkSet[i]; | |
if ( elem ) { | |
var match = false; | |
elem = elem[dir]; | |
while ( elem ) { | |
if ( elem.sizcache === doneName ) { | |
match = checkSet[elem.sizset]; | |
break; | |
} | |
if ( elem.nodeType === 1 ) { | |
if ( !isXML ) { | |
elem.sizcache = doneName; | |
elem.sizset = i; | |
} | |
if ( typeof cur !== "string" ) { | |
if ( elem === cur ) { | |
match = true; | |
break; | |
} | |
} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { | |
match = elem; | |
break; | |
} | |
} | |
elem = elem[dir]; | |
} | |
checkSet[i] = match; | |
} | |
} | |
} | |
if ( document.documentElement.contains ) { | |
Sizzle.contains = function( a, b ) { | |
return a !== b && (a.contains ? a.contains(b) : true); | |
}; | |
} else if ( document.documentElement.compareDocumentPosition ) { | |
Sizzle.contains = function( a, b ) { | |
return !!(a.compareDocumentPosition(b) & 16); | |
}; | |
} else { | |
Sizzle.contains = function() { | |
return false; | |
}; | |
} | |
Sizzle.isXML = function( elem ) { | |
// documentElement is verified for cases where it doesn't yet exist | |
// (such as loading iframes in IE - #4833) | |
var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; | |
return documentElement ? documentElement.nodeName !== "HTML" : false; | |
}; | |
var posProcess = function( selector, context ) { | |
var match, | |
tmpSet = [], | |
later = "", | |
root = context.nodeType ? [context] : context; | |
// Position selectors must be done after the filter | |
// And so must :not(positional) so we move all PSEUDOs to the end | |
while ( (match = Expr.match.PSEUDO.exec( selector )) ) { | |
later += match[0]; | |
selector = selector.replace( Expr.match.PSEUDO, "" ); | |
} | |
selector = Expr.relative[selector] ? selector + "*" : selector; | |
for ( var i = 0, l = root.length; i < l; i++ ) { | |
Sizzle( selector, root[i], tmpSet ); | |
} | |
return Sizzle.filter( later, tmpSet ); | |
}; | |
// EXPOSE | |
jQuery.find = Sizzle; | |
jQuery.expr = Sizzle.selectors; | |
jQuery.expr[":"] = jQuery.expr.filters; | |
jQuery.unique = Sizzle.uniqueSort; | |
jQuery.text = Sizzle.getText; | |
jQuery.isXMLDoc = Sizzle.isXML; | |
jQuery.contains = Sizzle.contains; | |
})(); | |
var runtil = /Until$/, | |
rparentsprev = /^(?:parents|prevUntil|prevAll)/, | |
// Note: This RegExp should be improved, or likely pulled from Sizzle | |
rmultiselector = /,/, | |
isSimple = /^.[^:#\[\.,]*$/, | |
slice = Array.prototype.slice, | |
POS = jQuery.expr.match.POS; | |
jQuery.fn.extend({ | |
find: function( selector ) { | |
var ret = this.pushStack( "", "find", selector ), | |
length = 0; | |
for ( var i = 0, l = this.length; i < l; i++ ) { | |
length = ret.length; | |
jQuery.find( selector, this[i], ret ); | |
if ( i > 0 ) { | |
// Make sure that the results are unique | |
for ( var n = length; n < ret.length; n++ ) { | |
for ( var r = 0; r < length; r++ ) { | |
if ( ret[r] === ret[n] ) { | |
ret.splice(n--, 1); | |
break; | |
} | |
} | |
} | |
} | |
} | |
return ret; | |
}, | |
has: function( target ) { | |
var targets = jQuery( target ); | |
return this.filter(function() { | |
for ( var i = 0, l = targets.length; i < l; i++ ) { | |
if ( jQuery.contains( this, targets[i] ) ) { | |
return true; | |
} | |
} | |
}); | |
}, | |
not: function( selector ) { | |
return this.pushStack( winnow(this, selector, false), "not", selector); | |
}, | |
filter: function( selector ) { | |
return this.pushStack( winnow(this, selector, true), "filter", selector ); | |
}, | |
is: function( selector ) { | |
return !!selector && jQuery.filter( selector, this ).length > 0; | |
}, | |
closest: function( selectors, context ) { | |
var ret = [], i, l, cur = this[0]; | |
if ( jQuery.isArray( selectors ) ) { | |
var match, selector, | |
matches = {}, | |
level = 1; | |
if ( cur && selectors.length ) { | |
for ( i = 0, l = selectors.length; i < l; i++ ) { | |
selector = selectors[i]; | |
if ( !matches[selector] ) { | |
matches[selector] = jQuery.expr.match.POS.test( selector ) ? | |
jQuery( selector, context || this.context ) : | |
selector; | |
} | |
} | |
while ( cur && cur.ownerDocument && cur !== context ) { | |
for ( selector in matches ) { | |
match = matches[selector]; | |
if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { | |
ret.push({ selector: selector, elem: cur, level: level }); | |
} | |
} | |
cur = cur.parentNode; | |
level++; | |
} | |
} | |
return ret; | |
} | |
var pos = POS.test( selectors ) ? | |
jQuery( selectors, context || this.context ) : null; | |
for ( i = 0, l = this.length; i < l; i++ ) { | |
cur = this[i]; | |
while ( cur ) { | |
if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { | |
ret.push( cur ); | |
break; | |
} else { | |
cur = cur.parentNode; | |
if ( !cur || !cur.ownerDocument || cur === context ) { | |
break; | |
} | |
} | |
} | |
} | |
ret = ret.length > 1 ? jQuery.unique(ret) : ret; | |
return this.pushStack( ret, "closest", selectors ); | |
}, | |
// Determine the position of an element within | |
// the matched set of elements | |
index: function( elem ) { | |
if ( !elem || typeof elem === "string" ) { | |
return jQuery.inArray( this[0], | |
// If it receives a string, the selector is used | |
// If it receives nothing, the siblings are used | |
elem ? jQuery( elem ) : this.parent().children() ); | |
} | |
// Locate the position of the desired element | |
return jQuery.inArray( | |
// If it receives a jQuery object, the first element is used | |
elem.jquery ? elem[0] : elem, this ); | |
}, | |
add: function( selector, context ) { | |
var set = typeof selector === "string" ? | |
jQuery( selector, context || this.context ) : | |
jQuery.makeArray( selector ), | |
all = jQuery.merge( this.get(), set ); | |
return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? | |
all : | |
jQuery.unique( all ) ); | |
}, | |
andSelf: function() { | |
return this.add( this.prevObject ); | |
} | |
}); | |
// A painfully simple check to see if an element is disconnected | |
// from a document (should be improved, where feasible). | |
function isDisconnected( node ) { | |
return !node || !node.parentNode || node.parentNode.nodeType === 11; | |
} | |
jQuery.each({ | |
parent: function( elem ) { | |
var parent = elem.parentNode; | |
return parent && parent.nodeType !== 11 ? parent : null; | |
}, | |
parents: function( elem ) { | |
return jQuery.dir( elem, "parentNode" ); | |
}, | |
parentsUntil: function( elem, i, until ) { | |
return jQuery.dir( elem, "parentNode", until ); | |
}, | |
next: function( elem ) { | |
return jQuery.nth( elem, 2, "nextSibling" ); | |
}, | |
prev: function( elem ) { | |
return jQuery.nth( elem, 2, "previousSibling" ); | |
}, | |
nextAll: function( elem ) { | |
return jQuery.dir( elem, "nextSibling" ); | |
}, | |
prevAll: function( elem ) { | |
return jQuery.dir( elem, "previousSibling" ); | |
}, | |
nextUntil: function( elem, i, until ) { | |
return jQuery.dir( elem, "nextSibling", until ); | |
}, | |
prevUntil: function( elem, i, until ) { | |
return jQuery.dir( elem, "previousSibling", until ); | |
}, | |
siblings: function( elem ) { | |
return jQuery.sibling( elem.parentNode.firstChild, elem ); | |
}, | |
children: function( elem ) { | |
return jQuery.sibling( elem.firstChild ); | |
}, | |
contents: function( elem ) { | |
return jQuery.nodeName( elem, "iframe" ) ? | |
elem.contentDocument || elem.contentWindow.document : | |
jQuery.makeArray( elem.childNodes ); | |
} | |
}, function( name, fn ) { | |
jQuery.fn[ name ] = function( until, selector ) { | |
var ret = jQuery.map( this, fn, until ); | |
if ( !runtil.test( name ) ) { | |
selector = until; | |
} | |
if ( selector && typeof selector === "string" ) { | |
ret = jQuery.filter( selector, ret ); | |
} | |
ret = this.length > 1 ? jQuery.unique( ret ) : ret; | |
if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { | |
ret = ret.reverse(); | |
} | |
return this.pushStack( ret, name, slice.call(arguments).join(",") ); | |
}; | |
}); | |
jQuery.extend({ | |
filter: function( expr, elems, not ) { | |
if ( not ) { | |
expr = ":not(" + expr + ")"; | |
} | |
return elems.length === 1 ? | |
jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : | |
jQuery.find.matches(expr, elems); | |
}, | |
dir: function( elem, dir, until ) { | |
var matched = [], | |
cur = elem[ dir ]; | |
while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { | |
if ( cur.nodeType === 1 ) { | |
matched.push( cur ); | |
} | |
cur = cur[dir]; | |
} | |
return matched; | |
}, | |
nth: function( cur, result, dir, elem ) { | |
result = result || 1; | |
var num = 0; | |
for ( ; cur; cur = cur[dir] ) { | |
if ( cur.nodeType === 1 && ++num === result ) { | |
break; | |
} | |
} | |
return cur; | |
}, | |
sibling: function( n, elem ) { | |
var r = []; | |
for ( ; n; n = n.nextSibling ) { | |
if ( n.nodeType === 1 && n !== elem ) { | |
r.push( n ); | |
} | |
} | |
return r; | |
} | |
}); | |
// Implement the identical functionality for filter and not | |
function winnow( elements, qualifier, keep ) { | |
if ( jQuery.isFunction( qualifier ) ) { | |
return jQuery.grep(elements, function( elem, i ) { | |
var retVal = !!qualifier.call( elem, i, elem ); | |
return retVal === keep; | |
}); | |
} else if ( qualifier.nodeType ) { | |
return jQuery.grep(elements, function( elem, i ) { | |
return (elem === qualifier) === keep; | |
}); | |
} else if ( typeof qualifier === "string" ) { | |
var filtered = jQuery.grep(elements, function( elem ) { | |
return elem.nodeType === 1; | |
}); | |
if ( isSimple.test( qualifier ) ) { | |
return jQuery.filter(qualifier, filtered, !keep); | |
} else { | |
qualifier = jQuery.filter( qualifier, filtered ); | |
} | |
} | |
return jQuery.grep(elements, function( elem, i ) { | |
return (jQuery.inArray( elem, qualifier ) >= 0) === keep; | |
}); | |
} | |
var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, | |
rleadingWhitespace = /^\s+/, | |
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, | |
rtagName = /<([\w:]+)/, | |
rtbody = /<tbody/i, | |
rhtml = /<|&#?\w+;/, | |
rnocache = /<(?:script|object|embed|option|style)/i, | |
// checked="checked" or checked (html5) | |
rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, | |
raction = /\=([^="'>\s]+\/)>/g, | |
wrapMap = { | |
option: [ 1, "<select multiple='multiple'>", "</select>" ], | |
legend: [ 1, "<fieldset>", "</fieldset>" ], | |
thead: [ 1, "<table>", "</table>" ], | |
tr: [ 2, "<table><tbody>", "</tbody></table>" ], | |
td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], | |
col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ], | |
area: [ 1, "<map>", "</map>" ], | |
_default: [ 0, "", "" ] | |
}; | |
wrapMap.optgroup = wrapMap.option; | |
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; | |
wrapMap.th = wrapMap.td; | |
// IE can't serialize <link> and <script> tags normally | |
if ( !jQuery.support.htmlSerialize ) { | |
wrapMap._default = [ 1, "div<div>", "</div>" ]; | |
} | |
jQuery.fn.extend({ | |
text: function( text ) { | |
if ( jQuery.isFunction(text) ) { | |
return this.each(function(i) { | |
var self = jQuery( this ); | |
self.text( text.call(this, i, self.text()) ); | |
}); | |
} | |
if ( typeof text !== "object" && text !== undefined ) { | |
return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); | |
} | |
return jQuery.text( this ); | |
}, | |
wrapAll: function( html ) { | |
if ( jQuery.isFunction( html ) ) { | |
return this.each(function(i) { | |
jQuery(this).wrapAll( html.call(this, i) ); | |
}); | |
} | |
if ( this[0] ) { | |
// The elements to wrap the target around | |
var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); | |
if ( this[0].parentNode ) { | |
wrap.insertBefore( this[0] ); | |
} | |
wrap.map(function() { | |
var elem = this; | |
while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { | |
elem = elem.firstChild; | |
} | |
return elem; | |
}).append(this); | |
} | |
return this; | |
}, | |
wrapInner: function( html ) { | |
if ( jQuery.isFunction( html ) ) { | |
return this.each(function(i) { | |
jQuery(this).wrapInner( html.call(this, i) ); | |
}); | |
} | |
return this.each(function() { | |
var self = jQuery( this ), | |
contents = self.contents(); | |
if ( contents.length ) { | |
contents.wrapAll( html ); | |
} else { | |
self.append( html ); | |
} | |
}); | |
}, | |
wrap: function( html ) { | |
return this.each(function() { | |
jQuery( this ).wrapAll( html ); | |
}); | |
}, | |
unwrap: function() { | |
return this.parent().each(function() { | |
if ( !jQuery.nodeName( this, "body" ) ) { | |
jQuery( this ).replaceWith( this.childNodes ); | |
} | |
}).end(); | |
}, | |
append: function() { | |
return this.domManip(arguments, true, function( elem ) { | |
if ( this.nodeType === 1 ) { | |
this.appendChild( elem ); | |
} | |
}); | |
}, | |
prepend: function() { | |
return this.domManip(arguments, true, function( elem ) { | |
if ( this.nodeType === 1 ) { | |
this.insertBefore( elem, this.firstChild ); | |
} | |
}); | |
}, | |
before: function() { | |
if ( this[0] && this[0].parentNode ) { | |
return this.domManip(arguments, false, function( elem ) { | |
this.parentNode.insertBefore( elem, this ); | |
}); | |
} else if ( arguments.length ) { | |
var set = jQuery(arguments[0]); | |
set.push.apply( set, this.toArray() ); | |
return this.pushStack( set, "before", arguments ); | |
} | |
}, | |
after: function() { | |
if ( this[0] && this[0].parentNode ) { | |
return this.domManip(arguments, false, function( elem ) { | |
this.parentNode.insertBefore( elem, this.nextSibling ); | |
}); | |
} else if ( arguments.length ) { | |
var set = this.pushStack( this, "after", arguments ); | |
set.push.apply( set, jQuery(arguments[0]).toArray() ); | |
return set; | |
} | |
}, | |
// keepData is for internal use only--do not document | |
remove: function( selector, keepData ) { | |
for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { | |
if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { | |
if ( !keepData && elem.nodeType === 1 ) { | |
jQuery.cleanData( elem.getElementsByTagName("*") ); | |
jQuery.cleanData( [ elem ] ); | |
} | |
if ( elem.parentNode ) { | |
elem.parentNode.removeChild( elem ); | |
} | |
} | |
} | |
return this; | |
}, | |
empty: function() { | |
for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { | |
// Remove element nodes and prevent memory leaks | |
if ( elem.nodeType === 1 ) { | |
jQuery.cleanData( elem.getElementsByTagName("*") ); | |
} | |
// Remove any remaining nodes | |
while ( elem.firstChild ) { | |
elem.removeChild( elem.firstChild ); | |
} | |
} | |
return this; | |
}, | |
clone: function( events ) { | |
// Do the clone | |
var ret = this.map(function() { | |
if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) { | |
// IE copies events bound via attachEvent when | |
// using cloneNode. Calling detachEvent on the | |
// clone will also remove the events from the orignal | |
// In order to get around this, we use innerHTML. | |
// Unfortunately, this means some modifications to | |
// attributes in IE that are actually only stored | |
// as properties will not be copied (such as the | |
// the name attribute on an input). | |
var html = this.outerHTML, | |
ownerDocument = this.ownerDocument; | |
if ( !html ) { | |
var div = ownerDocument.createElement("div"); | |
div.appendChild( this.cloneNode(true) ); | |
html = div.innerHTML; | |
} | |
return jQuery.clean([html.replace(rinlinejQuery, "") | |
// Handle the case in IE 8 where action=/test/> self-closes a tag | |
.replace(raction, '="$1">') | |
.replace(rleadingWhitespace, "")], ownerDocument)[0]; | |
} else { | |
return this.cloneNode(true); | |
} | |
}); | |
// Copy the events from the original to the clone | |
if ( events === true ) { | |
cloneCopyEvent( this, ret ); | |
cloneCopyEvent( this.find("*"), ret.find("*") ); | |
} | |
// Return the cloned set | |
return ret; | |
}, | |
html: function( value ) { | |
if ( value === undefined ) { | |
return this[0] && this[0].nodeType === 1 ? | |
this[0].innerHTML.replace(rinlinejQuery, "") : | |
null; | |
// See if we can take a shortcut and just use innerHTML | |
} else if ( typeof value === "string" && !rnocache.test( value ) && | |
(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && | |
!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { | |
value = value.replace(rxhtmlTag, "<$1></$2>"); | |
try { | |
for ( var i = 0, l = this.length; i < l; i++ ) { | |
// Remove element nodes and prevent memory leaks | |
if ( this[i].nodeType === 1 ) { | |
jQuery.cleanData( this[i].getElementsByTagName("*") ); | |
this[i].innerHTML = value; | |
} | |
} | |
// If using innerHTML throws an exception, use the fallback method | |
} catch(e) { | |
this.empty().append( value ); | |
} | |
} else if ( jQuery.isFunction( value ) ) { | |
this.each(function(i){ | |
var self = jQuery( this ); | |
self.html( value.call(this, i, self.html()) ); | |
}); | |
} else { | |
this.empty().append( value ); | |
} | |
return this; | |
}, | |
replaceWith: function( value ) { | |
if ( this[0] && this[0].parentNode ) { | |
// Make sure that the elements are removed from the DOM before they are inserted | |
// this can help fix replacing a parent with child elements | |
if ( jQuery.isFunction( value ) ) { | |
return this.each(function(i) { | |
var self = jQuery(this), old = self.html(); | |
self.replaceWith( value.call( this, i, old ) ); | |
}); | |
} | |
if ( typeof value !== "string" ) { | |
value = jQuery( value ).detach(); | |
} | |
return this.each(function() { | |
var next = this.nextSibling, | |
parent = this.parentNode; | |
jQuery( this ).remove(); | |
if ( next ) { | |
jQuery(next).before( value ); | |
} else { | |
jQuery(parent).append( value ); | |
} | |
}); | |
} else { | |
return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ); | |
} | |
}, | |
detach: function( selector ) { | |
return this.remove( selector, true ); | |
}, | |
domManip: function( args, table, callback ) { | |
var results, first, fragment, parent, | |
value = args[0], | |
scripts = []; | |
// We can't cloneNode fragments that contain checked, in WebKit | |
if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) { | |
return this.each(function() { | |
jQuery(this).domManip( args, table, callback, true ); | |
}); | |
} | |
if ( jQuery.isFunction(value) ) { | |
return this.each(function(i) { | |
var self = jQuery(this); | |
args[0] = value.call(this, i, table ? self.html() : undefined); | |
self.domManip( args, table, callback ); | |
}); | |
} | |
if ( this[0] ) { | |
parent = value && value.parentNode; | |
// If we're in a fragment, just use that instead of building a new one | |
if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) { | |
results = { fragment: parent }; | |
} else { | |
results = jQuery.buildFragment( args, this, scripts ); | |
} | |
fragment = results.fragment; | |
if ( fragment.childNodes.length === 1 ) { | |
first = fragment = fragment.firstChild; | |
} else { | |
first = fragment.firstChild; | |
} | |
if ( first ) { | |
table = table && jQuery.nodeName( first, "tr" ); | |
for ( var i = 0, l = this.length; i < l; i++ ) { | |
callback.call( | |
table ? | |
root(this[i], first) : | |
this[i], | |
i > 0 || results.cacheable || this.length > 1 ? | |
fragment.cloneNode(true) : | |
fragment | |
); | |
} | |
} | |
if ( scripts.length ) { | |
jQuery.each( scripts, evalScript ); | |
} | |
} | |
return this; | |
} | |
}); | |
function root( elem, cur ) { | |
return jQuery.nodeName(elem, "table") ? | |
(elem.getElementsByTagName("tbody")[0] || | |
elem.appendChild(elem.ownerDocument.createElement("tbody"))) : | |
elem; | |
} | |
function cloneCopyEvent(orig, ret) { | |
var i = 0; | |
ret.each(function() { | |
if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) { | |
return; | |
} | |
var oldData = jQuery.data( orig[i++] ), | |
curData = jQuery.data( this, oldData ), | |
events = oldData && oldData.events; | |
if ( events ) { | |
delete curData.handle; | |
curData.events = {}; | |
for ( var type in events ) { | |
for ( var handler in events[ type ] ) { | |
jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); | |
} | |
} | |
} | |
}); | |
} | |
jQuery.buildFragment = function( args, nodes, scripts ) { | |
var fragment, cacheable, cacheresults, | |
doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document); | |
// Only cache "small" (1/2 KB) strings that are associated with the main document | |
// Cloning options loses the selected state, so don't cache them | |
// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment | |
// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache | |
if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document && | |
!rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) { | |
cacheable = true; | |
cacheresults = jQuery.fragments[ args[0] ]; | |
if ( cacheresults ) { | |
if ( cacheresults !== 1 ) { | |
fragment = cacheresults; | |
} | |
} | |
} | |
if ( !fragment ) { | |
fragment = doc.createDocumentFragment(); | |
jQuery.clean( args, doc, fragment, scripts ); | |
} | |
if ( cacheable ) { | |
jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1; | |
} | |
return { fragment: fragment, cacheable: cacheable }; | |
}; | |
jQuery.fragments = {}; | |
jQuery.each({ | |
appendTo: "append", | |
prependTo: "prepend", | |
insertBefore: "before", | |
insertAfter: "after", | |
replaceAll: "replaceWith" | |
}, function( name, original ) { | |
jQuery.fn[ name ] = function( selector ) { | |
var ret = [], | |
insert = jQuery( selector ), | |
parent = this.length === 1 && this[0].parentNode; | |
if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { | |
insert[ original ]( this[0] ); | |
return this; | |
} else { | |
for ( var i = 0, l = insert.length; i < l; i++ ) { | |
var elems = (i > 0 ? this.clone(true) : this).get(); | |
jQuery( insert[i] )[ original ]( elems ); | |
ret = ret.concat( elems ); | |
} | |
return this.pushStack( ret, name, insert.selector ); | |
} | |
}; | |
}); | |
jQuery.extend({ | |
clean: function( elems, context, fragment, scripts ) { | |
context = context || document; | |
// !context.createElement fails in IE with an error but returns typeof 'object' | |
if ( typeof context.createElement === "undefined" ) { | |
context = context.ownerDocument || context[0] && context[0].ownerDocument || document; | |
} | |
var ret = []; | |
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { | |
if ( typeof elem === "number" ) { | |
elem += ""; | |
} | |
if ( !elem ) { | |
continue; | |
} | |
// Convert html string into DOM nodes | |
if ( typeof elem === "string" && !rhtml.test( elem ) ) { | |
elem = context.createTextNode( elem ); | |
} else if ( typeof elem === "string" ) { | |
// Fix "XHTML"-style tags in all browsers | |
elem = elem.replace(rxhtmlTag, "<$1></$2>"); | |
// Trim whitespace, otherwise indexOf won't work as expected | |
var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(), | |
wrap = wrapMap[ tag ] || wrapMap._default, | |
depth = wrap[0], | |
div = context.createElement("div"); | |
// Go to html and back, then peel off extra wrappers | |
div.innerHTML = wrap[1] + elem + wrap[2]; | |
// Move to the right depth | |
while ( depth-- ) { | |
div = div.lastChild; | |
} | |
// Remove IE's autoinserted <tbody> from table fragments | |
if ( !jQuery.support.tbody ) { | |
// String was a <table>, *may* have spurious <tbody> | |
var hasBody = rtbody.test(elem), | |
tbody = tag === "table" && !hasBody ? | |
div.firstChild && div.firstChild.childNodes : | |
// String was a bare <thead> or <tfoot> | |
wrap[1] === "<table>" && !hasBody ? | |
div.childNodes : | |
[]; | |
for ( var j = tbody.length - 1; j >= 0 ; --j ) { | |
if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { | |
tbody[ j ].parentNode.removeChild( tbody[ j ] ); | |
} | |
} | |
} | |
// IE completely kills leading whitespace when innerHTML is used | |
if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { | |
div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); | |
} | |
elem = div.childNodes; | |
} | |
if ( elem.nodeType ) { | |
ret.push( elem ); | |
} else { | |
ret = jQuery.merge( ret, elem ); | |
} | |
} | |
if ( fragment ) { | |
for ( i = 0; ret[i]; i++ ) { | |
if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { | |
scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); | |
} else { | |
if ( ret[i].nodeType === 1 ) { | |
ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) ); | |
} | |
fragment.appendChild( ret[i] ); | |
} | |
} | |
} | |
return ret; | |
}, | |
cleanData: function( elems ) { | |
var data, id, cache = jQuery.cache, | |
special = jQuery.event.special, | |
deleteExpando = jQuery.support.deleteExpando; | |
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { | |
if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { | |
continue; | |
} | |
id = elem[ jQuery.expando ]; | |
if ( id ) { | |
data = cache[ id ]; | |
if ( data && data.events ) { | |
for ( var type in data.events ) { | |
if ( special[ type ] ) { | |
jQuery.event.remove( elem, type ); | |
} else { | |
jQuery.removeEvent( elem, type, data.handle ); | |
} | |
} | |
} | |
if ( deleteExpando ) { | |
delete elem[ jQuery.expando ]; | |
} else if ( elem.removeAttribute ) { | |
elem.removeAttribute( jQuery.expando ); | |
} | |
delete cache[ id ]; | |
} | |
} | |
} | |
}); | |
function evalScript( i, elem ) { | |
if ( elem.src ) { | |
jQuery.ajax({ | |
url: elem.src, | |
async: false, | |
dataType: "script" | |
}); | |
} else { | |
jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); | |
} | |
if ( elem.parentNode ) { | |
elem.parentNode.removeChild( elem ); | |
} | |
} | |
var ralpha = /alpha\([^)]*\)/i, | |
ropacity = /opacity=([^)]*)/, | |
rdashAlpha = /-([a-z])/ig, | |
rupper = /([A-Z])/g, | |
rnumpx = /^-?\d+(?:px)?$/i, | |
rnum = /^-?\d/, | |
cssShow = { position: "absolute", visibility: "hidden", display: "block" }, | |
cssWidth = [ "Left", "Right" ], | |
cssHeight = [ "Top", "Bottom" ], | |
curCSS, | |
getComputedStyle, | |
currentStyle, | |
fcamelCase = function( all, letter ) { | |
return letter.toUpperCase(); | |
}; | |
jQuery.fn.css = function( name, value ) { | |
// Setting 'undefined' is a no-op | |
if ( arguments.length === 2 && value === undefined ) { | |
return this; | |
} | |
return jQuery.access( this, name, value, true, function( elem, name, value ) { | |
return value !== undefined ? | |
jQuery.style( elem, name, value ) : | |
jQuery.css( elem, name ); | |
}); | |
}; | |
jQuery.extend({ | |
// Add in style property hooks for overriding the default | |
// behavior of getting and setting a style property | |
cssHooks: { | |
opacity: { | |
get: function( elem, computed ) { | |
if ( computed ) { | |
// We should always get a number back from opacity | |
var ret = curCSS( elem, "opacity", "opacity" ); | |
return ret === "" ? "1" : ret; | |
} else { | |
return elem.style.opacity; | |
} | |
} | |
} | |
}, | |
// Exclude the following css properties to add px | |
cssNumber: { | |
"zIndex": true, | |
"fontWeight": true, | |
"opacity": true, | |
"zoom": true, | |
"lineHeight": true | |
}, | |
// Add in properties whose names you wish to fix before | |
// setting or getting the value | |
cssProps: { | |
// normalize float css property | |
"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" | |
}, | |
// Get and set the style property on a DOM Node | |
style: function( elem, name, value, extra ) { | |
// Don't set styles on text and comment nodes | |
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { | |
return; | |
} | |
// Make sure that we're working with the right name | |
var ret, origName = jQuery.camelCase( name ), | |
style = elem.style, hooks = jQuery.cssHooks[ origName ]; | |
name = jQuery.cssProps[ origName ] || origName; | |
// Check if we're setting a value | |
if ( value !== undefined ) { | |
// Make sure that NaN and null values aren't set. See: #7116 | |
if ( typeof value === "number" && isNaN( value ) || value == null ) { | |
return; | |
} | |
// If a number was passed in, add 'px' to the (except for certain CSS properties) | |
if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) { | |
value += "px"; | |
} | |
// If a hook was provided, use that value, otherwise just set the specified value | |
if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) { | |
// Wrapped to prevent IE from throwing errors when 'invalid' values are provided | |
// Fixes bug #5509 | |
try { | |
style[ name ] = value; | |
} catch(e) {} | |
} | |
} else { | |
// If a hook was provided get the non-computed value from there | |
if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { | |
return ret; | |
} | |
// Otherwise just get the value from the style object | |
return style[ name ]; | |
} | |
}, | |
css: function( elem, name, extra ) { | |
// Make sure that we're working with the right name | |
var ret, origName = jQuery.camelCase( name ), | |
hooks = jQuery.cssHooks[ origName ]; | |
name = jQuery.cssProps[ origName ] || origName; | |
// If a hook was provided get the computed value from there | |
if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { | |
return ret; | |
// Otherwise, if a way to get the computed value exists, use that | |
} else if ( curCSS ) { | |
return curCSS( elem, name, origName ); | |
} | |
}, | |
// A method for quickly swapping in/out CSS properties to get correct calculations | |
swap: function( elem, options, callback ) { | |
var old = {}; | |
// Remember the old values, and insert the new ones | |
for ( var name in options ) { | |
old[ name ] = elem.style[ name ]; | |
elem.style[ name ] = options[ name ]; | |
} | |
callback.call( elem ); | |
// Revert the old values | |
for ( name in options ) { | |
elem.style[ name ] = old[ name ]; | |
} | |
}, | |
camelCase: function( string ) { | |
return string.replace( rdashAlpha, fcamelCase ); | |
} | |
}); | |
// DEPRECATED, Use jQuery.css() instead | |
jQuery.curCSS = jQuery.css; | |
jQuery.each(["height", "width"], function( i, name ) { | |
jQuery.cssHooks[ name ] = { | |
get: function( elem, computed, extra ) { | |
var val; | |
if ( computed ) { | |
if ( elem.offsetWidth !== 0 ) { | |
val = getWH( elem, name, extra ); | |
} else { | |
jQuery.swap( elem, cssShow, function() { | |
val = getWH( elem, name, extra ); | |
}); | |
} | |
if ( val <= 0 ) { | |
val = curCSS( elem, name, name ); | |
if ( val === "0px" && currentStyle ) { | |
val = currentStyle( elem, name, name ); | |
} | |
if ( val != null ) { | |
// Should return "auto" instead of 0, use 0 for | |
// temporary backwards-compat | |
return val === "" || val === "auto" ? "0px" : val; | |
} | |
} | |
if ( val < 0 || val == null ) { | |
val = elem.style[ name ]; | |
// Should return "auto" instead of 0, use 0 for | |
// temporary backwards-compat | |
return val === "" || val === "auto" ? "0px" : val; | |
} | |
return typeof val === "string" ? val : val + "px"; | |
} | |
}, | |
set: function( elem, value ) { | |
if ( rnumpx.test( value ) ) { | |
// ignore negative width and height values #1599 | |
value = parseFloat(value); | |
if ( value >= 0 ) { | |
return value + "px"; | |
} | |
} else { | |
return value; | |
} | |
} | |
}; | |
}); | |
if ( !jQuery.support.opacity ) { | |
jQuery.cssHooks.opacity = { | |
get: function( elem, computed ) { | |
// IE uses filters for opacity | |
return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ? | |
(parseFloat(RegExp.$1) / 100) + "" : | |
computed ? "1" : ""; | |
}, | |
set: function( elem, value ) { | |
var style = elem.style; | |
// IE has trouble with opacity if it does not have layout | |
// Force it by setting the zoom level | |
style.zoom = 1; | |
// Set the alpha filter to set the opacity | |
var opacity = jQuery.isNaN(value) ? | |
"" : | |
"alpha(opacity=" + value * 100 + ")", | |
filter = style.filter || ""; | |
style.filter = ralpha.test(filter) ? | |
filter.replace(ralpha, opacity) : | |
style.filter + ' ' + opacity; | |
} | |
}; | |
} | |
if ( document.defaultView && document.defaultView.getComputedStyle ) { | |
getComputedStyle = function( elem, newName, name ) { | |
var ret, defaultView, computedStyle; | |
name = name.replace( rupper, "-$1" ).toLowerCase(); | |
if ( !(defaultView = elem.ownerDocument.defaultView) ) { | |
return undefined; | |
} | |
if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) { | |
ret = computedStyle.getPropertyValue( name ); | |
if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) { | |
ret = jQuery.style( elem, name ); | |
} | |
} | |
return ret; | |
}; | |
} | |
if ( document.documentElement.currentStyle ) { | |
currentStyle = function( elem, name ) { | |
var left, rsLeft, | |
ret = elem.currentStyle && elem.currentStyle[ name ], | |
style = elem.style; | |
// From the awesome hack by Dean Edwards | |
// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 | |
// If we're not dealing with a regular pixel number | |
// but a number that has a weird ending, we need to convert it to pixels | |
if ( !rnumpx.test( ret ) && rnum.test( ret ) ) { | |
// Remember the original values | |
left = style.left; | |
rsLeft = elem.runtimeStyle.left; | |
// Put in the new values to get a computed value out | |
elem.runtimeStyle.left = elem.currentStyle.left; | |
style.left = name === "fontSize" ? "1em" : (ret || 0); | |
ret = style.pixelLeft + "px"; | |
// Revert the changed values | |
style.left = left; | |
elem.runtimeStyle.left = rsLeft; | |
} | |
return ret === "" ? "auto" : ret; | |
}; | |
} | |
curCSS = getComputedStyle || currentStyle; | |
function getWH( elem, name, extra ) { | |
var which = name === "width" ? cssWidth : cssHeight, | |
val = name === "width" ? elem.offsetWidth : elem.offsetHeight; | |
if ( extra === "border" ) { | |
return val; | |
} | |
jQuery.each( which, function() { | |
if ( !extra ) { | |
val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0; | |
} | |
if ( extra === "margin" ) { | |
val += parseFloat(jQuery.css( elem, "margin" + this )) || 0; | |
} else { | |
val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0; | |
} | |
}); | |
return val; | |
} | |
if ( jQuery.expr && jQuery.expr.filters ) { | |
jQuery.expr.filters.hidden = function( elem ) { | |
var width = elem.offsetWidth, | |
height = elem.offsetHeight; | |
return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none"); | |
}; | |
jQuery.expr.filters.visible = function( elem ) { | |
return !jQuery.expr.filters.hidden( elem ); | |
}; | |
} | |
var jsc = jQuery.now(), | |
rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, | |
rselectTextarea = /^(?:select|textarea)/i, | |
rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, | |
rnoContent = /^(?:GET|HEAD)$/, | |
rbracket = /\[\]$/, | |
jsre = /\=\?(&|$)/, | |
rquery = /\?/, | |
rts = /([?&])_=[^&]*/, | |
rurl = /^(\w+:)?\/\/([^\/?#]+)/, | |
r20 = /%20/g, | |
rhash = /#.*$/, | |
// Keep a copy of the old load method | |
_load = jQuery.fn.load; | |
jQuery.fn.extend({ | |
load: function( url, params, callback ) { | |
if ( typeof url !== "string" && _load ) { | |
return _load.apply( this, arguments ); | |
// Don't do a request if no elements are being requested | |
} else if ( !this.length ) { | |
return this; | |
} | |
var off = url.indexOf(" "); | |
if ( off >= 0 ) { | |
var selector = url.slice(off, url.length); | |
url = url.slice(0, off); | |
} | |
// Default to a GET request | |
var type = "GET"; | |
// If the second parameter was provided | |
if ( params ) { | |
// If it's a function | |
if ( jQuery.isFunction( params ) ) { | |
// We assume that it's the callback | |
callback = params; | |
params = null; | |
// Otherwise, build a param string | |
} else if ( typeof params === "object" ) { | |
params = jQuery.param( params, jQuery.ajaxSettings.traditional ); | |
type = "POST"; | |
} | |
} | |
var self = this; | |
// Request the remote document | |
jQuery.ajax({ | |
url: url, | |
type: type, | |
dataType: "html", | |
data: params, | |
complete: function( res, status ) { | |
// If successful, inject the HTML into all the matched elements | |
if ( status === "success" || status === "notmodified" ) { | |
// See if a selector was specified | |
self.html( selector ? | |
// Create a dummy div to hold the results | |
jQuery("<div>") | |
// inject the contents of the document in, removing the scripts | |
// to avoid any 'Permission Denied' errors in IE | |
.append(res.responseText.replace(rscript, "")) | |
// Locate the specified elements | |
.find(selector) : | |
// If not, just inject the full result | |
res.responseText ); | |
} | |
if ( callback ) { | |
self.each( callback, [res.responseText, status, res] ); | |
} | |
} | |
}); | |
return this; | |
}, | |
serialize: function() { | |
return jQuery.param(this.serializeArray()); | |
}, | |
serializeArray: function() { | |
return this.map(function() { | |
return this.elements ? jQuery.makeArray(this.elements) : this; | |
}) | |
.filter(function() { | |
return this.name && !this.disabled && | |
(this.checked || rselectTextarea.test(this.nodeName) || | |
rinput.test(this.type)); | |
}) | |
.map(function( i, elem ) { | |
var val = jQuery(this).val(); | |
return val == null ? | |
null : | |
jQuery.isArray(val) ? | |
jQuery.map( val, function( val, i ) { | |
return { name: elem.name, value: val }; | |
}) : | |
{ name: elem.name, value: val }; | |
}).get(); | |
} | |
}); | |
// Attach a bunch of functions for handling common AJAX events | |
jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) { | |
jQuery.fn[o] = function( f ) { | |
return this.bind(o, f); | |
}; | |
}); | |
jQuery.extend({ | |
get: function( url, data, callback, type ) { | |
// shift arguments if data argument was omited | |
if ( jQuery.isFunction( data ) ) { | |
type = type || callback; | |
callback = data; | |
data = null; | |
} | |
return jQuery.ajax({ | |
type: "GET", | |
url: url, | |
data: data, | |
success: callback, | |
dataType: type | |
}); | |
}, | |
getScript: function( url, callback ) { | |
return jQuery.get(url, null, callback, "script"); | |
}, | |
getJSON: function( url, data, callback ) { | |
return jQuery.get(url, data, callback, "json"); | |
}, | |
post: function( url, data, callback, type ) { | |
// shift arguments if data argument was omited | |
if ( jQuery.isFunction( data ) ) { | |
type = type || callback; | |
callback = data; | |
data = {}; | |
} | |
return jQuery.ajax({ | |
type: "POST", | |
url: url, | |
data: data, | |
success: callback, | |
dataType: type | |
}); | |
}, | |
ajaxSetup: function( settings ) { | |
jQuery.extend( jQuery.ajaxSettings, settings ); | |
}, | |
ajaxSettings: { | |
url: location.href, | |
global: true, | |
type: "GET", | |
contentType: "application/x-www-form-urlencoded", | |
processData: true, | |
async: true, | |
/* | |
timeout: 0, | |
data: null, | |
username: null, | |
password: null, | |
traditional: false, | |
*/ | |
// This function can be overriden by calling jQuery.ajaxSetup | |
xhr: function() { | |
return new window.XMLHttpRequest(); | |
}, | |
accepts: { | |
xml: "application/xml, text/xml", | |
html: "text/html", | |
script: "text/javascript, application/javascript", | |
json: "application/json, text/javascript", | |
text: "text/plain", | |
_default: "*/*" | |
} | |
}, | |
ajax: function( origSettings ) { | |
var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings), | |
jsonp, status, data, type = s.type.toUpperCase(), noContent = rnoContent.test(type); | |
s.url = s.url.replace( rhash, "" ); | |
// Use original (not extended) context object if it was provided | |
s.context = origSettings && origSettings.context != null ? origSettings.context : s; | |
// convert data if not already a string | |
if ( s.data && s.processData && typeof s.data !== "string" ) { | |
s.data = jQuery.param( s.data, s.traditional ); | |
} | |
// Handle JSONP Parameter Callbacks | |
if ( s.dataType === "jsonp" ) { | |
if ( type === "GET" ) { | |
if ( !jsre.test( s.url ) ) { | |
s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?"; | |
} | |
} else if ( !s.data || !jsre.test(s.data) ) { | |
s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?"; | |
} | |
s.dataType = "json"; | |
} | |
// Build temporary JSONP function | |
if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) { | |
jsonp = s.jsonpCallback || ("jsonp" + jsc++); | |
// Replace the =? sequence both in the query string and the data | |
if ( s.data ) { | |
s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1"); | |
} | |
s.url = s.url.replace(jsre, "=" + jsonp + "$1"); | |
// We need to make sure | |
// that a JSONP style response is executed properly | |
s.dataType = "script"; | |
// Handle JSONP-style loading | |
var customJsonp = window[ jsonp ]; | |
window[ jsonp ] = function( tmp ) { | |
if ( jQuery.isFunction( customJsonp ) ) { | |
customJsonp( tmp ); | |
} else { | |
// Garbage collect | |
window[ jsonp ] = undefined; | |
try { | |
delete window[ jsonp ]; | |
} catch( jsonpError ) {} | |
} | |
data = tmp; | |
jQuery.handleSuccess( s, xhr, status, data ); | |
jQuery.handleComplete( s, xhr, status, data ); | |
if ( head ) { | |
head.removeChild( script ); | |
} | |
}; | |
} | |
if ( s.dataType === "script" && s.cache === null ) { | |
s.cache = false; | |
} | |
if ( s.cache === false && noContent ) { | |
var ts = jQuery.now(); | |
// try replacing _= if it is there | |
var ret = s.url.replace(rts, "$1_=" + ts); | |
// if nothing was replaced, add timestamp to the end | |
s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : ""); | |
} | |
// If data is available, append data to url for GET/HEAD requests | |
if ( s.data && noContent ) { | |
s.url += (rquery.test(s.url) ? "&" : "?") + s.data; | |
} | |
// Watch for a new set of requests | |
if ( s.global && jQuery.active++ === 0 ) { | |
jQuery.event.trigger( "ajaxStart" ); | |
} | |
// Matches an absolute URL, and saves the domain | |
var parts = rurl.exec( s.url ), | |
remote = parts && (parts[1] && parts[1].toLowerCase() !== location.protocol || parts[2].toLowerCase() !== location.host); | |
// If we're requesting a remote document | |
// and trying to load JSON or Script with a GET | |
if ( s.dataType === "script" && type === "GET" && remote ) { | |
var head = document.getElementsByTagName("head")[0] || document.documentElement; | |
var script = document.createElement("script"); | |
if ( s.scriptCharset ) { | |
script.charset = s.scriptCharset; | |
} | |
script.src = s.url; | |
// Handle Script loading | |
if ( !jsonp ) { | |
var done = false; | |
// Attach handlers for all browsers | |
script.onload = script.onreadystatechange = function() { | |
if ( !done && (!this.readyState || | |
this.readyState === "loaded" || this.readyState === "complete") ) { | |
done = true; | |
jQuery.handleSuccess( s, xhr, status, data ); | |
jQuery.handleComplete( s, xhr, status, data ); | |
// Handle memory leak in IE | |
script.onload = script.onreadystatechange = null; | |
if ( head && script.parentNode ) { | |
head.removeChild( script ); | |
} | |
} | |
}; | |
} | |
// Use insertBefore instead of appendChild to circumvent an IE6 bug. | |
// This arises when a base node is used (#2709 and #4378). | |
head.insertBefore( script, head.firstChild ); | |
// We handle everything using the script element injection | |
return undefined; | |
} | |
var requestDone = false; | |
// Create the request object | |
var xhr = s.xhr(); | |
if ( !xhr ) { | |
return; | |
} | |
// Open the socket | |
// Passing null username, generates a login popup on Opera (#2865) | |
if ( s.username ) { | |
xhr.open(type, s.url, s.async, s.username, s.password); | |
} else { | |
xhr.open(type, s.url, s.async); | |
} | |
// Need an extra try/catch for cross domain requests in Firefox 3 | |
try { | |
// Set content-type if data specified and content-body is valid for this type | |
if ( (s.data != null && !noContent) || (origSettings && origSettings.contentType) ) { | |
xhr.setRequestHeader("Content-Type", s.contentType); | |
} | |
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. | |
if ( s.ifModified ) { | |
if ( jQuery.lastModified[s.url] ) { | |
xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]); | |
} | |
if ( jQuery.etag[s.url] ) { | |
xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]); | |
} | |
} | |
// Set header so the called script knows that it's an XMLHttpRequest | |
// Only send the header if it's not a remote XHR | |
if ( !remote ) { | |
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); | |
} | |
// Set the Accepts header for the server, depending on the dataType | |
xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ? | |
s.accepts[ s.dataType ] + ", */*; q=0.01" : | |
s.accepts._default ); | |
} catch( headerError ) {} | |
// Allow custom headers/mimetypes and early abort | |
if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) { | |
// Handle the global AJAX counter | |
if ( s.global && jQuery.active-- === 1 ) { | |
jQuery.event.trigger( "ajaxStop" ); | |
} | |
// close opended socket | |
xhr.abort(); | |
return false; | |
} | |
if ( s.global ) { | |
jQuery.triggerGlobal( s, "ajaxSend", [xhr, s] ); | |
} | |
// Wait for a response to come back | |
var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) { | |
// The request was aborted | |
if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) { | |
// Opera doesn't call onreadystatechange before this point | |
// so we simulate the call | |
if ( !requestDone ) { | |
jQuery.handleComplete( s, xhr, status, data ); | |
} | |
requestDone = true; | |
if ( xhr ) { | |
xhr.onreadystatechange = jQuery.noop; | |
} | |
// The transfer is complete and the data is available, or the request timed out | |
} else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) { | |
requestDone = true; | |
xhr.onreadystatechange = jQuery.noop; | |
status = isTimeout === "timeout" ? | |
"timeout" : | |
!jQuery.httpSuccess( xhr ) ? | |
"error" : | |
s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? | |
"notmodified" : | |
"success"; | |
var errMsg; | |
if ( status === "success" ) { | |
// Watch for, and catch, XML document parse errors | |
try { | |
// process the data (runs the xml through httpData regardless of callback) | |
data = jQuery.httpData( xhr, s.dataType, s ); | |
} catch( parserError ) { | |
status = "parsererror"; | |
errMsg = parserError; | |
} | |
} | |
// Make sure that the request was successful or notmodified | |
if ( status === "success" || status === "notmodified" ) { | |
// JSONP handles its own success callback | |
if ( !jsonp ) { | |
jQuery.handleSuccess( s, xhr, status, data ); | |
} | |
} else { | |
jQuery.handleError( s, xhr, status, errMsg ); | |
} | |
// Fire the complete handlers | |
if ( !jsonp ) { | |
jQuery.handleComplete( s, xhr, status, data ); | |
} | |
if ( isTimeout === "timeout" ) { | |
xhr.abort(); | |
} | |
// Stop memory leaks | |
if ( s.async ) { | |
xhr = null; | |
} | |
} | |
}; | |
// Override the abort handler, if we can (IE 6 doesn't allow it, but that's OK) | |
// Opera doesn't fire onreadystatechange at all on abort | |
try { | |
var oldAbort = xhr.abort; | |
xhr.abort = function() { | |
if ( xhr ) { | |
// oldAbort has no call property in IE7 so | |
// just do it this way, which works in all | |
// browsers | |
Function.prototype.call.call( oldAbort, xhr ); | |
} | |
onreadystatechange( "abort" ); | |
}; | |
} catch( abortError ) {} | |
// Timeout checker | |
if ( s.async && s.timeout > 0 ) { | |
setTimeout(function() { | |
// Check to see if the request is still happening | |
if ( xhr && !requestDone ) { | |
onreadystatechange( "timeout" ); | |
} | |
}, s.timeout); | |
} | |
// Send the data | |
try { | |
xhr.send( noContent || s.data == null ? null : s.data ); | |
} catch( sendError ) { | |
jQuery.handleError( s, xhr, null, sendError ); | |
// Fire the complete handlers | |
jQuery.handleComplete( s, xhr, status, data ); | |
} | |
// firefox 1.5 doesn't fire statechange for sync requests | |
if ( !s.async ) { | |
onreadystatechange(); | |
} | |
// return XMLHttpRequest to allow aborting the request etc. | |
return xhr; | |
}, | |
// Serialize an array of form elements or a set of | |
// key/values into a query string | |
param: function( a, traditional ) { | |
var s = [], | |
add = function( key, value ) { | |
// If value is a function, invoke it and return its value | |
value = jQuery.isFunction(value) ? value() : value; | |
s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value); | |
}; | |
// Set traditional to true for jQuery <= 1.3.2 behavior. | |
if ( traditional === undefined ) { | |
traditional = jQuery.ajaxSettings.traditional; | |
} | |
// If an array was passed in, assume that it is an array of form elements. | |
if ( jQuery.isArray(a) || a.jquery ) { | |
// Serialize the form elements | |
jQuery.each( a, function() { | |
add( this.name, this.value ); | |
}); | |
} else { | |
// If traditional, encode the "old" way (the way 1.3.2 or older | |
// did it), otherwise encode params recursively. | |
for ( var prefix in a ) { | |
buildParams( prefix, a[prefix], traditional, add ); | |
} | |
} | |
// Return the resulting serialization | |
return s.join("&").replace(r20, "+"); | |
} | |
}); | |
function buildParams( prefix, obj, traditional, add ) { | |
if ( jQuery.isArray(obj) && obj.length ) { | |
// Serialize array item. | |
jQuery.each( obj, function( i, v ) { | |
if ( traditional || rbracket.test( prefix ) ) { | |
// Treat each array item as a scalar. | |
add( prefix, v ); | |
} else { | |
// If array item is non-scalar (array or object), encode its | |
// numeric index to resolve deserialization ambiguity issues. | |
// Note that rack (as of 1.0.0) can't currently deserialize | |
// nested arrays properly, and attempting to do so may cause | |
// a server error. Possible fixes are to modify rack's | |
// deserialization algorithm or to provide an option or flag | |
// to force array serialization to be shallow. | |
buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add ); | |
} | |
}); | |
} else if ( !traditional && obj != null && typeof obj === "object" ) { | |
if ( jQuery.isEmptyObject( obj ) ) { | |
add( prefix, "" ); | |
// Serialize object item. | |
} else { | |
jQuery.each( obj, function( k, v ) { | |
buildParams( prefix + "[" + k + "]", v, traditional, add ); | |
}); | |
} | |
} else { | |
// Serialize scalar item. | |
add( prefix, obj ); | |
} | |
} | |
// This is still on the jQuery object... for now | |
// Want to move this to jQuery.ajax some day | |
jQuery.extend({ | |
// Counter for holding the number of active queries | |
active: 0, | |
// Last-Modified header cache for next request | |
lastModified: {}, | |
etag: {}, | |
handleError: function( s, xhr, status, e ) { | |
// If a local callback was specified, fire it | |
if ( s.error ) { | |
s.error.call( s.context, xhr, status, e ); | |
} | |
// Fire the global callback | |
if ( s.global ) { | |
jQuery.triggerGlobal( s, "ajaxError", [xhr, s, e] ); | |
} | |
}, | |
handleSuccess: function( s, xhr, status, data ) { | |
// If a local callback was specified, fire it and pass it the data | |
if ( s.success ) { | |
s.success.call( s.context, data, status, xhr ); | |
} | |
// Fire the global callback | |
if ( s.global ) { | |
jQuery.triggerGlobal( s, "ajaxSuccess", [xhr, s] ); | |
} | |
}, | |
handleComplete: function( s, xhr, status ) { | |
// Process result | |
if ( s.complete ) { | |
s.complete.call( s.context, xhr, status ); | |
} | |
// The request was completed | |
if ( s.global ) { | |
jQuery.triggerGlobal( s, "ajaxComplete", [xhr, s] ); | |
} | |
// Handle the global AJAX counter | |
if ( s.global && jQuery.active-- === 1 ) { | |
jQuery.event.trigger( "ajaxStop" ); | |
} | |
}, | |
triggerGlobal: function( s, type, args ) { | |
(s.context && s.context.url == null ? jQuery(s.context) : jQuery.event).trigger(type, args); | |
}, | |
// Determines if an XMLHttpRequest was successful or not | |
httpSuccess: function( xhr ) { | |
try { | |
// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450 | |
return !xhr.status && location.protocol === "file:" || | |
xhr.status >= 200 && xhr.status < 300 || | |
xhr.status === 304 || xhr.status === 1223; | |
} catch(e) {} | |
return false; | |
}, | |
// Determines if an XMLHttpRequest returns NotModified | |
httpNotModified: function( xhr, url ) { | |
var lastModified = xhr.getResponseHeader("Last-Modified"), | |
etag = xhr.getResponseHeader("Etag"); | |
if ( lastModified ) { | |
jQuery.lastModified[url] = lastModified; | |
} | |
if ( etag ) { | |
jQuery.etag[url] = etag; | |
} | |
return xhr.status === 304; | |
}, | |
httpData: function( xhr, type, s ) { | |
var ct = xhr.getResponseHeader("content-type") || "", | |
xml = type === "xml" || !type && ct.indexOf("xml") >= 0, | |
data = xml ? xhr.responseXML : xhr.responseText; | |
if ( xml && data.documentElement.nodeName === "parsererror" ) { | |
jQuery.error( "parsererror" ); | |
} | |
// Allow a pre-filtering function to sanitize the response | |
// s is checked to keep backwards compatibility | |
if ( s && s.dataFilter ) { | |
data = s.dataFilter( data, type ); | |
} | |
// The filter can actually parse the response | |
if ( typeof data === "string" ) { | |
// Get the JavaScript object, if JSON is used. | |
if ( type === "json" || !type && ct.indexOf("json") >= 0 ) { | |
data = jQuery.parseJSON( data ); | |
// If the type is "script", eval it in global context | |
} else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) { | |
jQuery.globalEval( data ); | |
} | |
} | |
return data; | |
} | |
}); | |
/* | |
* Create the request object; Microsoft failed to properly | |
* implement the XMLHttpRequest in IE7 (can't request local files), | |
* so we use the ActiveXObject when it is available | |
* Additionally XMLHttpRequest can be disabled in IE7/IE8 so | |
* we need a fallback. | |
*/ | |
if ( window.ActiveXObject ) { | |
jQuery.ajaxSettings.xhr = function() { | |
if ( window.location.protocol !== "file:" ) { | |
try { | |
return new window.XMLHttpRequest(); | |
} catch(xhrError) {} | |
} | |
try { | |
return new window.ActiveXObject("Microsoft.XMLHTTP"); | |
} catch(activeError) {} | |
}; | |
} | |
// Does this browser support XHR requests? | |
jQuery.support.ajax = !!jQuery.ajaxSettings.xhr(); | |
var elemdisplay = {}, | |
rfxtypes = /^(?:toggle|show|hide)$/, | |
rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/, | |
timerId, | |
fxAttrs = [ | |
// height animations | |
[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ], | |
// width animations | |
[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ], | |
// opacity animations | |
[ "opacity" ] | |
]; | |
jQuery.fn.extend({ | |
show: function( speed, easing, callback ) { | |
var elem, display; | |
if ( speed || speed === 0 ) { | |
return this.animate( genFx("show", 3), speed, easing, callback); | |
} else { | |
for ( var i = 0, j = this.length; i < j; i++ ) { | |
elem = this[i]; | |
display = elem.style.display; | |
// Reset the inline display of this element to learn if it is | |
// being hidden by cascaded rules or not | |
if ( !jQuery.data(elem, "olddisplay") && display === "none" ) { | |
display = elem.style.display = ""; | |
} | |
// Set elements which have been overridden with display: none | |
// in a stylesheet to whatever the default browser style is | |
// for such an element | |
if ( display === "" && jQuery.css( elem, "display" ) === "none" ) { | |
jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName)); | |
} | |
} | |
// Set the display of most of the elements in a second loop | |
// to avoid the constant reflow | |
for ( i = 0; i < j; i++ ) { | |
elem = this[i]; | |
display = elem.style.display; | |
if ( display === "" || display === "none" ) { | |
elem.style.display = jQuery.data(elem, "olddisplay") || ""; | |
} | |
} | |
return this; | |
} | |
}, | |
hide: function( speed, easing, callback ) { | |
if ( speed || speed === 0 ) { | |
return this.animate( genFx("hide", 3), speed, easing, callback); | |
} else { | |
for ( var i = 0, j = this.length; i < j; i++ ) { | |
var display = jQuery.css( this[i], "display" ); | |
if ( display !== "none" ) { | |
jQuery.data( this[i], "olddisplay", display ); | |
} | |
} | |
// Set the display of the elements in a second loop | |
// to avoid the constant reflow | |
for ( i = 0; i < j; i++ ) { | |
this[i].style.display = "none"; | |
} | |
return this; | |
} | |
}, | |
// Save the old toggle function | |
_toggle: jQuery.fn.toggle, | |
toggle: function( fn, fn2, callback ) { | |
var bool = typeof fn === "boolean"; | |
if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) { | |
this._toggle.apply( this, arguments ); | |
} else if ( fn == null || bool ) { | |
this.each(function() { | |
var state = bool ? fn : jQuery(this).is(":hidden"); | |
jQuery(this)[ state ? "show" : "hide" ](); | |
}); | |
} else { | |
this.animate(genFx("toggle", 3), fn, fn2, callback); | |
} | |
return this; | |
}, | |
fadeTo: function( speed, to, easing, callback ) { | |
return this.filter(":hidden").css("opacity", 0).show().end() | |
.animate({opacity: to}, speed, easing, callback); | |
}, | |
animate: function( prop, speed, easing, callback ) { | |
var optall = jQuery.speed(speed, easing, callback); | |
if ( jQuery.isEmptyObject( prop ) ) { | |
return this.each( optall.complete ); | |
} | |
return this[ optall.queue === false ? "each" : "queue" ](function() { | |
// XXX 'this' does not always have a nodeName when running the | |
// test suite | |
var opt = jQuery.extend({}, optall), p, | |
isElement = this.nodeType === 1, | |
hidden = isElement && jQuery(this).is(":hidden"), | |
self = this; | |
for ( p in prop ) { | |
var name = jQuery.camelCase( p ); | |
if ( p !== name ) { | |
prop[ name ] = prop[ p ]; | |
delete prop[ p ]; | |
p = name; | |
} | |
if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) { | |
return opt.complete.call(this); | |
} | |
if ( isElement && ( p === "height" || p === "width" ) ) { | |
// Make sure that nothing sneaks out | |
// Record all 3 overflow attributes because IE does not | |
// change the overflow attribute when overflowX and | |
// overflowY are set to the same value | |
opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ]; | |
// Set display property to inline-block for height/width | |
// animations on inline elements that are having width/height | |
// animated | |
if ( jQuery.css( this, "display" ) === "inline" && | |
jQuery.css( this, "float" ) === "none" ) { | |
if ( !jQuery.support.inlineBlockNeedsLayout ) { | |
this.style.display = "inline-block"; | |
} else { | |
var display = defaultDisplay(this.nodeName); | |
// inline-level elements accept inline-block; | |
// block-level elements need to be inline with layout | |
if ( display === "inline" ) { | |
this.style.display = "inline-block"; | |
} else { | |
this.style.display = "inline"; | |
this.style.zoom = 1; | |
} | |
} | |
} | |
} | |
if ( jQuery.isArray( prop[p] ) ) { | |
// Create (if needed) and add to specialEasing | |
(opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1]; | |
prop[p] = prop[p][0]; | |
} | |
} | |
if ( opt.overflow != null ) { | |
this.style.overflow = "hidden"; | |
} | |
opt.curAnim = jQuery.extend({}, prop); | |
jQuery.each( prop, function( name, val ) { | |
var e = new jQuery.fx( self, opt, name ); | |
if ( rfxtypes.test(val) ) { | |
e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop ); | |
} else { | |
var parts = rfxnum.exec(val), | |
start = e.cur() || 0; | |
if ( parts ) { | |
var end = parseFloat( parts[2] ), | |
unit = parts[3] || "px"; | |
// We need to compute starting value | |
if ( unit !== "px" ) { | |
jQuery.style( self, name, (end || 1) + unit); | |
start = ((end || 1) / e.cur()) * start; | |
jQuery.style( self, name, start + unit); | |
} | |
// If a +=/-= token was provided, we're doing a relative animation | |
if ( parts[1] ) { | |
end = ((parts[1] === "-=" ? -1 : 1) * end) + start; | |
} | |
e.custom( start, end, unit ); | |
} else { | |
e.custom( start, val, "" ); | |
} | |
} | |
}); | |
// For JS strict compliance | |
return true; | |
}); | |
}, | |
stop: function( clearQueue, gotoEnd ) { | |
var timers = jQuery.timers; | |
if ( clearQueue ) { | |
this.queue([]); | |
} | |
this.each(function() { | |
// go in reverse order so anything added to the queue during the loop is ignored | |
for ( var i = timers.length - 1; i >= 0; i-- ) { | |
if ( timers[i].elem === this ) { | |
if (gotoEnd) { | |
// force the next step to be the last | |
timers[i](true); | |
} | |
timers.splice(i, 1); | |
} | |
} | |
}); | |
// start the next in the queue if the last step wasn't forced | |
if ( !gotoEnd ) { | |
this.dequeue(); | |
} | |
return this; | |
} | |
}); | |
function genFx( type, num ) { | |
var obj = {}; | |
jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() { | |
obj[ this ] = type; | |
}); | |
return obj; | |
} | |
// Generate shortcuts for custom animations | |
jQuery.each({ | |
slideDown: genFx("show", 1), | |
slideUp: genFx("hide", 1), | |
slideToggle: genFx("toggle", 1), | |
fadeIn: { opacity: "show" }, | |
fadeOut: { opacity: "hide" }, | |
fadeToggle: { opacity: "toggle" } | |
}, function( name, props ) { | |
jQuery.fn[ name ] = function( speed, easing, callback ) { | |
return this.animate( props, speed, easing, callback ); | |
}; | |
}); | |
jQuery.extend({ | |
speed: function( speed, easing, fn ) { | |
var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : { | |
complete: fn || !fn && easing || | |
jQuery.isFunction( speed ) && speed, | |
duration: speed, | |
easing: fn && easing || easing && !jQuery.isFunction(easing) && easing | |
}; | |
opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : | |
opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default; | |
// Queueing | |
opt.old = opt.complete; | |
opt.complete = function() { | |
if ( opt.queue !== false ) { | |
jQuery(this).dequeue(); | |
} | |
if ( jQuery.isFunction( opt.old ) ) { | |
opt.old.call( this ); | |
} | |
}; | |
return opt; | |
}, | |
easing: { | |
linear: function( p, n, firstNum, diff ) { | |
return firstNum + diff * p; | |
}, | |
swing: function( p, n, firstNum, diff ) { | |
return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum; | |
} | |
}, | |
timers: [], | |
fx: function( elem, options, prop ) { | |
this.options = options; | |
this.elem = elem; | |
this.prop = prop; | |
if ( !options.orig ) { | |
options.orig = {}; | |
} | |
} | |
}); | |
jQuery.fx.prototype = { | |
// Simple function for setting a style value | |
update: function() { | |
if ( this.options.step ) { | |
this.options.step.call( this.elem, this.now, this ); | |
} | |
(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this ); | |
}, | |
// Get the current size | |
cur: function() { | |
if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) { | |
return this.elem[ this.prop ]; | |
} | |
var r = parseFloat( jQuery.css( this.elem, this.prop ) ); | |
return r && r > -10000 ? r : 0; | |
}, | |
// Start an animation from one number to another | |
custom: function( from, to, unit ) { | |
var self = this, | |
fx = jQuery.fx; | |
this.startTime = jQuery.now(); | |
this.start = from; | |
this.end = to; | |
this.unit = unit || this.unit || "px"; | |
this.now = this.start; | |
this.pos = this.state = 0; | |
function t( gotoEnd ) { | |
return self.step(gotoEnd); | |
} | |
t.elem = this.elem; | |
if ( t() && jQuery.timers.push(t) && !timerId ) { | |
timerId = setInterval(fx.tick, fx.interval); | |
} | |
}, | |
// Simple 'show' function | |
show: function() { | |
// Remember where we started, so that we can go back to it later | |
this.options.orig[this.prop] = jQuery.style( this.elem, this.prop ); | |
this.options.show = true; | |
// Begin the animation | |
// Make sure that we start at a small width/height to avoid any | |
// flash of content | |
this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur()); | |
// Start by showing the element | |
jQuery( this.elem ).show(); | |
}, | |
// Simple 'hide' function | |
hide: function() { | |
// Remember where we started, so that we can go back to it later | |
this.options.orig[this.prop] = jQuery.style( this.elem, this.prop ); | |
this.options.hide = true; | |
// Begin the animation | |
this.custom(this.cur(), 0); | |
}, | |
// Each step of an animation | |
step: function( gotoEnd ) { | |
var t = jQuery.now(), done = true; | |
if ( gotoEnd || t >= this.options.duration + this.startTime ) { | |
this.now = this.end; | |
this.pos = this.state = 1; | |
this.update(); | |
this.options.curAnim[ this.prop ] = true; | |
for ( var i in this.options.curAnim ) { | |
if ( this.options.curAnim[i] !== true ) { | |
done = false; | |
} | |
} | |
if ( done ) { | |
// Reset the overflow | |
if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) { | |
var elem = this.elem, | |
options = this.options; | |
jQuery.each( [ "", "X", "Y" ], function (index, value) { | |
elem.style[ "overflow" + value ] = options.overflow[index]; | |
} ); | |
} | |
// Hide the element if the "hide" operation was done | |
if ( this.options.hide ) { | |
jQuery(this.elem).hide(); | |
} | |
// Reset the properties, if the item has been hidden or shown | |
if ( this.options.hide || this.options.show ) { | |
for ( var p in this.options.curAnim ) { | |
jQuery.style( this.elem, p, this.options.orig[p] ); | |
} | |
} | |
// Execute the complete function | |
this.options.complete.call( this.elem ); | |
} | |
return false; | |
} else { | |
var n = t - this.startTime; | |
this.state = n / this.options.duration; | |
// Perform the easing function, defaults to swing | |
var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop]; | |
var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear"); | |
this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration); | |
this.now = this.start + ((this.end - this.start) * this.pos); | |
// Perform the next step of the animation | |
this.update(); | |
} | |
return true; | |
} | |
}; | |
jQuery.extend( jQuery.fx, { | |
tick: function() { | |
var timers = jQuery.timers; | |
for ( var i = 0; i < timers.length; i++ ) { | |
if ( !timers[i]() ) { | |
timers.splice(i--, 1); | |
} | |
} | |
if ( !timers.length ) { | |
jQuery.fx.stop(); | |
} | |
}, | |
interval: 13, | |
stop: function() { | |
clearInterval( timerId ); | |
timerId = null; | |
}, | |
speeds: { | |
slow: 600, | |
fast: 200, | |
// Default speed | |
_default: 400 | |
}, | |
step: { | |
opacity: function( fx ) { | |
jQuery.style( fx.elem, "opacity", fx.now ); | |
}, | |
_default: function( fx ) { | |
if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) { | |
fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit; | |
} else { | |
fx.elem[ fx.prop ] = fx.now; | |
} | |
} | |
} | |
}); | |
if ( jQuery.expr && jQuery.expr.filters ) { | |
jQuery.expr.filters.animated = function( elem ) { | |
return jQuery.grep(jQuery.timers, function( fn ) { | |
return elem === fn.elem; | |
}).length; | |
}; | |
} | |
function defaultDisplay( nodeName ) { | |
if ( !elemdisplay[ nodeName ] ) { | |
var elem = jQuery("<" + nodeName + ">").appendTo("body"), | |
display = elem.css("display"); | |
elem.remove(); | |
if ( display === "none" || display === "" ) { | |
display = "block"; | |
} | |
elemdisplay[ nodeName ] = display; | |
} | |
return elemdisplay[ nodeName ]; | |
} | |
var rtable = /^t(?:able|d|h)$/i, | |
rroot = /^(?:body|html)$/i; | |
if ( "getBoundingClientRect" in document.documentElement ) { | |
jQuery.fn.offset = function( options ) { | |
var elem = this[0], box; | |
if ( options ) { | |
return this.each(function( i ) { | |
jQuery.offset.setOffset( this, options, i ); | |
}); | |
} | |
if ( !elem || !elem.ownerDocument ) { | |
return null; | |
} | |
if ( elem === elem.ownerDocument.body ) { | |
return jQuery.offset.bodyOffset( elem ); | |
} | |
try { | |
box = elem.getBoundingClientRect(); | |
} catch(e) {} | |
var doc = elem.ownerDocument, | |
docElem = doc.documentElement; | |
// Make sure we're not dealing with a disconnected DOM node | |
if ( !box || !jQuery.contains( docElem, elem ) ) { | |
return box || { top: 0, left: 0 }; | |
} | |
var body = doc.body, | |
win = getWindow(doc), | |
clientTop = docElem.clientTop || body.clientTop || 0, | |
clientLeft = docElem.clientLeft || body.clientLeft || 0, | |
scrollTop = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ), | |
scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft), | |
top = box.top + scrollTop - clientTop, | |
left = box.left + scrollLeft - clientLeft; | |
return { top: top, left: left }; | |
}; | |
} else { | |
jQuery.fn.offset = function( options ) { | |
var elem = this[0]; | |
if ( options ) { | |
return this.each(function( i ) { | |
jQuery.offset.setOffset( this, options, i ); | |
}); | |
} | |
if ( !elem || !elem.ownerDocument ) { | |
return null; | |
} | |
if ( elem === elem.ownerDocument.body ) { | |
return jQuery.offset.bodyOffset( elem ); | |
} | |
jQuery.offset.initialize(); | |
var computedStyle, | |
offsetParent = elem.offsetParent, | |
prevOffsetParent = elem, | |
doc = elem.ownerDocument, | |
docElem = doc.documentElement, | |
body = doc.body, | |
defaultView = doc.defaultView, | |
prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle, | |
top = elem.offsetTop, | |
left = elem.offsetLeft; | |
while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) { | |
if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) { | |
break; | |
} | |
computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle; | |
top -= elem.scrollTop; | |
left -= elem.scrollLeft; | |
if ( elem === offsetParent ) { | |
top += elem.offsetTop; | |
left += elem.offsetLeft; | |
if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) { | |
top += parseFloat( computedStyle.borderTopWidth ) || 0; | |
left += parseFloat( computedStyle.borderLeftWidth ) || 0; | |
} | |
prevOffsetParent = offsetParent; | |
offsetParent = elem.offsetParent; | |
} | |
if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) { | |
top += parseFloat( computedStyle.borderTopWidth ) || 0; | |
left += parseFloat( computedStyle.borderLeftWidth ) || 0; | |
} | |
prevComputedStyle = computedStyle; | |
} | |
if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) { | |
top += body.offsetTop; | |
left += body.offsetLeft; | |
} | |
if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) { | |
top += Math.max( docElem.scrollTop, body.scrollTop ); | |
left += Math.max( docElem.scrollLeft, body.scrollLeft ); | |
} | |
return { top: top, left: left }; | |
}; | |
} | |
jQuery.offset = { | |
initialize: function() { | |
var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0, | |
html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>"; | |
jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } ); | |
container.innerHTML = html; | |
body.insertBefore( container, body.firstChild ); | |
innerDiv = container.firstChild; | |
checkDiv = innerDiv.firstChild; | |
td = innerDiv.nextSibling.firstChild.firstChild; | |
this.doesNotAddBorder = (checkDiv.offsetTop !== 5); | |
this.doesAddBorderForTableAndCells = (td.offsetTop === 5); | |
checkDiv.style.position = "fixed"; | |
checkDiv.style.top = "20px"; | |
// safari subtracts parent border width here which is 5px | |
this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15); | |
checkDiv.style.position = checkDiv.style.top = ""; | |
innerDiv.style.overflow = "hidden"; | |
innerDiv.style.position = "relative"; | |
this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5); | |
this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop); | |
body.removeChild( container ); | |
body = container = innerDiv = checkDiv = table = td = null; | |
jQuery.offset.initialize = jQuery.noop; | |
}, | |
bodyOffset: function( body ) { | |
var top = body.offsetTop, | |
left = body.offsetLeft; | |
jQuery.offset.initialize(); | |
if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) { | |
top += parseFloat( jQuery.css(body, "marginTop") ) || 0; | |
left += parseFloat( jQuery.css(body, "marginLeft") ) || 0; | |
} | |
return { top: top, left: left }; | |
}, | |
setOffset: function( elem, options, i ) { | |
var position = jQuery.css( elem, "position" ); | |
// set position first, in-case top/left are set even on static elem | |
if ( position === "static" ) { | |
elem.style.position = "relative"; | |
} | |
var curElem = jQuery( elem ), | |
curOffset = curElem.offset(), | |
curCSSTop = jQuery.css( elem, "top" ), | |
curCSSLeft = jQuery.css( elem, "left" ), | |
calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1), | |
props = {}, curPosition = {}, curTop, curLeft; | |
// need to be able to calculate position if either top or left is auto and position is absolute | |
if ( calculatePosition ) { | |
curPosition = curElem.position(); | |
} | |
curTop = calculatePosition ? curPosition.top : parseInt( curCSSTop, 10 ) || 0; | |
curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0; | |
if ( jQuery.isFunction( options ) ) { | |
options = options.call( elem, i, curOffset ); | |
} | |
if (options.top != null) { | |
props.top = (options.top - curOffset.top) + curTop; | |
} | |
if (options.left != null) { | |
props.left = (options.left - curOffset.left) + curLeft; | |
} | |
if ( "using" in options ) { | |
options.using.call( elem, props ); | |
} else { | |
curElem.css( props ); | |
} | |
} | |
}; | |
jQuery.fn.extend({ | |
position: function() { | |
if ( !this[0] ) { | |
return null; | |
} | |
var elem = this[0], | |
// Get *real* offsetParent | |
offsetParent = this.offsetParent(), | |
// Get correct offsets | |
offset = this.offset(), | |
parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); | |
// Subtract element margins | |
// note: when an element has margin: auto the offsetLeft and marginLeft | |
// are the same in Safari causing offset.left to incorrectly be 0 | |
offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; | |
offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; | |
// Add offsetParent borders | |
parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; | |
parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; | |
// Subtract the two offsets | |
return { | |
top: offset.top - parentOffset.top, | |
left: offset.left - parentOffset.left | |
}; | |
}, | |
offsetParent: function() { | |
return this.map(function() { | |
var offsetParent = this.offsetParent || document.body; | |
while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { | |
offsetParent = offsetParent.offsetParent; | |
} | |
return offsetParent; | |
}); | |
} | |
}); | |
// Create scrollLeft and scrollTop methods | |
jQuery.each( ["Left", "Top"], function( i, name ) { | |
var method = "scroll" + name; | |
jQuery.fn[ method ] = function(val) { | |
var elem = this[0], win; | |
if ( !elem ) { | |
return null; | |
} | |
if ( val !== undefined ) { | |
// Set the scroll offset | |
return this.each(function() { | |
win = getWindow( this ); | |
if ( win ) { | |
win.scrollTo( | |
!i ? val : jQuery(win).scrollLeft(), | |
i ? val : jQuery(win).scrollTop() | |
); | |
} else { | |
this[ method ] = val; | |
} | |
}); | |
} else { | |
win = getWindow( elem ); | |
// Return the scroll offset | |
return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] : | |
jQuery.support.boxModel && win.document.documentElement[ method ] || | |
win.document.body[ method ] : | |
elem[ method ]; | |
} | |
}; | |
}); | |
function getWindow( elem ) { | |
return jQuery.isWindow( elem ) ? | |
elem : | |
elem.nodeType === 9 ? | |
elem.defaultView || elem.parentWindow : | |
false; | |
} | |
// Create innerHeight, innerWidth, outerHeight and outerWidth methods | |
jQuery.each([ "Height", "Width" ], function( i, name ) { | |
var type = name.toLowerCase(); | |
// innerHeight and innerWidth | |
jQuery.fn["inner" + name] = function() { | |
return this[0] ? | |
parseFloat( jQuery.css( this[0], type, "padding" ) ) : | |
null; | |
}; | |
// outerHeight and outerWidth | |
jQuery.fn["outer" + name] = function( margin ) { | |
return this[0] ? | |
parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) : | |
null; | |
}; | |
jQuery.fn[ type ] = function( size ) { | |
// Get window width or height | |
var elem = this[0]; | |
if ( !elem ) { | |
return size == null ? null : this; | |
} | |
if ( jQuery.isFunction( size ) ) { | |
return this.each(function( i ) { | |
var self = jQuery( this ); | |
self[ type ]( size.call( this, i, self[ type ]() ) ); | |
}); | |
} | |
if ( jQuery.isWindow( elem ) ) { | |
// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode | |
return elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] || | |
elem.document.body[ "client" + name ]; | |
// Get document width or height | |
} else if ( elem.nodeType === 9 ) { | |
// Either scroll[Width/Height] or offset[Width/Height], whichever is greater | |
return Math.max( | |
elem.documentElement["client" + name], | |
elem.body["scroll" + name], elem.documentElement["scroll" + name], | |
elem.body["offset" + name], elem.documentElement["offset" + name] | |
); | |
// Get or set width or height on the element | |
} else if ( size === undefined ) { | |
var orig = jQuery.css( elem, type ), | |
ret = parseFloat( orig ); | |
return jQuery.isNaN( ret ) ? orig : ret; | |
// Set the width or height on the element (default to pixels if value is unitless) | |
} else { | |
return this.css( type, typeof size === "string" ? size : size + "px" ); | |
} | |
}; | |
}); | |
})(window); | |
/*! | |
* jQuery UI Widget @VERSION | |
* | |
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
* | |
* http://docs.jquery.com/UI/Widget | |
*/ | |
(function( $, undefined ) { | |
// jQuery 1.4+ | |
if ( $.cleanData ) { | |
var _cleanData = $.cleanData; | |
$.cleanData = function( elems ) { | |
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { | |
$( elem ).triggerHandler( "remove" ); | |
} | |
_cleanData( elems ); | |
}; | |
} else { | |
var _remove = $.fn.remove; | |
$.fn.remove = function( selector, keepData ) { | |
return this.each(function() { | |
if ( !keepData ) { | |
if ( !selector || $.filter( selector, [ this ] ).length ) { | |
$( "*", this ).add( [ this ] ).each(function() { | |
$( this ).triggerHandler( "remove" ); | |
}); | |
} | |
} | |
return _remove.call( $(this), selector, keepData ); | |
}); | |
}; | |
} | |
$.widget = function( name, base, prototype ) { | |
var namespace = name.split( "." )[ 0 ], | |
fullName; | |
name = name.split( "." )[ 1 ]; | |
fullName = namespace + "-" + name; | |
if ( !prototype ) { | |
prototype = base; | |
base = $.Widget; | |
} | |
// create selector for plugin | |
$.expr[ ":" ][ fullName ] = function( elem ) { | |
return !!$.data( elem, name ); | |
}; | |
$[ namespace ] = $[ namespace ] || {}; | |
$[ namespace ][ name ] = function( options, element ) { | |
// allow instantiation without initializing for simple inheritance | |
if ( arguments.length ) { | |
this._createWidget( options, element ); | |
} | |
}; | |
var basePrototype = new base(); | |
// we need to make the options hash a property directly on the new instance | |
// otherwise we'll modify the options hash on the prototype that we're | |
// inheriting from | |
// $.each( basePrototype, function( key, val ) { | |
// if ( $.isPlainObject(val) ) { | |
// basePrototype[ key ] = $.extend( {}, val ); | |
// } | |
// }); | |
basePrototype.options = $.extend( true, {}, basePrototype.options ); | |
$[ namespace ][ name ].prototype = $.extend( true, basePrototype, { | |
namespace: namespace, | |
widgetName: name, | |
widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, | |
widgetBaseClass: fullName | |
}, prototype ); | |
$.widget.bridge( name, $[ namespace ][ name ] ); | |
}; | |
$.widget.bridge = function( name, object ) { | |
$.fn[ name ] = function( options ) { | |
var isMethodCall = typeof options === "string", | |
args = Array.prototype.slice.call( arguments, 1 ), | |
returnValue = this; | |
// allow multiple hashes to be passed on init | |
options = !isMethodCall && args.length ? | |
$.extend.apply( null, [ true, options ].concat(args) ) : | |
options; | |
// prevent calls to internal methods | |
if ( isMethodCall && options.charAt( 0 ) === "_" ) { | |
return returnValue; | |
} | |
if ( isMethodCall ) { | |
this.each(function() { | |
var instance = $.data( this, name ); | |
if ( !instance ) { | |
throw "cannot call methods on " + name + " prior to initialization; " + | |
"attempted to call method '" + options + "'"; | |
} | |
if ( !$.isFunction( instance[options] ) ) { | |
throw "no such method '" + options + "' for " + name + " widget instance"; | |
} | |
var methodValue = instance[ options ].apply( instance, args ); | |
if ( methodValue !== instance && methodValue !== undefined ) { | |
returnValue = methodValue; | |
return false; | |
} | |
}); | |
} else { | |
this.each(function() { | |
var instance = $.data( this, name ); | |
if ( instance ) { | |
instance.option( options || {} )._init(); | |
} else { | |
$.data( this, name, new object( options, this ) ); | |
} | |
}); | |
} | |
return returnValue; | |
}; | |
}; | |
$.Widget = function( options, element ) { | |
// allow instantiation without initializing for simple inheritance | |
if ( arguments.length ) { | |
this._createWidget( options, element ); | |
} | |
}; | |
$.Widget.prototype = { | |
widgetName: "widget", | |
widgetEventPrefix: "", | |
options: { | |
disabled: false | |
}, | |
_createWidget: function( options, element ) { | |
// $.widget.bridge stores the plugin instance, but we do it anyway | |
// so that it's stored even before the _create function runs | |
$.data( element, this.widgetName, this ); | |
this.element = $( element ); | |
this.options = $.extend( true, {}, | |
this.options, | |
this._getCreateOptions(), | |
options ); | |
var self = this; | |
this.element.bind( "remove." + this.widgetName, function() { | |
self.destroy(); | |
}); | |
this._create(); | |
this._trigger( "create" ); | |
this._init(); | |
}, | |
_getCreateOptions: function() { | |
var options = {}; | |
if ( $.metadata ) { | |
options = $.metadata.get( element )[ this.widgetName ]; | |
} | |
return options; | |
}, | |
_create: function() {}, | |
_init: function() {}, | |
destroy: function() { | |
this.element | |
.unbind( "." + this.widgetName ) | |
.removeData( this.widgetName ); | |
this.widget() | |
.unbind( "." + this.widgetName ) | |
.removeAttr( "aria-disabled" ) | |
.removeClass( | |
this.widgetBaseClass + "-disabled " + | |
"ui-state-disabled" ); | |
}, | |
widget: function() { | |
return this.element; | |
}, | |
option: function( key, value ) { | |
var options = key; | |
if ( arguments.length === 0 ) { | |
// don't return a reference to the internal hash | |
return $.extend( {}, this.options ); | |
} | |
if (typeof key === "string" ) { | |
if ( value === undefined ) { | |
return this.options[ key ]; | |
} | |
options = {}; | |
options[ key ] = value; | |
} | |
this._setOptions( options ); | |
return this; | |
}, | |
_setOptions: function( options ) { | |
var self = this; | |
$.each( options, function( key, value ) { | |
self._setOption( key, value ); | |
}); | |
return this; | |
}, | |
_setOption: function( key, value ) { | |
this.options[ key ] = value; | |
if ( key === "disabled" ) { | |
this.widget() | |
[ value ? "addClass" : "removeClass"]( | |
this.widgetBaseClass + "-disabled" + " " + | |
"ui-state-disabled" ) | |
.attr( "aria-disabled", value ); | |
} | |
return this; | |
}, | |
enable: function() { | |
return this._setOption( "disabled", false ); | |
}, | |
disable: function() { | |
return this._setOption( "disabled", true ); | |
}, | |
_trigger: function( type, event, data ) { | |
var callback = this.options[ type ]; | |
event = $.Event( event ); | |
event.type = ( type === this.widgetEventPrefix ? | |
type : | |
this.widgetEventPrefix + type ).toLowerCase(); | |
data = data || {}; | |
// copy original event properties over to the new event | |
// this would happen if we could call $.event.fix instead of $.Event | |
// but we don't have a way to force an event to be fixed multiple times | |
if ( event.originalEvent ) { | |
for ( var i = $.event.props.length, prop; i; ) { | |
prop = $.event.props[ --i ]; | |
event[ prop ] = event.originalEvent[ prop ]; | |
} | |
} | |
this.element.trigger( event, data ); | |
return !( $.isFunction(callback) && | |
callback.call( this.element[0], event, data ) === false || | |
event.isDefaultPrevented() ); | |
} | |
}; | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : widget factory extentions for mobile | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.widget( "mobile.widget", { | |
_getCreateOptions: function() { | |
var elem = this.element, | |
options = {}; | |
$.each( this.options, function( option ) { | |
var value = elem.data( option.replace( /[A-Z]/g, function( c ) { | |
return "-" + c.toLowerCase(); | |
} ) ); | |
if ( value !== undefined ) { | |
options[ option ] = value; | |
} | |
}); | |
return options; | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : resolution and CSS media query related helpers and behavior | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
var $window = $(window), | |
$html = $( "html" ), | |
//media-query-like width breakpoints, which are translated to classes on the html element | |
resolutionBreakpoints = [320,480,768,1024]; | |
/* $.mobile.media method: pass a CSS media type or query and get a bool return | |
note: this feature relies on actual media query support for media queries, though types will work most anywhere | |
examples: | |
$.mobile.media('screen') //>> tests for screen media type | |
$.mobile.media('screen and (min-width: 480px)') //>> tests for screen media type with window width > 480px | |
$.mobile.media('@media screen and (-webkit-min-device-pixel-ratio: 2)') //>> tests for webkit 2x pixel ratio (iPhone 4) | |
*/ | |
$.mobile.media = (function() { | |
// TODO: use window.matchMedia once at least one UA implements it | |
var cache = {}, | |
testDiv = $( "<div id='jquery-mediatest'>" ), | |
fakeBody = $( "<body>" ).append( testDiv ); | |
return function( query ) { | |
if ( !( query in cache ) ) { | |
var styleBlock = $( "<style type='text/css'>" + | |
"@media " + query + "{#jquery-mediatest{position:absolute;}}" + | |
"</style>" ); | |
$html.prepend( fakeBody ).prepend( styleBlock ); | |
cache[ query ] = testDiv.css( "position" ) === "absolute"; | |
fakeBody.add( styleBlock ).remove(); | |
} | |
return cache[ query ]; | |
}; | |
})(); | |
/* | |
private function for adding/removing breakpoint classes to HTML element for faux media-query support | |
It does not require media query support, instead using JS to detect screen width > cross-browser support | |
This function is called on orientationchange, resize, and mobileinit, and is bound via the 'htmlclass' event namespace | |
*/ | |
function detectResolutionBreakpoints(){ | |
var currWidth = $window.width(), | |
minPrefix = "min-width-", | |
maxPrefix = "max-width-", | |
minBreakpoints = [], | |
maxBreakpoints = [], | |
unit = "px", | |
breakpointClasses; | |
$html.removeClass( minPrefix + resolutionBreakpoints.join(unit + " " + minPrefix) + unit + " " + | |
maxPrefix + resolutionBreakpoints.join( unit + " " + maxPrefix) + unit ); | |
$.each(resolutionBreakpoints,function( i, breakPoint ){ | |
if( currWidth >= breakPoint ){ | |
minBreakpoints.push( minPrefix + breakPoint + unit ); | |
} | |
if( currWidth <= breakPoint ){ | |
maxBreakpoints.push( maxPrefix + breakPoint + unit ); | |
} | |
}); | |
if( minBreakpoints.length ){ breakpointClasses = minBreakpoints.join(" "); } | |
if( maxBreakpoints.length ){ breakpointClasses += " " + maxBreakpoints.join(" "); } | |
$html.addClass( breakpointClasses ); | |
}; | |
/* $.mobile.addResolutionBreakpoints method: | |
pass either a number or an array of numbers and they'll be added to the min/max breakpoint classes | |
Examples: | |
$.mobile.addResolutionBreakpoints( 500 ); | |
$.mobile.addResolutionBreakpoints( [500, 1200] ); | |
*/ | |
$.mobile.addResolutionBreakpoints = function( newbps ){ | |
if( $.type( newbps ) === "array" ){ | |
resolutionBreakpoints = resolutionBreakpoints.concat( newbps ); | |
} | |
else { | |
resolutionBreakpoints.push( newbps ); | |
} | |
resolutionBreakpoints.sort(function(a,b){ return a-b; }); | |
detectResolutionBreakpoints(); | |
}; | |
/* on mobileinit, add classes to HTML element | |
and set handlers to update those on orientationchange and resize*/ | |
$(document).bind("mobileinit.htmlclass", function(){ | |
/* bind to orientationchange and resize | |
to add classes to HTML element for min/max breakpoints and orientation */ | |
$window.bind("orientationchange.htmlclass resize.htmlclass", function(event){ | |
//add orientation class to HTML element on flip/resize. | |
if(event.orientation){ | |
$html.removeClass( "portrait landscape" ).addClass( event.orientation ); | |
} | |
//add classes to HTML element for min/max breakpoints | |
detectResolutionBreakpoints(); | |
}); | |
//trigger event manually | |
$window.trigger( "orientationchange.htmlclass" ); | |
}); | |
})(jQuery); | |
/* | |
* jQuery Mobile Framework : support tests | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
var fakeBody = $( "<body>" ).prependTo( "html" ), | |
fbCSS = fakeBody[0].style, | |
vendors = ['webkit','moz','o'], | |
webos = window.palmGetResource || window.PalmServiceBridge, //only used to rule out scrollTop | |
bb = window.blackberry; //only used to rule out box shadow, as it's filled opaque on BB | |
//thx Modernizr | |
function propExists( prop ){ | |
var uc_prop = prop.charAt(0).toUpperCase() + prop.substr(1), | |
props = (prop + ' ' + vendors.join(uc_prop + ' ') + uc_prop).split(' '); | |
for(var v in props){ | |
if( fbCSS[ props[v] ] !== undefined ){ | |
return true; | |
} | |
} | |
}; | |
//test for dynamic-updating base tag support (allows us to avoid href,src attr rewriting) | |
function baseTagTest(){ | |
var fauxBase = location.protocol + '//' + location.host + location.pathname + "ui-dir/", | |
base = $("<base>", {"href": fauxBase}).appendTo("head"), | |
link = $( "<a href='testurl'></a>" ).prependTo( fakeBody ), | |
rebase = link[0].href; | |
base.remove(); | |
return rebase.indexOf(fauxBase) === 0; | |
}; | |
$.extend( $.support, { | |
orientation: "orientation" in window, | |
touch: "ontouchend" in document, | |
cssTransitions: "WebKitTransitionEvent" in window, | |
pushState: !!history.pushState, | |
mediaquery: $.mobile.media('only all'), | |
cssPseudoElement: !!propExists('content'), | |
boxShadow: !!propExists('boxShadow') && !bb, | |
scrollTop: ("pageXOffset" in window || "scrollTop" in document.documentElement || "scrollTop" in fakeBody[0]) && !webos, | |
dynamicBaseTag: baseTagTest() | |
}); | |
fakeBody.remove(); | |
//for ruling out shadows via css | |
if( !$.support.boxShadow ){ $('html').addClass('ui-mobile-nosupport-boxshadow'); } | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : events | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
// add new event shortcuts | |
$.each( "touchstart touchmove touchend orientationchange tap taphold swipe swipeleft swiperight scrollstart scrollstop".split( " " ), function( i, name ) { | |
$.fn[ name ] = function( fn ) { | |
return fn ? this.bind( name, fn ) : this.trigger( name ); | |
}; | |
$.attrFn[ name ] = true; | |
}); | |
var supportTouch = $.support.touch, | |
scrollEvent = "touchmove scroll", | |
touchStartEvent = supportTouch ? "touchstart" : "mousedown", | |
touchStopEvent = supportTouch ? "touchend" : "mouseup", | |
touchMoveEvent = supportTouch ? "touchmove" : "mousemove"; | |
// also handles scrollstop | |
$.event.special.scrollstart = { | |
enabled: true, | |
setup: function() { | |
var thisObject = this, | |
$this = $( thisObject ), | |
scrolling, | |
timer; | |
function trigger( event, state ) { | |
scrolling = state; | |
var originalType = event.type; | |
event.type = scrolling ? "scrollstart" : "scrollstop"; | |
$.event.handle.call( thisObject, event ); | |
event.type = originalType; | |
} | |
// iPhone triggers scroll after a small delay; use touchmove instead | |
$this.bind( scrollEvent, function( event ) { | |
if ( !$.event.special.scrollstart.enabled ) { | |
return; | |
} | |
if ( !scrolling ) { | |
trigger( event, true ); | |
} | |
clearTimeout( timer ); | |
timer = setTimeout(function() { | |
trigger( event, false ); | |
}, 50 ); | |
}); | |
} | |
}; | |
// also handles taphold | |
$.event.special.tap = { | |
setup: function() { | |
var thisObject = this, | |
$this = $( thisObject ); | |
$this | |
.bind( touchStartEvent, function( event ) { | |
if ( event.which && event.which !== 1 ) { | |
return; | |
} | |
var moved = false, | |
touching = true, | |
origPos = [ event.pageX, event.pageY ], | |
originalType, | |
timer; | |
function moveHandler() { | |
if ((Math.abs(origPos[0] - event.pageX) > 10) || | |
(Math.abs(origPos[1] - event.pageY) > 10)) { | |
moved = true; | |
} | |
} | |
timer = setTimeout(function() { | |
if ( touching && !moved ) { | |
originalType = event.type; | |
event.type = "taphold"; | |
$.event.handle.call( thisObject, event ); | |
event.type = originalType; | |
} | |
}, 750 ); | |
$this | |
.one( touchMoveEvent, moveHandler) | |
.one( touchStopEvent, function( event ) { | |
$this.unbind( touchMoveEvent, moveHandler ); | |
clearTimeout( timer ); | |
touching = false; | |
if ( !moved ) { | |
originalType = event.type; | |
event.type = "tap"; | |
$.event.handle.call( thisObject, event ); | |
event.type = originalType; | |
} | |
}); | |
}); | |
} | |
}; | |
// also handles swipeleft, swiperight | |
$.event.special.swipe = { | |
setup: function() { | |
var thisObject = this, | |
$this = $( thisObject ); | |
$this | |
.bind( touchStartEvent, function( event ) { | |
var data = event.originalEvent.touches ? | |
event.originalEvent.touches[ 0 ] : | |
event, | |
start = { | |
time: (new Date).getTime(), | |
coords: [ data.pageX, data.pageY ], | |
origin: $( event.target ) | |
}, | |
stop; | |
function moveHandler( event ) { | |
if ( !start ) { | |
return; | |
} | |
var data = event.originalEvent.touches ? | |
event.originalEvent.touches[ 0 ] : | |
event; | |
stop = { | |
time: (new Date).getTime(), | |
coords: [ data.pageX, data.pageY ] | |
}; | |
// prevent scrolling | |
if ( Math.abs( start.coords[0] - stop.coords[0] ) > 10 ) { | |
event.preventDefault(); | |
} | |
} | |
$this | |
.bind( touchMoveEvent, moveHandler ) | |
.one( touchStopEvent, function( event ) { | |
$this.unbind( touchMoveEvent, moveHandler ); | |
if ( start && stop ) { | |
if ( stop.time - start.time < 1000 && | |
Math.abs( start.coords[0] - stop.coords[0]) > 30 && | |
Math.abs( start.coords[1] - stop.coords[1]) < 75 ) { | |
start.origin | |
.trigger( "swipe" ) | |
.trigger( start.coords[0] > stop.coords[0] ? "swipeleft" : "swiperight" ); | |
} | |
} | |
start = stop = undefined; | |
}); | |
}); | |
} | |
}; | |
(function($){ | |
// "Cowboy" Ben Alman | |
var win = $(window), | |
special_event, | |
get_orientation, | |
last_orientation; | |
$.event.special.orientationchange = special_event = { | |
setup: function(){ | |
// If the event is supported natively, return false so that jQuery | |
// will bind to the event using DOM methods. | |
if ( $.support.orientation ) { return false; } | |
// Get the current orientation to avoid initial double-triggering. | |
last_orientation = get_orientation(); | |
// Because the orientationchange event doesn't exist, simulate the | |
// event by testing window dimensions on resize. | |
win.bind( "resize", handler ); | |
}, | |
teardown: function(){ | |
// If the event is not supported natively, return false so that | |
// jQuery will unbind the event using DOM methods. | |
if ( $.support.orientation ) { return false; } | |
// Because the orientationchange event doesn't exist, unbind the | |
// resize event handler. | |
win.unbind( "resize", handler ); | |
}, | |
add: function( handleObj ) { | |
// Save a reference to the bound event handler. | |
var old_handler = handleObj.handler; | |
handleObj.handler = function( event ) { | |
// Modify event object, adding the .orientation property. | |
event.orientation = get_orientation(); | |
// Call the originally-bound event handler and return its result. | |
return old_handler.apply( this, arguments ); | |
}; | |
} | |
}; | |
// If the event is not supported natively, this handler will be bound to | |
// the window resize event to simulate the orientationchange event. | |
function handler() { | |
// Get the current orientation. | |
var orientation = get_orientation(); | |
if ( orientation !== last_orientation ) { | |
// The orientation has changed, so trigger the orientationchange event. | |
last_orientation = orientation; | |
win.trigger( "orientationchange" ); | |
} | |
}; | |
// Get the current page orientation. This method is exposed publicly, should it | |
// be needed, as jQuery.event.special.orientationchange.orientation() | |
special_event.orientation = get_orientation = function() { | |
var elem = document.documentElement; | |
return elem && elem.clientWidth / elem.clientHeight < 1.1 ? "portrait" : "landscape"; | |
}; | |
})(jQuery); | |
$.each({ | |
scrollstop: "scrollstart", | |
taphold: "tap", | |
swipeleft: "swipe", | |
swiperight: "swipe" | |
}, function( event, sourceEvent ) { | |
$.event.special[ event ] = { | |
setup: function() { | |
$( this ).bind( sourceEvent, $.noop ); | |
} | |
}; | |
}); | |
})( jQuery ); | |
/*! | |
* jQuery hashchange event - v1.3 - 7/21/2010 | |
* http://benalman.com/projects/jquery-hashchange-plugin/ | |
* | |
* Copyright (c) 2010 "Cowboy" Ben Alman | |
* Dual licensed under the MIT and GPL licenses. | |
* http://benalman.com/about/license/ | |
*/ | |
// Script: jQuery hashchange event | |
// | |
// *Version: 1.3, Last updated: 7/21/2010* | |
// | |
// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/ | |
// GitHub - http://github.com/cowboy/jquery-hashchange/ | |
// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js | |
// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped) | |
// | |
// About: License | |
// | |
// Copyright (c) 2010 "Cowboy" Ben Alman, | |
// Dual licensed under the MIT and GPL licenses. | |
// http://benalman.com/about/license/ | |
// | |
// About: Examples | |
// | |
// These working examples, complete with fully commented code, illustrate a few | |
// ways in which this plugin can be used. | |
// | |
// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/ | |
// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/ | |
// | |
// About: Support and Testing | |
// | |
// Information about what version or versions of jQuery this plugin has been | |
// tested with, what browsers it has been tested in, and where the unit tests | |
// reside (so you can test it yourself). | |
// | |
// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2 | |
// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5, | |
// Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5. | |
// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/ | |
// | |
// About: Known issues | |
// | |
// While this jQuery hashchange event implementation is quite stable and | |
// robust, there are a few unfortunate browser bugs surrounding expected | |
// hashchange event-based behaviors, independent of any JavaScript | |
// window.onhashchange abstraction. See the following examples for more | |
// information: | |
// | |
// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/ | |
// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/ | |
// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/ | |
// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/ | |
// | |
// Also note that should a browser natively support the window.onhashchange | |
// event, but not report that it does, the fallback polling loop will be used. | |
// | |
// About: Release History | |
// | |
// 1.3 - (7/21/2010) Reorganized IE6/7 Iframe code to make it more | |
// "removable" for mobile-only development. Added IE6/7 document.title | |
// support. Attempted to make Iframe as hidden as possible by using | |
// techniques from http://www.paciellogroup.com/blog/?p=604. Added | |
// support for the "shortcut" format $(window).hashchange( fn ) and | |
// $(window).hashchange() like jQuery provides for built-in events. | |
// Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and | |
// lowered its default value to 50. Added <jQuery.fn.hashchange.domain> | |
// and <jQuery.fn.hashchange.src> properties plus document-domain.html | |
// file to address access denied issues when setting document.domain in | |
// IE6/7. | |
// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin | |
// from a page on another domain would cause an error in Safari 4. Also, | |
// IE6/7 Iframe is now inserted after the body (this actually works), | |
// which prevents the page from scrolling when the event is first bound. | |
// Event can also now be bound before DOM ready, but it won't be usable | |
// before then in IE6/7. | |
// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug | |
// where browser version is incorrectly reported as 8.0, despite | |
// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag. | |
// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special | |
// window.onhashchange functionality into a separate plugin for users | |
// who want just the basic event & back button support, without all the | |
// extra awesomeness that BBQ provides. This plugin will be included as | |
// part of jQuery BBQ, but also be available separately. | |
(function($,window,undefined){ | |
'$:nomunge'; // Used by YUI compressor. | |
// Reused string. | |
var str_hashchange = 'hashchange', | |
// Method / object references. | |
doc = document, | |
fake_onhashchange, | |
special = $.event.special, | |
// Does the browser support window.onhashchange? Note that IE8 running in | |
// IE7 compatibility mode reports true for 'onhashchange' in window, even | |
// though the event isn't supported, so also test document.documentMode. | |
doc_mode = doc.documentMode, | |
supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 ); | |
// Get location.hash (or what you'd expect location.hash to be) sans any | |
// leading #. Thanks for making this necessary, Firefox! | |
function get_fragment( url ) { | |
url = url || location.href; | |
return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' ); | |
}; | |
// Method: jQuery.fn.hashchange | |
// | |
// Bind a handler to the window.onhashchange event or trigger all bound | |
// window.onhashchange event handlers. This behavior is consistent with | |
// jQuery's built-in event handlers. | |
// | |
// Usage: | |
// | |
// > jQuery(window).hashchange( [ handler ] ); | |
// | |
// Arguments: | |
// | |
// handler - (Function) Optional handler to be bound to the hashchange | |
// event. This is a "shortcut" for the more verbose form: | |
// jQuery(window).bind( 'hashchange', handler ). If handler is omitted, | |
// all bound window.onhashchange event handlers will be triggered. This | |
// is a shortcut for the more verbose | |
// jQuery(window).trigger( 'hashchange' ). These forms are described in | |
// the <hashchange event> section. | |
// | |
// Returns: | |
// | |
// (jQuery) The initial jQuery collection of elements. | |
// Allow the "shortcut" format $(elem).hashchange( fn ) for binding and | |
// $(elem).hashchange() for triggering, like jQuery does for built-in events. | |
$.fn[ str_hashchange ] = function( fn ) { | |
return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange ); | |
}; | |
// Property: jQuery.fn.hashchange.delay | |
// | |
// The numeric interval (in milliseconds) at which the <hashchange event> | |
// polling loop executes. Defaults to 50. | |
// Property: jQuery.fn.hashchange.domain | |
// | |
// If you're setting document.domain in your JavaScript, and you want hash | |
// history to work in IE6/7, not only must this property be set, but you must | |
// also set document.domain BEFORE jQuery is loaded into the page. This | |
// property is only applicable if you are supporting IE6/7 (or IE8 operating | |
// in "IE7 compatibility" mode). | |
// | |
// In addition, the <jQuery.fn.hashchange.src> property must be set to the | |
// path of the included "document-domain.html" file, which can be renamed or | |
// modified if necessary (note that the document.domain specified must be the | |
// same in both your main JavaScript as well as in this file). | |
// | |
// Usage: | |
// | |
// jQuery.fn.hashchange.domain = document.domain; | |
// Property: jQuery.fn.hashchange.src | |
// | |
// If, for some reason, you need to specify an Iframe src file (for example, | |
// when setting document.domain as in <jQuery.fn.hashchange.domain>), you can | |
// do so using this property. Note that when using this property, history | |
// won't be recorded in IE6/7 until the Iframe src file loads. This property | |
// is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7 | |
// compatibility" mode). | |
// | |
// Usage: | |
// | |
// jQuery.fn.hashchange.src = 'path/to/file.html'; | |
$.fn[ str_hashchange ].delay = 50; | |
/* | |
$.fn[ str_hashchange ].domain = null; | |
$.fn[ str_hashchange ].src = null; | |
*/ | |
// Event: hashchange event | |
// | |
// Fired when location.hash changes. In browsers that support it, the native | |
// HTML5 window.onhashchange event is used, otherwise a polling loop is | |
// initialized, running every <jQuery.fn.hashchange.delay> milliseconds to | |
// see if the hash has changed. In IE6/7 (and IE8 operating in "IE7 | |
// compatibility" mode), a hidden Iframe is created to allow the back button | |
// and hash-based history to work. | |
// | |
// Usage as described in <jQuery.fn.hashchange>: | |
// | |
// > // Bind an event handler. | |
// > jQuery(window).hashchange( function(e) { | |
// > var hash = location.hash; | |
// > ... | |
// > }); | |
// > | |
// > // Manually trigger the event handler. | |
// > jQuery(window).hashchange(); | |
// | |
// A more verbose usage that allows for event namespacing: | |
// | |
// > // Bind an event handler. | |
// > jQuery(window).bind( 'hashchange', function(e) { | |
// > var hash = location.hash; | |
// > ... | |
// > }); | |
// > | |
// > // Manually trigger the event handler. | |
// > jQuery(window).trigger( 'hashchange' ); | |
// | |
// Additional Notes: | |
// | |
// * The polling loop and Iframe are not created until at least one handler | |
// is actually bound to the 'hashchange' event. | |
// * If you need the bound handler(s) to execute immediately, in cases where | |
// a location.hash exists on page load, via bookmark or page refresh for | |
// example, use jQuery(window).hashchange() or the more verbose | |
// jQuery(window).trigger( 'hashchange' ). | |
// * The event can be bound before DOM ready, but since it won't be usable | |
// before then in IE6/7 (due to the necessary Iframe), recommended usage is | |
// to bind it inside a DOM ready handler. | |
// Override existing $.event.special.hashchange methods (allowing this plugin | |
// to be defined after jQuery BBQ in BBQ's source code). | |
special[ str_hashchange ] = $.extend( special[ str_hashchange ], { | |
// Called only when the first 'hashchange' event is bound to window. | |
setup: function() { | |
// If window.onhashchange is supported natively, there's nothing to do.. | |
if ( supports_onhashchange ) { return false; } | |
// Otherwise, we need to create our own. And we don't want to call this | |
// until the user binds to the event, just in case they never do, since it | |
// will create a polling loop and possibly even a hidden Iframe. | |
$( fake_onhashchange.start ); | |
}, | |
// Called only when the last 'hashchange' event is unbound from window. | |
teardown: function() { | |
// If window.onhashchange is supported natively, there's nothing to do.. | |
if ( supports_onhashchange ) { return false; } | |
// Otherwise, we need to stop ours (if possible). | |
$( fake_onhashchange.stop ); | |
} | |
}); | |
// fake_onhashchange does all the work of triggering the window.onhashchange | |
// event for browsers that don't natively support it, including creating a | |
// polling loop to watch for hash changes and in IE 6/7 creating a hidden | |
// Iframe to enable back and forward. | |
fake_onhashchange = (function(){ | |
var self = {}, | |
timeout_id, | |
// Remember the initial hash so it doesn't get triggered immediately. | |
last_hash = get_fragment(), | |
fn_retval = function(val){ return val; }, | |
history_set = fn_retval, | |
history_get = fn_retval; | |
// Start the polling loop. | |
self.start = function() { | |
timeout_id || poll(); | |
}; | |
// Stop the polling loop. | |
self.stop = function() { | |
timeout_id && clearTimeout( timeout_id ); | |
timeout_id = undefined; | |
}; | |
// This polling loop checks every $.fn.hashchange.delay milliseconds to see | |
// if location.hash has changed, and triggers the 'hashchange' event on | |
// window when necessary. | |
function poll() { | |
var hash = get_fragment(), | |
history_hash = history_get( last_hash ); | |
if ( hash !== last_hash ) { | |
history_set( last_hash = hash, history_hash ); | |
$(window).trigger( str_hashchange ); | |
} else if ( history_hash !== last_hash ) { | |
location.href = location.href.replace( /#.*/, '' ) + history_hash; | |
} | |
timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay ); | |
}; | |
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | |
// vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv | |
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | |
$.browser.msie && !supports_onhashchange && (function(){ | |
// Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8 | |
// when running in "IE7 compatibility" mode. | |
var iframe, | |
iframe_src; | |
// When the event is bound and polling starts in IE 6/7, create a hidden | |
// Iframe for history handling. | |
self.start = function(){ | |
if ( !iframe ) { | |
iframe_src = $.fn[ str_hashchange ].src; | |
iframe_src = iframe_src && iframe_src + get_fragment(); | |
// Create hidden Iframe. Attempt to make Iframe as hidden as possible | |
// by using techniques from http://www.paciellogroup.com/blog/?p=604. | |
iframe = $('<iframe tabindex="-1" title="empty"/>').hide() | |
// When Iframe has completely loaded, initialize the history and | |
// start polling. | |
.one( 'load', function(){ | |
iframe_src || history_set( get_fragment() ); | |
poll(); | |
}) | |
// Load Iframe src if specified, otherwise nothing. | |
.attr( 'src', iframe_src || 'javascript:0' ) | |
// Append Iframe after the end of the body to prevent unnecessary | |
// initial page scrolling (yes, this works). | |
.insertAfter( 'body' )[0].contentWindow; | |
// Whenever `document.title` changes, update the Iframe's title to | |
// prettify the back/next history menu entries. Since IE sometimes | |
// errors with "Unspecified error" the very first time this is set | |
// (yes, very useful) wrap this with a try/catch block. | |
doc.onpropertychange = function(){ | |
try { | |
if ( event.propertyName === 'title' ) { | |
iframe.document.title = doc.title; | |
} | |
} catch(e) {} | |
}; | |
} | |
}; | |
// Override the "stop" method since an IE6/7 Iframe was created. Even | |
// if there are no longer any bound event handlers, the polling loop | |
// is still necessary for back/next to work at all! | |
self.stop = fn_retval; | |
// Get history by looking at the hidden Iframe's location.hash. | |
history_get = function() { | |
return get_fragment( iframe.location.href ); | |
}; | |
// Set a new history item by opening and then closing the Iframe | |
// document, *then* setting its location.hash. If document.domain has | |
// been set, update that as well. | |
history_set = function( hash, history_hash ) { | |
var iframe_doc = iframe.document, | |
domain = $.fn[ str_hashchange ].domain; | |
if ( hash !== history_hash ) { | |
// Update Iframe with any initial `document.title` that might be set. | |
iframe_doc.title = doc.title; | |
// Opening the Iframe's document after it has been closed is what | |
// actually adds a history entry. | |
iframe_doc.open(); | |
// Set document.domain for the Iframe document as well, if necessary. | |
domain && iframe_doc.write( '<script>document.domain="' + domain + '"</script>' ); | |
iframe_doc.close(); | |
// Update the Iframe's hash, for great justice. | |
iframe.location.hash = hash; | |
} | |
}; | |
})(); | |
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
// ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^ | |
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
return self; | |
})(); | |
})(jQuery,this); | |
/*! | |
* jQuery Mobile v@VERSION | |
* http://jquerymobile.com/ | |
* | |
* Copyright 2010, jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function( $, window, undefined ) { | |
//jQuery.mobile configurable options | |
$.extend( $.mobile, { | |
//define the url parameter used for referencing widget-generated sub-pages. | |
//Translates to to example.html&ui-page=subpageIdentifier | |
//hash segment before &ui-page= is used to make Ajax request | |
subPageUrlKey: 'ui-page', | |
//anchor links with a data-rel, or pages with a data-role, that match these selectors will be untrackable in history | |
//(no change in URL, not bookmarkable) | |
nonHistorySelectors: 'dialog', | |
//class assigned to page currently in view, and during transitions | |
activePageClass: 'ui-page-active', | |
//class used for "active" button state, from CSS framework | |
activeBtnClass: 'ui-btn-active', | |
//automatically handle link clicks through Ajax, when possible | |
ajaxLinksEnabled: true, | |
//automatically handle form submissions through Ajax, when possible | |
ajaxFormsEnabled: true, | |
//set default transition - 'none' for no transitions | |
defaultTransition: 'slide', | |
//show loading message during Ajax requests | |
//if false, message will not appear, but loading classes will still be toggled on html el | |
loadingMessage: "loading", | |
//configure meta viewport tag's content attr: | |
metaViewportContent: "width=device-width, minimum-scale=1, maximum-scale=1", | |
//support conditions that must be met in order to proceed | |
gradeA: function(){ | |
return $.support.mediaquery; | |
} | |
}); | |
//trigger mobileinit event - useful hook for configuring $.mobile settings before they're used | |
$( window.document ).trigger('mobileinit'); | |
//support conditions | |
//if device support condition(s) aren't met, leave things as they are -> a basic, usable experience, | |
//otherwise, proceed with the enhancements | |
if ( !$.mobile.gradeA() ) { | |
return; | |
} | |
//define vars for interal use | |
var $window = $(window), | |
$html = $('html'), | |
$head = $('head'), | |
//loading div which appears during Ajax requests | |
//will not appear if $.mobile.loadingMessage is false | |
$loader = $.mobile.loadingMessage ? | |
$('<div class="ui-loader ui-body-a ui-corner-all">'+ | |
'<span class="ui-icon ui-icon-loading spin"></span>'+ | |
'<h1>'+ $.mobile.loadingMessage +'</h1>'+ | |
'</div>') | |
: undefined; | |
//add mobile, initial load "rendering" classes to docEl | |
$html.addClass('ui-mobile ui-mobile-rendering'); | |
//define & prepend meta viewport tag, if content is defined | |
$.mobile.metaViewportContent ? $("<meta>", { name: "viewport", content: $.mobile.metaViewportContent}).prependTo( $head ) : undefined; | |
//expose some core utilities | |
$.extend($.mobile, { | |
// turn on/off page loading message. | |
pageLoading: function ( done ) { | |
if ( done ) { | |
$html.removeClass( "ui-loading" ); | |
} else { | |
if( $.mobile.loadingMessage ){ | |
$loader.appendTo($.mobile.pageContainer).css({top: $(window).scrollTop() + 75}); | |
} | |
$html.addClass( "ui-loading" ); | |
} | |
}, | |
//scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value | |
silentScroll: function( ypos ) { | |
// prevent scrollstart and scrollstop events | |
$.event.special.scrollstart.enabled = false; | |
setTimeout(function() { | |
window.scrollTo( 0, ypos || 0 ); | |
},20); | |
setTimeout(function() { | |
$.event.special.scrollstart.enabled = true; | |
}, 150 ); | |
} | |
}); | |
//dom-ready inits | |
$(function(){ | |
//find present pages | |
var $pages = $("[data-role='page']"); | |
//set up active page | |
$.mobile.startPage = $.mobile.activePage = $pages.first(); | |
//set page container | |
$.mobile.pageContainer = $.mobile.startPage.parent().addClass('ui-mobile-viewport'); | |
//cue page loading message | |
$.mobile.pageLoading(); | |
//initialize all pages present | |
$pages.page(); | |
//trigger a new hashchange, hash or not | |
$window.trigger( "hashchange", [ true ] ); | |
//remove rendering class | |
$html.removeClass('ui-mobile-rendering'); | |
}); | |
//window load event | |
//hide iOS browser chrome on load | |
$window.load( $.mobile.silentScroll ); | |
})( jQuery, this ); | |
/* | |
* jQuery Mobile Framework : core utilities for auto ajax navigation, base tag mgmt, | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
//define vars for interal use | |
var $window = $(window), | |
$html = $('html'), | |
$head = $('head'), | |
//url path helpers for use in relative url management | |
path = { | |
//get path from current hash, or from a file path | |
get: function( newPath ){ | |
if( newPath == undefined ){ | |
newPath = location.hash; | |
} | |
newPath = newPath.replace(/#/,'').split('/'); | |
newPath.pop(); | |
return newPath.join('/') + (newPath.length ? '/' : ''); | |
}, | |
//return the substring of a filepath before the sub-page key, for making a server request | |
getFilePath: function( path ){ | |
var splitkey = '&' + $.mobile.subPageUrlKey; | |
return path.indexOf( splitkey ) > -1 ? path.split( splitkey )[0] : path; | |
}, | |
set: function( path, disableListening){ | |
if(disableListening) { hashListener = false; } | |
location.hash = path; | |
}, | |
//location pathname from intial directory request | |
origin: null, | |
setOrigin: function(){ | |
path.origin = path.get( location.protocol + '//' + location.host + location.pathname ); | |
} | |
}, | |
//base element management, defined depending on dynamic base tag support | |
base = $.support.dynamicBaseTag ? { | |
//define base element, for use in routing asset urls that are referenced in Ajax-requested markup | |
element: $("<base>", { href: path.origin }).prependTo( $head ), | |
//set the generated BASE element's href attribute to a new page's base path | |
set: function( href ){ | |
base.element.attr('href', path.origin + path.get( href )); | |
}, | |
//set the generated BASE element's href attribute to a new page's base path | |
reset: function(){ | |
base.element.attr('href', path.origin ); | |
} | |
} : undefined, | |
//will be defined when a link is clicked and given an active class | |
$activeClickedLink = null, | |
//array of pages that are visited during a single page load | |
//length will grow as pages are visited, and shrink as "back" link/button is clicked | |
//each item has a url (string matches ID), and transition (saved for reuse when "back" link/button is clicked) | |
urlStack = [ { | |
url: location.hash.replace( /^#/, "" ), | |
transition: undefined | |
} ], | |
//define first selector to receive focus when a page is shown | |
focusable = "[tabindex],a,button:visible,select:visible,input", | |
//contains role for next page, if defined on clicked link via data-rel | |
nextPageRole = null, | |
//enable/disable hashchange event listener | |
//toggled internally when location.hash is updated to match the url of a successful page load | |
hashListener = true; | |
//set location pathname from intial directory request | |
path.setOrigin(); | |
/* | |
internal utility functions | |
--------------------------------------*/ | |
//direct focus to the page title, or otherwise first focusable element | |
function reFocus( page ){ | |
var pageTitle = page.find( ".ui-title:eq(0)" ); | |
if( pageTitle.length ){ | |
pageTitle.focus(); | |
} | |
else{ | |
page.find( focusable ).eq(0).focus(); | |
} | |
}; | |
//remove active classes after page transition or error | |
function removeActiveLinkClass( forceRemoval ){ | |
if( !!$activeClickedLink && (!$activeClickedLink.closest( '.ui-page-active' ).length || forceRemoval )){ | |
$activeClickedLink.removeClass( $.mobile.activeBtnClass ); | |
} | |
$activeClickedLink = null; | |
}; | |
//animation complete callback | |
$.fn.animationComplete = function( callback ){ | |
if($.support.cssTransitions){ | |
return $(this).one('webkitAnimationEnd', callback); | |
} | |
else{ | |
callback(); | |
} | |
}; | |
/* exposed $.mobile methods */ | |
//update location.hash, with or without triggering hashchange event | |
$.mobile.updateHash = path.set; | |
//url stack, useful when plugins need to be aware of previous pages viewed | |
$.mobile.urlStack = urlStack; | |
// changepage function | |
$.mobile.changePage = function( to, transition, back, changeHash){ | |
//from is always the currently viewed page | |
var toIsArray = $.type(to) === "array", | |
from = toIsArray ? to[0] : $.mobile.activePage, | |
to = toIsArray ? to[1] : to, | |
url = fileUrl = $.type(to) === "string" ? to.replace( /^#/, "" ) : null, | |
data = undefined, | |
type = 'get', | |
isFormRequest = false, | |
duplicateCachedPage = null, | |
back = (back !== undefined) ? back : ( urlStack.length > 1 && urlStack[ urlStack.length - 2 ].url === url ), | |
transition = (transition !== undefined) ? transition : $.mobile.defaultTransition; | |
if( $.type(to) === "object" && to.url ){ | |
url = to.url, | |
data = to.data, | |
type = to.type, | |
isFormRequest = true; | |
//make get requests bookmarkable | |
if( data && type == 'get' ){ | |
url += "?" + data; | |
data = undefined; | |
} | |
} | |
//reset base to pathname for new request | |
if(base){ base.reset(); } | |
// if the new href is the same as the previous one | |
if ( back ) { | |
var pop = urlStack.pop(); | |
if( pop ){ | |
transition = pop.transition; | |
} | |
} else { | |
urlStack.push({ url: url, transition: transition }); | |
} | |
//function for transitioning between two existing pages | |
function transitionPages() { | |
//kill the keyboard | |
$( window.document.activeElement ).blur(); | |
//get current scroll distance | |
var currScroll = $window.scrollTop(); | |
//set as data for returning to that spot | |
from.data('lastScroll', currScroll); | |
//trigger before show/hide events | |
from.data("page")._trigger("beforehide", {nextPage: to}); | |
to.data("page")._trigger("beforeshow", {prevPage: from}); | |
function loadComplete(){ | |
$.mobile.pageLoading( true ); | |
//trigger show/hide events, allow preventing focus change through return false | |
if( from.data("page")._trigger("hide", null, {nextPage: to}) !== false && to.data("page")._trigger("show", null, {prevPage: from}) !== false ){ | |
$.mobile.activePage = to; | |
} | |
reFocus( to ); | |
if( changeHash !== false && url ){ | |
path.set(url, true); | |
} | |
removeActiveLinkClass(); | |
//if there's a duplicateCachedPage, remove it from the DOM now that it's hidden | |
if( duplicateCachedPage != null ){ | |
duplicateCachedPage.remove(); | |
} | |
//jump to top or prev scroll, if set | |
$.mobile.silentScroll( to.data( 'lastScroll' ) ); | |
}; | |
if(transition && (transition !== 'none')){ | |
$.mobile.pageContainer.addClass('ui-mobile-viewport-transitioning'); | |
// animate in / out | |
from.addClass( transition + " out " + ( back ? "reverse" : "" ) ); | |
to.addClass( $.mobile.activePageClass + " " + transition + | |
" in " + ( back ? "reverse" : "" ) ); | |
// callback - remove classes, etc | |
to.animationComplete(function() { | |
from.add( to ).removeClass("out in reverse " + transition ); | |
from.removeClass( $.mobile.activePageClass ); | |
loadComplete(); | |
$.mobile.pageContainer.removeClass('ui-mobile-viewport-transitioning'); | |
}); | |
} | |
else{ | |
from.removeClass( $.mobile.activePageClass ); | |
to.addClass( $.mobile.activePageClass ); | |
loadComplete(); | |
} | |
}; | |
//shared page enhancements | |
function enhancePage(){ | |
//set next page role, if defined | |
if ( nextPageRole ) { | |
to.attr( "data-role", nextPageRole ); | |
nextPageRole = undefined; | |
} | |
//run page plugin | |
to.page(); | |
}; | |
//if url is a string | |
if( url ){ | |
to = $( "[id='" + url + "']" ), | |
fileUrl = path.getFilePath(url); | |
} | |
else{ //find base url of element, if avail | |
var toID = to.attr('id'), | |
toIDfileurl = path.getFilePath(toID); | |
if(toID != toIDfileurl){ | |
fileUrl = toIDfileurl; | |
} | |
} | |
// find the "to" page, either locally existing in the dom or by creating it through ajax | |
if ( to.length && !isFormRequest ) { | |
if( fileUrl && base ){ | |
base.set( fileUrl ); | |
} | |
enhancePage(); | |
transitionPages(); | |
} else { | |
//if to exists in DOM, save a reference to it in duplicateCachedPage for removal after page change | |
if( to.length ){ | |
duplicateCachedPage = to; | |
} | |
$.mobile.pageLoading(); | |
$.ajax({ | |
url: fileUrl, | |
type: type, | |
data: data, | |
success: function( html ) { | |
if(base){ base.set(fileUrl); } | |
var all = $("<div></div>"); | |
//workaround to allow scripts to execute when included in page divs | |
all.get(0).innerHTML = html; | |
to = all.find('[data-role="page"]'); | |
//rewrite src and href attrs to use a base url | |
if( !$.support.dynamicBaseTag ){ | |
var newPath = path.get( fileUrl ); | |
to.find('[src],link[href]').each(function(){ | |
var thisAttr = $(this).is('[href]') ? 'href' : 'src', | |
thisUrl = $(this).attr(thisAttr); | |
//if full path exists and is same, chop it - helps IE out | |
thisUrl.replace( location.protocol + '//' + location.host + location.pathname, '' ); | |
if( !/^(\w+:|#|\/)/.test(thisUrl) ){ | |
$(this).attr(thisAttr, newPath + thisUrl); | |
} | |
}); | |
} | |
//preserve ID on a retrieved page | |
if ( to.attr('id') ) { | |
//wrap page and transfer data-attrs if it has an ID | |
var copyAttrs = ['data-role', 'data-theme', 'data-fullscreen'], //TODO: more page-level attrs? | |
wrapper = to.wrap( "<div>" ).parent(); | |
$.each(copyAttrs,function(i){ | |
if( to.attr( copyAttrs[ i ] ) ){ | |
wrapper.attr( copyAttrs[ i ], to.attr( copyAttrs[ i ] ) ); | |
to.removeAttr( copyAttrs[ i ] ); | |
} | |
}); | |
to = wrapper; | |
} | |
to | |
.attr( "id", fileUrl ) | |
.appendTo( $.mobile.pageContainer ); | |
enhancePage(); | |
transitionPages(); | |
}, | |
error: function() { | |
$.mobile.pageLoading( true ); | |
removeActiveLinkClass(true); | |
$("<div class='ui-loader ui-overlay-shadow ui-body-e ui-corner-all'><h1>Error Loading Page</h1></div>") | |
.css({ "display": "block", "opacity": 0.96, "top": $(window).scrollTop() + 100 }) | |
.appendTo( $.mobile.pageContainer ) | |
.delay( 800 ) | |
.fadeOut( 400, function(){ | |
$(this).remove(); | |
}); | |
} | |
}); | |
} | |
}; | |
/* Event Bindings - hashchange, submit, and click */ | |
//bind to form submit events, handle with Ajax | |
$('form').live('submit', function(event){ | |
if( !$.mobile.ajaxFormsEnabled ){ return; } | |
var type = $(this).attr("method"), | |
url = $(this).attr( "action" ).replace( location.protocol + "//" + location.host, ""); | |
//external submits use regular HTTP | |
if( /^(:?\w+:)/.test( url ) ){ | |
return; | |
} | |
//if it's a relative href, prefix href with base url | |
if( url.indexOf('/') && url.indexOf('#') !== 0 ){ | |
url = path.get() + url; | |
} | |
$.mobile.changePage({ | |
url: url, | |
type: type, | |
data: $(this).serialize() | |
}, | |
undefined, | |
undefined, | |
true | |
); | |
event.preventDefault(); | |
}); | |
//click routing - direct to HTTP or Ajax, accordingly | |
$( "a" ).live( "click", function(event) { | |
if( !$.mobile.ajaxLinksEnabled ){ return; } | |
var $this = $(this), | |
//get href, remove same-domain protocol and host | |
href = $this.attr( "href" ).replace( location.protocol + "//" + location.host, ""), | |
//if target attr is specified, it's external, and we mimic _blank... for now | |
target = $this.is( "[target]" ), | |
//if it still starts with a protocol, it's external, or could be :mailto, etc | |
external = target || /^(:?\w+:)/.test( href ) || $this.is( "[rel=external]" ), | |
target = $this.is( "[target]" ); | |
if( href === '#' ){ | |
//for links created purely for interaction - ignore | |
return false; | |
} | |
$activeClickedLink = $this.closest( ".ui-btn" ).addClass( $.mobile.activeBtnClass ); | |
if( external || !$.mobile.ajaxLinksEnabled ){ | |
//remove active link class if external | |
removeActiveLinkClass(true); | |
//deliberately redirect, in case click was triggered | |
if( target ){ | |
window.open(href); | |
} | |
else{ | |
location.href = href; | |
} | |
} | |
else { | |
//use ajax | |
var transition = $this.data( "transition" ), | |
back = $this.data( "back" ), | |
changeHashOnSuccess = !$this.is( "[data-rel="+ $.mobile.nonHistorySelectors +"]" ); | |
nextPageRole = $this.attr( "data-rel" ); | |
//if it's a relative href, prefix href with base url | |
if( href.indexOf('/') && href.indexOf('#') !== 0 ){ | |
href = path.get() + href; | |
} | |
href.replace(/^#/,''); | |
$.mobile.changePage(href, transition, back, changeHashOnSuccess); | |
} | |
event.preventDefault(); | |
}); | |
//hashchange event handler | |
$window.bind( "hashchange", function(e, triggered) { | |
if( !hashListener ){ | |
hashListener = true; | |
return; | |
} | |
if( $(".ui-page-active").is("[data-role=" + $.mobile.nonHistorySelectors + "]") ){ | |
return; | |
} | |
var to = location.hash, | |
transition = triggered ? false : undefined; | |
//if to is defined, use it | |
if ( to ){ | |
$.mobile.changePage( to, transition); | |
} | |
//there's no hash, the active page is not the start page, and it's not manually triggered hashchange | |
//we probably backed out to the first page visited | |
else if( $.mobile.activePage.length && $.mobile.startPage[0] !== $.mobile.activePage[0] && !triggered ) { | |
$.mobile.changePage( $.mobile.startPage, transition, true ); | |
} | |
//probably the first page - show it | |
else{ | |
$.mobile.startPage.trigger("pagebeforeshow", {prevPage: $('')}); | |
$.mobile.startPage.addClass( $.mobile.activePageClass ); | |
$.mobile.pageLoading( true ); | |
if( $.mobile.startPage.trigger("pageshow", {prevPage: $('')}) !== false ){ | |
reFocus($.mobile.startPage); | |
} | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : "page" plugin | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.widget( "mobile.page", $.mobile.widget, { | |
options: { | |
backBtnText: "Back", | |
addBackBtn: true, | |
degradeInputs: { | |
color: false, | |
date: false, | |
datetime: false, | |
"datetime-local": false, | |
email: false, | |
month: false, | |
number: false, | |
range: "number", | |
search: true, | |
tel: false, | |
time: false, | |
url: false, | |
week: false | |
} | |
}, | |
_create: function() { | |
var $elem = this.element, | |
o = this.options; | |
if ( this._trigger( "beforeCreate" ) === false ) { | |
return; | |
} | |
//some of the form elements currently rely on the presence of ui-page and ui-content | |
// classes so we'll handle page and content roles outside of the main role processing | |
// loop below. | |
$elem.find( "[data-role='page'], [data-role='content']" ).andSelf().each(function() { | |
$(this).addClass( "ui-" + $(this).data( "role" ) ); | |
}); | |
$elem.find( "[data-role='nojs']" ).addClass( "ui-nojs" ); | |
this._enchanceControls(); | |
// pre-find data els | |
var $dataEls = $elem.find( "[data-role]" ).andSelf().each(function() { | |
var $this = $( this ), | |
role = $this.data( "role" ), | |
theme = $this.data( "theme" ); | |
//apply theming and markup modifications to page,header,content,footer | |
if ( role === "header" || role === "footer" ) { | |
$this.addClass( "ui-bar-" + (theme || $this.parent('[data-role=page]').data( "theme" ) || "a") ); | |
// add ARIA role | |
$this.attr( "role", role === "header" ? "banner" : "contentinfo" ); | |
//right,left buttons | |
var $headeranchors = $this.children( "a" ), | |
leftbtn = $headeranchors.hasClass( "ui-btn-left" ), | |
rightbtn = $headeranchors.hasClass( "ui-btn-right" ); | |
if ( !leftbtn ) { | |
leftbtn = $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length; | |
} | |
if ( !rightbtn ) { | |
rightbtn = $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length; | |
} | |
// auto-add back btn on pages beyond first view | |
if ( o.addBackBtn && role === "header" && | |
($.mobile.urlStack.length > 1 || $(".ui-page").length > 1) && | |
!leftbtn && !$this.data( "noBackBtn" ) ) { | |
$( "<a href='#' class='ui-btn-left' data-icon='arrow-l'>"+ o.backBtnText +"</a>" ) | |
.click(function() { | |
history.back(); | |
return false; | |
}) | |
.prependTo( $this ); | |
} | |
//page title | |
$this.children( "h1, h2, h3, h4, h5, h6" ) | |
.addClass( "ui-title" ) | |
//regardless of h element number in src, it becomes h1 for the enhanced page | |
.attr({ "tabindex": "0", "role": "heading", "aria-level": "1" }); | |
} else if ( role === "content" ) { | |
if ( theme ) { | |
$this.addClass( "ui-body-" + theme ); | |
} | |
// add ARIA role | |
$this.attr( "role", "main" ); | |
} else if ( role === "page" ) { | |
$this.addClass( "ui-body-" + (theme || "c") ); | |
} | |
switch(role) { | |
case "header": | |
case "footer": | |
case "page": | |
case "content": | |
$this.addClass( "ui-" + role ); | |
break; | |
case "collapsible": | |
case "fieldcontain": | |
case "navbar": | |
case "listview": | |
case "dialog": | |
$this[ role ](); | |
break; | |
} | |
}); | |
//links in bars, or those with data-role become buttons | |
$elem.find( "[data-role='button'], .ui-bar a, .ui-header a, .ui-footer a" ) | |
.not( ".ui-btn" ) | |
.buttonMarkup(); | |
$elem | |
.find("[data-role='controlgroup']") | |
.controlgroup(); | |
//links within content areas | |
$elem.find( "a:not(.ui-btn):not(.ui-link-inherit)" ) | |
.addClass( "ui-link" ); | |
//fix toolbars | |
$elem.fixHeaderFooter(); | |
}, | |
_enchanceControls: function() { | |
var o = this.options; | |
// degrade inputs to avoid poorly implemented native functionality | |
this.element.find( "input" ).each(function() { | |
var type = this.getAttribute( "type" ), | |
optType = o.degradeInputs[ type ] || "text"; | |
if ( o.degradeInputs[ type ] ) { | |
$( this ).replaceWith( | |
$( "<div>" ).html( $(this).clone() ).html() | |
.replace( /type="([a-zA-Z]+)"/, "type="+ optType +" data-type='$1'" ) ); | |
} | |
}); | |
// enchance form controls | |
this.element | |
.find( "[type='radio'], [type='checkbox']" ) | |
.checkboxradio(); | |
this.element | |
.find( "button, [type='button'], [type='submit'], [type='reset'], [type='image']" ) | |
.not( ".ui-nojs" ) | |
.button(); | |
this.element | |
.find( "input, textarea" ) | |
.not( "[type='radio'], [type='checkbox'], button, [type='button'], [type='submit'], [type='reset'], [type='image']" ) | |
.textinput(); | |
this.element | |
.find( "input, select" ) | |
.filter( "[data-role='slider'], [data-type='range']" ) | |
.slider(); | |
this.element | |
.find( "select:not([data-role='slider'])" ) | |
.selectmenu(); | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery UI Position @VERSION | |
* | |
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
* | |
* http://docs.jquery.com/UI/Position | |
*/ | |
(function( $, undefined ) { | |
$.ui = $.ui || {}; | |
var horizontalPositions = /left|center|right/, | |
verticalPositions = /top|center|bottom/, | |
center = "center", | |
_position = $.fn.position, | |
_offset = $.fn.offset; | |
$.fn.position = function( options ) { | |
if ( !options || !options.of ) { | |
return _position.apply( this, arguments ); | |
} | |
// make a copy, we don't want to modify arguments | |
options = $.extend( {}, options ); | |
var target = $( options.of ), | |
targetElem = target[0], | |
collision = ( options.collision || "flip" ).split( " " ), | |
offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ], | |
targetWidth, | |
targetHeight, | |
basePosition; | |
if ( targetElem.nodeType === 9 ) { | |
targetWidth = target.width(); | |
targetHeight = target.height(); | |
basePosition = { top: 0, left: 0 }; | |
// TODO: use $.isWindow() in 1.9 | |
} else if ( targetElem.setTimeout ) { | |
targetWidth = target.width(); | |
targetHeight = target.height(); | |
basePosition = { top: target.scrollTop(), left: target.scrollLeft() }; | |
} else if ( targetElem.preventDefault ) { | |
// force left top to allow flipping | |
options.at = "left top"; | |
targetWidth = targetHeight = 0; | |
basePosition = { top: options.of.pageY, left: options.of.pageX }; | |
} else { | |
targetWidth = target.outerWidth(); | |
targetHeight = target.outerHeight(); | |
basePosition = target.offset(); | |
} | |
// force my and at to have valid horizontal and veritcal positions | |
// if a value is missing or invalid, it will be converted to center | |
$.each( [ "my", "at" ], function() { | |
var pos = ( options[this] || "" ).split( " " ); | |
if ( pos.length === 1) { | |
pos = horizontalPositions.test( pos[0] ) ? | |
pos.concat( [center] ) : | |
verticalPositions.test( pos[0] ) ? | |
[ center ].concat( pos ) : | |
[ center, center ]; | |
} | |
pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center; | |
pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center; | |
options[ this ] = pos; | |
}); | |
// normalize collision option | |
if ( collision.length === 1 ) { | |
collision[ 1 ] = collision[ 0 ]; | |
} | |
// normalize offset option | |
offset[ 0 ] = parseInt( offset[0], 10 ) || 0; | |
if ( offset.length === 1 ) { | |
offset[ 1 ] = offset[ 0 ]; | |
} | |
offset[ 1 ] = parseInt( offset[1], 10 ) || 0; | |
if ( options.at[0] === "right" ) { | |
basePosition.left += targetWidth; | |
} else if (options.at[0] === center ) { | |
basePosition.left += targetWidth / 2; | |
} | |
if ( options.at[1] === "bottom" ) { | |
basePosition.top += targetHeight; | |
} else if ( options.at[1] === center ) { | |
basePosition.top += targetHeight / 2; | |
} | |
basePosition.left += offset[ 0 ]; | |
basePosition.top += offset[ 1 ]; | |
return this.each(function() { | |
var elem = $( this ), | |
elemWidth = elem.outerWidth(), | |
elemHeight = elem.outerHeight(), | |
marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, | |
marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, | |
collisionWidth = elemWidth + marginLeft + | |
parseInt( $.curCSS( this, "marginRight", true ) ) || 0, | |
collisionHeight = elemHeight + marginTop + | |
parseInt( $.curCSS( this, "marginBottom", true ) ) || 0, | |
position = $.extend( {}, basePosition ), | |
collisionPosition; | |
if ( options.my[0] === "right" ) { | |
position.left -= elemWidth; | |
} else if ( options.my[0] === center ) { | |
position.left -= elemWidth / 2; | |
} | |
if ( options.my[1] === "bottom" ) { | |
position.top -= elemHeight; | |
} else if ( options.my[1] === center ) { | |
position.top -= elemHeight / 2; | |
} | |
// prevent fractions (see #5280) | |
position.left = parseInt( position.left ); | |
position.top = parseInt( position.top ); | |
collisionPosition = { | |
left: position.left - marginLeft, | |
top: position.top - marginTop | |
}; | |
$.each( [ "left", "top" ], function( i, dir ) { | |
if ( $.ui.position[ collision[i] ] ) { | |
$.ui.position[ collision[i] ][ dir ]( position, { | |
targetWidth: targetWidth, | |
targetHeight: targetHeight, | |
elemWidth: elemWidth, | |
elemHeight: elemHeight, | |
collisionPosition: collisionPosition, | |
collisionWidth: collisionWidth, | |
collisionHeight: collisionHeight, | |
offset: offset, | |
my: options.my, | |
at: options.at | |
}); | |
} | |
}); | |
if ( $.fn.bgiframe ) { | |
elem.bgiframe(); | |
} | |
elem.offset( $.extend( position, { using: options.using } ) ); | |
}); | |
}; | |
$.ui.position = { | |
fit: { | |
left: function( position, data ) { | |
var win = $( window ), | |
over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); | |
position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left ); | |
}, | |
top: function( position, data ) { | |
var win = $( window ), | |
over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); | |
position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top ); | |
} | |
}, | |
flip: { | |
left: function( position, data ) { | |
if ( data.at[0] === center ) { | |
return; | |
} | |
var win = $( window ), | |
over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), | |
myOffset = data.my[ 0 ] === "left" ? | |
-data.elemWidth : | |
data.my[ 0 ] === "right" ? | |
data.elemWidth : | |
0, | |
atOffset = data.at[ 0 ] === "left" ? | |
data.targetWidth : | |
-data.targetWidth, | |
offset = -2 * data.offset[ 0 ]; | |
position.left += data.collisionPosition.left < 0 ? | |
myOffset + atOffset + offset : | |
over > 0 ? | |
myOffset + atOffset + offset : | |
0; | |
}, | |
top: function( position, data ) { | |
if ( data.at[1] === center ) { | |
return; | |
} | |
var win = $( window ), | |
over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), | |
myOffset = data.my[ 1 ] === "top" ? | |
-data.elemHeight : | |
data.my[ 1 ] === "bottom" ? | |
data.elemHeight : | |
0, | |
atOffset = data.at[ 1 ] === "top" ? | |
data.targetHeight : | |
-data.targetHeight, | |
offset = -2 * data.offset[ 1 ]; | |
position.top += data.collisionPosition.top < 0 ? | |
myOffset + atOffset + offset : | |
over > 0 ? | |
myOffset + atOffset + offset : | |
0; | |
} | |
} | |
}; | |
// offset setter from jQuery 1.4 | |
if ( !$.offset.setOffset ) { | |
$.offset.setOffset = function( elem, options ) { | |
// set position first, in-case top/left are set even on static elem | |
if ( /static/.test( $.curCSS( elem, "position" ) ) ) { | |
elem.style.position = "relative"; | |
} | |
var curElem = $( elem ), | |
curOffset = curElem.offset(), | |
curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, | |
curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, | |
props = { | |
top: (options.top - curOffset.top) + curTop, | |
left: (options.left - curOffset.left) + curLeft | |
}; | |
if ( 'using' in options ) { | |
options.using.call( elem, props ); | |
} else { | |
curElem.css( props ); | |
} | |
}; | |
$.fn.offset = function( options ) { | |
var elem = this[ 0 ]; | |
if ( !elem || !elem.ownerDocument ) { return null; } | |
if ( options ) { | |
return this.each(function() { | |
$.offset.setOffset( this, options ); | |
}); | |
} | |
return _offset.call( this ); | |
}; | |
} | |
}( jQuery )); | |
/* | |
* jQuery Mobile Framework : "fixHeaderFooter" plugin - on-demand positioning for headers,footers | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.fn.fixHeaderFooter = function(options){ | |
if( !$.support.scrollTop ){ return $(this); } | |
return $(this).each(function(){ | |
if( $(this).data('fullscreen') ){ $(this).addClass('ui-page-fullscreen'); } | |
$(this).find('.ui-header[data-position="fixed"]').addClass('ui-header-fixed ui-fixed-inline fade'); //should be slidedown | |
$(this).find('.ui-footer[data-position="fixed"]').addClass('ui-footer-fixed ui-fixed-inline fade'); //should be slideup | |
}); | |
}; | |
//single controller for all showing,hiding,toggling | |
$.fixedToolbars = (function(){ | |
if( !$.support.scrollTop ){ return; } | |
var currentstate = 'inline', | |
delayTimer, | |
ignoreTargets = 'a,input,textarea,select,button,label,.ui-header-fixed,.ui-footer-fixed', | |
toolbarSelector = '.ui-header-fixed:first, .ui-footer-fixed:not(.ui-footer-duplicate):last', | |
stickyFooter, //for storing quick references to duplicate footers | |
supportTouch = $.support.touch, | |
touchStartEvent = supportTouch ? "touchstart" : "mousedown", | |
touchStopEvent = supportTouch ? "touchend" : "mouseup", | |
stateBefore = null, | |
scrollTriggered = false; | |
$(function() { | |
$(document) | |
.bind(touchStartEvent,function(event){ | |
if( $(event.target).closest(ignoreTargets).length ){ return; } | |
stateBefore = currentstate; | |
$.fixedToolbars.hide(true); | |
}) | |
.bind('scrollstart',function(event){ | |
if( $(event.target).closest(ignoreTargets).length ){ return; } //because it could be a touchmove... | |
scrollTriggered = true; | |
if(stateBefore == null){ stateBefore = currentstate; } | |
$.fixedToolbars.hide(true); | |
}) | |
.bind(touchStopEvent,function(event){ | |
if( $(event.target).closest(ignoreTargets).length ){ return; } | |
if( !scrollTriggered ){ | |
$.fixedToolbars.toggle(stateBefore); | |
stateBefore = null; | |
} | |
}) | |
.bind('scrollstop',function(event){ | |
if( $(event.target).closest(ignoreTargets).length ){ return; } | |
scrollTriggered = false; | |
$.fixedToolbars.toggle( stateBefore == 'overlay' ? 'inline' : 'overlay' ); | |
stateBefore = null; | |
}); | |
//function to return another footer already in the dom with the same data-id | |
function findStickyFooter(el){ | |
var thisFooter = el.find('[data-role="footer"]'); | |
return $( '.ui-footer[data-id="'+ thisFooter.data('id') +'"]:not(.ui-footer-duplicate)' ).not(thisFooter); | |
} | |
//before page is shown, check for duplicate footer | |
$('.ui-page').live('pagebeforeshow', function(event, ui){ | |
stickyFooter = findStickyFooter( $(event.target) ); | |
if( stickyFooter.length ){ | |
//if the existing footer is the first of its kind, create a placeholder before stealing it | |
if( stickyFooter.parents('.ui-page:eq(0)').find('.ui-footer[data-id="'+ stickyFooter.data('id') +'"]').length == 1 ){ | |
stickyFooter.before( stickyFooter.clone().addClass('ui-footer-duplicate') ); | |
} | |
$(event.target).find('[data-role="footer"]').addClass('ui-footer-duplicate'); | |
stickyFooter.appendTo($.pageContainer).css('top',0); | |
setTop(stickyFooter); | |
} | |
}); | |
//after page is shown, append footer to new page | |
$('.ui-page').live('pageshow', function(event, ui){ | |
if( stickyFooter && stickyFooter.length ){ | |
stickyFooter.appendTo(event.target).css('top',0); | |
} | |
$.fixedToolbars.show(true, this); | |
}); | |
}); | |
// element.getBoundingClientRect() is broken in iOS 3.2.1 on the iPad. The | |
// coordinates inside of the rect it returns don't have the page scroll position | |
// factored out of it like the other platforms do. To get around this, | |
// we'll just calculate the top offset the old fashioned way until core has | |
// a chance to figure out how to handle this situation. | |
// | |
// TODO: We'll need to get rid of getOffsetTop() once a fix gets folded into core. | |
function getOffsetTop(ele) | |
{ | |
var top = 0; | |
if (ele) | |
{ | |
var op = ele.offsetParent, body = document.body; | |
top = ele.offsetTop; | |
while (ele && ele != body) | |
{ | |
top += ele.scrollTop || 0; | |
if (ele == op) | |
{ | |
top += op.offsetTop; | |
op = ele.offsetParent; | |
} | |
ele = ele.parentNode; | |
} | |
} | |
return top; | |
} | |
function setTop(el){ | |
var fromTop = $(window).scrollTop(), | |
thisTop = getOffsetTop(el[0]), // el.offset().top returns the wrong value on iPad iOS 3.2.1, call our workaround instead. | |
thisCSStop = el.css('top') == 'auto' ? 0 : parseFloat(el.css('top')), | |
screenHeight = window.innerHeight, | |
thisHeight = el.outerHeight(), | |
useRelative = el.parents('.ui-page:not(.ui-page-fullscreen)').length, | |
relval; | |
if( el.is('.ui-header-fixed') ){ | |
relval = fromTop - thisTop + thisCSStop; | |
if( relval < thisTop){ relval = 0; } | |
return el.css('top', ( useRelative ) ? relval : fromTop); | |
} | |
else{ | |
//relval = -1 * (thisTop - (fromTop + screenHeight) + thisCSStop + thisHeight); | |
//if( relval > thisTop ){ relval = 0; } | |
relval = fromTop + screenHeight - thisHeight - (thisTop - thisCSStop); | |
return el.css('top', ( useRelative ) ? relval : fromTop + screenHeight - thisHeight ); | |
} | |
} | |
//exposed methods | |
return { | |
show: function(immediately, page){ | |
currentstate = 'overlay'; | |
var $ap = page ? $(page) : ($.mobile.activePage ? $.mobile.activePage : $(".ui-page-active")); | |
return $ap.children( toolbarSelector ).each(function(){ | |
var el = $(this), | |
fromTop = $(window).scrollTop(), | |
thisTop = getOffsetTop(el[0]), // el.offset().top returns the wrong value on iPad iOS 3.2.1, call our workaround instead. | |
screenHeight = window.innerHeight, | |
thisHeight = el.outerHeight(), | |
alreadyVisible = (el.is('.ui-header-fixed') && fromTop <= thisTop + thisHeight) || (el.is('.ui-footer-fixed') && thisTop <= fromTop + screenHeight); | |
//add state class | |
el.addClass('ui-fixed-overlay').removeClass('ui-fixed-inline'); | |
if( !alreadyVisible && !immediately ){ | |
el.addClass('in').animationComplete(function(){ | |
el.removeClass('in'); | |
}); | |
} | |
setTop(el); | |
}); | |
}, | |
hide: function(immediately){ | |
currentstate = 'inline'; | |
var $ap = $.mobile.activePage ? $.mobile.activePage : $(".ui-page-active"); | |
return $ap.children( toolbarSelector ).each(function(){ | |
var el = $(this); | |
var thisCSStop = el.css('top'); thisCSStop = thisCSStop == 'auto' ? 0 : parseFloat(thisCSStop); | |
//add state class | |
el.addClass('ui-fixed-inline').removeClass('ui-fixed-overlay'); | |
if (thisCSStop < 0 || (el.is('.ui-header-fixed') && thisCSStop != 0)) | |
{ | |
if(immediately){ | |
el.css('top',0); | |
} | |
else{ | |
if( el.css('top') !== 'auto' && parseFloat(el.css('top')) !== 0 ){ | |
var classes = 'out reverse'; | |
el.addClass(classes).animationComplete(function(){ | |
el.removeClass(classes); | |
el.css('top',0); | |
}); | |
} | |
} | |
} | |
}); | |
}, | |
hideAfterDelay: function(){ | |
delayTimer = setTimeout(function(){ | |
$.fixedToolbars.hide(); | |
}, 3000); | |
}, | |
toggle: function(from){ | |
if(from){ currentstate = from; } | |
return (currentstate == 'overlay') ? $.fixedToolbars.hide() : $.fixedToolbars.show(); | |
} | |
}; | |
})(); | |
})(jQuery); | |
/* | |
* jQuery Mobile Framework : "checkboxradio" plugin | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.widget( "mobile.checkboxradio", $.mobile.widget, { | |
options: { | |
theme: null | |
}, | |
_create: function(){ | |
var input = this.element, | |
label = $("label[for='" + input.attr( "id" ) + "']"), | |
inputtype = input.attr( "type" ), | |
checkedicon = "ui-icon-" + inputtype + "-on", | |
uncheckedicon = "ui-icon-" + inputtype + "-off"; | |
if ( inputtype != "checkbox" && inputtype != "radio" ) { return; } | |
label | |
.buttonMarkup({ | |
theme: this.options.theme, | |
icon: this.element.parents( "[data-type='horizontal']" ).length ? undefined : uncheckedicon, | |
shadow: false | |
}); | |
// wrap the input + label in a div | |
input | |
.add( label ) | |
.wrapAll( "<div class='ui-" + inputtype +"'></div>" ); | |
label.bind({ | |
mouseover: function() { | |
if( $(this).parent().is('.ui-disabled') ){ return false; } | |
}, | |
mousedown: function() { | |
if( $(this).parent().is('.ui-disabled') ){ return false; } | |
label.data( "state", input.attr( "checked" ) ); | |
}, | |
click: function() { | |
setTimeout(function() { | |
if ( input.attr( "checked" ) === label.data( "state" ) ) { | |
input.trigger( "click" ); | |
} | |
}, 1); | |
} | |
}); | |
input | |
.bind({ | |
click: function() { | |
$( "input[name='" + input.attr( "name" ) + "'][type='" + inputtype + "']" ).checkboxradio( "refresh" ); | |
}, | |
focus: function() { | |
label.addClass( "ui-focus" ); | |
}, | |
blur: function() { | |
label.removeClass( "ui-focus" ); | |
} | |
}); | |
this.refresh(); | |
}, | |
refresh: function( ){ | |
var input = this.element, | |
label = $("label[for='" + input.attr( "id" ) + "']"), | |
inputtype = input.attr( "type" ), | |
icon = label.find( ".ui-icon" ), | |
checkedicon = "ui-icon-" + inputtype + "-on", | |
uncheckedicon = "ui-icon-" + inputtype + "-off"; | |
if ( input[0].checked ) { | |
label.addClass( "ui-btn-active" ); | |
icon.addClass( checkedicon ); | |
icon.removeClass( uncheckedicon ); | |
} else { | |
label.removeClass( "ui-btn-active" ); | |
icon.removeClass( checkedicon ); | |
icon.addClass( uncheckedicon ); | |
} | |
if( input.is( ":disabled" ) ){ | |
this.disable(); | |
} | |
else { | |
this.enable(); | |
} | |
}, | |
disable: function(){ | |
this.element.attr("disabled",true).parent().addClass("ui-disabled"); | |
}, | |
enable: function(){ | |
this.element.attr("disabled",false).parent().removeClass("ui-disabled"); | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : "textinput" plugin for text inputs, textareas | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.widget( "mobile.textinput", $.mobile.widget, { | |
options: { | |
theme: null | |
}, | |
_create: function(){ | |
var input = this.element, | |
o = this.options, | |
theme = o.theme, | |
themeclass; | |
if ( !theme ) { | |
var themedParent = this.element.closest("[class*='ui-bar-'],[class*='ui-body-']"); | |
theme = themedParent.length ? | |
/ui-(bar|body)-([a-z])/.exec( themedParent.attr("class") )[2] : | |
"c"; | |
} | |
themeclass = " ui-body-" + theme; | |
$('label[for='+input.attr('id')+']').addClass('ui-input-text'); | |
input.addClass('ui-input-text ui-body-'+ o.theme); | |
var focusedEl = input; | |
//"search" input widget | |
if( input.is('[type="search"],[data-type="search"]') ){ | |
focusedEl = input.wrap('<div class="ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-search'+ themeclass +'"></div>').parent(); | |
var clearbtn = $('<a href="#" class="ui-input-clear" title="clear text">clear text</a>') | |
.click(function(){ | |
input.val('').focus(); | |
input.trigger('change'); | |
clearbtn.addClass('ui-input-clear-hidden'); | |
return false; | |
}) | |
.appendTo(focusedEl) | |
.buttonMarkup({icon: 'delete', iconpos: 'notext', corners:true, shadow:true}); | |
function toggleClear(){ | |
if(input.val() == ''){ | |
clearbtn.addClass('ui-input-clear-hidden'); | |
} | |
else{ | |
clearbtn.removeClass('ui-input-clear-hidden'); | |
} | |
} | |
toggleClear(); | |
input.keyup(toggleClear); | |
} | |
else{ | |
input.addClass('ui-corner-all ui-shadow-inset' + themeclass); | |
} | |
input | |
.focus(function(){ | |
focusedEl.addClass('ui-focus'); | |
}) | |
.blur(function(){ | |
focusedEl.removeClass('ui-focus'); | |
}); | |
//autogrow | |
if ( input.is('textarea') ) { | |
var extraLineHeight = 15, | |
keyupTimeoutBuffer = 100, | |
keyup = function() { | |
var scrollHeight = input[0].scrollHeight, | |
clientHeight = input[0].clientHeight; | |
if ( clientHeight < scrollHeight ) { | |
input.css({ height: (scrollHeight + extraLineHeight) }); | |
} | |
}, | |
keyupTimeout; | |
input.keyup(function() { | |
clearTimeout( keyupTimeout ); | |
keyupTimeout = setTimeout( keyup, keyupTimeoutBuffer ); | |
}); | |
} | |
}, | |
disable: function(){ | |
( this.element.attr("disabled",true).is('[type="search"],[data-type="search"]') ? this.element.parent() : this.element ).addClass("ui-disabled"); | |
}, | |
enable: function(){ | |
( this.element.attr("disabled", false).is('[type="search"],[data-type="search"]') ? this.element.parent() : this.element ).removeClass("ui-disabled"); | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : "selectmenu" plugin | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.widget( "mobile.selectmenu", $.mobile.widget, { | |
options: { | |
theme: null, | |
disabled: false, | |
icon: 'arrow-d', | |
iconpos: 'right', | |
inline: null, | |
corners: true, | |
shadow: true, | |
iconshadow: true, | |
menuPageTheme: 'b', | |
overlayTheme: 'a' | |
}, | |
_create: function(){ | |
var self = this, | |
o = this.options, | |
select = this.element | |
.attr( "tabindex", "-1" ) | |
.wrap( "<div class='ui-select'>" ), | |
selectID = select.attr( "id" ), | |
label = $( "label[for="+ selectID +"]" ).addClass( "ui-select" ), | |
buttonId = selectID + "-button", | |
menuId = selectID + "-menu", | |
thisPage = select.closest( ".ui-page" ), | |
button = $( "<a>", { | |
"href": "#", | |
"role": "button", | |
"id": buttonId, | |
"aria-haspopup": "true", | |
"aria-owns": menuId | |
}) | |
.text( $( select[0].options.item(select[0].selectedIndex) ).text() ) | |
.insertBefore( select ) | |
.buttonMarkup({ | |
theme: o.theme, | |
icon: o.icon, | |
iconpos: o.iconpos, | |
inline: o.inline, | |
corners: o.corners, | |
shadow: o.shadow, | |
iconshadow: o.iconshadow | |
}), | |
theme = /ui-btn-up-([a-z])/.exec( button.attr("class") )[1], | |
menuPage = $( "<div data-role='dialog' data-theme='"+ o.menuPageTheme +"'>" + | |
"<div data-role='header'>" + | |
"<div class='ui-title'>" + label.text() + "</div>"+ | |
"</div>"+ | |
"<div data-role='content'></div>"+ | |
"</div>" ) | |
.appendTo( $.mobile.pageContainer ) | |
.page(), | |
menuPageContent = menuPage.find( ".ui-content" ), | |
screen = $( "<div>", {"class": "ui-selectmenu-screen ui-screen-hidden"}) | |
.appendTo( thisPage ), | |
listbox = $( "<div>", { "class": "ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all pop ui-body-" + o.overlayTheme } ) | |
.insertAfter(screen), | |
list = $( "<ul>", { | |
"class": "ui-selectmenu-list", | |
"id": menuId, | |
"role": "listbox", | |
"aria-labelledby": buttonId, | |
"data-theme": theme | |
}) | |
.appendTo( listbox ), | |
menuType; | |
//expose to other methods | |
$.extend(self, { | |
select: select, | |
selectID: selectID, | |
label: label, | |
buttonId:buttonId, | |
menuId:menuId, | |
thisPage:thisPage, | |
button:button, | |
menuPage:menuPage, | |
menuPageContent:menuPageContent, | |
screen:screen, | |
listbox:listbox, | |
list:list, | |
menuType:menuType | |
}); | |
//create list from select, update state | |
self.refresh(); | |
//disable if specified | |
if( this.options.disabled ){ this.disable(); } | |
//events on native select | |
select | |
.change(function(){ | |
self.refresh(); | |
}) | |
.focus(function(){ | |
$(this).blur(); | |
button.focus(); | |
}); | |
//button events | |
button.bind( $.support.touch ? "touchstart" : "click", function(event){ | |
self.open(); | |
return false; | |
}); | |
//events for list items | |
list.delegate("li",'click', function(){ | |
//update select | |
var newIndex = list.find( "li" ).index( this ), | |
prevIndex = select[0].selectedIndex; | |
select[0].selectedIndex = newIndex; | |
//trigger change event | |
if(newIndex !== prevIndex){ | |
select.trigger( "change" ); | |
} | |
self.refresh(); | |
//hide custom select | |
self.close(); | |
return false; | |
}); | |
//events on "screen" overlay | |
screen.click(function(){ | |
self.close(); | |
return false; | |
}); | |
}, | |
_buildList: function(){ | |
var self = this; | |
self.list.empty().filter('.ui-listview').listview('destroy'); | |
//populate menu with options from select element | |
self.select.find( "option" ).each(function( i ){ | |
var anchor = $("<a>", { | |
"role": "option", | |
"href": "#" | |
}) | |
.text( $(this).text() ); | |
$( "<li>", {"data-icon": "checkbox-on"}) | |
.append( anchor ) | |
.appendTo( self.list ); | |
}); | |
//now populated, create listview | |
self.list.listview(); | |
}, | |
refresh: function( forceRebuild ){ | |
var self = this, | |
select = this.element, | |
selected = select[0].selectedIndex; | |
if( forceRebuild || select[0].options.length > self.list.find('li').length ){ | |
self._buildList(); | |
} | |
self.button.find( ".ui-btn-text" ).text( $(select[0].options.item(selected)).text() ); | |
self.list | |
.find('li').removeClass( $.mobile.activeBtnClass ).attr('aria-selected', false) | |
.eq(selected).addClass( $.mobile.activeBtnClass ).find('a').attr('aria-selected', true); | |
}, | |
open: function(){ | |
if( this.options.disabled ){ return; } | |
var self = this, | |
menuHeight = self.list.outerHeight(), | |
menuWidth = self.list.outerWidth(), | |
scrollTop = $(window).scrollTop(), | |
btnOffset = self.button.offset().top, | |
screenHeight = window.innerHeight, | |
screenWidth = window.innerWidth; | |
//add active class to button | |
self.button.addClass( $.mobile.activeBtnClass ); | |
function focusMenuItem(){ | |
self.list.find( ".ui-btn-active" ).focus(); | |
} | |
if( menuHeight > screenHeight - 80 || !$.support.scrollTop ){ | |
//for webos (set lastscroll using button offset) | |
if( scrollTop == 0 && btnOffset > screenHeight ){ | |
self.thisPage.one('pagehide',function(){ | |
$(this).data('lastScroll', btnOffset); | |
}); | |
} | |
self.menuPage.one('pageshow',focusMenuItem); | |
self.menuType = "page"; | |
self.menuPageContent.append( self.list ); | |
$.mobile.changePage(self.menuPage, 'pop', false, false); | |
} | |
else { | |
self.menuType = "overlay"; | |
self.screen | |
.height( $(document).height() ) | |
.removeClass('ui-screen-hidden'); | |
self.listbox | |
.append( self.list ) | |
.removeClass( "ui-selectmenu-hidden" ) | |
.position({ | |
my: "center center", | |
at: "center center", | |
of: self.button, | |
collision: "fit" | |
}) | |
.addClass("in"); | |
focusMenuItem(); | |
} | |
}, | |
close: function(){ | |
if( this.options.disabled ){ return; } | |
var self = this; | |
function focusButton(){ | |
setTimeout(function(){ | |
self.button.focus(); | |
//remove active class from button | |
self.button.removeClass( $.mobile.activeBtnClass ); | |
}, 40); | |
self.listbox.removeAttr('style').append( self.list ); | |
} | |
if(self.menuType == "page"){ | |
$.mobile.changePage([self.menuPage,self.thisPage], 'pop', true, false); | |
self.menuPage.one("pagehide",function(){ | |
focusButton(); | |
//return false; | |
}); | |
} | |
else{ | |
self.screen.addClass( "ui-screen-hidden" ); | |
self.listbox.addClass( "ui-selectmenu-hidden" ).removeAttr( "style" ).removeClass("in"); | |
focusButton(); | |
} | |
}, | |
disable: function(){ | |
this.element.attr("disabled",true); | |
this.button.addClass('ui-disabled').attr("aria-disabled", true); | |
return this._setOption( "disabled", true ); | |
}, | |
enable: function(){ | |
this.element.attr("disabled",false); | |
this.button.removeClass('ui-disabled').attr("aria-disabled", false); | |
return this._setOption( "disabled", false ); | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : plugin for making button-like links | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.fn.buttonMarkup = function( options ){ | |
return this.each( function() { | |
var el = $( this ), | |
o = $.extend( {}, $.fn.buttonMarkup.defaults, el.data(), options), | |
// Classes Defined | |
buttonClass, | |
innerClass = "ui-btn-inner", | |
iconClass; | |
if ( attachEvents ) { | |
attachEvents(); | |
} | |
// if not, try to find closest theme container | |
if ( !o.theme ) { | |
var themedParent = el.closest("[class*='ui-bar-'],[class*='ui-body-']"); | |
o.theme = themedParent.length ? | |
/ui-(bar|body)-([a-z])/.exec( themedParent.attr("class") )[2] : | |
"c"; | |
} | |
buttonClass = "ui-btn ui-btn-up-" + o.theme; | |
if ( o.inline ) { | |
buttonClass += " ui-btn-inline"; | |
} | |
if ( o.icon ) { | |
o.icon = "ui-icon-" + o.icon; | |
o.iconpos = o.iconpos || "left"; | |
iconClass = "ui-icon " + o.icon; | |
if ( o.shadow ) { | |
iconClass += " ui-icon-shadow" | |
} | |
} | |
if ( o.iconpos ) { | |
buttonClass += " ui-btn-icon-" + o.iconpos; | |
if ( o.iconpos == "notext" && !el.attr("title") ) { | |
el.attr( "title", el.text() ); | |
} | |
} | |
if ( o.corners ) { | |
buttonClass += " ui-btn-corner-all"; | |
innerClass += " ui-btn-corner-all"; | |
} | |
if ( o.shadow ) { | |
buttonClass += " ui-shadow"; | |
} | |
el | |
.attr( "data-theme", o.theme ) | |
.addClass( buttonClass ); | |
var wrap = ("<D class='" + innerClass + "'><D class='ui-btn-text'></D>" + | |
( o.icon ? "<span class='" + iconClass + "'></span>" : "" ) + | |
"</D>").replace(/D/g, o.wrapperEls); | |
el.wrapInner( wrap ); | |
}); | |
}; | |
$.fn.buttonMarkup.defaults = { | |
corners: true, | |
shadow: true, | |
iconshadow: true, | |
wrapperEls: "span" | |
}; | |
var attachEvents = function() { | |
$(".ui-btn").live({ | |
mousedown: function() { | |
var theme = $(this).attr( "data-theme" ); | |
$(this).removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-down-" + theme ); | |
}, | |
mouseup: function() { | |
var theme = $(this).attr( "data-theme" ); | |
$(this).removeClass( "ui-btn-down-" + theme ).addClass( "ui-btn-up-" + theme ); | |
}, | |
"mouseover focus": function() { | |
var theme = $(this).attr( "data-theme" ); | |
$(this).removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-hover-" + theme ); | |
}, | |
"mouseout blur": function() { | |
var theme = $(this).attr( "data-theme" ); | |
$(this).removeClass( "ui-btn-hover-" + theme ).addClass( "ui-btn-up-" + theme ); | |
} | |
}); | |
attachEvents = null; | |
}; | |
})(jQuery); | |
/* | |
* jQuery Mobile Framework : "button" plugin - links that proxy to native input/buttons | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.widget( "mobile.button", $.mobile.widget, { | |
options: { | |
theme: null, | |
icon: null, | |
iconpos: null, | |
inline: null, | |
corners: true, | |
shadow: true, | |
iconshadow: true | |
}, | |
_create: function(){ | |
var $el = this.element, | |
o = this.options, | |
type = $el.attr('type'); | |
$el | |
.addClass('ui-btn-hidden') | |
.attr('tabindex','-1'); | |
//add ARIA role | |
this.button = $( "<a>", { | |
"href": "#", | |
"role": "button", | |
"aria-label": $el.attr( "type" ) | |
} ) | |
.text( $el.text() || $el.val() ) | |
.insertBefore( $el ) | |
.click(function(){ | |
if(!o.disabled){ | |
if( type == "submit" ){ | |
$(this).closest('form').submit(); | |
} | |
else{ | |
$el.click(); | |
} | |
} | |
return false; | |
}) | |
.buttonMarkup({ | |
theme: o.theme, | |
icon: o.icon, | |
iconpos: o.iconpos, | |
inline: o.inline, | |
corners: o.corners, | |
shadow: o.shadow, | |
iconshadow: o.iconshadow | |
}); | |
}, | |
enable: function(){ | |
this.element.attr("disabled", false); | |
this.button.removeClass("ui-disabled").attr("aria-disabled", false); | |
return this._setOption("disabled", false); | |
}, | |
disable: function(){ | |
this.element.attr("disabled", true); | |
this.button.addClass("ui-disabled").attr("aria-disabled", true); | |
return this._setOption("disabled", true); | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : "slider" plugin | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.widget( "mobile.slider", $.mobile.widget, { | |
options: { | |
theme: null, | |
trackTheme: null, | |
disabled: false | |
}, | |
_create: function(){ | |
var self = this, | |
control = this.element, | |
parentTheme = control.parents('[class*=ui-bar-],[class*=ui-body-]').eq(0), | |
parentTheme = parentTheme.length ? parentTheme.attr('class').match(/ui-(bar|body)-([a-z])/)[2] : 'c', | |
theme = this.options.theme ? this.options.theme : parentTheme, | |
trackTheme = this.options.trackTheme ? this.options.trackTheme : parentTheme, | |
cType = control[0].nodeName.toLowerCase(), | |
selectClass = (cType == 'select') ? 'ui-slider-switch' : '', | |
controlID = control.attr('id'), | |
labelID = controlID + '-label', | |
label = $('[for='+ controlID +']').attr('id',labelID), | |
val = (cType == 'input') ? parseFloat(control.val()) : control[0].selectedIndex, | |
min = (cType == 'input') ? parseFloat(control.attr('min')) : 0, | |
max = (cType == 'input') ? parseFloat(control.attr('max')) : control.find('option').length-1, | |
slider = $('<div class="ui-slider '+ selectClass +' ui-btn-down-'+ trackTheme+' ui-btn-corner-all" role="application"></div>'), | |
handle = $('<a href="#" class="ui-slider-handle"></a>') | |
.appendTo(slider) | |
.buttonMarkup({corners: true, theme: theme, shadow: true}) | |
.attr({ | |
'role': 'slider', | |
'aria-valuemin': min, | |
'aria-valuemax': max, | |
'aria-valuenow': val, | |
'aria-valuetext': val, | |
'title': val, | |
'aria-labelledby': labelID | |
}); | |
$.extend(this, { | |
slider: slider, | |
handle: handle, | |
dragging: false, | |
beforeStart: null | |
}); | |
if(cType == 'select'){ | |
slider.wrapInner('<div class="ui-slider-inneroffset"></div>'); | |
var options = control.find('option'); | |
control.find('option').each(function(i){ | |
var side = (i==0) ?'b':'a', | |
corners = (i==0) ? 'right' :'left', | |
theme = (i==0) ? ' ui-btn-down-' + trackTheme :' ui-btn-active'; | |
$('<div class="ui-slider-labelbg ui-slider-labelbg-'+ side + theme +' ui-btn-corner-'+ corners+'"></div>').prependTo(slider); | |
$('<span class="ui-slider-label ui-slider-label-'+ side + theme +' ui-btn-corner-'+ corners+'" role="img">'+$(this).text()+'</span>').prependTo(handle); | |
}); | |
} | |
label.addClass('ui-slider'); | |
control | |
.addClass((cType == 'input') ? 'ui-slider-input' : 'ui-slider-switch') | |
.keyup(function(){ | |
self.refresh( $(this).val() ); | |
}); | |
$(document).bind($.support.touch ? "touchmove" : "mousemove", function(event){ | |
if ( self.dragging ) { | |
self.refresh( event ); | |
return false; | |
} | |
}); | |
slider | |
.bind($.support.touch ? "touchstart" : "mousedown", function(event){ | |
self.dragging = true; | |
if ( cType === "select" ) { | |
self.beforeStart = control[0].selectedIndex; | |
} | |
self.refresh( event ); | |
return false; | |
}); | |
slider | |
.add(document) | |
.bind($.support.touch ? "touchend" : "mouseup", function(){ | |
if ( self.dragging ) { | |
self.dragging = false; | |
if ( cType === "select" ) { | |
if ( self.beforeStart === control[0].selectedIndex ) { | |
//tap occurred, but value didn't change. flip it! | |
self.refresh( self.beforeStart === 0 ? 1 : 0 ); | |
} | |
var curval = (cType === "input") ? parseFloat(control.val()) : control[ 0 ].selectedIndex; | |
var snapped = Math.round( curval / (max - min) * 100 ); | |
handle | |
.addClass("ui-slider-handle-snapping") | |
.css("left", snapped + "%") | |
.animationComplete(function(){ | |
handle.removeClass("ui-slider-handle-snapping"); | |
}); | |
} | |
return false; | |
} | |
}); | |
slider.insertAfter(control); | |
handle.bind('click', function(e){ return false; }); | |
this.refresh(); | |
}, | |
refresh: function(val){ | |
if ( this.options.disabled ) { return; } | |
var control = this.element, percent, | |
cType = control[0].nodeName.toLowerCase(), | |
min = (cType === "input") ? parseFloat(control.attr("min")) : 0, | |
max = (cType === "input") ? parseFloat(control.attr("max")) : control.find("option").length - 1; | |
if ( typeof val === "object" ) { | |
var data = val.originalEvent.touches ? val.originalEvent.touches[ 0 ] : val, | |
// a slight tolerance helped get to the ends of the slider | |
tol = 8; | |
if ( !this.dragging | |
|| data.pageX < this.slider.offset().left - tol | |
|| data.pageX > this.slider.offset().left + this.slider.width() + tol ) { | |
return; | |
} | |
percent = Math.round( ((data.pageX - this.slider.offset().left) / this.slider.width() ) * 100 ); | |
} else { | |
if ( val == null ) { | |
val = (cType === "input") ? parseFloat(control.val()) : control[ 0 ].selectedIndex; | |
} | |
percent = (parseFloat(val) - min) / (max - min) * 100; | |
} | |
if ( isNaN(percent) ) { return; } | |
if ( percent < 0 ) { percent = 0; } | |
if ( percent > 100 ) { percent = 100; } | |
var newval = Math.round( (percent / 100) * (max - min) ) + min; | |
if ( newval < min ) { newval = min; } | |
if ( newval > max ) { newval = max; } | |
//flip the stack of the bg colors | |
if ( percent > 60 && cType === "select" ) { | |
} | |
this.handle.css("left", percent + "%"); | |
this.handle.attr({ | |
"aria-valuenow": (cType === "input") ? newval : control.find("option").eq(newval).attr("value"), | |
"aria-valuetext": (cType === "input") ? newval : control.find("option").eq(newval).text(), | |
title: newval | |
}); | |
// add/remove classes for flip toggle switch | |
if ( cType === "select" ) { | |
if ( newval === 0 ) { | |
this.slider.addClass("ui-slider-switch-a") | |
.removeClass("ui-slider-switch-b"); | |
} else { | |
this.slider.addClass("ui-slider-switch-b") | |
.removeClass("ui-slider-switch-a"); | |
} | |
} | |
// update control's value | |
if ( cType === "input" ) { | |
control.val(newval); | |
} else { | |
control[ 0 ].selectedIndex = newval; | |
} | |
control.trigger("change"); | |
}, | |
enable: function(){ | |
this.element.attr("disabled", false); | |
this.slider.removeClass("ui-disabled").attr("aria-disabled", false); | |
return this._setOption("disabled", false); | |
}, | |
disable: function(){ | |
this.element.attr("disabled", true); | |
this.slider.addClass("ui-disabled").attr("aria-disabled", true); | |
return this._setOption("disabled", true); | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : "collapsible" plugin | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.widget( "mobile.collapsible", $.mobile.widget, { | |
options: { | |
expandCueText: ' click to expand contents', | |
collapseCueText: ' click to collapse contents', | |
collapsed: false, | |
heading: '>:header,>legend', | |
theme: null, | |
iconTheme: 'd' | |
}, | |
_create: function(){ | |
var $el = this.element, | |
o = this.options, | |
collapsibleContain = $el.addClass('ui-collapsible-contain'), | |
collapsibleHeading = $el.find(o.heading).eq(0), | |
collapsibleContent = collapsibleContain.wrapInner('<div class="ui-collapsible-content"></div>').find('.ui-collapsible-content'), | |
collapsibleParent = $el.closest('[data-role="collapsible-set"]').addClass('ui-collapsible-set'); | |
//replace collapsibleHeading if it's a legend | |
if(collapsibleHeading.is('legend')){ | |
collapsibleHeading = $('<div role="heading">'+ collapsibleHeading.html() +'</div>').insertBefore(collapsibleHeading); | |
collapsibleHeading.next().remove(); | |
} | |
//drop heading in before content | |
collapsibleHeading.insertBefore(collapsibleContent); | |
//modify markup & attributes | |
collapsibleHeading.addClass('ui-collapsible-heading') | |
.append('<span class="ui-collapsible-heading-status"></span>') | |
.wrapInner('<a href="#" class="ui-collapsible-heading-toggle"></a>') | |
.find('a:eq(0)') | |
.buttonMarkup({ | |
shadow: !!!collapsibleParent.length, | |
corners:false, | |
iconPos: 'left', | |
icon: 'plus', | |
theme: o.theme | |
}) | |
.find('.ui-icon') | |
.removeAttr('class') | |
.buttonMarkup({ | |
shadow: true, | |
corners:true, | |
iconPos: 'notext', | |
icon: 'plus', | |
theme: o.iconTheme | |
}); | |
if( !collapsibleParent.length ){ | |
collapsibleHeading | |
.find('a:eq(0)') | |
.addClass('ui-corner-all') | |
.find('.ui-btn-inner') | |
.addClass('ui-corner-all'); | |
} | |
else { | |
if( collapsibleContain.data('collapsible-last') ){ | |
collapsibleHeading | |
.find('a:eq(0), .ui-btn-inner') | |
.addClass('ui-corner-bottom'); | |
} | |
} | |
//events | |
collapsibleContain | |
.bind('collapse', function(event){ | |
if( !event.isDefaultPrevented() ){ | |
event.preventDefault(); | |
collapsibleHeading | |
.addClass('ui-collapsible-heading-collapsed') | |
.find('.ui-collapsible-heading-status').text(o.expandCueText); | |
collapsibleHeading.find('.ui-icon').removeClass('ui-icon-minus').addClass('ui-icon-plus'); | |
collapsibleContent.addClass('ui-collapsible-content-collapsed').attr('aria-hidden',true); | |
if( collapsibleContain.data('collapsible-last') ){ | |
collapsibleHeading | |
.find('a:eq(0), .ui-btn-inner') | |
.addClass('ui-corner-bottom'); | |
} | |
} | |
}) | |
.bind('expand', function(event){ | |
if( !event.isDefaultPrevented() ){ | |
event.preventDefault(); | |
collapsibleHeading | |
.removeClass('ui-collapsible-heading-collapsed') | |
.find('.ui-collapsible-heading-status').text(o.collapseCueText); | |
collapsibleHeading.find('.ui-icon').removeClass('ui-icon-plus').addClass('ui-icon-minus'); | |
collapsibleContent.removeClass('ui-collapsible-content-collapsed').attr('aria-hidden',false); | |
if( collapsibleContain.data('collapsible-last') ){ | |
collapsibleHeading | |
.find('a:eq(0), .ui-btn-inner') | |
.removeClass('ui-corner-bottom'); | |
} | |
} | |
}) | |
.trigger(o.collapsed ? 'collapse' : 'expand'); | |
//close others in a set | |
if( collapsibleParent.length && !collapsibleParent.data("collapsiblebound") ){ | |
collapsibleParent | |
.data("collapsiblebound", true) | |
.bind("expand", function( event ){ | |
$(this).find( ".ui-collapsible-contain" ) | |
.not( $(event.target).closest( ".ui-collapsible-contain" ) ) | |
.not( "> .ui-collapsible-contain .ui-collapsible-contain" ) | |
.trigger( "collapse" ); | |
}) | |
var set = collapsibleParent.find('[data-role=collapsible]') | |
set.first() | |
.find('a:eq(0)') | |
.addClass('ui-corner-top') | |
.find('.ui-btn-inner') | |
.addClass('ui-corner-top'); | |
set.last().data('collapsible-last', true) | |
} | |
collapsibleHeading.bind( $.support.touch ? "touchstart" : "click", function(){ | |
if( collapsibleHeading.is('.ui-collapsible-heading-collapsed') ){ | |
collapsibleContain.trigger('expand'); | |
} | |
else { | |
collapsibleContain.trigger('collapse'); | |
} | |
return false; | |
}); | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework: "controlgroup" plugin - corner-rounding for groups of buttons, checks, radios, etc | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.fn.controlgroup = function(options){ | |
return $(this).each(function(){ | |
var o = $.extend({ | |
direction: $( this ).data( "type" ) || "vertical", | |
shadow: false | |
},options); | |
var groupheading = $(this).find('>legend'), | |
flCorners = o.direction == 'horizontal' ? ['ui-corner-left', 'ui-corner-right'] : ['ui-corner-top', 'ui-corner-bottom'], | |
type = $(this).find('input:eq(0)').attr('type'); | |
//replace legend with more stylable replacement div | |
if( groupheading.length ){ | |
$(this).wrapInner('<div class="ui-controlgroup-controls"></div>'); | |
$('<div role="heading" class="ui-controlgroup-label">'+ groupheading.html() +'</div>').insertBefore( $(this).children(0) ); | |
groupheading.remove(); | |
} | |
$(this).addClass('ui-corner-all ui-controlgroup ui-controlgroup-'+o.direction); | |
function flipClasses(els){ | |
els | |
.removeClass('ui-btn-corner-all ui-shadow') | |
.eq(0).addClass(flCorners[0]) | |
.end() | |
.filter(':last').addClass(flCorners[1]).addClass('ui-controlgroup-last'); | |
} | |
flipClasses($(this).find('.ui-btn')); | |
flipClasses($(this).find('.ui-btn-inner')); | |
if(o.shadow){ | |
$(this).addClass('ui-shadow'); | |
} | |
}); | |
}; | |
})(jQuery); | |
/* | |
* jQuery Mobile Framework : "fieldcontain" plugin - simple class additions to make form row separators | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.fn.fieldcontain = function(options){ | |
return $(this).addClass('ui-field-contain ui-body ui-br'); | |
}; | |
})(jQuery); | |
/* | |
* jQuery Mobile Framework : "listview" plugin | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.widget( "mobile.listview", $.mobile.widget, { | |
options: { | |
theme: "c", | |
countTheme: "c", | |
headerTheme: "b", | |
dividerTheme: "b", | |
splitIcon: "arrow-r", | |
splitTheme: "b", | |
inset: false | |
}, | |
_create: function() { | |
var $list = this.element, | |
o = this.options; | |
// create listview markup | |
$list | |
.addClass( "ui-listview" ) | |
.attr( "role", "listbox" ) | |
if ( o.inset ) { | |
$list.addClass( "ui-listview-inset ui-corner-all ui-shadow" ); | |
} | |
$list.delegate( ".ui-li", "focusin", function() { | |
$( this ).attr( "tabindex", "0" ); | |
}); | |
this._itemApply( $list, $list ); | |
this.refresh( true ); | |
//keyboard events for menu items | |
$list.keydown(function( e ) { | |
var target = $( e.target ), | |
li = target.closest( "li" ); | |
// switch logic based on which key was pressed | |
switch ( e.keyCode ) { | |
// up or left arrow keys | |
case 38: | |
var prev = li.prev(); | |
// if there's a previous option, focus it | |
if ( prev.length ) { | |
target | |
.blur() | |
.attr( "tabindex", "-1" ); | |
prev.find( "a" ).first().focus(); | |
} | |
return false; | |
break; | |
// down or right arrow keys | |
case 40: | |
var next = li.next(); | |
// if there's a next option, focus it | |
if ( next.length ) { | |
target | |
.blur() | |
.attr( "tabindex", "-1" ); | |
next.find( "a" ).first().focus(); | |
} | |
return false; | |
break; | |
case 39: | |
var a = li.find( "a.ui-li-link-alt" ); | |
if ( a.length ) { | |
target.blur(); | |
a.first().focus(); | |
} | |
return false; | |
break; | |
case 37: | |
var a = li.find( "a.ui-link-inherit" ); | |
if ( a.length ) { | |
target.blur(); | |
a.first().focus(); | |
} | |
return false; | |
break; | |
// if enter or space is pressed, trigger click | |
case 13: | |
case 32: | |
target.trigger( "click" ); | |
return false; | |
break; | |
} | |
}); | |
// tapping the whole LI triggers click on the first link | |
$list.delegate( "li", "click", function(event) { | |
if ( !$( event.target ).closest( "a" ).length ) { | |
$( this ).find( "a" ).first().trigger( "click" ); | |
return false; | |
} | |
}); | |
}, | |
_itemApply: function( $list, item ) { | |
// TODO class has to be defined in markup | |
item.find( ".ui-li-count" ) | |
.addClass( "ui-btn-up-" + ($list.data( "counttheme" ) || this.options.countTheme) + " ui-btn-corner-all" ); | |
item.find( "h1, h2, h3, h4, h5, h6" ).addClass( "ui-li-heading" ); | |
item.find( "p, dl" ).addClass( "ui-li-desc" ); | |
item.find( "img" ).addClass( "ui-li-thumb" ).each(function() { | |
$( this ).closest( "li" ) | |
.addClass( $(this).is( ".ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" ); | |
}); | |
var aside = item.find( ".ui-li-aside" ); | |
if ( aside.length ) { | |
aside.each(function(i, el) { | |
$(el).prependTo( $(el).parent() ); //shift aside to front for css float | |
}); | |
} | |
if ( $.support.cssPseudoElement || !$.nodeName( item[0], "ol" ) ) { | |
return; | |
} | |
}, | |
_removeCorners: function(li){ | |
li | |
.add( li.find(".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb") ) | |
.removeClass( "ui-corner-top ui-corner-bottom ui-corner-br ui-corner-bl ui-corner-tr ui-corner-tl" ); | |
}, | |
refresh: function( create ) { | |
this._createSubPages(); | |
var o = this.options, | |
$list = this.element, | |
self = this, | |
dividertheme = $list.data( "dividertheme" ) || o.dividerTheme, | |
li = $list.children( "li" ), | |
counter = $.support.cssPseudoElement || !$.nodeName( $list[0], "ol" ) ? 0 : 1; | |
if ( counter ) { | |
$list.find( ".ui-li-dec" ).remove(); | |
} | |
li.attr({ "role": "option", "tabindex": "-1" }); | |
li.first().attr( "tabindex", "0" ); | |
li.each(function( pos ) { | |
var item = $( this ), | |
itemClass = "ui-li"; | |
// If we're creating the element, we update it regardless | |
if ( !create && item.hasClass( "ui-li" ) ) { | |
return; | |
} | |
var a = item.find( "a" ); | |
if ( a.length ) { | |
item | |
.buttonMarkup({ | |
wrapperEls: "div", | |
shadow: false, | |
corners: false, | |
iconpos: "right", | |
icon: a.length > 1 ? false : item.data("icon") || "arrow-r", | |
theme: o.theme | |
}); | |
a.first().addClass( "ui-link-inherit" ); | |
if ( a.length > 1 ) { | |
itemClass += " ui-li-has-alt"; | |
var last = a.last(), | |
splittheme = $list.data( "splittheme" ) || last.data( "theme" ) || o.splitTheme; | |
last | |
.attr( "title", last.text() ) | |
.addClass( "ui-li-link-alt" ) | |
.empty() | |
.buttonMarkup({ | |
shadow: false, | |
corners: false, | |
theme: o.theme, | |
icon: false, | |
iconpos: false | |
}) | |
.find( ".ui-btn-inner" ) | |
.append( $( "<span>" ).buttonMarkup({ | |
shadow: true, | |
corners: true, | |
theme: splittheme, | |
iconpos: "notext", | |
icon: $list.data( "spliticon" ) || last.data( "icon" ) || o.splitIcon | |
} ) ); | |
} | |
} else if ( item.data( "role" ) === "list-divider" ) { | |
itemClass += " ui-li-divider ui-btn ui-bar-" + dividertheme; | |
item.attr( "role", "heading" ); | |
//reset counter when a divider heading is encountered | |
if ( counter ) { | |
counter = 1; | |
} | |
} else { | |
itemClass += " ui-li-static ui-btn-up-" + o.theme; | |
} | |
if( o.inset ){ | |
if ( pos === 0 ) { | |
itemClass += " ui-corner-top"; | |
item | |
.add( item.find( ".ui-btn-inner" ) ) | |
.find( ".ui-li-link-alt" ) | |
.addClass( "ui-corner-tr" ) | |
.end() | |
.find( ".ui-li-thumb" ) | |
.addClass( "ui-corner-tl" ); | |
self._removeCorners( item.next() ); | |
} else if ( pos === li.length - 1 ) { | |
itemClass += " ui-corner-bottom"; | |
item | |
.add( item.find( ".ui-btn-inner" ) ) | |
.find( ".ui-li-link-alt" ) | |
.addClass( "ui-corner-br" ) | |
.end() | |
.find( ".ui-li-thumb" ) | |
.addClass( "ui-corner-bl" ); | |
self._removeCorners( item.prev() ); | |
} | |
} | |
if ( counter && itemClass.indexOf( "ui-li-divider" ) < 0 ) { | |
item | |
.find( ".ui-link-inherit" ).first() | |
.addClass( "ui-li-jsnumbering" ) | |
.prepend( "<span class='ui-li-dec'>" + (counter++) + ". </span>" ); | |
} | |
item.addClass( itemClass ); | |
if ( !create ) { | |
self._itemApply( $list, item ); | |
} | |
}); | |
}, | |
//create a string for ID/subpage url creation | |
_idStringEscape: function( str ){ | |
return str.replace(/[^a-zA-Z0-9]/g, '-'); | |
}, | |
_createSubPages: function() { | |
var parentList = this.element, | |
parentPage = parentList.closest( ".ui-page" ), | |
parentId = parentPage.attr( "id" ), | |
o = this.options, | |
self = this, | |
persistentFooterID = parentPage.find( "[data-role='footer']" ).data( "id" ); | |
$( parentList.find( "ul, ol" ).toArray().reverse() ).each(function( i ) { | |
var list = $( this ), | |
parent = list.parent(), | |
title = parent.contents()[ 0 ].nodeValue.split("\n")[0], | |
id = parentId + "&" + $.mobile.subPageUrlKey + "=" + self._idStringEscape(title + " " + i), | |
theme = list.data( "theme" ) || o.theme, | |
countTheme = list.data( "counttheme" ) || parentList.data( "counttheme" ) || o.countTheme, | |
newPage = list.wrap( "<div data-role='page'><div data-role='content'></div></div>" ) | |
.parent() | |
.before( "<div data-role='header' data-theme='" + o.headerTheme + "'><div class='ui-title'>" + title + "</div></div>" ) | |
.after( persistentFooterID ? $( "<div>", { "data-role": "footer", "data-id": persistentFooterID, "class": "ui-footer-duplicate" } ) : "" ) | |
.parent() | |
.attr({ | |
id: id, | |
"data-theme": theme, | |
"data-count-theme": countTheme | |
}) | |
.appendTo( $.mobile.pageContainer ); | |
newPage.page(); | |
parent.html( "<a href='#" + id + "'>" + title + "</a>" ); | |
}).listview(); | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : "listview" filter extension | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.mobile.listview.prototype.options.filter = false; | |
$( "[data-role='listview']" ).live( "listviewcreate", function() { | |
var list = $( this ), | |
listview = list.data( "listview" ); | |
if ( !listview.options.filter ) { | |
return; | |
} | |
var wrapper = $( "<form>", { "class": "ui-listview-filter ui-bar-c", "role": "search" } ), | |
search = $( "<input>", { | |
placeholder: "Filter results...", | |
"data-type": "search" | |
}) | |
.bind( "keyup change", function() { | |
var val = this.value.toLowerCase();; | |
list.children().show(); | |
if ( val ) { | |
list.children().filter(function() { | |
return $( this ).text().toLowerCase().indexOf( val ) === -1; | |
}).hide(); | |
} | |
//listview._numberItems(); | |
}) | |
.appendTo( wrapper ) | |
.textinput(); | |
wrapper.insertBefore( list ); | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : "dialog" plugin. | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. | |
* Note: Code is in draft form and is subject to change | |
*/ | |
(function($, undefined ) { | |
$.widget( "mobile.dialog", $.mobile.widget, { | |
options: {}, | |
_create: function(){ | |
var self = this, | |
$el = self.element, | |
$prevPage = $.mobile.activePage, | |
$closeBtn = $('<a href="#" data-icon="delete" data-iconpos="notext">Close</a>'); | |
$el.delegate("a, form", "click submit", function(e){ | |
if( e.type == "click" && ( $(e.target).closest('[data-back]')[0] || this==$closeBtn[0] ) ){ | |
self.close(); | |
return false; | |
} | |
//otherwise, assume we're headed somewhere new. set activepage to dialog so the transition will work | |
$.mobile.activePage = self.element; | |
}); | |
this.element | |
.bind("pageshow",function(){ | |
return false; | |
}) | |
//add ARIA role | |
.attr("role","dialog") | |
.addClass('ui-page ui-dialog ui-body-a') | |
.find('[data-role=header]') | |
.addClass('ui-corner-top ui-overlay-shadow') | |
.prepend( $closeBtn ) | |
.end() | |
.find('.ui-content:not([class*="ui-body-"])') | |
.addClass('ui-body-c') | |
.end() | |
.find('.ui-content,[data-role=footer]') | |
.last() | |
.addClass('ui-corner-bottom ui-overlay-shadow'); | |
$(window).bind('hashchange',function(){ | |
if( $el.is('.ui-page-active') ){ | |
self.close(); | |
$el.bind('pagehide',function(){ | |
$.mobile.updateHash( $prevPage.attr('id'), true); | |
}); | |
} | |
}); | |
}, | |
close: function(){ | |
$.mobile.changePage([this.element, $.mobile.activePage], undefined, true, true ); | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : "navbar" plugin | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.widget( "mobile.navbar", $.mobile.widget, { | |
options: { | |
iconpos: 'top', | |
grid: null | |
}, | |
_create: function(){ | |
var $navbar = this.element, | |
$navbtns = $navbar.find("a"), | |
iconpos = $navbtns.filter('[data-icon]').length ? this.options.iconpos : undefined; | |
$navbar | |
.addClass('ui-navbar') | |
.attr("role","navigation") | |
.find("ul") | |
.grid({grid: this.options.grid }); | |
if( !iconpos ){ | |
$navbar.addClass("ui-navbar-noicons"); | |
} | |
$navbtns | |
.buttonMarkup({ | |
corners: false, | |
shadow: false, | |
iconpos: iconpos | |
}); | |
$navbar.delegate("a", "click",function(event){ | |
$navbtns.removeClass("ui-btn-active"); | |
}); | |
} | |
}); | |
})( jQuery ); | |
/* | |
* jQuery Mobile Framework : plugin for creating CSS grids | |
* Copyright (c) jQuery Project | |
* Dual licensed under the MIT or GPL Version 2 licenses. | |
* http://jquery.org/license | |
*/ | |
(function($, undefined ) { | |
$.fn.grid = function(options){ | |
return $(this).each(function(){ | |
var o = $.extend({ | |
grid: null | |
},options); | |
var $kids = $(this).children(), | |
gridCols = {a: 2, b:3, c:4, d:5}, | |
grid = o.grid, | |
iterator; | |
if( !grid ){ | |
if( $kids.length <= 5 ){ | |
for(var letter in gridCols){ | |
if(gridCols[letter] == $kids.length){ grid = letter; } | |
} | |
} | |
else{ | |
grid = 'a'; | |
} | |
} | |
iterator = gridCols[grid]; | |
$(this).addClass('ui-grid-' + grid); | |
$kids.filter(':nth-child(' + iterator + 'n+1)').addClass('ui-block-a'); | |
$kids.filter(':nth-child(' + iterator + 'n+2)').addClass('ui-block-b'); | |
if(iterator > 2){ | |
$kids.filter(':nth-child(3n+3)').addClass('ui-block-c'); | |
} | |
if(iterator> 3){ | |
$kids.filter(':nth-child(4n+4)').addClass('ui-block-d'); | |
} | |
if(iterator > 4){ | |
$kids.filter(':nth-child(5n+5)').addClass('ui-block-e'); | |
} | |
}); | |
}; | |
})(jQuery); | |
<?php | <?php |
include('common.inc.php'); | include('common.inc.php'); |
include_header("Routes"); | include_header("Routes"); |
/* data-filter="true">'; | echo' |
echo "<script> $('#routeList').listnav({prefixes: ['to'] }); </script>";*/ | <div data-role="navbar"> |
echo ' <ul data-role="listview">'; | <ul> |
<li><a href="routeList.php">By Final Destination...</a></li> | |
<li><a href="routeList.php?bynumber=yes">By Number... </a></li> | |
<!--<li><a href="routeList.php?bysuburb=yes">By Suburb... </a></li>--> | |
</ul> | |
</div> | |
'; | |
echo ' <ul data-role="listview" data-inset="true">'; | |
$url = $APIurl."/json/routes"; | $url = $APIurl."/json/routes"; |
$contents = json_decode(getPage($url)); | |
debug(print_r($contents,true)); | |
$contents = json_decode(getPage($url)); | function 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"; | |
} | |
} | |
if ($_REQUEST['bynumber']) { | if ($_REQUEST['bynumber']) { |
$routeSeries = Array(); | $routeSeries = Array(); |
$seriesRange = Array(); | |
foreach ($contents as $key => $row) { | foreach ($contents as $key => $row) { |
foreach (explode(" ",$row[1]) as $routeNumber ) { | foreach (explode(" ",$row[1]) as $routeNumber ) { |
$seriesNum = substr($routeNumber, 0, -1)."0"; | $seriesNum = substr($routeNumber, 0, -1)."0"; |
if ($seriesNum == "0") $seriesNum = $routeNumber; | if ($seriesNum == "0") $seriesNum = $routeNumber; |
$finalDigit = substr($routeNumber, sizeof($routeNumber)-1, 1); | |
if (isset($seriesRange[$seriesNum])) { | |
if ($finalDigit < $seriesRange[$seriesNum]['max']) | |
$seriesRange[$seriesNum]['max'] = $routeNumber; | |
if ($finalDigit > $seriesRange[$seriesNum]['min']) | |
$seriesRange[$seriesNum]['min'] = $routeNumber; | |
} else { | |
$seriesRange[$seriesNum]['max'] = $routeNumber; | |
$seriesRange[$seriesNum]['min'] = $routeNumber; | |
} | |
$routeSeries[$seriesNum][$seriesNum."-".$row[1]."-".$row[0]] = $row; | $routeSeries[$seriesNum][$seriesNum."-".$row[1]."-".$row[0]] = $row; |
} | } |
} | } |
ksort($routeSeries); | ksort($routeSeries); |
ksort($seriesRange); | |
echo '<div class="noscriptnav"> Go to route numbers: '; | |
foreach ($seriesRange as $series => $range) | |
{ | |
if ($range['min'] == $range['max']) echo "<a href=\"#$series\">$series</a> "; | |
else echo "<a href=\"#$series\">{$range['min']}-{$range['max']}</a> "; | |
} | |
echo "</div> | |
<script> | |
$('.noscriptnav').hide(); | |
</script>"; | |
foreach ($routeSeries as $series => $routes) | foreach ($routeSeries as $series => $routes) |
{ | { |
echo '<li>'.$series."... <ul>\n"; | echo '<a name="'.$series.'"></a>'; |
foreach($routes as $row) { | if ($series <= 9) echo '<li>'.$series."<ul>\n"; |
echo '<li>'.$row[1].' <a href="route.php?routeid='.$row[0].'">'.$row[2]."</a></li>\n"; | else echo "<li>{$seriesRange[$series]['min']}-{$seriesRange[$series]['max']}<ul>\n"; |
} | printRoutes($routes); |
echo "</ul></li>\n"; | echo "</ul></li>\n"; |
} | } |
} else { | } else { |
foreach ($contents as $key => $row) { | foreach ($contents as $key => $row) { |
$routeDestinations[$row[2]][] = $row; | $routeDestinations[$row[2]][] = $row; |
} | } |
echo '<div class="noscriptnav"> Go to Destination: '; | |
foreach(ksort($routeDestinations) as $destination => $routes) | |
{ | |
echo "<a href=\"#$destination\">$destination</a> "; | |
} | |
echo "</div> | |
<script> | |
$('.noscriptnav').hide(); | |
</script>"; | |
foreach ($routeDestinations as $destination => $routes) | foreach ($routeDestinations as $destination => $routes) |
{ | { |
echo '<a name="'.$destination.'"></a>'; | |
echo '<li>'.$destination."... <ul>\n"; | echo '<li>'.$destination."... <ul>\n"; |
foreach($routes as $row) { | printRoutes($routes); |
echo '<li>'.$row[1].' <a href="trip.php?routeid='.$row[0].'">'.$row[2]."</a></li>\n"; | |
} | |
echo "</ul></li>\n"; | echo "</ul></li>\n"; |
} | } |
} | } |
echo "</ul>\n"; | echo "</ul>\n"; |
echo' | |
<div data-role="footer" data-id="foo1" data-position="fixed"> | |
<div data-role="navbar"> | |
<ul> | |
<li><a href="routeList.php" class="ui-btn-active">By Final Destination...</a></li> | |
<li><a href="routeList.php?bynumber=yes">By Number... </a></li> | |
<li><a href="routeList.php?bysuburb=yes">By Suburb... </a></li> | |
</ul> | |
'; | |
include_footer(); | include_footer(); |
?> | ?> |
#!/usr/bin/python2.5 | #!/usr/bin/python2.5 |
# Copyright (C) 2007 Google Inc. | # Copyright (C) 2007 Google Inc. |
# | # |
# Licensed under the Apache License, Version 2.0 (the "License"); | # Licensed under the Apache License, Version 2.0 (the "License"); |
# you may not use this file except in compliance with the License. | # you may not use this file except in compliance with the License. |
# You may obtain a copy of the License at | # You may obtain a copy of the License at |
# | # |
# http://www.apache.org/licenses/LICENSE-2.0 | # http://www.apache.org/licenses/LICENSE-2.0 |
# | # |
# Unless required by applicable law or agreed to in writing, software | # Unless required by applicable law or agreed to in writing, software |
# distributed under the License is distributed on an "AS IS" BASIS, | # distributed under the License is distributed on an "AS IS" BASIS, |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
# See the License for the specific language governing permissions and | # See the License for the specific language governing permissions and |
# limitations under the License. | # limitations under the License. |
""" | """ |
An example application that uses the transitfeed module. | An example application that uses the transitfeed module. |
You must provide a Google Maps API key. | You must provide a Google Maps API key. |
""" | """ |
import BaseHTTPServer, sys, urlparse | import BaseHTTPServer, sys, urlparse |
import bisect | import bisect |
from gtfsscheduleviewer.marey_graph import MareyGraph | from gtfsscheduleviewer.marey_graph import MareyGraph |
import gtfsscheduleviewer | import gtfsscheduleviewer |
import mimetypes | import mimetypes |
import os.path | import os.path |
import re | import re |
import signal | import signal |
import simplejson | import simplejson |
import socket | import socket |
import time | import time |
import transitfeed | import transitfeed |
from transitfeed import util | from transitfeed import util |
import urllib | import urllib |
# By default Windows kills Python with Ctrl+Break. Instead make Ctrl+Break | # By default Windows kills Python with Ctrl+Break. Instead make Ctrl+Break |
# raise a KeyboardInterrupt. | # raise a KeyboardInterrupt. |
if hasattr(signal, 'SIGBREAK'): | if hasattr(signal, 'SIGBREAK'): |
signal.signal(signal.SIGBREAK, signal.default_int_handler) | signal.signal(signal.SIGBREAK, signal.default_int_handler) |
mimetypes.add_type('text/plain', '.vbs') | mimetypes.add_type('text/plain', '.vbs') |
class ResultEncoder(simplejson.JSONEncoder): | class ResultEncoder(simplejson.JSONEncoder): |
def default(self, obj): | def default(self, obj): |
try: | try: |
iterable = iter(obj) | iterable = iter(obj) |
except TypeError: | except TypeError: |
pass | pass |
else: | else: |
return list(iterable) | return list(iterable) |
return simplejson.JSONEncoder.default(self, obj) | return simplejson.JSONEncoder.default(self, obj) |
# Code taken from | # Code taken from |
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/425210/index_txt | # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/425210/index_txt |
# An alternate approach is shown at | # An alternate approach is shown at |
# http://mail.python.org/pipermail/python-list/2003-July/212751.html | # http://mail.python.org/pipermail/python-list/2003-July/212751.html |
# but it requires multiple threads. A sqlite object can only be used from one | # but it requires multiple threads. A sqlite object can only be used from one |
# thread. | # thread. |
class StoppableHTTPServer(BaseHTTPServer.HTTPServer): | class StoppableHTTPServer(BaseHTTPServer.HTTPServer): |
def server_bind(self): | def server_bind(self): |
BaseHTTPServer.HTTPServer.server_bind(self) | BaseHTTPServer.HTTPServer.server_bind(self) |
self.socket.settimeout(1) | self.socket.settimeout(1) |
self._run = True | self._run = True |
def get_request(self): | def get_request(self): |
while self._run: | while self._run: |
try: | try: |
sock, addr = self.socket.accept() | sock, addr = self.socket.accept() |
sock.settimeout(None) | sock.settimeout(None) |
return (sock, addr) | return (sock, addr) |
except socket.timeout: | except socket.timeout: |
pass | pass |
def stop(self): | def stop(self): |
self._run = False | self._run = False |
def serve(self): | def serve(self): |
while self._run: | while self._run: |
self.handle_request() | self.handle_request() |
def StopToTuple(stop): | def StopToTuple(stop): |
"""Return tuple as expected by javascript function addStopMarkerFromList""" | """Return tuple as expected by javascript function addStopMarkerFromList""" |
return (stop.stop_id, stop.stop_name, float(stop.stop_lat), | return (stop.stop_id, stop.stop_name, float(stop.stop_lat), |
float(stop.stop_lon), stop.location_type) | float(stop.stop_lon), stop.location_type) |
class ScheduleRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): | class ScheduleRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
def do_GET(self): | def do_GET(self): |
scheme, host, path, x, params, fragment = urlparse.urlparse(self.path) | scheme, host, path, x, params, fragment = urlparse.urlparse(self.path) |
parsed_params = {} | parsed_params = {} |
for k in params.split('&'): | for k in params.split('&'): |
k = urllib.unquote(k) | k = urllib.unquote(k) |
if '=' in k: | if '=' in k: |
k, v = k.split('=', 1) | k, v = k.split('=', 1) |
parsed_params[k] = unicode(v, 'utf8') | parsed_params[k] = unicode(v, 'utf8') |
else: | else: |
parsed_params[k] = '' | parsed_params[k] = '' |
if path == '/': | if path == '/': |
return self.handle_GET_home() | return self.handle_GET_home() |
m = re.match(r'/json/([a-z]{1,64})', path) | m = re.match(r'/json/([a-z]{1,64})', path) |
if m: | if m: |
handler_name = 'handle_json_GET_%s' % m.group(1) | handler_name = 'handle_json_GET_%s' % m.group(1) |
handler = getattr(self, handler_name, None) | handler = getattr(self, handler_name, None) |
if callable(handler): | if callable(handler): |
return self.handle_json_wrapper_GET(handler, parsed_params) | return self.handle_json_wrapper_GET(handler, parsed_params) |
# Restrict allowable file names to prevent relative path attacks etc | # Restrict allowable file names to prevent relative path attacks etc |
m = re.match(r'/file/([a-z0-9_-]{1,64}\.?[a-z0-9_-]{1,64})$', path) | m = re.match(r'/file/([a-z0-9_-]{1,64}\.?[a-z0-9_-]{1,64})$', path) |
if m and m.group(1): | if m and m.group(1): |
try: | try: |
f, mime_type = self.OpenFile(m.group(1)) | f, mime_type = self.OpenFile(m.group(1)) |
return self.handle_static_file_GET(f, mime_type) | return self.handle_static_file_GET(f, mime_type) |
except IOError, e: | except IOError, e: |
print "Error: unable to open %s" % m.group(1) | print "Error: unable to open %s" % m.group(1) |
# Ignore and treat as 404 | # Ignore and treat as 404 |
m = re.match(r'/([a-z]{1,64})', path) | m = re.match(r'/([a-z]{1,64})', path) |
if m: | if m: |
handler_name = 'handle_GET_%s' % m.group(1) | handler_name = 'handle_GET_%s' % m.group(1) |
handler = getattr(self, handler_name, None) | handler = getattr(self, handler_name, None) |
if callable(handler): | if callable(handler): |
return handler(parsed_params) | return handler(parsed_params) |
return self.handle_GET_default(parsed_params, path) | return self.handle_GET_default(parsed_params, path) |
def OpenFile(self, filename): | def OpenFile(self, filename): |
"""Try to open filename in the static files directory of this server. | """Try to open filename in the static files directory of this server. |
Return a tuple (file object, string mime_type) or raise an exception.""" | Return a tuple (file object, string mime_type) or raise an exception.""" |
(mime_type, encoding) = mimetypes.guess_type(filename) | (mime_type, encoding) = mimetypes.guess_type(filename) |
assert mime_type | assert mime_type |
# A crude guess of when we should use binary mode. Without it non-unix | # A crude guess of when we should use binary mode. Without it non-unix |
# platforms may corrupt binary files. | # platforms may corrupt binary files. |
if mime_type.startswith('text/'): | if mime_type.startswith('text/'): |
mode = 'r' | mode = 'r' |
else: | else: |
mode = 'rb' | mode = 'rb' |
return open(os.path.join(self.server.file_dir, filename), mode), mime_type | return open(os.path.join(self.server.file_dir, filename), mode), mime_type |
def handle_GET_default(self, parsed_params, path): | def handle_GET_default(self, parsed_params, path): |
self.send_error(404) | self.send_error(404) |
def handle_static_file_GET(self, fh, mime_type): | def handle_static_file_GET(self, fh, mime_type): |
content = fh.read() | content = fh.read() |
self.send_response(200) | self.send_response(200) |
self.send_header('Content-Type', mime_type) | self.send_header('Content-Type', mime_type) |
self.send_header('Content-Length', str(len(content))) | self.send_header('Content-Length', str(len(content))) |
self.end_headers() | self.end_headers() |
self.wfile.write(content) | self.wfile.write(content) |
def AllowEditMode(self): | def AllowEditMode(self): |
return False | return False |
def handle_GET_home(self): | def handle_GET_home(self): |
schedule = self.server.schedule | schedule = self.server.schedule |
(min_lat, min_lon, max_lat, max_lon) = schedule.GetStopBoundingBox() | (min_lat, min_lon, max_lat, max_lon) = schedule.GetStopBoundingBox() |
forbid_editing = ('true', 'false')[self.AllowEditMode()] | forbid_editing = ('true', 'false')[self.AllowEditMode()] |
agency = ', '.join(a.agency_name for a in schedule.GetAgencyList()).encode('utf-8') | agency = ', '.join(a.agency_name for a in schedule.GetAgencyList()).encode('utf-8') |
key = self.server.key | key = self.server.key |
host = self.server.host | host = self.server.host |
# A very simple template system. For a fixed set of values replace [xxx] | # A very simple template system. For a fixed set of values replace [xxx] |
# with the value of local variable xxx | # with the value of local variable xxx |
f, _ = self.OpenFile('index.html') | f, _ = self.OpenFile('index.html') |
content = f.read() | content = f.read() |
for v in ('agency', 'min_lat', 'min_lon', 'max_lat', 'max_lon', 'key', | for v in ('agency', 'min_lat', 'min_lon', 'max_lat', 'max_lon', 'key', |
'host', 'forbid_editing'): | 'host', 'forbid_editing'): |
content = content.replace('[%s]' % v, str(locals()[v])) | content = content.replace('[%s]' % v, str(locals()[v])) |
self.send_response(200) | self.send_response(200) |
self.send_header('Content-Type', 'text/html') | self.send_header('Content-Type', 'text/html') |
self.send_header('Content-Length', str(len(content))) | self.send_header('Content-Length', str(len(content))) |
self.end_headers() | self.end_headers() |
self.wfile.write(content) | self.wfile.write(content) |
def handle_json_GET_routepatterns(self, params): | def handle_json_GET_routepatterns(self, params): |
"""Given a route_id generate a list of patterns of the route. For each | """Given a route_id generate a list of patterns of the route. For each |
pattern include some basic information and a few sample trips.""" | pattern include some basic information and a few sample trips.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
route = schedule.GetRoute(params.get('route', None)) | route = schedule.GetRoute(params.get('route', None)) |
if not route: | if not route: |
self.send_error(404) | self.send_error(404) |
return | return |
time = int(params.get('time', 0)) | time = int(params.get('time', 0)) |
sample_size = 10 # For each pattern return the start time for this many trips | sample_size = 10 # For each pattern return the start time for this many trips |
pattern_id_trip_dict = route.GetPatternIdTripDict() | pattern_id_trip_dict = route.GetPatternIdTripDict() |
patterns = [] | patterns = [] |
for pattern_id, trips in pattern_id_trip_dict.items(): | for pattern_id, trips in pattern_id_trip_dict.items(): |
time_stops = trips[0].GetTimeStops() | time_stops = trips[0].GetTimeStops() |
if not time_stops: | if not time_stops: |
continue | continue |
has_non_zero_trip_type = False; | has_non_zero_trip_type = False; |
for trip in trips: | for trip in trips: |
if trip['trip_type'] and trip['trip_type'] != '0': | if trip['trip_type'] and trip['trip_type'] != '0': |
has_non_zero_trip_type = True | has_non_zero_trip_type = True |
name = u'%s to %s, %d stops' % (time_stops[0][2].stop_name, time_stops[-1][2].stop_name, len(time_stops)) | name = u'%s to %s, %d stops' % (time_stops[0][2].stop_name, time_stops[-1][2].stop_name, len(time_stops)) |
transitfeed.SortListOfTripByTime(trips) | transitfeed.SortListOfTripByTime(trips) |
num_trips = len(trips) | num_trips = len(trips) |
if num_trips <= sample_size: | if num_trips <= sample_size: |
start_sample_index = 0 | start_sample_index = 0 |
num_after_sample = 0 | num_after_sample = 0 |
else: | else: |
# Will return sample_size trips that start after the 'time' param. | # Will return sample_size trips that start after the 'time' param. |
# Linear search because I couldn't find a built-in way to do a binary | # Linear search because I couldn't find a built-in way to do a binary |
# search with a custom key. | # search with a custom key. |
start_sample_index = len(trips) | start_sample_index = len(trips) |
for i, trip in enumerate(trips): | for i, trip in enumerate(trips): |
if trip.GetStartTime() >= time: | if trip.GetStartTime() >= time: |
start_sample_index = i | start_sample_index = i |
break | break |
num_after_sample = num_trips - (start_sample_index + sample_size) | num_after_sample = num_trips - (start_sample_index + sample_size) |
if num_after_sample < 0: | if num_after_sample < 0: |
# Less than sample_size trips start after 'time' so return all the | # Less than sample_size trips start after 'time' so return all the |
# last sample_size trips. | # last sample_size trips. |
num_after_sample = 0 | num_after_sample = 0 |
start_sample_index = num_trips - sample_size | start_sample_index = num_trips - sample_size |
sample = [] | sample = [] |
for t in trips[start_sample_index:start_sample_index + sample_size]: | for t in trips[start_sample_index:start_sample_index + sample_size]: |
sample.append( (t.GetStartTime(), t.trip_id) ) | sample.append( (t.GetStartTime(), t.trip_id) ) |
patterns.append((name, pattern_id, start_sample_index, sample, | patterns.append((name, pattern_id, start_sample_index, sample, |
num_after_sample, (0,1)[has_non_zero_trip_type])) | num_after_sample, (0,1)[has_non_zero_trip_type])) |
patterns.sort() | patterns.sort() |
return patterns | return patterns |
def handle_json_wrapper_GET(self, handler, parsed_params): | def handle_json_wrapper_GET(self, handler, parsed_params): |
"""Call handler and output the return value in JSON.""" | """Call handler and output the return value in JSON.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
result = handler(parsed_params) | result = handler(parsed_params) |
content = ResultEncoder().encode(result) | content = ResultEncoder().encode(result) |
self.send_response(200) | self.send_response(200) |
self.send_header('Content-Type', 'text/plain') | self.send_header('Content-Type', 'text/plain') |
self.send_header('Content-Length', str(len(content))) | self.send_header('Content-Length', str(len(content))) |
self.end_headers() | self.end_headers() |
self.wfile.write(content) | self.wfile.write(content) |
def handle_json_GET_routes(self, params): | def handle_json_GET_routes(self, params): |
"""Return a list of all routes.""" | """Return a list of all routes.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
result = [] | result = [] |
for r in schedule.GetRouteList(): | for r in schedule.GetRouteList(): |
result.append( (r.route_id, r.route_short_name, r.route_long_name) ) | 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]) | result.sort(key = lambda x: x[1:3]) |
return result | return result |
def handle_json_GET_routerow(self, params): | def handle_json_GET_routerow(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
route = schedule.GetRoute(params.get('route', None)) | route = schedule.GetRoute(params.get('route', None)) |
return [transitfeed.Route._FIELD_NAMES, route.GetFieldValuesTuple()] | return [transitfeed.Route._FIELD_NAMES, route.GetFieldValuesTuple()] |
def handle_json_GET_routetrips(self, params): | def handle_json_GET_routetrips(self, params): |
""" Get a trip for a route_id (preferablly the next one) """ | """ Get a trip for a route_id (preferablly the next one) """ |
schedule = self.server.schedule | schedule = self.server.schedule |
query = params.get('route_id', None).lower() | query = params.get('route_id', None).lower() |
result = [] | result = [] |
for t in schedule.GetTripList(): | for t in schedule.GetTripList(): |
if t.route_id == query: | if t.route_id == query: |
result.append ( (t.GetStartTime(), t.trip_id) ) | result.append ( (t.GetStartTime(), t.trip_id) ) |
""" UGH fails for 300s """ | |
"""return result""" | |
return sorted(result, key=lambda trip: trip[0]) | return sorted(result, key=lambda trip: trip[0]) |
def handle_json_GET_triprows(self, params): | def handle_json_GET_triprows(self, params): |
"""Return a list of rows from the feed file that are related to this | """Return a list of rows from the feed file that are related to this |
trip.""" | trip.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
try: | try: |
trip = schedule.GetTrip(params.get('trip', None)) | trip = schedule.GetTrip(params.get('trip', None)) |
except KeyError: | except KeyError: |
# if a non-existent trip is searched for, the return nothing | # if a non-existent trip is searched for, the return nothing |
return | return |
route = schedule.GetRoute(trip.route_id) | route = schedule.GetRoute(trip.route_id) |
trip_row = dict(trip.iteritems()) | trip_row = dict(trip.iteritems()) |
route_row = dict(route.iteritems()) | route_row = dict(route.iteritems()) |
return [['trips.txt', trip_row], ['routes.txt', route_row]] | return [['trips.txt', trip_row], ['routes.txt', route_row]] |
def handle_json_GET_tripstoptimes(self, params): | def handle_json_GET_tripstoptimes(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
try: | try: |
trip = schedule.GetTrip(params.get('trip')) | trip = schedule.GetTrip(params.get('trip')) |
except KeyError: | except KeyError: |
# if a non-existent trip is searched for, the return nothing | # if a non-existent trip is searched for, the return nothing |
return | return |
time_stops = trip.GetTimeStops() | time_stops = trip.GetTimeStops() |
stops = [] | stops = [] |
times = [] | times = [] |
for arr,dep,stop in time_stops: | for arr,dep,stop in time_stops: |
stops.append(StopToTuple(stop)) | stops.append(StopToTuple(stop)) |
times.append(arr) | times.append(arr) |
return [stops, times] | return [stops, times] |
def handle_json_GET_tripshape(self, params): | def handle_json_GET_tripshape(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
try: | try: |
trip = schedule.GetTrip(params.get('trip')) | trip = schedule.GetTrip(params.get('trip')) |
except KeyError: | except KeyError: |
# if a non-existent trip is searched for, the return nothing | # if a non-existent trip is searched for, the return nothing |
return | return |
points = [] | points = [] |
if trip.shape_id: | if trip.shape_id: |
shape = schedule.GetShape(trip.shape_id) | shape = schedule.GetShape(trip.shape_id) |
for (lat, lon, dist) in shape.points: | for (lat, lon, dist) in shape.points: |
points.append((lat, lon)) | points.append((lat, lon)) |
else: | else: |
time_stops = trip.GetTimeStops() | time_stops = trip.GetTimeStops() |
for arr,dep,stop in time_stops: | for arr,dep,stop in time_stops: |
points.append((stop.stop_lat, stop.stop_lon)) | points.append((stop.stop_lat, stop.stop_lon)) |
return points | return points |
def handle_json_GET_neareststops(self, params): | def handle_json_GET_neareststops(self, params): |
"""Return a list of the nearest 'limit' stops to 'lat', 'lon'""" | """Return a list of the nearest 'limit' stops to 'lat', 'lon'""" |
schedule = self.server.schedule | schedule = self.server.schedule |
lat = float(params.get('lat')) | lat = float(params.get('lat')) |
lon = float(params.get('lon')) | lon = float(params.get('lon')) |
limit = int(params.get('limit')) | limit = int(params.get('limit')) |
stops = schedule.GetNearestStops(lat=lat, lon=lon, n=limit) | stops = schedule.GetNearestStops(lat=lat, lon=lon, n=limit) |
return [StopToTuple(s) for s in stops] | return [StopToTuple(s) for s in stops] |
def handle_json_GET_boundboxstops(self, params): | def handle_json_GET_boundboxstops(self, params): |
"""Return a list of up to 'limit' stops within bounding box with 'n','e' | """Return a list of up to 'limit' stops within bounding box with 'n','e' |
and 's','w' in the NE and SW corners. Does not handle boxes crossing | and 's','w' in the NE and SW corners. Does not handle boxes crossing |
longitude line 180.""" | longitude line 180.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
n = float(params.get('n')) | n = float(params.get('n')) |
e = float(params.get('e')) | e = float(params.get('e')) |
s = float(params.get('s')) | s = float(params.get('s')) |
w = float(params.get('w')) | w = float(params.get('w')) |
limit = int(params.get('limit')) | limit = int(params.get('limit')) |
stops = schedule.GetStopsInBoundingBox(north=n, east=e, south=s, west=w, n=limit) | stops = schedule.GetStopsInBoundingBox(north=n, east=e, south=s, west=w, n=limit) |
return [StopToTuple(s) for s in stops] | return [StopToTuple(s) for s in stops] |
def handle_json_GET_stops(self, params): | def handle_json_GET_stops(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
return [StopToTuple(s) for s in schedule.GetStopList()] | return [StopToTuple(s) for s in schedule.GetStopList()] |
def handle_json_GET_timingpoints(self, params): | def handle_json_GET_timingpoints(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
matches = [] | matches = [] |
for s in schedule.GetStopList(): | for s in schedule.GetStopList(): |
if s.stop_code.find("Wj") == -1: | if s.stop_code.find("Wj") == -1: |
matches.append(StopToTuple(s)) | matches.append(StopToTuple(s)) |
return matches | return matches |
def handle_json_GET_stopsearch(self, params): | def handle_json_GET_stopsearch(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
query = params.get('q', None).lower() | query = params.get('q', None).lower() |
matches = [] | matches = [] |
for s in schedule.GetStopList(): | for s in schedule.GetStopList(): |
if s.stop_id.lower().find(query) != -1 or s.stop_name.lower().find(query) != -1: | if s.stop_id.lower().find(query) != -1 or s.stop_name.lower().find(query) != -1: |
matches.append(StopToTuple(s)) | matches.append(StopToTuple(s)) |
return matches | return matches |
def handle_json_GET_stop(self, params): | def handle_json_GET_stop(self, params): |
schedule = self.server.schedule | schedule = self.server.schedule |
query = params.get('stop_id', None).lower() | query = params.get('stop_id', None).lower() |
for s in schedule.GetStopList(): | for s in schedule.GetStopList(): |
if s.stop_id.lower() == query: | if s.stop_id.lower() == query: |
return StopToTuple(s) | return StopToTuple(s) |
return [] | return [] |
def handle_json_GET_stoptrips(self, params): | def handle_json_GET_stoptrips(self, params): |
"""Given a stop_id and time in seconds since midnight return the next | """Given a stop_id and time in seconds since midnight return the next |
trips to visit the stop.""" | trips to visit the stop.""" |
schedule = self.server.schedule | schedule = self.server.schedule |
stop = schedule.GetStop(params.get('stop', None)) | stop = schedule.GetStop(params.get('stop', None)) |
time = int(params.get('time', 0)) | time = int(params.get('time', 0)) |
service_period = params.get('service_period', None) | service_period = params.get('service_period', None) |
time_trips = stop.GetStopTimeTrips(schedule) | time_trips = stop.GetStopTimeTrips(schedule) |
time_trips.sort() # OPT: use bisect.insort to make this O(N*ln(N)) -> O(N) | time_trips.sort() # OPT: use bisect.insort to make this O(N*ln(N)) -> O(N) |
# Keep the first 15 after param 'time'. | # Keep the first 15 after param 'time'. |
# Need make a tuple to find correct bisect point | # Need make a tuple to find correct bisect point |
time_trips = time_trips[bisect.bisect_left(time_trips, (time, 0)):] | time_trips = time_trips[bisect.bisect_left(time_trips, (time, 0)):] |
time_trips = time_trips[:15] | time_trips = time_trips[:15] |
# TODO: combine times for a route to show next 2 departure times | # TODO: combine times for a route to show next 2 departure times |
result = [] | result = [] |
for time, (trip, index), tp in time_trips: | for time, (trip, index), tp in time_trips: |
headsign = None | headsign = None |
# Find the most recent headsign from the StopTime objects | # Find the most recent headsign from the StopTime objects |
for stoptime in trip.GetStopTimes()[index::-1]: | for stoptime in trip.GetStopTimes()[index::-1]: |
if stoptime.stop_headsign: | if stoptime.stop_headsign: |
headsign = stoptime.stop_headsign | headsign = stoptime.stop_headsign |
break | break |
# If stop_headsign isn't found, look for a trip_headsign | # If stop_headsign isn't found, look for a trip_headsign |
if not headsign: | if not headsign: |
headsign = trip.trip_headsign | headsign = trip.trip_headsign |
route = schedule.GetRoute(trip.route_id) | route = schedule.GetRoute(trip.route_id) |
trip_name = '' | trip_name = '' |
if route.route_short_name: | if route.route_short_name: |
trip_name += route.route_short_name | trip_name += route.route_short_name |
if route.route_long_name: | if route.route_long_name: |
if len(trip_name): | if len(trip_name): |
trip_name += " - " | trip_name += " - " |
trip_name += route.route_long_name | trip_name += route.route_long_name |
if headsign: | if headsign: |
trip_name += " (Direction: %s)" % headsign | trip_name += " (Direction: %s)" % headsign |
if service_period == None or trip.service_id == service_period: | if service_period == None or trip.service_id == service_period: |
result.append((time, (trip.trip_id, trip_name, trip.service_id), tp)) | result.append((time, (trip.trip_id, trip_name, trip.service_id), tp)) |
return result | return result |
def handle_GET_ttablegraph(self,params): | def handle_GET_ttablegraph(self,params): |
"""Draw a Marey graph in SVG for a pattern (collection of trips in a route | """Draw a Marey graph in SVG for a pattern (collection of trips in a route |
that visit the same sequence of stops).""" | that visit the same sequence of stops).""" |
schedule = self.server.schedule | schedule = self.server.schedule |
marey = MareyGraph() | marey = MareyGraph() |
trip = schedule.GetTrip(params.get('trip', None)) | trip = schedule.GetTrip(params.get('trip', None)) |
route = schedule.GetRoute(trip.route_id) | route = schedule.GetRoute(trip.route_id) |
height = int(params.get('height', 300)) | height = int(params.get('height', 300)) |
if not route: | if not route: |
print 'no such route' | print 'no such route' |
self.send_error(404) | self.send_error(404) |
return | return |
pattern_id_trip_dict = route.GetPatternIdTripDict() | pattern_id_trip_dict = route.GetPatternIdTripDict() |
pattern_id = trip.pattern_id | pattern_id = trip.pattern_id |
if pattern_id not in pattern_id_trip_dict: | if pattern_id not in pattern_id_trip_dict: |
print 'no pattern %s found in %s' % (pattern_id, pattern_id_trip_dict.keys()) | print 'no pattern %s found in %s' % (pattern_id, pattern_id_trip_dict.keys()) |
self.send_error(404) | self.send_error(404) |
return | return |
triplist = pattern_id_trip_dict[pattern_id] | triplist = pattern_id_trip_dict[pattern_id] |
pattern_start_time = min((t.GetStartTime() for t in triplist)) | pattern_start_time = min((t.GetStartTime() for t in triplist)) |
pattern_end_time = max((t.GetEndTime() for t in triplist)) | pattern_end_time = max((t.GetEndTime() for t in triplist)) |
marey.SetSpan(pattern_start_time,pattern_end_time) | marey.SetSpan(pattern_start_time,pattern_end_time) |
marey.Draw(triplist[0].GetPattern(), triplist, height) | marey.Draw(triplist[0].GetPattern(), triplist, height) |
content = marey.Draw() | content = marey.Draw() |
self.send_response(200) | self.send_response(200) |
self.send_header('Content-Type', 'image/svg+xml') | self.send_header('Content-Type', 'image/svg+xml') |
self.send_header('Content-Length', str(len(content))) | self.send_header('Content-Length', str(len(content))) |
self.end_headers() | self.end_headers() |
self.wfile.write(content) | self.wfile.write(content) |
def FindPy2ExeBase(): | def FindPy2ExeBase(): |
"""If this is running in py2exe return the install directory else return | """If this is running in py2exe return the install directory else return |
None""" | None""" |
# py2exe puts gtfsscheduleviewer in library.zip. For py2exe setup.py is | # py2exe puts gtfsscheduleviewer in library.zip. For py2exe setup.py is |
# configured to put the data next to library.zip. | # configured to put the data next to library.zip. |
windows_ending = gtfsscheduleviewer.__file__.find('\\library.zip\\') | windows_ending = gtfsscheduleviewer.__file__.find('\\library.zip\\') |
if windows_ending != -1: | if windows_ending != -1: |
return transitfeed.__file__[:windows_ending] | return transitfeed.__file__[:windows_ending] |
else: | else: |
return None | return None |
def FindDefaultFileDir(): | def FindDefaultFileDir(): |
"""Return the path of the directory containing the static files. By default | """Return the path of the directory containing the static files. By default |
the directory is called 'files'. The location depends on where setup.py put | the directory is called 'files'. The location depends on where setup.py put |
it.""" | it.""" |
base = FindPy2ExeBase() | base = FindPy2ExeBase() |
if base: | if base: |
return os.path.join(base, 'schedule_viewer_files') | return os.path.join(base, 'schedule_viewer_files') |
else: | else: |
# For all other distributions 'files' is in the gtfsscheduleviewer | # For all other distributions 'files' is in the gtfsscheduleviewer |
# directory. | # directory. |
base = os.path.dirname(gtfsscheduleviewer.__file__) # Strip __init__.py | base = os.path.dirname(gtfsscheduleviewer.__file__) # Strip __init__.py |
return os.path.join(base, 'files') | return os.path.join(base, 'files') |
def GetDefaultKeyFilePath(): | def GetDefaultKeyFilePath(): |
"""In py2exe return absolute path of file in the base directory and in all | """In py2exe return absolute path of file in the base directory and in all |
other distributions return relative path 'key.txt'""" | other distributions return relative path 'key.txt'""" |
windows_base = FindPy2ExeBase() | windows_base = FindPy2ExeBase() |
if windows_base: | if windows_base: |
return os.path.join(windows_base, 'key.txt') | return os.path.join(windows_base, 'key.txt') |
else: | else: |
return 'key.txt' | return 'key.txt' |
def main(RequestHandlerClass = ScheduleRequestHandler): | def main(RequestHandlerClass = ScheduleRequestHandler): |
usage = \ | usage = \ |
'''%prog [options] [<input GTFS.zip>] | '''%prog [options] [<input GTFS.zip>] |
Runs a webserver that lets you explore a <input GTFS.zip> in your browser. | Runs a webserver that lets you explore a <input GTFS.zip> in your browser. |
If <input GTFS.zip> is omited the filename is read from the console. Dragging | If <input GTFS.zip> is omited the filename is read from the console. Dragging |
a file into the console may enter the filename. | a file into the console may enter the filename. |
''' | ''' |
parser = util.OptionParserLongError( | parser = util.OptionParserLongError( |
usage=usage, version='%prog '+transitfeed.__version__) | usage=usage, version='%prog '+transitfeed.__version__) |
parser.add_option('--feed_filename', '--feed', dest='feed_filename', | parser.add_option('--feed_filename', '--feed', dest='feed_filename', |
help='file name of feed to load') | help='file name of feed to load') |
parser.add_option('--key', dest='key', | parser.add_option('--key', dest='key', |
help='Google Maps API key or the name ' | help='Google Maps API key or the name ' |
'of a text file that contains an API key') | 'of a text file that contains an API key') |
parser.add_option('--host', dest='host', help='Host name of Google Maps') | parser.add_option('--host', dest='host', help='Host name of Google Maps') |
parser.add_option('--port', dest='port', type='int', | parser.add_option('--port', dest='port', type='int', |
help='port on which to listen') | help='port on which to listen') |
parser.add_option('--file_dir', dest='file_dir', | parser.add_option('--file_dir', dest='file_dir', |
help='directory containing static files') | help='directory containing static files') |
parser.add_option('-n', '--noprompt', action='store_false', | parser.add_option('-n', '--noprompt', action='store_false', |
dest='manual_entry', | dest='manual_entry', |
help='disable interactive prompts') | help='disable interactive prompts') |
parser.set_defaults(port=8765, | parser.set_defaults(port=8765, |
host='maps.google.com', | host='maps.google.com', |
file_dir=FindDefaultFileDir(), | file_dir=FindDefaultFileDir(), |
manual_entry=True) | manual_entry=True) |
(options, args) = parser.parse_args() | (options, args) = parser.parse_args() |
if not os.path.isfile(os.path.join(options.file_dir, 'index.html')): | if not os.path.isfile(os.path.join(options.file_dir, 'index.html')): |
print "Can't find index.html with --file_dir=%s" % options.file_dir | print "Can't find index.html with --file_dir=%s" % options.file_dir |
exit(1) | exit(1) |
if not options.feed_filename and len(args) == 1: | if not options.feed_filename and len(args) == 1: |
options.feed_filename = args[0] | options.feed_filename = args[0] |
if not options.feed_filename and options.manual_entry: | if not options.feed_filename and options.manual_entry: |
options.feed_filename = raw_input('Enter Feed Location: ').strip('"') | options.feed_filename = raw_input('Enter Feed Location: ').strip('"') |
default_key_file = GetDefaultKeyFilePath() | default_key_file = GetDefaultKeyFilePath() |
if not options.key and os.path.isfile(default_key_file): | if not options.key and os.path.isfile(default_key_file): |
options.key = open(default_key_file).read().strip() | options.key = open(default_key_file).read().strip() |
if options.key and os.path.isfile(options.key): | if options.key and os.path.isfile(options.key): |
options.key = open(options.key).read().strip() | options.key = open(options.key).read().strip() |
schedule = transitfeed.Schedule(problem_reporter=transitfeed.ProblemReporter()) | schedule = transitfeed.Schedule(problem_reporter=transitfeed.ProblemReporter()) |
print 'Loading data from feed "%s"...' % options.feed_filename | print 'Loading data from feed "%s"...' % options.feed_filename |
print '(this may take a few minutes for larger cities)' | print '(this may take a few minutes for larger cities)' |
schedule.Load(options.feed_filename) | schedule.Load(options.feed_filename) |
server = StoppableHTTPServer(server_address=('', options.port), | server = StoppableHTTPServer(server_address=('', options.port), |
RequestHandlerClass=RequestHandlerClass) | RequestHandlerClass=RequestHandlerClass) |
server.key = options.key | server.key = options.key |
server.schedule = schedule | server.schedule = schedule |
server.file_dir = options.file_dir | server.file_dir = options.file_dir |
server.host = options.host | server.host = options.host |
server.feed_path = options.feed_filename | server.feed_path = options.feed_filename |
print ("To view, point your browser at http://localhost:%d/" % | print ("To view, point your browser at http://localhost:%d/" % |
(server.server_port)) | (server.server_port)) |
server.serve_forever() | server.serve_forever() |
if __name__ == '__main__': | if __name__ == '__main__': |
main() | main() |
cache/tiles | |
cache/map | |
[InternetShortcut] | |
URL=http://gplotter.offwhite.net/ | |
[InternetShortcut] | |
URL=http://brennan.offwhite.net/blog/2005/07/23/new-google-maps-icons-free/ | |
Binary files /dev/null and b/busui/staticmaplite/images/markers/Thumbs.db differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb1.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb10.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb11.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb12.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb13.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb14.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb15.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb16.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb17.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb18.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb19.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb2.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb20.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb21.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb22.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb23.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb24.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb25.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb3.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb4.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb5.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb6.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb7.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb8.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconb9.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong1.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong10.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong11.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong12.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong13.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong14.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong15.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong16.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong17.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong18.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong19.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong2.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong20.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong21.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong22.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong23.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong24.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong25.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong3.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong4.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong5.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong6.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong7.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong8.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icong9.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr1.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr10.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr11.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr12.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr13.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr14.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr15.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr16.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr17.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr18.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr19.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr2.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr20.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr21.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr22.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr23.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr24.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr25.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr3.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr4.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr5.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr6.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr7.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr8.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/iconr9.png differ
Binary files /dev/null and b/busui/staticmaplite/images/markers/icons.psd differ
Binary files a/busui/staticmaplite/images/markers/lightblue1.png and b/busui/staticmaplite/images/markers/lightblue1.png differ
Binary files a/busui/staticmaplite/images/markers/lightblue2.png and b/busui/staticmaplite/images/markers/lightblue2.png differ
Binary files a/busui/staticmaplite/images/markers/lightblue3.png and b/busui/staticmaplite/images/markers/lightblue3.png differ
Binary files a/busui/staticmaplite/images/markers/lightblue4.png and b/busui/staticmaplite/images/markers/lightblue4.png differ
Binary files a/busui/staticmaplite/images/markers/lightblue5.png and b/busui/staticmaplite/images/markers/lightblue5.png differ
Binary files a/busui/staticmaplite/images/markers/ol-marker-blue.png and b/busui/staticmaplite/images/markers/ol-marker-blue.png differ
Binary files a/busui/staticmaplite/images/markers/ol-marker-gold.png and b/busui/staticmaplite/images/markers/ol-marker-gold.png differ
Binary files a/busui/staticmaplite/images/markers/ol-marker-green.png and b/busui/staticmaplite/images/markers/ol-marker-green.png differ
Binary files a/busui/staticmaplite/images/markers/ol-marker.png and b/busui/staticmaplite/images/markers/ol-marker.png differ
Binary files a/busui/staticmaplite/images/osm_logo.png and b/busui/staticmaplite/images/osm_logo.png differ
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de-de" lang="de-de"> | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de-de" lang="de-de"> |
<head> | <head> |
<!-- | <!-- |
CSS based on template of Dandelion wiki engine by Radomir Dopieralski who released this | CSS based on template of Dandelion wiki engine by Radomir Dopieralski who released this |
template under the terms of GNU GPL. http://dandelion.sheep.art.pl/ | template under the terms of GNU GPL. http://dandelion.sheep.art.pl/ |
--> | --> |
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> | <meta http-equiv="content-type" content="text/html; charset=utf-8" /> |
<title>staticMapLite</title> | <title>staticMapLite</title> |
<style type="text/css"> | <style type="text/css"> |
html{font:96% sans-serif;color:#000;background:#f7f7f7;line-height:1.4;} | html{font:96% sans-serif;color:#000;background:#f7f7f7;line-height:1.4;} |
body{color:#333;} | body{color:#333;} |
#wrapper{margin:auto;width:60em;position:relative;} | #wrapper{margin:auto;width:60em;position:relative;} |
#header{padding:0px 0px 7px 0px; height: 1em;} | #header{padding:0px 0px 7px 0px; height: 1em;} |
#header h1 { float:left; width: 40%; } | #header h1 { float:left; width: 40%; } |
#content{background:white;padding:1em;border:1px solid #e0d78a;outline:0.5em solid #fef4a4; margin:0.5em 0;padding:20px;min-height:20em;} | #content{background:white;padding:1em;border:1px solid #e0d78a;outline:0.5em solid #fef4a4; margin:0.5em 0;padding:20px;min-height:20em;} |
h1{margin-top:0px;} | h1{margin-top:0px;} |
h1,h2,h3,h4,h5,h6{letter-spacing:0.05em;color:#1474CA;font-weight:normal;} | h1,h2,h3,h4,h5,h6{letter-spacing:0.05em;color:#1474CA;font-weight:normal;} |
h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover{text-decoration:none;} | h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover{text-decoration:none;} |
a{color:#1474CA;text-decoration:none;} | a{color:#1474CA;text-decoration:none;} |
a:visited{color:#1474CA;} | a:visited{color:#1474CA;} |
a.pending{color:#c174a0;} | a.pending{color:#c174a0;} |
a:hover{text-decoration:underline;} | a:hover{text-decoration:underline;} |
a img{border:none;} | a img{border:none;} |
input,textarea{font-size:94%;border:1px solid #999;background:#fff;color:#666;outline:0.2em solid #eee;padding:0px;line-height:1.2;margin:0.5em;vertical-align:middle;} | input,textarea{font-size:94%;border:1px solid #999;background:#fff;color:#666;outline:0.2em solid #eee;padding:0px;line-height:1.2;margin:0.5em;vertical-align:middle;} |
textarea{display:block;margin:0.5em auto;width:100%;} | textarea{display:block;margin:0.5em auto;width:100%;} |
pre{outline:0.4em solid #eee;padding:0.5em;margin:0.5em;border:1px solid #e0d78a;background:#fef4a4;color:#644e22;} | pre{outline:0.4em solid #eee;padding:0.5em;margin:0.5em;border:1px solid #e0d78a;background:#fef4a4;color:#644e22;} |
img{border:1px solid #ccc;outline:0.25em solid #eee;padding:0.25em;margin:0.25em 0 0.25em 0.5em;background:#fff;} | img{border:1px solid #ccc;outline:0.25em solid #eee;padding:0.25em;margin:0.25em 0 0.25em 0.5em;background:#fff;} |
hr{height:0;border:none;color:#fff;background:transparent;border-bottom:1px solid #ccc; margin:0.5em 0;} | hr{height:0;border:none;color:#fff;background:transparent;border-bottom:1px solid #ccc; margin:0.5em 0;} |
#diff {outline:none;border:none;} | #diff {outline:none;border:none;} |
#diff ins{color:green;text-decoration:none;font-weight:bold;} | #diff ins{color:green;text-decoration:none;font-weight:bold;} |
#diff del{color:red;text-decoration:line-through;} | #diff del{color:red;text-decoration:line-through;} |
#diff{background:#fff;line-height:1.25;padding:1em;white-space:pre-wrap;word-wrap:break-word; white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;width:97%;} | #diff{background:#fff;line-height:1.25;padding:1em;white-space:pre-wrap;word-wrap:break-word; white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;width:97%;} |
hr{margin:10px 0 10px 0;height:0px;overflow:hidden;border:0px;border-top:2px solid #ccc;} | hr{margin:10px 0 10px 0;height:0px;overflow:hidden;border:0px;border-top:2px solid #ccc;} |
.error{color:#F25A5A;font-weight:bold;} | .error{color:#F25A5A;font-weight:bold;} |
form{display:inline;} | form{display:inline;} |
#contentTextarea{height:44em;} | #contentTextarea{height:44em;} |
#toc{margin:5px 0 5px 10px;padding:6px 5px 7px 0px;float:right;list-style:none;outline:0.4em solid #eee;background:#fef4a4;border:1px solid #e0d78a;} | #toc{margin:5px 0 5px 10px;padding:6px 5px 7px 0px;float:right;list-style:none;outline:0.4em solid #eee;background:#fef4a4;border:1px solid #e0d78a;} |
#toc ul{list-style:none;padding:3px 0 3px 10px;} | #toc ul{list-style:none;padding:3px 0 3px 10px;} |
#toc li{font-size:11px;padding-left:10px;} | #toc li{font-size:11px;padding-left:10px;} |
#toc ul li{font-size:10px;} | #toc ul li{font-size:10px;} |
#toc ul ul li{font-size:9px;} | #toc ul ul li{font-size:9px;} |
#toc ul ul ul li{font-size:8px;} | #toc ul ul ul li{font-size:8px;} |
#toc ul ul ul ul li{font-size:7px;} | #toc ul ul ul ul li{font-size:7px;} |
.pageVersionsList{letter-spacing:0px;font-variant:normal;font-size:12px;} | .pageVersionsList{letter-spacing:0px;font-variant:normal;font-size:12px;} |
#renameForm{float:left;} | #renameForm{float:left;} |
.clear{clear:both;} | .clear{clear:both;} |
.tagList{padding:0.2em 0.4em 0.2em 0.4em;margin-top:0.5em;border:1px dashed #e0d78a;background:#fef4a4;color:#644e22;} | .tagList{padding:0.2em 0.4em 0.2em 0.4em;margin-top:0.5em;border:1px dashed #e0d78a;background:#fef4a4;color:#644e22;} |
.tagCloud{float:right;width:200px;padding:0.5em;margin:1em;border:1px dashed #e0d78a;background:#fef4a4;color:#644e22;} | .tagCloud{float:right;width:200px;padding:0.5em;margin:1em;border:1px dashed #e0d78a;background:#fef4a4;color:#644e22;} |
#fileTable{border-collapse:collapse;} | #fileTable{border-collapse:collapse;} |
#fileTable td{border:1px solid #FEF4A4;padding:2px 6px 2px 6px;} | #fileTable td{border:1px solid #FEF4A4;padding:2px 6px 2px 6px;} |
h2 span.par-edit, h3 span.par-edit, h4 span.par-edit, h5 span.par-edit, h6 span.par-edit {display:none;} | h2 span.par-edit, h3 span.par-edit, h4 span.par-edit, h5 span.par-edit, h6 span.par-edit {display:none;} |
h2:hover span.par-edit, h3:hover span.par-edit, h4:hover span.par-edit, h5:hover span.par-edit, h6:hover span.par-edit {display:inline;font-size:x-small;} | h2:hover span.par-edit, h3:hover span.par-edit, h4:hover span.par-edit, h5:hover span.par-edit, h6:hover span.par-edit {display:inline;font-size:x-small;} |
.comment-item { border:1px solid #999;color:#666;outline:0.2em solid #eee; } | .comment-item { border:1px solid #999;color:#666;outline:0.2em solid #eee; } |
.resizeTextareaDiv { margin-top: 5px;} | .resizeTextareaDiv { margin-top: 5px;} |
a.toolbarTextareaItem { padding-right: 10px; } | a.toolbarTextareaItem { padding-right: 10px; } |
a.external:after { content: "\2197";} | a.external:after { content: "\2197";} |
</style> | </style> |
</head> | </head> |
<body> | <body> |
<div id="wrapper"> | <div id="wrapper"> |
<div id="header"> | <div id="header"> |
</div> | </div> |
<div id="content"> | <div id="content"> |
<div class="par-div"> | <div class="par-div"> |
<h2> | <h2> |
staticMapLite - simple map for your website | staticMapLite - simple map for your website |
</h2> | </h2> |
<p> | <p> |
<img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=865x512&maptype=mapnik" width="865" height="512" /></p> | <img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=865x512&maptype=mapnik" width="865" height="512" /></p> |
<p> | <p> |
This image was created using the following simple <img> tag: | This image was created using the following simple <img> tag: |
<pre><img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=865x512&maptype=mapnik" /></pre> | <pre><img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=865x512&maptype=mapnik" /></pre> |
</p> | </p> |
</div> | </div> |
<hr /> | <hr /> |
<div class="par-div"> | <div class="par-div"> |
<h3> | <h3> |
Place Markers | Place Markers |
</h3> | </h3> |
<p> | <p> |
<img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=865x512&maptype=mapnik&markers=40.702147,-74.015794,lightblue1|40.711614,-74.012318,lightblue2|40.718217,-73.998284,lightblue3" width="865" height="512" /> | <img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=865x512&maptype=mapnik&markers=40.702147,-74.015794,lightblue1|40.711614,-74.012318,lightblue2|40.718217,-73.998284,lightblue3" width="865" height="512" /> |
</p><p> Add markers by appending them to the image URL: | </p><p> Add markers by appending them to the image URL: |
<pre>markers=40.702147,-74.015794,lightblue1|40.711614,-74.012318,lightblue2|40.718217,-73.998284,lightblue3</pre> | <pre>markers=40.702147,-74.015794,lightblue1|40.711614,-74.012318,lightblue2|40.718217,-73.998284,lightblue3</pre> |
</p> | </p> |
</div> | </div> |
<hr /> | <hr /> |
<div class="par-div"> | <div class="par-div"> |
<h3> | <h3> |
Use Different Map Styles (Tile Sources) | Use Different Map Styles (Tile Sources) |
</h3> | </h3> |
<p> | <p> |
<div style="float:left; margin-right: 10px"> | <div style="float:left; margin-right: 10px"> |
<img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=256x256&maptype=mapnik" width="256" height="256" /> | <img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=256x256&maptype=mapnik" width="256" height="256" /> |
<pre>maptype=mapnik</pre> | <pre>maptype=mapnik</pre> |
</div> | </div> |
<div style="float:left; margin-right: 10px"> | <div style="float:left; margin-right: 10px"> |
<img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=256x256&maptype=osmarenderer" width="256" height="256" /> | <img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=256x256&maptype=osmarenderer" width="256" height="256" /> |
<pre>maptype=osmarenderer</pre> | <pre>maptype=osmarenderer</pre> |
</div> | </div> |
<div style="float:left; margin-right: 10px"> | <div style="float:left; margin-right: 10px"> |
<img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=256x256&maptype=cycle" width="256" height="256" /> | <img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=256x256&maptype=cycle" width="256" height="256" /> |
<pre>maptype=cycle</pre> | <pre>maptype=cycle</pre> |
</div> | </div> |
<br style="clear:both" /> | <br style="clear:both" /> |
</p> | </p> |
</div> | </div> |
</div> | </div> |
<div id="footer"> | <div id="footer"> |
<div style="text-align:center;padding:7px;color:#ccc"> | <div style="text-align:center;padding:7px;color:#ccc"> |
sponsored by <a href="http://dfacts.de">dFacts Network</a> | sponsored by <a href="http://dfacts.de">dFacts Network</a> |
</div> | </div> |
</div> | </div> |
</div> | </div> |
</body> | </body> |
</html> | </html> |
chcon -R -t httpd_sys_content_rw_t cache | |
<?php | <?php |
/** | /** |
* staticMapLite 0.02 | * staticMapLite 0.02 |
* | * |
* Copyright 2009 Gerhard Koch | * Copyright 2009 Gerhard Koch |
* | * |
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); |
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. |
* You may obtain a copy of the License at | * You may obtain a copy of the License at |
* | * |
* http://www.apache.org/licenses/LICENSE-2.0 | * http://www.apache.org/licenses/LICENSE-2.0 |
* | * |
* Unless required by applicable law or agreed to in writing, software | * Unless required by applicable law or agreed to in writing, software |
* distributed under the License is distributed on an "AS IS" BASIS, | * distributed under the License is distributed on an "AS IS" BASIS, |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
* See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and |
* limitations under the License. | * limitations under the License. |
* | * |
* @author Gerhard Koch <gerhard.koch AT ymail.com> | * @author Gerhard Koch <gerhard.koch AT ymail.com> |
* | * |
* USAGE: | * USAGE: |
* | * |
* staticmap.php?center=40.714728,-73.998672&zoom=14&size=512x512&maptype=mapnik&markers=40.702147,-74.015794,blues|40.711614,-74.012318,greeng|40.718217,-73.998284,redc | * staticmap.php?center=40.714728,-73.998672&zoom=14&size=512x512&maptype=mapnik&markers=40.702147,-74.015794,blues|40.711614,-74.012318,greeng|40.718217,-73.998284,redc |
* | * |
*/ | */ |
error_reporting(0); | error_reporting(0); |
ini_set('display_errors','off'); | ini_set('display_errors','off'); |
Class staticMapLite { | Class staticMapLite { |
protected $tileSize = 256; | protected $tileSize = 256; |
protected $tileSrcUrl = array( 'mapnik' => 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png', | protected $tileSrcUrl = array( 'mapnik' => 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png', |
'osmarenderer' => 'http://c.tah.openstreetmap.org/Tiles/tile/{Z}/{X}/{Y}.png', | 'osmarenderer' => 'http://c.tah.openstreetmap.org/Tiles/tile/{Z}/{X}/{Y}.png', |
'cycle' => 'http://c.andy.sandbox.cloudmade.com/tiles/cycle/{Z}/{X}/{Y}.png' | 'cycle' => 'http://c.andy.sandbox.cloudmade.com/tiles/cycle/{Z}/{X}/{Y}.png' |
); | ); |
protected $tileDefaultSrc = 'mapnik'; | protected $tileDefaultSrc = 'mapnik'; |
protected $markerBaseDir = 'images/markers'; | protected $markerBaseDir = 'images/markers'; |
protected $osmLogo = 'images/osm_logo.png'; | protected $osmLogo = 'images/osm_logo.png'; |
protected $useTileCache = true; | protected $useTileCache = true; |
protected $tileCacheBaseDir = 'cache/tiles'; | protected $tileCacheBaseDir = './cache/tiles'; |
protected $useMapCache = true; | protected $useMapCache = true; |
protected $mapCacheBaseDir = 'cache/maps'; | protected $mapCacheBaseDir = './cache/maps'; |
protected $mapCacheID = ''; | protected $mapCacheID = ''; |
protected $mapCacheFile = ''; | protected $mapCacheFile = ''; |
protected $mapCacheExtension = 'png'; | protected $mapCacheExtension = 'png'; |
protected $zoom, $lat, $lon, $width, $height, $markers, $image, $maptype; | protected $zoom, $lat, $lon, $width, $height, $markers, $image, $maptype; |
protected $centerX, $centerY, $offsetX, $offsetY; | protected $centerX, $centerY, $offsetX, $offsetY; |
public function __construct(){ | public function __construct(){ |
$this->zoom = 0; | $this->zoom = 0; |
$this->lat = 0; | $this->lat = 0; |
$this->lon = 0; | $this->lon = 0; |
$this->width = 500; | $this->width = 500; |
$this->height = 350; | $this->height = 350; |
$this->markers = array(); | $this->markers = array(); |
$this->maptype = $this->tileDefaultSrc; | $this->maptype = $this->tileDefaultSrc; |
} | } |
public function parseParams(){ | public function parseParams(){ |
global $_GET; | global $_GET; |
// get zoom from GET paramter | // get zoom from GET paramter |
$this->zoom = $_GET['zoom']?intval($_GET['zoom']):0; | $this->zoom = $_GET['zoom']?intval($_GET['zoom']):0; |
if($this->zoom>18)$this->zoom = 18; | if($this->zoom>18)$this->zoom = 18; |
// get lat and lon from GET paramter | // get lat and lon from GET paramter |
list($this->lat,$this->lon) = split(',',$_GET['center']); | list($this->lat,$this->lon) = split(',',$_GET['center']); |
$this->lat = floatval($this->lat); | $this->lat = floatval($this->lat); |
$this->lon = floatval($this->lon); | $this->lon = floatval($this->lon); |
// get zoom from GET paramter | // get zoom from GET paramter |
if($_GET['size']){ | if($_GET['size']){ |
list($this->width, $this->height) = split('x',$_GET['size']); | list($this->width, $this->height) = split('x',$_GET['size']); |
$this->width = intval($this->width); | $this->width = intval($this->width); |
$this->height = intval($this->height); | $this->height = intval($this->height); |
} | } |
if($_GET['markers']){ | if($_GET['markers']){ |
$markers = split('%7C|\|',$_GET['markers']); | $markers = split('%7C|\|',$_GET['markers']); |
foreach($markers as $marker){ | foreach($markers as $marker){ |
list($markerLat, $markerLon, $markerImage) = split(',',$marker); | list($markerLat, $markerLon, $markerImage) = split(',',$marker); |
$markerLat = floatval($markerLat); | $markerLat = floatval($markerLat); |
$markerLon = floatval($markerLon); | $markerLon = floatval($markerLon); |
$markerImage = basename($markerImage); | $markerImage = basename($markerImage); |
$this->markers[] = array('lat'=>$markerLat, 'lon'=>$markerLon, 'image'=>$markerImage); | $this->markers[] = array('lat'=>$markerLat, 'lon'=>$markerLon, 'image'=>$markerImage); |
} | } |
} | } |
if($_GET['maptype']){ | if($_GET['maptype']){ |
if(array_key_exists($_GET['maptype'],$this->tileSrcUrl)) $this->maptype = $_GET['maptype']; | if(array_key_exists($_GET['maptype'],$this->tileSrcUrl)) $this->maptype = $_GET['maptype']; |
} | } |
} | } |
public function lonToTile($long, $zoom){ | public function lonToTile($long, $zoom){ |
return (($long + 180) / 360) * pow(2, $zoom); | return (($long + 180) / 360) * pow(2, $zoom); |
} | } |
public function latToTile($lat, $zoom){ | public function latToTile($lat, $zoom){ |
return (1 - log(tan($lat * pi()/180) + 1 / cos($lat* pi()/180)) / pi()) /2 * pow(2, $zoom); | return (1 - log(tan($lat * pi()/180) + 1 / cos($lat* pi()/180)) / pi()) /2 * pow(2, $zoom); |
} | } |
public function initCoords(){ | public function initCoords(){ |
$this->centerX = $this->lonToTile($this->lon, $this->zoom); | $this->centerX = $this->lonToTile($this->lon, $this->zoom); |
$this->centerY = $this->latToTile($this->lat, $this->zoom); | $this->centerY = $this->latToTile($this->lat, $this->zoom); |
$this->offsetX = floor((floor($this->centerX)-$this->centerX)*$this->tileSize); | $this->offsetX = floor((floor($this->centerX)-$this->centerX)*$this->tileSize); |
$this->offsetY = floor((floor($this->centerY)-$this->centerY)*$this->tileSize); | $this->offsetY = floor((floor($this->centerY)-$this->centerY)*$this->tileSize); |
} | } |
public function createBaseMap(){ | public function createBaseMap(){ |
$this->image = imagecreatetruecolor($this->width, $this->height); | $this->image = imagecreatetruecolor($this->width, $this->height); |
$startX = floor($this->centerX-($this->width/$this->tileSize)/2); | $startX = floor($this->centerX-($this->width/$this->tileSize)/2); |
$startY = floor($this->centerY-($this->height/$this->tileSize)/2); | $startY = floor($this->centerY-($this->height/$this->tileSize)/2); |
$endX = ceil($this->centerX+($this->width/$this->tileSize)/2); | $endX = ceil($this->centerX+($this->width/$this->tileSize)/2); |
$endY = ceil($this->centerY+($this->height/$this->tileSize)/2); | $endY = ceil($this->centerY+($this->height/$this->tileSize)/2); |
$this->offsetX = -floor(($this->centerX-floor($this->centerX))*$this->tileSize); | $this->offsetX = -floor(($this->centerX-floor($this->centerX))*$this->tileSize); |
$this->offsetY = -floor(($this->centerY-floor($this->centerY))*$this->tileSize); | $this->offsetY = -floor(($this->centerY-floor($this->centerY))*$this->tileSize); |
$this->offsetX += floor($this->width/2); | $this->offsetX += floor($this->width/2); |
$this->offsetY += floor($this->height/2); | $this->offsetY += floor($this->height/2); |
$this->offsetX += floor($startX-floor($this->centerX))*$this->tileSize; | $this->offsetX += floor($startX-floor($this->centerX))*$this->tileSize; |
$this->offsetY += floor($startY-floor($this->centerY))*$this->tileSize; | $this->offsetY += floor($startY-floor($this->centerY))*$this->tileSize; |
for($x=$startX; $x<=$endX; $x++){ | for($x=$startX; $x<=$endX; $x++){ |
for($y=$startY; $y<=$endY; $y++){ | for($y=$startY; $y<=$endY; $y++){ |
$url = str_replace(array('{Z}','{X}','{Y}'),array($this->zoom, $x, $y), $this->tileSrcUrl[$this->maptype]); | $url = str_replace(array('{Z}','{X}','{Y}'),array($this->zoom, $x, $y), $this->tileSrcUrl[$this->maptype]); |
$tileImage = imagecreatefromstring($this->fetchTile($url)); | $tileImage = imagecreatefromstring($this->fetchTile($url)); |
$destX = ($x-$startX)*$this->tileSize+$this->offsetX; | $destX = ($x-$startX)*$this->tileSize+$this->offsetX; |
$destY = ($y-$startY)*$this->tileSize+$this->offsetY; | $destY = ($y-$startY)*$this->tileSize+$this->offsetY; |
imagecopy($this->image, $tileImage, $destX, $destY, 0, 0, $this->tileSize, $this->tileSize); | imagecopy($this->image, $tileImage, $destX, $destY, 0, 0, $this->tileSize, $this->tileSize); |
} | } |
} | } |
} | } |
public function placeMarkers(){ | public function placeMarkers(){ |
foreach($this->markers as $marker){ | foreach($this->markers as $marker){ |
$markerLat = $marker['lat']; | $markerLat = $marker['lat']; |
$markerLon = $marker['lon']; | $markerLon = $marker['lon']; |
$markerImage = $marker['image']; | $markerImage = $marker['image']; |
$markerIndex++; | $markerIndex++; |
$markerFilename = $markerImage?(file_exists($this->markerBaseDir.'/'.$markerImage.".png")?$markerImage:'lightblue'.$markerIndex):'lightblue'.$markerIndex; | $markerFilename = $markerImage?(file_exists($this->markerBaseDir.'/'.$markerImage.".png")?$markerImage:'lightblue'.$markerIndex):'lightblue'.$markerIndex; |
if(file_exists($this->markerBaseDir.'/'.$markerFilename.".png")){ | if(file_exists($this->markerBaseDir.'/'.$markerFilename.".png")){ |
$markerImg = imagecreatefrompng($this->markerBaseDir.'/'.$markerFilename.".png"); | $markerImg = imagecreatefrompng($this->markerBaseDir.'/'.$markerFilename.".png"); |
} else { | } else { |
$markerImg = imagecreatefrompng($this->markerBaseDir.'/lightblue1.png'); | $markerImg = imagecreatefrompng($this->markerBaseDir.'/lightblue1.png'); |
} | } |
$destX = floor(($this->width/2)-$this->tileSize*($this->centerX-$this->lonToTile($markerLon, $this->zoom))); | $destX = floor(($this->width/2)-$this->tileSize*($this->centerX-$this->lonToTile($markerLon, $this->zoom))); |
$destY = floor(($this->height/2)-$this->tileSize*($this->centerY-$this->latToTile($markerLat, $this->zoom))); | $destY = floor(($this->height/2)-$this->tileSize*($this->centerY-$this->latToTile($markerLat, $this->zoom))); |
$destY = $destY - imagesy($markerImg); | $destY = $destY - imagesy($markerImg); |
imagecopy($this->image, $markerImg, $destX, $destY, 0, 0, imagesx($markerImg), imagesy($markerImg)); | imagecopy($this->image, $markerImg, $destX, $destY, 0, 0, imagesx($markerImg), imagesy($markerImg)); |
}; | }; |
} | } |
public function tileUrlToFilename($url){ | public function tileUrlToFilename($url){ |
return $this->tileCacheBaseDir."/".str_replace(array('http://'),'',$url); | return $this->tileCacheBaseDir."/".str_replace(array('http://'),'',$url); |
} | } |
public function checkTileCache($url){ | public function checkTileCache($url){ |
$filename = $this->tileUrlToFilename($url); | $filename = $this->tileUrlToFilename($url); |
if(file_exists($filename)){ | if(file_exists($filename)){ |
return file_get_contents($filename); | return file_get_contents($filename); |
} | } |
} | } |
public function checkMapCache(){ | public function checkMapCache(){ |
$this->mapCacheID = md5($this->serializeParams()); | $this->mapCacheID = md5($this->serializeParams()); |
$filename = $this->mapCacheIDToFilename(); | $filename = $this->mapCacheIDToFilename(); |
if(file_exists($filename)) return true; | if(file_exists($filename)) return true; |
} | } |
public function serializeParams(){ | public function serializeParams(){ |
return join("&",array($this->zoom,$this->lat,$this->lon,$this->width,$this->height, serialize($this->markers),$this->maptype)); | return join("&",array($this->zoom,$this->lat,$this->lon,$this->width,$this->height, serialize($this->markers),$this->maptype)); |
} | } |
public function mapCacheIDToFilename(){ | public function mapCacheIDToFilename(){ |
if(!$this->mapCacheFile){ | if(!$this->mapCacheFile){ |
$this->mapCacheFile = $this->mapCacheBaseDir."/".substr($this->mapCacheID,0,2)."/".substr($this->mapCacheID,2,2)."/".substr($this->mapCacheID,4); | $this->mapCacheFile = $this->mapCacheBaseDir."/".substr($this->mapCacheID,0,2)."/".substr($this->mapCacheID,2,2)."/".substr($this->mapCacheID,4); |
} | } |
return $this->mapCacheFile.".".$this->mapCacheExtension; | return $this->mapCacheFile.".".$this->mapCacheExtension; |
} | } |
public function mkdir_recursive($pathname, $mode){ | public function mkdir_recursive($pathname, $mode){ |
is_dir(dirname($pathname)) || $this->mkdir_recursive(dirname($pathname), $mode); | return mkdir($pathname, $mode, true); |
return is_dir($pathname) || @mkdir($pathname, $mode); | |
} | } |
public function writeTileToCache($url, $data){ | public function writeTileToCache($url, $data){ |
$filename = $this->tileUrlToFilename($url); | $filename = $this->tileUrlToFilename($url); |
$this->mkdir_recursive(dirname($filename),0777); | $this->mkdir_recursive(dirname($filename),0777); |
file_put_contents($filename, $data); | file_put_contents($filename, $data); |
} | } |
public function fetchTile($url){ | public function fetchTile($url){ |
if($this->useTileCache && ($cached = $this->checkTileCache($url))) return $cached; | if($this->useTileCache && ($cached = $this->checkTileCache($url))) return $cached; |
$ch = curl_init(); | $ch = curl_init(); |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0"); | curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0"); |
curl_setopt($ch, CURLOPT_URL, $url); | curl_setopt($ch, CURLOPT_URL, $url); |
$tile = curl_exec($ch); | $tile = curl_exec($ch); |
curl_close($ch); | curl_close($ch); |
if($this->useTileCache){ | if($this->useTileCache){ |
$this->writeTileToCache($url,$tile); | $this->writeTileToCache($url,$tile); |
} | } |
return $tile; | return $tile; |
} | } |
public function copyrightNotice(){ | public function copyrightNotice(){ |
$logoImg = imagecreatefrompng($this->osmLogo); | $logoImg = imagecreatefrompng($this->osmLogo); |
imagecopy($this->image, $logoImg, imagesx($this->image)-imagesx($logoImg), imagesy($this->image)-imagesy($logoImg), 0, 0, imagesx($logoImg), imagesy($logoImg)); | imagecopy($this->image, $logoImg, imagesx($this->image)-imagesx($logoImg), imagesy($this->image)-imagesy($logoImg), 0, 0, imagesx($logoImg), imagesy($logoImg)); |
} | } |
public function sendHeader(){ | public function sendHeader(){ |
header('Content-Type: image/png'); | header('Content-Type: image/png'); |
$expires = 60*60*24*14; | $expires = 60*60*24*14; |
header("Pragma: public"); | header("Pragma: public"); |
header("Cache-Control: maxage=".$expires); | header("Cache-Control: maxage=".$expires); |
header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT'); | header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT'); |
} | } |
public function makeMap(){ | public function makeMap(){ |
$this->initCoords(); | $this->initCoords(); |
$this->createBaseMap(); | $this->createBaseMap(); |
if(count($this->markers))$this->placeMarkers(); | if(count($this->markers))$this->placeMarkers(); |
if($this->osmLogo) $this->copyrightNotice(); | if($this->osmLogo) $this->copyrightNotice(); |
} | } |
public function showMap(){ | public function showMap(){ |
$this->parseParams(); | $this->parseParams(); |
if($this->useMapCache){ | if($this->useMapCache){ |
// use map cache, so check cache for map | // use map cache, so check cache for map |
if(!$this->checkMapCache()){ | if(!$this->checkMapCache()){ |
// map is not in cache, needs to be build | // map is not in cache, needs to be build |
$this->makeMap(); | $this->makeMap(); |
$this->mkdir_recursive(dirname($this->mapCacheIDToFilename()),0777); | $this->mkdir_recursive(dirname($this->mapCacheIDToFilename()),0777); |
imagepng($this->image,$this->mapCacheIDToFilename(),9); | imagepng($this->image,$this->mapCacheIDToFilename(),9); |
$this->sendHeader(); | $this->sendHeader(); |
if(file_exists($this->mapCacheIDToFilename())){ | if(file_exists($this->mapCacheIDToFilename())){ |
return file_get_contents($this->mapCacheIDToFilename()); | return file_get_contents($this->mapCacheIDToFilename()); |
} else { | } else { |
return imagepng($this->image); | return imagepng($this->image); |
} | } |
} else { | } else { |
// map is in cache | // map is in cache |
$this->sendHeader(); | $this->sendHeader(); |
return file_get_contents($this->mapCacheIDToFilename()); | return file_get_contents($this->mapCacheIDToFilename()); |
} | } |
} else { | } else { |
// no cache, make map, send headers and deliver png | // no cache, make map, send headers and deliver png |
$this->makeMap(); | $this->makeMap(); |
$this->sendHeader(); | $this->sendHeader(); |
return imagepng($this->image); | return imagepng($this->image); |
} | } |
} | } |
} | } |
$map = new staticMapLite(); | $map = new staticMapLite(); |
print $map->showMap(); | print $map->showMap(); |
?> | ?> |
<?php | <?php |
include('common.inc.php'); | include('common.inc.php'); |
$url = $APIurl."/json/stop?stop_id=".$_REQUEST['stopid']; | $url = $APIurl."/json/stop?stop_id=".$_REQUEST['stopid']; |
$stop = json_decode(getPage($url)); | $stop = json_decode(getPage($url)); |
include_header("Trips passing ".$stop[1]); | include_header("Trips passing ".$stop[1]); |
echo '<div data-role="content" class="ui-content" role="main"><p>'.staticmap(Array(0 => Array($stop[2],$stop[3]))).'</p>'; | echo '<div data-role="content" class="ui-content" role="main"><p>'.staticmap(Array(0 => Array($stop[2],$stop[3]))).'</p>'; |
echo ' <ul data-role="listview" >'; | // change date/time/service_period |
echo ' <ul data-role="listview" data-inset="true">'; | |
$url = $APIurl."/json/stoptrips?stop=".$_REQUEST['stopid']."&time=".midnight_seconds()."&service_period=".service_period(); | $url = $APIurl."/json/stoptrips?stop=".$_REQUEST['stopid']."&time=".midnight_seconds()."&service_period=".service_period(); |
$trips = json_decode(getPage($url)); | $trips = json_decode(getPage($url)); |
debug(print_r($trips,true)); | |
foreach ($trips as $row) | foreach ($trips as $row) |
{ | { |
echo '<li>'; | echo '<li>'; |
echo '<h3><a href="trip.php?stopid='.$_REQUEST['stopid'].'&tripid='.$row[1][0].'">'.$row[1][1].'</a></h3>'; | echo '<h3><a href="trip.php?stopid='.$_REQUEST['stopid'].'&tripid='.$row[1][0].'">'.$row[1][1].'</a></h3>'; |
echo '<p class="ui-li-aside"><strong>'.midnight_seconds_to_time($row[0]).'</strong></p>'; | echo '<p class="ui-li-aside"><strong>'.midnight_seconds_to_time($row[0]).'</strong></p>'; |
echo '</li>'; | echo '</li>'; |
} | } |
if (sizeof($trips) == 0) echo "<li> <center>No trips in the near future.</center> </li>"; | if (sizeof($trips) == 0) echo "<li> <center>No trips in the near future.</center> </li>"; |
echo '</ul></div>'; | echo '</ul></div>'; |
include_footer(); | include_footer(); |
?> | ?> |
<?php | <?php |
include('common.inc.php'); | include('common.inc.php'); |
include_header("Stops"); | include_header("Stops"); |
echo ' <ul data-role="listview" data-filter="true">'; | echo' |
<div data-role="navbar"> | |
<ul> | |
<li><a href="stopList.php">Timing Points</a></li> | |
<li><a href="stopList.php?allstops=yes">All Stops</a></li> | |
</ul> | |
</div> | |
'; | |
echo '<div class="noscriptnav"> Go to letter: '; | |
foreach(range('A','Z') as $letter) | |
{ | |
echo "<a href=\"#$letter\">$letter</a> "; | |
} | |
echo "</div> | |
<script> | |
$('.noscriptnav').hide(); | |
</script>"; | |
echo ' <ul data-role="listview" data-filter="true" data-inset="true" >'; | |
$url = $APIurl."/json/timingpoints"; | $url = $APIurl."/json/timingpoints"; |
if ($_REQUEST['allstops']) $url = $APIurl."/json/stops"; | if ($_REQUEST['allstops']) $url = $APIurl."/json/stops"; |
if ($_REQUEST['lat'] && $_REQUEST['lon']) $url = $APIurl."/json/neareststops?lat={$_REQUEST['lat']}&lon={$_REQUEST['lon']}&limit=15"; | if ($_REQUEST['lat'] && $_REQUEST['lon']) $url = $APIurl."/json/neareststops?lat={$_REQUEST['lat']}&lon={$_REQUEST['lon']}&limit=15"; |
$contents = json_decode(getPage($url)); | $contents = json_decode(getPage($url)); |
debug(print_r($contents,true)); | |
foreach ($contents as $key => $row) { | foreach ($contents as $key => $row) { |
$stopName[$key] = $row[1]; | $stopName[$key] = $row[1]; |
} | } |
// Sort the data with volume descending, edition ascending | // Sort the stops by name |
// Add $data as the last parameter, to sort by the common key | |
array_multisort($stopName, SORT_ASC, $contents); | array_multisort($stopName, SORT_ASC, $contents); |
$firstletter = ""; | |
foreach ($contents as $row) | foreach ($contents as $row) |
{ | { |
if (substr($row[1],0,1) != $firstletter){ | |
echo "<a name=$firstletter></a>"; | |
$firstletter = substr($row[1],0,1); | |
} | |
echo '<li><a href="stop.php?stopid='.$row[0].'">'.$row[1].'</a></li>'; | echo '<li><a href="stop.php?stopid='.$row[0].'">'.$row[1].'</a></li>'; |
} | } |
echo '</ul>'; | echo '</ul>'; |
echo' | |
<div data-role="footer" data-id="foo1" data-position="fixed"> | |
<div data-role="navbar"> | |
<ul> | |
<li><a href="stopList.php" class="ui-btn-active">Timing Points</a></li> | |
<li><a href="stopList.php?allstops=yes">All Stops</a></li> | |
</ul> | |
'; | |
include_footer(); | include_footer(); |
?> | ?> |
<?php | <?php |
include('common.inc.php'); | include('common.inc.php'); |
$tripid = $_REQUEST['tripid']; | $tripid = $_REQUEST['tripid']; |
if ($_REQUEST['routeid']) { | if ($_REQUEST['routeid']) { |
$url = $APIurl."/json/routetrips?route_id=".$_REQUEST['routeid']; | $url = $APIurl."/json/routetrips?route_id=".$_REQUEST['routeid']; |
$trips = json_decode(getPage($url)); | $trips = json_decode(getPage($url)); |
debug(print_r($trips,true)); | |
foreach ($trips as $trip) | foreach ($trips as $trip) |
{ | { |
if ($trip[0] < midnight_seconds()) { | if ($trip[0] < midnight_seconds()) { |
$tripid = $trip[1]; | $tripid = $trip[1]; |
break; | break; |
} | } |
} | } |
if (!($tripid > 0)) $tripid = $trips[0][1]; | if (!($tripid > 0)) $tripid = $trips[0][1]; |
} | } |
$url = $APIurl."/json/triprows?trip=".$tripid; | $url = $APIurl."/json/triprows?trip=".$tripid; |
$trips = array_flatten(json_decode(getPage($url))); | $trips = array_flatten(json_decode(getPage($url))); |
debug(print_r($trips,true)); | |
include_header("Stops on ". $trips[1]->route_short_name . ' '. $trips[1]->route_long_name); | include_header("Stops on ". $trips[1]->route_short_name . ' '. $trips[1]->route_long_name); |
echo ' <ul data-role="listview" >'; | echo ' <ul data-role="listview" data-inset="true">'; |
$url = $APIurl."/json/tripstoptimes?trip=".$tripid; | $url = $APIurl."/json/tripstoptimes?trip=".$tripid; |
$json = json_decode(getPage($url)); | $json = json_decode(getPage($url)); |
debug(print_r($json,true)); | |
$stops = $json[0]; | $stops = $json[0]; |
$times = $json[1]; | $times = $json[1]; |
foreach ($stops as $key => $row) | foreach ($stops as $key => $row) |
{ | { |
echo '<li>'; | echo '<li>'; |
echo '<h3><a href="stop.php?stopid='.$row[0].'">'.$row[1].'</a></h3>'; | echo '<h3><a href="stop.php?stopid='.$row[0].'">'.$row[1].'</a></h3>'; |
echo '<p class="ui-li-aside">'.midnight_seconds_to_time($times[$key]).'</p>'; | echo '<p class="ui-li-aside">'.midnight_seconds_to_time($times[$key]).'</p>'; |
echo '</li>'; | echo '</li>'; |
} | } |
echo '</ul>'; | echo '</ul>'; |
include_footer(); | include_footer(); |
?> | ?> |
<?php | <?php |
include('common.inc.php'); | include('common.inc.php'); |
if ($_REQUEST['time']) { | include_header("Trip Planner", true, true); |
$toPlace = geocode($_REQUEST['to'],false); | function tripPlanForm($errorMessage = "") |
$fromPlace = geocode($_REQUEST['from'],false); | { |
$url = "http://localhost:8080/opentripplanner-api-webapp/ws/plan?_dc=1290254798856&arriveBy=false&date=11%2F17%2F2010&time=1%3A06%20pm&mode=TRANSIT%2CWALK&optimize=QUICK&maxWalkDistance=840&wheelchair=false&toPlace=$toPlace&fromPlace=$fromPlace&intermediatePlaces="; | $from = (isset($_REQUEST['from']) ? $_REQUEST['from'] : "Brigalow"); |
$ch = curl_init($url); | $to = (isset($_REQUEST['to']) ? $_REQUEST['to'] : "Barry"); |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); | $date = (isset($_REQUEST['date']) ? $_REQUEST['date'] : date("m/d/Y")); |
curl_setopt( $ch, CURLOPT_HEADER, 0 ); | $time = (isset($_REQUEST['time']) ? $_REQUEST['time'] : date("h:ia")); |
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept: application/json")); | echo "<font color=red>$errorMessage</font>"; |
$page = curl_exec($ch); | echo '<form action="tripPlanner.php" method="post"> |
curl_close($ch); | <div data-role="fieldcontain"> |
$tripplan = json_decode($page); | <label for="from">I would like to go from</label> |
echo "<h1> From: {$tripplan->plan->from->name} </h1>"; | <input type="text" name="from" id="from" value="' . $from . '" /> |
echo "<h1> To: {$tripplan->plan->to->name} </h1>"; | <a href="#" style="display:none" name="fromHere" id="fromHere"/>Here?</a> |
echo "<h1> At: {$tripplan->plan->date} </h1>"; | </div> |
foreach ($tripplan->plan->itineraries->itinerary as $itineraryNumber => $itinerary ){ | <div data-role="fieldcontain"> |
echo "<hr> <h2> Option #".($itineraryNumber+1)."<h2>"; | <label for="to"> to </label> |
echo "Duration: ".floor($itinerary->duration/60000)." minutes ({$itinerary->startTime} to {$itinerary->endTime})<br>\n"; | <input type="text" name="to" id="to" value="' . $to . '" /> |
echo "Walking time: ".floor($itinerary->walkTime/60000)." minutes ({$itinerary->walkDistance} meters)<br>\n"; | <a href="#" style="display:none" name="toHere" id="toHere"/>Here?</a> |
echo "Transit time: ".floor($itinerary->transitTime/60000)." minutes<br>\n"; | </div> |
echo "Waiting time: ".floor($itinerary->waitingTime/60000)." minutes<br>\n"; | <div data-role="fieldcontain"> |
$legMarkers = Array(); | <label for="date"> on </label> |
foreach ($itinerary->legs->leg as $legNumber => $leg ){ | <input type="date" name="date" id="date" value="' . $date . '" /> |
$legMarkers[] = Array($leg->from->lat,$leg->from->lon); | </div> |
} | <div data-role="fieldcontain"> |
echo staticmap($legMarkers)."<br>\n"; | <label for="time"> at </label> |
foreach ($itinerary->legs->leg as $legNumber => $leg ){ | <input type="time" name="time" id="time" value="' . $time . '" /> |
echo "Leg #".($legNumber+1)." (from: {$leg->from->name} to {$leg->to->name}, ".floor($leg->duration/60000)." minutes) <br>\n"; | </div> |
$legArray = object2array($leg); | <input type="submit" value="Go!"></form>'; |
if ($legArray["@mode"] === "BUS") { | echo "<script> |
echo "Take bus {$legArray['@route']} ".str_replace("To","towards",$legArray['@headsign'])."<br>"; | $('#toHere').click(function(event) { $('#to').val(getCookie('geolocate')); return false;}); |
} | $('#toHere').show(); |
else { | $('#fromHere').click(function(event) { $('#from').val(getCookie('geolocate')); return false;}); |
foreach ($leg->steps->walkSteps as $stepNumber => $step ){ | $('#fromHere').show(); |
echo "Walking step $stepNumber $step->absoluteDirection / $step->relativeDirection on $step->streetName for $step->distance meters / ".floor($step->duration/60000)." minutes<br>\n"; | |
} | </script>"; |
} | } |
} | |
} | function processItinerary($itineraryNumber, $itinerary) |
} else { | { |
echo '<form> I would like to go from <input type="text" name="from" value="Brigalow"></input> to | 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>"; |
<input type="text" name="to" value="Barry"></input> on <input type="text" name="date" value="1:00pm"> at <input type="text" name="time" value="1:00pm"></input> | echo "Walking time: " . floor($itinerary->walkTime / 60000) . " minutes (" . floor($itinerary->walkDistance) . " meters)<br>\n"; |
<input type="submit"></form>'; | echo "Transit time: " . floor($itinerary->transitTime / 60000) . " minutes<br>\n"; |
echo "Waiting time: " . floor($itinerary->waitingTime / 60000) . " minutes<br>\n"; | |
} | |
include_footer(); | if (is_array($itinerary->legs->leg)) { |
$legMarkers = array(); | |
foreach ($itinerary->legs->leg as $legNumber => $leg) { | |
$legMarkers[] = array($leg->from->lat, $leg->from->lon); | |
} | |
echo '' . staticmap($legMarkers) . "<br>\n"; | |
echo '<ul>'; | |
foreach ($itinerary->legs->leg as $legNumber => $leg) { | |
echo '<li>'; | |
processLeg($legNumber, $leg); | |
echo "</li>"; | |
} | |
echo "</ul>"; | |
} else { | |
echo '' . staticmap(array(array($itinerary->legs->leg->from->lat, $itinerary->legs->leg->from->lon))) . "<br>\n"; | |
processLeg(0, $itinerary->legs->leg); | |
} | |
echo "</p></div>"; | |
} | |
function processLeg($legNumber, $leg) { | |
$legArray = object2array($leg); | |
echo '<h3>Leg #' . ($legNumber + 1) . " ( {$legArray['@mode']} from: {$leg->from->name} to {$leg->to->name}, " . floor($leg->duration / 60000) . " minutes) </h3>\n"; | |
if ($legArray["@mode"] === "BUS") { | |
echo "Take bus {$legArray['@route']} " . str_replace("To", "towards", $legArray['@headsign']) . "<br>"; | |
} else { | |
$walkStepMarkers = array(); | |
foreach ($leg->steps->walkSteps as $stepNumber => $step) { | |
$walkStepMarkers[] = array($step->lat, $step->lon); | |
} | |
echo "" . staticmap($walkStepMarkers, "icong") . "<br>\n"; | |
foreach ($leg->steps->walkSteps as $stepNumber => $step) { | |
echo "Walking step " . ($stepNumber + 1) . " $step->absoluteDirection / $step->relativeDirection on $step->streetName for " . floor($step->distance) . " meters<br>\n"; | |
} | |
} | |
} | |
if ($_REQUEST['time']) { | |
$toPlace = (startsWith($_REQUEST['to'], "-") ? $_REQUEST['to'] : geocode(urlencode($_REQUEST['to']), false)); | |
$fromPlace = (startsWith($_REQUEST['from'], "-") ? $_REQUEST['from'] : geocode(urlencode($_REQUEST['from']), false)); | |
if ($toPlace == "" || $fromPlace == "") { | |
$errorMessage = ""; | |
if ($toPlace === "") | |
$errorMessage .= urlencode($_REQUEST['to']) . " not found.<br>\n"; | |
if ($fromPlace === "") | |
$errorMessage .= urlencode($_REQUEST['from']) . " not found.<br>\n"; | |
tripPlanForm($errorMessage); | |
} else { | |
$url = "http://localhost:8080/opentripplanner-api-webapp/ws/plan?_dc=1290254798856&arriveBy=false&date=" . urlencode($_REQUEST['date']) . "&time=" . urlencode($_REQUEST['time']) . "&mode=TRANSIT%2CWALK&optimize=QUICK&maxWalkDistance=840&wheelchair=false&toPlace=$toPlace&fromPlace=$fromPlace&intermediatePlaces="; | |
$ch = curl_init($url); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
curl_setopt($ch, CURLOPT_HEADER, 0); | |
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept: application/json")); | |
$page = curl_exec($ch); | |
curl_close($ch); | |
$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>"; | |
if (is_array($tripplan->plan->itineraries->itinerary)) { | |
echo '<div data-role="collapsible-set">'; | |
foreach ($tripplan->plan->itineraries->itinerary as $itineraryNumber => $itinerary) { | |
processItinerary($itineraryNumber, $itinerary); | |
} | |
echo "</div>"; | |
} else { | |
processItinerary(0, $tripplan->plan->itineraries->itinerary); | |
} | |
} | |
} else { | |
tripPlanForm(); | |
} | |
include_footer(); | |
?> | ?> |
<html xmlns="http://www.w3.org/1999/xhtml"> | <html xmlns="http://www.w3.org/1999/xhtml"> |
<head> | <head> |
<script src="openlayers/OpenLayers.js"></script> | <script src="openlayers/OpenLayers.js"></script> |
<SCRIPT TYPE="text/javascript" SRC="OpenStreetMap.js"></SCRIPT> | <SCRIPT TYPE="text/javascript" SRC="OpenStreetMap.js"></SCRIPT> |
<script type="text/javascript"> | <script type="text/javascript"> |
function init() | function init() |
{ | { |
var extent = new OpenLayers.Bounds(148.98, -35.48, 149.25, -35.15); | var extent = new OpenLayers.Bounds(148.98, -35.48, 149.25, -35.15); |
// set up the map options | // set up the map options |
var options = | var options = |
{ | { |
maxExtent: extent, | maxExtent: extent, |
numZoomLevels: 20, | numZoomLevels: 20, |
}; | }; |
// create the ol map object | // create the ol map object |
var map = new OpenLayers.Map('map', options); | var map = new OpenLayers.Map('map', options); |
var osmtiles = new OpenLayers.Layer.OSM("local", "http://10.0.1.153/tiles/${z}/${x}/${y}.png"); | var osmtiles = new OpenLayers.Layer.OSM("local", "http://localhost/tiles/${z}/${x}/${y}.png"); |
// use http://open.atlas.free.fr/GMapsTransparenciesImgOver.php and http://code.google.com/p/googletilecutter/ to make tiles | // use http://open.atlas.free.fr/GMapsTransparenciesImgOver.php and http://code.google.com/p/googletilecutter/ to make tiles |
var graphic = new OpenLayers.Layer.Image( | var graphic = new OpenLayers.Layer.Image( |
'Weekday Bus Map', | 'Weekday Bus Map', |
'weekday_bus_map.png', | 'weekday_bus_map.png', |
new OpenLayers.Bounds(149.0, -35.47, 149.16, -35.16), | new OpenLayers.Bounds(149.0, -35.47, 149.16, -35.16), |
new OpenLayers.Size(1191, 2268), | new OpenLayers.Size(1191, 2268), |
{baseLayer: false} | {baseLayer: false} |
); | ); |
var nearmap = new OpenLayers.Layer.OSM.NearMap("NearMap"); | var nearmap = new OpenLayers.Layer.OSM.NearMap("NearMap"); |
var routes = new OpenLayers.Layer.GML("Routes", "displayroutes.kml.php", { | var routes = new OpenLayers.Layer.GML("Routes", "displayroutes.kml.php", { |
format: OpenLayers.Format.KML, | format: OpenLayers.Format.KML, |
formatOptions: { | formatOptions: { |
extractStyles: true, | extractStyles: true, |
extractAttributes: true, | extractAttributes: true, |
maxDepth: 2 | maxDepth: 2 |
} | } |
}); | }); |
var stopicon = new OpenLayers.Icon("http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png",new OpenLayers.Size(32,32)); | var stopicon = new OpenLayers.Icon("http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png",new OpenLayers.Size(32,32)); |
var stops = new OpenLayers.Layer.GeoRSS("Stops", "displaystops.georss.php", { icon: stopicon }); | var stops = new OpenLayers.Layer.GeoRSS("Stops", "displaystops.georss.php", { icon: stopicon }); |
var timeicon = new OpenLayers.Icon("http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png",new OpenLayers.Size(32,32)); | var timeicon = new OpenLayers.Icon("http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png",new OpenLayers.Size(32,32)); |
var timepoints = new OpenLayers.Layer.GeoRSS("Timing Points", "displaytimepoints.georss.php", { icon: timeicon }); | var timepoints = new OpenLayers.Layer.GeoRSS("Timing Points", "displaytimepoints.georss.php", { icon: timeicon }); |
map.addLayers([osmtiles,stops,routes,timepoints,nearmap]); | map.addLayers([osmtiles,stops,routes,timepoints,nearmap]); |
var lonLat = new OpenLayers.LonLat(149.11, -35.28).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()); | var lonLat = new OpenLayers.LonLat(149.11, -35.28).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()); |
map.setCenter(lonLat, 13); | map.setCenter(lonLat, 13); |
map.addControl( new OpenLayers.Control.LayerSwitcher({'ascending':false})); | map.addControl( new OpenLayers.Control.LayerSwitcher({'ascending':false})); |
map.addControl(new OpenLayers.Control.MousePosition( | map.addControl(new OpenLayers.Control.MousePosition( |
{ | { |
displayProjection: new OpenLayers.Projection("EPSG:4326"), | displayProjection: new OpenLayers.Projection("EPSG:4326"), |
suffix: "__________________________________" | suffix: "__________________________________" |
})); | })); |
map.addControl(new OpenLayers.Control.MousePosition( | map.addControl(new OpenLayers.Control.MousePosition( |
{ | { |
displayProjection: new OpenLayers.Projection("EPSG:900913") | displayProjection: new OpenLayers.Projection("EPSG:900913") |
})); | })); |
} | } |
</script> | </script> |
</head> | </head> |
<body onload="init()"> | <body onload="init()"> |
<div id="map" width="100%" height="100%" class="smallmap"></div> | <div id="map" width="100%" height="100%" class="smallmap"></div> |
</body> | </body> |
</html> | </html> |
require 'rubygems' | require 'rubygems' |
require 'nokogiri' | require 'nokogiri' |
require 'open-uri' | require 'open-uri' |
require 'pp' | require 'pp' |
require 'yaml' | require 'yaml' |
class Array | class Array |
def to_yaml_style | def to_yaml_style |
:inline | :inline |
end | end |
end | end |
def makeTimetable(table, period, short_name) | def makeTimetable(table, period, short_name) |
timetable = {"between_stops" => [], "short_name" => short_name} | timetable = {"between_stops" => [], "short_name" => short_name} |
time_points = table.xpath('tr[1]//th').map do |tp| | time_points = table.xpath('tr[1]//th').map do |tp| |
if tp.content != "\302\240" && tp.content != "" && tp.content != "<br/>" | if tp.content != "\302\240" && tp.content != "" && tp.content != "<br/>" |
timing_point = tp.content.squeeze(" ").gsub("Bus Station"," Bus Station ").gsub(" Platform"," (Platform").gsub(" - "," - ").gsub("\n"," ").gsub("\r"," ").gsub("\t"," ").gsub("\\"," / ").gsub("/"," / ").gsub(","," ").gsub("\302\240","").squeeze(" ").strip | timing_point = tp.content.squeeze(" ").gsub("Shops"," ").gsub("Bus Station"," Bus Station ").gsub("Interchange"," Bus Station ").gsub(" Platform"," (Platform") |
timing_point = timing_point.gsub("Machonochie","Maconochie").gsub("Hume"," ").gsub("Market Place","Marketplace").gsub("Terminus Fyshwick","Terminus") | |
timing_point = timing_point.gsub(" - "," - ").gsub("\n"," ").gsub("\r"," ").gsub("\t"," ").gsub("\\"," / ").gsub("/"," / ").gsub(","," ").gsub("\302\240","").squeeze(" ").strip | |
if (tp.content.match('Platform')) | if (tp.content.match('Platform')) |
timing_point.concat(")") | timing_point.concat(")") |
end; | end; |
if tp.to_s.match(/[0-9][0-9][0-9]/) or tp.to_s.include? "Wheelchair" | if tp.to_s.match(/[0-9][0-9][0-9]/) or tp.to_s.include? "Wheelchair" |
timing_point = nil | timing_point = nil |
end | end |
timing_point | timing_point |
end | end |
end | end |
time_points.delete(nil) | time_points.delete(nil) |
timetable["time_points"] = time_points.to_a | timetable["time_points"] = time_points.to_a |
timetable["long_name"] = "To " + time_points.last | timetable["long_name"] = "To " + time_points.last |
periodtimes = [] | periodtimes = [] |
table.css('tr').each do |row| | table.css('tr').each do |row| |
times = row.css('td').map do |cell| | times = row.css('td').map do |cell| |
time = cell.content.squeeze(" ").strip | time = cell.content.squeeze(" ").strip |
time = time.gsub(/ *A\S?M/,"a").gsub(/ ?P\S?M/,"p").gsub(/ *a\S?m/,"a").gsub(/ ?p\S?m/,"p") | time = time.gsub(/ *A\S?M/,"a").gsub(/ ?P\S?M/,"p").gsub(/ *a\S?m/,"a").gsub(/ ?p\S?m/,"p") |
time = time.gsub("12:08 AM","1208x").gsub(":","").gsub("1.","1").gsub("2.","2").gsub("3.","3").gsub("4.","4") | time = time.gsub("12:08 AM","1208x").gsub(":","").gsub("1.","1").gsub("2.","2").gsub("3.","3").gsub("4.","4") |
time = time.gsub("5.","5").gsub("6.","6").gsub("7.","7").gsub("8.","8").gsub("9.","9").gsub("10.","10") | time = time.gsub("5.","5").gsub("6.","6").gsub("7.","7").gsub("8.","8").gsub("9.","9").gsub("10.","10") |
time = time.gsub("11.","11").gsub("12.","12").gsub(/\.+/,"-").gsub("\302\240","") | time = time.gsub("11.","11").gsub("12.","12").gsub(/\.+/,"-").gsub("\302\240","") |
if time == "" or time.include? "chool" or time.include? "On Race Days" or time.include? "Bus" | if time == "" or time.include? "chool" or time.include? "On Race Days" or time.include? "Bus" |
time = nil # This hacky way is faster than using position()>1 xpath on <TD>s! | time = nil # This hacky way is faster than using position()>1 xpath on <TD>s! |
end | end |
time | time |
end | end |
times.delete(nil) | times.delete(nil) |
if not times.empty? | if not times.empty? |
if not (route = times.shift) | if not (route = times.shift) |
raise("TODO: account for shifting route numbers eg. intertown/redex 62/162") | raise("TODO: account for shifting route numbers eg. intertown/redex 62/162") |
end | end |
periodtimes << times.to_a | periodtimes << times.to_a |
end | end |
end | end |
if periodtimes.size < 1 | if periodtimes.size < 1 |
raise "No times for route " + short_name + " in period " + period | raise "No times for route " + short_name + " in period " + period |
end | end |
timetable[period] = periodtimes.to_a | timetable[period] = periodtimes.to_a |
# pp timetable | # pp timetable |
filename = timetable["short_name"] + "-" + timetable["long_name"]+ "." + period + ".yml" | filename = timetable["short_name"] + "-" + timetable["long_name"]+ "." + period + ".yml" |
filename = filename.downcase.gsub(" ","-").gsub("/","-").gsub("(","").gsub(")","") | filename = filename.downcase.gsub(" ","-").gsub("/","-").gsub("(","").gsub(")","") |
puts "Saving " + filename | puts "Saving " + filename |
File.open("#{File.dirname(__FILE__)}/output/"+filename, "w") do |f| | File.open("#{File.dirname(__FILE__)}/output/"+filename, "w") do |f| |
f.write timetable.to_yaml | f.write timetable.to_yaml |
end | end |
timetable | timetable |
end | end |
Dir.glob("source-html/*oute*.htm*") { |file| | Dir.glob("source-html/*oute*.htm*") { |file| |
puts "Opened " + file | puts "Opened " + file |
doc = Nokogiri::HTML(open(file)) | doc = Nokogiri::HTML(open(file)) |
# Search for nodes by css | # Search for nodes by css |
timetables = [] | timetables = [] |
short_name = ""; | short_name = ""; |
doc.xpath('//title').each do |title| | doc.xpath('//title').each do |title| |
short_name = title.content.gsub("Route_","").gsub("Route ","").gsub("route ","").gsub(", ","/").gsub("ACTION Buses Timetable for ","").squeeze(" ").strip | short_name = title.content.gsub("Route_","").gsub("Route ","").gsub("route ","").gsub(", ","/").gsub("ACTION Buses Timetable for ","").squeeze(" ").strip |
end | end |
if short_name == "" | if short_name == "" |
raise "Route number(s) not found in <title> tag" | raise "Route number(s) not found in <title> tag" |
end | end |
doc.xpath('//table[preceding::text()="Weekdays"]').each do |table| | doc.xpath('//table[preceding::text()="Weekdays"]').each do |table| |
timetables << makeTimetable(table, "stop_times", short_name) | timetables << makeTimetable(table, "stop_times", short_name) |
end | end |
doc.xpath('//table[preceding::text()="This timetable is effective from Monday 15th November 2010."]').each do |table| | doc.xpath('//table[preceding::text()="This timetable is effective from Monday 15th November 2010."]').each do |table| |
if short_name[0].chr != "9" or short_name.size == 1 | if short_name[0].chr != "9" or short_name.size == 1 |
timetables << makeTimetable(table, "stop_times", short_name) | timetables << makeTimetable(table, "stop_times", short_name) |
end | end |
end | end |
#all tables are weekdays on some really malformatted timetables | #all tables are weekdays on some really malformatted timetables |
if short_name == "170" | if short_name == "170" |
doc.xpath('//table').each do |table| | doc.xpath('//table').each do |table| |
timetables << makeTimetable(table, "stop_times", short_name) | timetables << makeTimetable(table, "stop_times", short_name) |
end | end |
end | end |
#weekends | #weekends |
doc.xpath('//table[preceding::text()="Saturdays" and following::a]').each do |table| | doc.xpath('//table[preceding::text()="Saturdays" and following::a]').each do |table| |
timetables << makeTimetable(table, "stop_times_saturday", short_name) | timetables << makeTimetable(table, "stop_times_saturday", short_name) |
end | end |
doc.xpath('//table[preceding::text()="Sundays"]').each do |table| | doc.xpath('//table[preceding::text()="Sundays"]').each do |table| |
timetables << makeTimetable(table, "stop_times_sunday", short_name) | timetables << makeTimetable(table, "stop_times_sunday", short_name) |
end | end |
#930/934 special cases | #930/934 special cases |
doc.xpath('//table[preceding::text()="Saturday" and following::h2]').each do |table| | doc.xpath('//table[preceding::text()="Saturday" and following::h2]').each do |table| |
timetables << makeTimetable(table, "stop_times_saturday", short_name) | timetables << makeTimetable(table, "stop_times_saturday", short_name) |
end | end |
doc.xpath('//table[preceding::text()="Sunday"]').each do |table| | doc.xpath('//table[preceding::text()="Sunday"]').each do |table| |
timetables << makeTimetable(table, "stop_times_sunday", short_name) | timetables << makeTimetable(table, "stop_times_sunday", short_name) |
end | end |
#route 81 = Weekdays - School Holidays Only | #route 81 = Weekdays - School Holidays Only |
doc.xpath('//table[preceding::text()="Weekdays - School Holidays Only "]').each do |table| | doc.xpath('//table[preceding::text()="Weekdays - School Holidays Only "]').each do |table| |
timetable = makeTimetable(table, "stop_times", short_name) | timetable = makeTimetable(table, "stop_times", short_name) |
#TODO set active date range to only be holidays | #TODO set active date range to only be holidays |
timetables << timetable; | timetables << timetable; |
end | end |
if timetables.size > 2 | if timetables.size > 2 |
puts "WARNING: " + file + " more than 2 timetables (weekend split?):" + timetables.size.to_s | puts "WARNING: " + file + " more than 2 timetables (weekend split?):" + timetables.size.to_s |
end | end |
if timetables.size < 2 | if timetables.size < 2 |
puts "WARNING: " + file + " less than 2 timetables (weekday loop service?):" + timetables.size.to_s | puts "WARNING: " + file + " less than 2 timetables (weekday loop service?):" + timetables.size.to_s |
elsif not (timetables[0]["time_points"] - timetables[1]["time_points"].reverse).empty? | elsif not (timetables[0]["time_points"] - timetables[1]["time_points"].reverse).empty? |
puts "WARNING: first pair of timetable timing points are not complementary for "+ file | puts "WARNING: first pair of timetable timing points are not complementary for "+ file |
pp(timetables[0]["time_points"] - timetables[1]["time_points"].reverse) | pp(timetables[0]["time_points"] - timetables[1]["time_points"].reverse) |
end | end |
if timetables.size < 1 | if timetables.size < 1 |
raise "No timetables extracted from " + file | raise "No timetables extracted from " + file |
end | end |
} | } |
require 'rubygems' | require 'rubygems' |
require 'pp' | require 'pp' |
require 'yaml' | require 'yaml' |
class Array | class Array |
def to_yaml_style | def to_yaml_style |
:inline | :inline |
end | end |
end | end |
Dir.chdir("output") | Dir.chdir("output") |
def getTimePoints() | def getTimePoints() |
$time_points = [] | $time_points = [] |
$time_points_sources = Hash.new([]) | $time_points_sources = Hash.new([]) |
Dir.glob("*.yml") { |file| | Dir.glob("*.yml") { |file| |
timetable = YAML::load_file(file) | timetable = YAML::load_file(file) |
$time_points = $time_points | timetable["time_points"] | $time_points = $time_points | timetable["time_points"] |
timetable["time_points"].each do |timepoint| | timetable["time_points"].each do |timepoint| |
$time_points_sources[timepoint] = $time_points_sources[timepoint] | [ file ] | $time_points_sources[timepoint] = $time_points_sources[timepoint] | [ file ] |
end | end |
} | } |
end | end |
def correctTimePoints() | def correctTimePoints() |
time_point_corrections = {"North Lynehamham" => "North Lyneham", | time_point_corrections = {"North Lynehamham" => "North Lyneham", |
"Woden Bus Station Platform 10)" => "Woden Bus Station (Platform 10)", | "Woden Bus Station Platform 10)" => "Woden Bus Station (Platform 10)", |
"Saint AndrewsVillage Hughes"=>"Saint Andrews Village Hughes", | "Saint AndrewsVillage Hughes"=>"Saint Andrews Village Hughes", |
"Flemmington Road / Sandford St"=>"Flemington Road / Sandford St", | "Flemmington Road / Sandford St"=>"Flemington Road / Sandford St", |
"City Interchange"=>"City Bus Station", | "City Interchange"=>"City Bus Station", |
"City Interchange (Platform 9)"=>"City Bus Station (Platform 9)", | "City Interchange (Platform 9)"=>"City Bus Station (Platform 9)", |
"City Bus Station Platfrom 9"=>"City Bus Station (Platform 9)", | "City Bus Station Platfrom 9"=>"City Bus Station (Platform 9)", |
"Belconnen Community Bus StationPlatform 2)"=>"Belconnen Community Bus Station (Platform 2)", | "Belconnen Community Bus StationPlatform 2)"=>"Belconnen Community Bus Station (Platform 2)", |
"Bridbabella Gardens Nursing Home"=>"Brindabella Gardens Nursing Home", | "Bridbabella Gardens Nursing Home"=>"Brindabella Gardens Nursing Home", |
"Bridbabella GardensNursing Home"=> "Brindabella Gardens Nursing Home", | "Bridbabella GardensNursing Home"=> "Brindabella Gardens Nursing Home", |
"BrindabellaBusiness Park"=> "Brindabella Business Park", | "BrindabellaBusiness Park"=> "Brindabella Business Park", |
"NarrabundahTerminus"=>"Narrabundah Terminus", | "NarrabundahTerminus"=>"Narrabundah Terminus", |
"Railway StationKingston"=>"Railway Station Kingston", | "Railway StationKingston"=>"Railway Station Kingston", |
"Saint AndrewsVillage Hughes"=>"Saint Andrews Village Hughes", | "Saint AndrewsVillage Hughes"=>"Saint Andrews Village Hughes", |
"Dickson ShopsAntill Street"=>"Dickson Shops", | "DicksonAntill Street"=>"Dickson", |
"Cohen St Bus Station (Platform 3)" => "Cohen Street Bus Station (Platform 3)", | "Cohen St Bus Station (Platform 3)" => "Cohen Street Bus Station (Platform 3)", |
"Cohen St Bus Station (Platform 6)" => "Cohen Street Bus Station (Platform 6)", | "Cohen St Bus Station (Platform 6)" => "Cohen Street Bus Station (Platform 6)", |
"Newcastle Streetafter Isa Street" => "Newcastle Street after Isa Street", | "Newcastle Streetafter Isa Street" => "Newcastle Street after Isa Street", |
"Newcastle St after Isa St" => "Newcastle Street after Isa Street", | "Newcastle St after Isa St" => "Newcastle Street after Isa Street", |
"Newcastle Street after Isa St" => "Newcastle Street after Isa Street", | "Newcastle Street after Isa St" => "Newcastle Street after Isa Street", |
"Northbourne Ave / Antill St" => "Northbourne Avenue / Antill St", | "Northbourne Ave / Antill St" => "Northbourne Avenue / Antill St", |
"Macarthur / Northbourne" => "Macarthur / Northbourne Ave", | "Macarthur / Northbourne" => "Macarthur / Northbourne Ave", |
"Macarthur Ave / Northbourne" => "Macarthur / Northbourne Ave", | "Macarthur Ave / Northbourne" => "Macarthur / Northbourne Ave", |
"Kings Ave / National Cct"=> "Kings Ave / National Circuit", | "Kings Ave / National Cct"=> "Kings Ave / National Circuit", |
"Kosciuszco Ave / Everard Street"=>"Kosciuszko / Everard", | "Kosciuszco Ave / Everard Street"=>"Kosciuszko / Everard", |
"Lithgow St Terminus" => "Lithgow St Terminus Fyshwick", | "Lithgow St Terminus" => "Lithgow St Terminus Fyshwick", |
"Hospice Menindee Dr" => "Hospice / Menindee Dr", | "Hospice Menindee Dr" => "Hospice / Menindee Dr", |
"Gungahlin Market Place"=> "Gungahlin Marketplace", | "Gungahlin Market Place"=> "Gungahlin Marketplace", |
"Gwyder Square Kaleen"=> "Gwydir Square Kaleen", | "Gwyder Square Kaleen"=> "Gwydir Square Kaleen", |
"Flemington Road / Nullabor Ave"=>"Flemington Rd / Nullabor Ave", | "Flemington Road / Nullabor Ave"=>"Flemington Rd / Nullabor Ave", |
"Flemington Road / Sandford St"=>"Flemington Rd / Sandford St", | "Flemington Road / Sandford St"=>"Flemington Rd / Sandford St", |
"Heagney Cres Clift Cres Richardson"=> "Heagney / Clift Richardson", | "Heagney Cres Clift Cres Richardson"=> "Heagney / Clift Richardson", |
"Charnwood Shops (Tillyard Drive)"=> "Charnwood Shops", | "Charnwood (Tillyard Drive)"=> "Charnwood", |
"charnwood Shops"=> "Charnwood Shops", | "charnwood"=> "Charnwood", |
"Black Moutain- Telstra Tower"=>"Black Mountain Telstra Tower", | "Black Moutain- Telstra Tower"=>"Black Mountain Telstra Tower", |
"Bonython Primary"=> "Bonython Primary School", | "Bonython Primary"=> "Bonython Primary School", |
"Athllon Drive / Sulwood Dr Kambah"=>"Athllon / Sulwood Kambah", | "Athllon Drive / Sulwood Dr Kambah"=>"Athllon / Sulwood Kambah", |
"Alexander Machonochie Centre Hume"=>"Alexander Maconochie Centre", | "Alexander Machonochie Centre Hume"=>"Alexander Maconochie Centre", |
"Alexander Maconochie Centre Hume"=>"Alexander Maconochie Centre", | "Alexander Maconochie Centre Hume"=>"Alexander Maconochie Centre", |
"Anthony Rolfe Ave / Moonight Ave" =>"Anthony Rolfe Av / Moonlight Av", | "Anthony Rolfe Ave / Moonight Ave" =>"Anthony Rolfe Av / Moonlight Av", |
"Australian National Botanic Gardens"=>"Botanic Gardens", | "Australian National Botanic Gardens"=>"Botanic Gardens", |
"Calwell shops"=> "Calwell Shops", | "Calwell shops"=> "Calwell", |
"Chuculba / William Slim Drive"=>"Chuculba / William Slim Dr", | "Chuculba / William Slim Drive"=>"Chuculba / William Slim Dr", |
"Fyshwick direct Factory Outlet"=>"Fyshwick Direct Factory Outlet", | "Fyshwick direct Factory Outlet"=>"Fyshwick Direct Factory Outlet", |
"Kaleen Village / Maibrynong"=>"Kaleen Village / Marybrynong", | "Kaleen Village / Maibrynong"=>"Kaleen Village / Marybrynong", |
"Kaleen Village / Marybrynong Ave"=>"Kaleen Village / Marybrynong", | "Kaleen Village / Marybrynong Ave"=>"Kaleen Village / Marybrynong", |
"National Aquarium"=>"National Zoo and Aquarium", | "National Aquarium"=>"National Zoo and Aquarium", |
"chisholm Shops"=>"Chisholm Shops", | "chisholm"=>"Chisholm", |
"O'connor Shops"=>"O'Connor Shops", | "O'connor"=>"O'Connor", |
"Mckellar Shops"=>"McKellar Shops", | "Mckellar"=>"McKellar", |
"Melba shops"=> "Melba Shops", | |
"William Web / Ginninderra Drive"=>"William Webb / Ginninderra Drive", | "William Web / Ginninderra Drive"=>"William Webb / Ginninderra Drive", |
"Procor / Mead"=>"Proctor / Mead", | "Procor / Mead"=>"Proctor / Mead", |
"Fyshwick DirectFactory Outlet"=>"Fyshwick Direct Factory Outlet", | "Fyshwick DirectFactory Outlet"=>"Fyshwick Direct Factory Outlet", |
"Yarrulumla Shops"=>"Yarralumla Shops", | "Yarrulumla"=>"Yarralumla", |
"Tharwa Dr / Pocket Ave"=>"Tharwa Dr / Pockett Ave", | "Tharwa Dr / Pocket Ave"=>"Tharwa Dr / Pockett Ave", |
"Paul Coe / Mirrebei Dr"=>"Paul Coe / Mirrabei Dr", | "Paul Coe / Mirrebei Dr"=>"Paul Coe / Mirrabei Dr", |
"Mirrebei Drive / Dam Wall"=>"Mirrabei Drive / Dam Wall", | "Mirrebei Drive / Dam Wall"=>"Mirrabei Drive / Dam Wall", |
"Tharwa / Knoke" => "Tharwa Drive / Knoke Ave", | "Tharwa / Knoke" => "Tharwa Drive / Knoke Ave", |
"Tharwa / Pocket" => "Tharwa Dr / Pockett Ave", | "Tharwa / Pocket" => "Tharwa Drive / Pockett Ave", |
'Tharwa Dr / Pockett Ave' => "Tharwa Drive / Pockett Ave", | |
"Outrim / Duggan" => "Outtrim / Duggan", | "Outrim / Duggan" => "Outtrim / Duggan", |
"ANU Burton and Garran Hall Daley Rd" => "Burton and Garran Hall Daley Road", | "ANU Burton and Garran Hall Daley Rd" => "Burton and Garran Hall Daley Road", |
"Farrer Primary"=>"Farrer Primary School", | "Farrer Primary"=>"Farrer Primary School", |
"St Thomas More Campbell"=>"St Thomas More's Campbell", | "St Thomas More Campbell"=>"St Thomas More's Campbell", |
"Lyneham Shops"=>"Lyneham Shops Wattle Street", | "Lyneham Wattle Street"=>"Lyneham / Wattle St", |
"Dickson" => "Dickson / Antill St", | |
'Dickson Antill Street' => 'Dickson / Antill St', | |
"Livingston / Kambah" => "Kambah / Livingston St", | |
'Melba shops' => 'Melba', | |
'St Clare of Assisi' => 'St Clare of Assisi Primary', | |
'War Memorial Limestone Ave' => 'War Memorial / Limestone Ave' | |
} | } |
time_point_corrections.each do |wrong, right| | time_point_corrections.each do |wrong, right| |
$time_points_sources[wrong].each do |wrongfile| | $time_points_sources[wrong].each do |wrongfile| |
badtimetable = YAML::load_file(wrongfile) | badtimetable = YAML::load_file(wrongfile) |
badentrynumber = badtimetable["time_points"].index wrong | badentrynumber = badtimetable["time_points"].index wrong |
badtimetable["time_points"][badentrynumber] = right | badtimetable["time_points"][badentrynumber] = right |
puts "Corrected '" + wrong + "' to '" + right + "' in " + wrongfile | puts "Corrected '" + wrong + "' to '" + right + "' in " + wrongfile |
File.open(wrongfile, "w") do |f| | File.open(wrongfile, "w") do |f| |
f.write badtimetable.to_yaml | f.write badtimetable.to_yaml |
end | end |
end | end |
end | end |
end | end |
getTimePoints() | getTimePoints() |
#pp $time_points.sort! | #pp $time_points.sort! |
#pp $time_points_sources.sort | #pp $time_points_sources.sort |
correctTimePoints() | correctTimePoints() |
getTimePoints() | getTimePoints() |
correctTimePoints() | correctTimePoints() |
getTimePoints() | getTimePoints() |
pp $time_points.sort! | pp $time_points.sort! |
#!/usr/bin/ruby | #!/usr/bin/ruby |
require 'highline.rb' | require 'highline.rb' |
include HighLine | include HighLine |
require 'rubygems' | require 'rubygems' |
require 'postgres' | require 'postgres' |
require 'json' | require 'json' |
require 'net/http' | require 'net/http' |
def cbr_geocode(query) | def cbr_geocode(query) |
base_url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?query=" | base_url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?query=" |
url = "#{base_url}#{URI.encode(query)}&bbox=-35.47,148.83,-35.16,149.25&return_location=true" | url = "#{base_url}#{URI.encode(query)}&bbox=-35.47,148.83,-35.16,149.25&return_location=true" |
resp = Net::HTTP.get_response(URI.parse(url)) | resp = Net::HTTP.get_response(URI.parse(url)) |
data = resp.body | data = resp.body |
pp url | pp url |
# we convert the returned JSON data to native Ruby | # we convert the returned JSON data to native Ruby |
# data structure - a hash | # data structure - a hash |
result = JSON.parse(data) | result = JSON.parse(data) |
# if the hash has 'Error' as a key, we raise an error | # if the hash has 'Error' as a key, we raise an error |
if result.has_key? 'Error' | if result.has_key? 'Error' |
raise "web service error" | raise "web service error" |
end | end |
return result | return result |
end | end |
class Array | class Array |
def find_dups | def find_dups |
inject(Hash.new(0)) { |h,e| h[e] += 1; h }.select { |k,v| v > 1 }.collect { |x| x.first } | inject(Hash.new(0)) { |h,e| h[e] += 1; h }.select { |k,v| v > 1 }.collect { |x| x.first } |
end | end |
end | end |
require 'yaml' | require 'yaml' |
require 'pp' | require 'pp' |
Dir.chdir("output") | Dir.chdir("output") |
def getTimePoints() | def getTimePoints() |
$time_points = [] | $time_points = [] |
$time_points_sources = Hash.new([]) | $time_points_sources = Hash.new([]) |
Dir.glob("*.yml") { |file| | Dir.glob("*.yml") { |file| |
pp file | |
timetable = YAML::load_file(file) | timetable = YAML::load_file(file) |
$time_points = $time_points | timetable["time_points"] | $time_points = $time_points | timetable["time_points"] |
timetable["time_points"].each do |timepoint| | timetable["time_points"].each do |timepoint| |
$time_points_sources[timepoint] = $time_points_sources[timepoint] | [ file ] | $time_points_sources[timepoint] = $time_points_sources[timepoint] | [ file ] |
end | end |
} | } |
end | end |
getTimePoints() | getTimePoints() |
$time_points.sort! | $time_points.sort! |
connbus = PGconn.connect("localhost", 5432, '', '', "bus", "postgres", | connbus = PGconn.connect("localhost", 5432, '', '', "bus", "postgres", |
"snmc") | "snmc") |
if ask_if("Insert Timing Point names to database?") | if ask_if("Insert Timing Point names to database?") |
$time_points.each do |time_point| | $time_points.each do |time_point| |
begin | begin |
time_point = time_point.gsub(/\\/, '\&\&').gsub(/'/, "''") # DON'T PUT MORE GSUB HERE | time_point = time_point.gsub(/\\/, '\&\&').gsub(/'/, "''") # DON'T PUT MORE GSUB HERE |
res = connbus.exec("INSERT INTO timing_point (name) VALUES ('#{time_point}')") | res = connbus.exec("INSERT INTO timing_point (name) VALUES ('#{time_point}')") |
puts "Put '#{time_point}' into DB" | puts "Put '#{time_point}' into DB" |
rescue PGError => e | rescue PGError => e |
puts "Error inserting '#{time_point}' to DB #{e}" | puts "Error inserting '#{time_point}' to DB #{e}" |
#conn.close() if conn | #conn.close() if conn |
end | end |
end | end |
end | end |
if ask_if("Fill null Timing Points from geocoder?") | if ask_if("Fill null Timing Points from geocoder?") |
begin | begin |
null_points = connbus.exec('SELECT name FROM timing_point WHERE lat IS null OR lng IS null;') | null_points = connbus.exec('SELECT name FROM timing_point WHERE lat IS null OR lng IS null;') |
rescue PGError => e | rescue PGError => e |
puts "Error selecting null points from DB #{e}" | puts "Error selecting null points from DB #{e}" |
#conn.close() if conn | #conn.close() if conn |
end | end |
null_points.each do |null_point_name| | null_points.each do |null_point_name| |
pp null_point_name | pp null_point_name |
name = null_point_name.to_s.gsub(/\\/, '\&\&').gsub(/'/, "''") | name = null_point_name.to_s.gsub(/\\/, '\&\&').gsub(/'/, "''") |
results = cbr_geocode(null_point_name.to_s.gsub("Shops", "")) | results = cbr_geocode(null_point_name.to_s.gsub("Shops", "")) |
if !results.empty? | if !results.empty? |
results['features'].each_with_index { |feature,index| | results['features'].each_with_index { |feature,index| |
print "#{index}: #{feature['properties']['name']} (#{feature['location']}) => #{feature['centroid']['coordinates']}\n" | print "#{index}: #{feature['properties']['name']} (#{feature['location']}) => #{feature['centroid']['coordinates']}\n" |
} | } |
nodeID = ask("Enter selected node ID:", :integer) | nodeID = ask("Enter selected node ID:", :integer) |
if results['features'].at(nodeID) != nil | if results['features'].at(nodeID) != nil |
node = results['features'][nodeID] | node = results['features'][nodeID] |
puts "Location #{node['centroid']['coordinates'][0]},#{node['centroid']['coordinates'][1]} for #{null_point_name}" | puts "Location #{node['centroid']['coordinates'][0]},#{node['centroid']['coordinates'][1]} for #{null_point_name}" |
begin | begin |
res = connbus.exec("UPDATE timing_point SET lat = #{node['centroid']['coordinates'][0]*10000000}, lng = | res = connbus.exec("UPDATE timing_point SET lat = #{node['centroid']['coordinates'][0]*10000000}, lng = |
#{node['centroid']['coordinates'][1]*10000000},guess = true WHERE name = '#{name}'") | #{node['centroid']['coordinates'][1]*10000000},guess = true WHERE name = '#{name}'") |
puts "Put '#{null_point_name}' into DB" | puts "Put '#{null_point_name}' into DB" |
rescue PGError => e | rescue PGError => e |
puts "Error inserting '#{null_point_name}' to DB #{e}" | puts "Error inserting '#{null_point_name}' to DB #{e}" |
ask_if("Continue?") | ask_if("Continue?") |
#conn.close() if conn | #conn.close() if conn |
end | end |
else | else |
puts "Uhh, there was no suggestion ID like that. Try again next time!" | puts "Uhh, there was no suggestion ID like that. Try again next time!" |
end | end |
else | else |
puts "Uhh, there were no geocoding results. Try again next time!" | puts "Uhh, there were no geocoding results. Try again next time!" |
end | end |
end | end |
end | end |
<?php | <?php |
function getPage($url) | function getPage($url) |
{ | { |
$ch = curl_init($url); | $ch = curl_init($url); |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); | curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); |
curl_setopt( $ch, CURLOPT_HEADER, 0 ); | curl_setopt( $ch, CURLOPT_HEADER, 0 ); |
$page = curl_exec($ch); | $page = curl_exec($ch); |
curl_close($ch); | curl_close($ch); |
return $page; | return $page; |
} | } |
// | // |
// http://developers.cloudmade.com/wiki/geocoding-http-api/Documentation | // http://developers.cloudmade.com/wiki/geocoding-http-api/Documentation |
$conn = pg_connect("dbname=bus user=postgres password=snmc"); | $conn = pg_connect("dbname=bus user=postgres password=snmc"); |
if (!$conn) { | if (!$conn) { |
echo "An error occured.\n"; | echo "An error occured.\n"; |
exit; | exit; |
} | } |
$sql = "Select * from stops where name is null"; | $sql = "Select * from stops where name is null or suburb is null"; |
$result_stops = pg_query($conn, $sql); | $result_stops = pg_query($conn, $sql); |
if (!$result_stops) { | if (!$result_stops) { |
cho("Error in SQL query: " . pg_last_error() ."<br>\n"); | echo("Error in SQL query: " . pg_last_error() ."<br>\n"); |
} | } |
while ($stop = pg_fetch_assoc($result_stops)) { | while ($stop = pg_fetch_assoc($result_stops)) { |
echo "Processing ".$stop['geohash'] . " ... "; | if ($stop['name'] == "") { |
echo "Processing ".$stop['geohash'] . " streetname ... "; | |
$url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?around=".($stop['lat']/10000000).",".($stop['lng']/10000000)."&distance=closest&object_type=road"; | $url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?around=".($stop['lat']/10000000).",".($stop['lng']/10000000)."&distance=closest&object_type=road"; |
$contents = json_decode(getPage($url)); | $contents = json_decode(getPage($url)); |
print_r($contents); | |
$name = $contents->features[0]->properties->name; | $name = $contents->features[0]->properties->name; |
//todo suburb/locality select * from suburbs where the_geom @> 'POINT(149.075704592122 -35.21751569325)'::geometry | |
echo "Saving $name ! <br>" ; | echo "Saving $name ! <br>" ; |
$result_save = pg_query($conn, "UPDATE stops set name = '".pg_escape_string($name)."' where geohash = '{$stop['geohash']}' "); | $result_save = pg_query($conn, "UPDATE stops set name = '".pg_escape_string($name)."' where geohash = '{$stop['geohash']}' "); |
if (!$result_save) { | if (!$result_save) { |
echo("Error in SQL query: " . pg_last_error() ."<br>\n"); | echo("Error in SQL query: " . pg_last_error() ."<br>\n"); |
} | |
} | |
if ($stop['suburb'] == "") { | |
echo "Processing ".$stop['geohash'] . " suburb ... "; | |
$sql = "select * from suburbs where the_geom @> 'POINT(".($stop['lng']/10000000)." ".($stop['lat']/10000000).")'::geometry"; | |
$result_suburbs = pg_query($conn, $sql); | |
if (!$result_suburbs) { | |
echo("Error in SQL query: " . pg_last_error() ."<br>\n"); | |
} | |
$suburbs = ""; | |
while ($suburb = pg_fetch_assoc($result_suburbs)) { | |
$suburbs .= $suburb['name_2006'].";"; | |
} | |
echo "Saving $suburbs ! <br>" ; | |
$result_save = pg_query($conn, "UPDATE stops set suburb = '".pg_escape_string($suburbs)."' where geohash = '{$stop['geohash']}' "); | |
if (!$result_save) { | |
echo("Error in SQL query: " . pg_last_error() ."<br>\n"); | |
} | |
} | } |
flush(); | flush(); |
} | } |
?> | ?> |
options: | options: |
start_date: 20101115 | start_date: 20101115 |
end_date: 20111231 | end_date: 20111231 |
remove_date: 20111231 | remove_date: 20111231 |
agency_name: ACT Internal Omnibus Network (ACTION) | agency_name: ACT Internal Omnibus Network (ACTION) |
agency_url: http://www.action.act.gov.au/ | agency_url: http://www.action.act.gov.au/ |
agency_timezone: Australia/Sydney | agency_timezone: Australia/Sydney |
stops: | stops: |
- { name: ACTEW AGL House,stop_code: ACTEW AGL House, lat: -35.282374, lng: 149.132047} | - { name: ACTEW AGL House,stop_code: ACTEW AGL House, lat: -35.282374, lng: 149.132047} |
- { name: ADFA,stop_code: ADFA, lat: -35.2937972, lng: 149.1643403} | - { name: ADFA,stop_code: ADFA, lat: -35.2937972, lng: 149.1643403} |
- { name: Ainslie,stop_code: Ainslie, lat: -35.2620105, lng: 149.1443302} | - { name: Ainslie,stop_code: Ainslie, lat: -35.2620105, lng: 149.1443302} |
- { name: Ainslie Shops,stop_code: Ainslie Shops, lat: -35.26198, lng: 149.14535} | |
- { name: Alexander Maconochie Centre,stop_code: Alexander Maconochie Centre, lat: -35.3720651, lng: 149.1696618} | - { name: Alexander Maconochie Centre,stop_code: Alexander Maconochie Centre, lat: -35.3720651, lng: 149.1696618} |
- { name: Alpen & Clifford St,stop_code: Alpen & Clifford St, lat: -35.20562, lng: 149.06259} | - { name: Alpen & Clifford St,stop_code: Alpen & Clifford St, lat: -35.20562, lng: 149.06259} |
- { name: Anthony Rolfe Av / Moonlight Av,stop_code: Anthony Rolfe Av / Moonlight Av, lat: -35.1856021, lng: 149.1543639} | - { name: Anthony Rolfe Av / Moonlight Av,stop_code: Anthony Rolfe Av / Moonlight Av, lat: -35.1856021, lng: 149.1543639} |
- { name: Aranda,stop_code: Aranda, lat: -35.257534, lng: 149.0762963} | - { name: Aranda,stop_code: Aranda, lat: -35.257534, lng: 149.0762963} |
- { name: Aranda Shops,stop_code: Aranda Shops, lat: -35.25753, lng: 149.0763} | |
- { name: Athllon / Sulwood Kambah,stop_code: Athllon / Sulwood Kambah, lat: -35.38442, lng: 149.09328} | - { name: Athllon / Sulwood Kambah,stop_code: Athllon / Sulwood Kambah, lat: -35.38442, lng: 149.09328} |
- { name: Australian Institute of Sport,stop_code: Australian Institute of Sport, lat: -35.246351, lng: 149.101478} | - { name: Australian Institute of Sport,stop_code: Australian Institute of Sport, lat: -35.246351, lng: 149.101478} |
- { name: Belconnen Community Bus Station,stop_code: Belconnen Community Bus Station, lat: -35.23987, lng: 149.0619} | - { name: Belconnen Community Bus Station,stop_code: Belconnen Community Bus Station, lat: -35.23987, lng: 149.0619} |
- { name: Belconnen Community Bus Station (Platform 1),stop_code: Belconnen Community Bus Station (Platform 1), lat: -35.23982, lng: 149.06978} | - { name: Belconnen Community Bus Station (Platform 1),stop_code: Belconnen Community Bus Station (Platform 1), lat: -35.23982, lng: 149.06978} |
- { name: Belconnen Community Bus Station (Platform 2),stop_code: Belconnen Community Bus Station (Platform 2), lat: -35.23982, lng: 149.06926} | - { name: Belconnen Community Bus Station (Platform 2),stop_code: Belconnen Community Bus Station (Platform 2), lat: -35.23982, lng: 149.06926} |
- { name: Belconnen Community Bus Station (Platform 3),stop_code: Belconnen Community Bus Station (Platform 3), lat: -35.23986, lng: 149.06847} | - { name: Belconnen Community Bus Station (Platform 3),stop_code: Belconnen Community Bus Station (Platform 3), lat: -35.23986, lng: 149.06847} |
- { name: Belconnen Community Bus Station (Platform 4),stop_code: Belconnen Community Bus Station (Platform 4), lat: -35.23994, lng: 149.06887} | - { name: Belconnen Community Bus Station (Platform 4),stop_code: Belconnen Community Bus Station (Platform 4), lat: -35.23994, lng: 149.06887} |
- { name: Belconnen Community Bus Station (Platform 5),stop_code: Belconnen Community Bus Station (Platform 5), lat: -35.23994, lng: 149.06928} | - { name: Belconnen Community Bus Station (Platform 5),stop_code: Belconnen Community Bus Station (Platform 5), lat: -35.23994, lng: 149.06928} |
- { name: Belconnen Community Bus Station (Platform 6),stop_code: Belconnen Community Bus Station (Platform 6), lat: -35.23994, lng: 149.0698} | - { name: Belconnen Community Bus Station (Platform 6),stop_code: Belconnen Community Bus Station (Platform 6), lat: -35.23994, lng: 149.0698} |
- { name: Belconnen Way,stop_code: Belconnen Way, lat: -35.24809, lng: 149.06765} | - { name: Belconnen Way,stop_code: Belconnen Way, lat: -35.24809, lng: 149.06765} |
- { name: Bimberi Centre,stop_code: Bimberi Centre, lat: -35.2219941, lng: 149.1546928} | - { name: Bimberi Centre,stop_code: Bimberi Centre, lat: -35.2219941, lng: 149.1546928} |
- { name: Black Mountain Telstra Tower,stop_code: Black Mountain Telstra Tower, lat: -35.2748058, lng: 149.0972461} | - { name: Black Mountain Telstra Tower,stop_code: Black Mountain Telstra Tower, lat: -35.2748058, lng: 149.0972461} |
- { name: Bonython,stop_code: Bonython, lat: -35.4297416, lng: 149.0814517} | - { name: Bonython,stop_code: Bonython, lat: -35.4297416, lng: 149.0814517} |
- { name: Bonython Primary School,stop_code: Bonython Primary School, lat: -35.431019, lng: 149.0831217} | - { name: Bonython Primary School,stop_code: Bonython Primary School, lat: -35.431019, lng: 149.0831217} |
- { name: Botanic Gardens,stop_code: Botanic Gardens, lat: -35.278643, lng: 149.1093237} | - { name: Botanic Gardens,stop_code: Botanic Gardens, lat: -35.278643, lng: 149.1093237} |
- { name: Brindabella Business Park,stop_code: Brindabella Business Park, lat: -35.314496, lng: 149.189145} | - { name: Brindabella Business Park,stop_code: Brindabella Business Park, lat: -35.314496, lng: 149.189145} |
- { name: Brindabella Gardens Nursing Home,stop_code: Brindabella Gardens Nursing Home, lat: -35.3294459, lng: 149.0806116} | - { name: Brindabella Gardens Nursing Home,stop_code: Brindabella Gardens Nursing Home, lat: -35.3294459, lng: 149.0806116} |
- { name: Bugden Sternberg,stop_code: Bugden Sternberg, lat: -35.4017223, lng: 149.0992172} | - { name: Bugden Sternberg,stop_code: Bugden Sternberg, lat: -35.4017223, lng: 149.0992172} |
- { name: Burton and Garran Hall Daley Road,stop_code: Burton and Garran Hall Daley Road, lat: -35.2753671, lng: 149.1172822} | - { name: Burton and Garran Hall Daley Road,stop_code: Burton and Garran Hall Daley Road, lat: -35.2753671, lng: 149.1172822} |
- { name: Calvary Hospital,stop_code: Calvary Hospital, lat: -35.25212, lng: 149.09088} | - { name: Calvary Hospital,stop_code: Calvary Hospital, lat: -35.25212, lng: 149.09088} |
- { name: Calwell Shops,stop_code: Calwell Shops, lat: -35.43524, lng: 149.113942} | - { name: Calwell,stop_code: Calwell, lat: -35.43524, lng: 149.113942} |
- { name: Cameron Ave Bus Station,stop_code: Cameron Ave Bus Station, lat: -35.2410195, lng: 149.0722506} | - { name: Cameron Ave Bus Station,stop_code: Cameron Ave Bus Station, lat: -35.2410195, lng: 149.0722506} |
- { name: Cameron Ave Bus Station (Platform 1),stop_code: Cameron Ave Bus Station (Platform 1), lat: -35.2410195, lng: 149.0722506} | - { name: Cameron Ave Bus Station (Platform 1),stop_code: Cameron Ave Bus Station (Platform 1), lat: -35.2410195, lng: 149.0722506} |
- { name: Cameron Ave Bus Station (Platform 2),stop_code: Cameron Ave Bus Station (Platform 2), lat: -35.2410108, lng: 149.0717142} | - { name: Cameron Ave Bus Station (Platform 2),stop_code: Cameron Ave Bus Station (Platform 2), lat: -35.2410108, lng: 149.0717142} |
- { name: Cameron Ave Bus Station (Platform 3),stop_code: Cameron Ave Bus Station (Platform 3), lat: -35.2410064, lng: 149.0710758} | - { name: Cameron Ave Bus Station (Platform 3),stop_code: Cameron Ave Bus Station (Platform 3), lat: -35.2410064, lng: 149.0710758} |
- { name: Cameron Ave Bus Station (Platform 4),stop_code: Cameron Ave Bus Station (Platform 4), lat: -35.2411773, lng: 149.0709793} | - { name: Cameron Ave Bus Station (Platform 4),stop_code: Cameron Ave Bus Station (Platform 4), lat: -35.2411773, lng: 149.0709793} |
- { name: Cameron Ave Bus Station (Platform 5),stop_code: Cameron Ave Bus Station (Platform 5), lat: -35.241186, lng: 149.0720789} | - { name: Cameron Ave Bus Station (Platform 5),stop_code: Cameron Ave Bus Station (Platform 5), lat: -35.241186, lng: 149.0720789} |
- { name: Campbell Park Offices,stop_code: Campbell Park Offices, lat: -35.28368, lng: 149.17045} | - { name: Campbell Park Offices,stop_code: Campbell Park Offices, lat: -35.28368, lng: 149.17045} |
- { name: Canberra College Weston Campus,stop_code: Canberra College Weston Campus, lat: -35.3490278, lng: 149.0486277} | - { name: Canberra College Weston Campus,stop_code: Canberra College Weston Campus, lat: -35.3490278, lng: 149.0486277} |
- { name: Canberra Hospital,stop_code: Canberra Hospital, lat: -35.3459462, lng: 149.1012001} | - { name: Canberra Hospital,stop_code: Canberra Hospital, lat: -35.3459462, lng: 149.1012001} |
- { name: Canberra Times,stop_code: Canberra Times, lat: -35.3245431, lng: 149.1705533} | - { name: Canberra Times,stop_code: Canberra Times, lat: -35.3245431, lng: 149.1705533} |
- { name: Caswell Drive,stop_code: Caswell Drive, lat: -35.25922, lng: 149.08576} | - { name: Caswell Drive,stop_code: Caswell Drive, lat: -35.25922, lng: 149.08576} |
- { name: Causeway,stop_code: Causeway, lat: -35.31615, lng: 149.15058} | - { name: Causeway,stop_code: Causeway, lat: -35.31615, lng: 149.15058} |
- { name: Centrelink Tuggeranong,stop_code: Centrelink Tuggeranong, lat: -35.4207496, lng: 149.0700973} | - { name: Centrelink Tuggeranong,stop_code: Centrelink Tuggeranong, lat: -35.4207496, lng: 149.0700973} |
- { name: Chapman,stop_code: Chapman, lat: -35.3557877, lng: 149.0408111} | - { name: Chapman,stop_code: Chapman, lat: -35.3557877, lng: 149.0408111} |
- { name: Chapman Shops,stop_code: Chapman Shops, lat: -35.35579, lng: 149.04082} | |
- { name: Charnwood,stop_code: Charnwood, lat: -35.2052138, lng: 149.0337266} | - { name: Charnwood,stop_code: Charnwood, lat: -35.2052138, lng: 149.0337266} |
- { name: Charnwood Shops,stop_code: Charnwood Shops, lat: -35.20472, lng: 149.03336} | |
- { name: Charnwood Tillyard Dr,stop_code: Charnwood Tillyard Dr, lat: -35.20295, lng: 149.04027} | - { name: Charnwood Tillyard Dr,stop_code: Charnwood Tillyard Dr, lat: -35.20295, lng: 149.04027} |
- { name: Chifley,stop_code: Chifley, lat: -35.350985, lng: 149.077319} | - { name: Chifley,stop_code: Chifley, lat: -35.350985, lng: 149.077319} |
- { name: Chifley Shops,stop_code: Chifley Shops, lat: -35.35099, lng: 149.07732} | - { name: Chisholm,stop_code: Chisholm, lat: -35.41341, lng: 149.12833} |
- { name: Chisholm Shops,stop_code: Chisholm Shops, lat: -35.41341, lng: 149.12833} | |
- { name: Chuculba / William Slim Dr,stop_code: Chuculba / William Slim Dr, lat: -35.208931, lng: 149.088499} | - { name: Chuculba / William Slim Dr,stop_code: Chuculba / William Slim Dr, lat: -35.208931, lng: 149.088499} |
- { name: CIT Weston,stop_code: CIT Weston, lat: -35.330234, lng: 149.058632} | - { name: CIT Weston,stop_code: CIT Weston, lat: -35.330234, lng: 149.058632} |
- { name: City Bus Station,stop_code: City Bus Station, lat: -35.2794346, lng: 149.1305879} | - { name: City Bus Station,stop_code: City Bus Station, lat: -35.2794346, lng: 149.1305879} |
- { name: City Bus Station (Platform 1),stop_code: City Bus Station (Platform 1), lat: -35.2794346, lng: 149.1305879} | - { name: City Bus Station (Platform 1),stop_code: City Bus Station (Platform 1), lat: -35.2794346, lng: 149.1305879} |
- { name: City Bus Station (Platform 10),stop_code: City Bus Station (Platform 10), lat: -35.2793571, lng: 149.1293659} | - { name: City Bus Station (Platform 10),stop_code: City Bus Station (Platform 10), lat: -35.2793571, lng: 149.1293659} |
- { name: City Bus Station (Platform 11),stop_code: City Bus Station (Platform 11), lat: -35.2787905, lng: 149.1288627} | - { name: City Bus Station (Platform 11),stop_code: City Bus Station (Platform 11), lat: -35.2787905, lng: 149.1288627} |
- { name: City Bus Station (Platform 2),stop_code: City Bus Station (Platform 2), lat: -35.278907, lng: 149.130612} | - { name: City Bus Station (Platform 2),stop_code: City Bus Station (Platform 2), lat: -35.278907, lng: 149.130612} |
- { name: City Bus Station (Platform 3),stop_code: City Bus Station (Platform 3), lat: -35.2787886, lng: 149.1304779} | - { name: City Bus Station (Platform 3),stop_code: City Bus Station (Platform 3), lat: -35.2787886, lng: 149.1304779} |
- { name: City Bus Station (Platform 4),stop_code: City Bus Station (Platform 4), lat: -35.2785658, lng: 149.1301727} | - { name: City Bus Station (Platform 4),stop_code: City Bus Station (Platform 4), lat: -35.2785658, lng: 149.1301727} |
- { name: City Bus Station (Platform 5),stop_code: City Bus Station (Platform 5), lat: -35.2785242, lng: 149.1297348} | - { name: City Bus Station (Platform 5),stop_code: City Bus Station (Platform 5), lat: -35.2785242, lng: 149.1297348} |
- { name: City Bus Station (Platform 7),stop_code: City Bus Station (Platform 7), lat: -35.27843, lng: 149.130345} | - { name: City Bus Station (Platform 7),stop_code: City Bus Station (Platform 7), lat: -35.27843, lng: 149.130345} |
- { name: City Bus Station (Platform 8),stop_code: City Bus Station (Platform 8), lat: -35.2778798, lng: 149.1305995} | - { name: City Bus Station (Platform 8),stop_code: City Bus Station (Platform 8), lat: -35.2778798, lng: 149.1305995} |
- { name: City Bus Station (Platform 9),stop_code: City Bus Station (Platform 9), lat: -35.2783224, lng: 149.130726} | - { name: City Bus Station (Platform 9),stop_code: City Bus Station (Platform 9), lat: -35.2783224, lng: 149.130726} |
- { name: City West,stop_code: City West, lat: -35.2788605, lng: 149.1257969} | - { name: City West,stop_code: City West, lat: -35.2788605, lng: 149.1257969} |
- { name: Cnr Kerrigan/Lhotsky,stop_code: Cnr Kerrigan/Lhotsky, lat: -35.1995716, lng: 149.0285277} | - { name: Cnr Kerrigan/Lhotsky,stop_code: Cnr Kerrigan/Lhotsky, lat: -35.1995716, lng: 149.0285277} |
- { name: Cnr Tillyard Dr & Spalding St,stop_code: Cnr Tillyard Dr & Spalding St, lat: -35.2040477, lng: 149.0393052} | - { name: Cnr Tillyard Dr & Spalding St,stop_code: Cnr Tillyard Dr & Spalding St, lat: -35.2040477, lng: 149.0393052} |
- { name: Cohen Street Bus Station,stop_code: Cohen Street Bus Station, lat: -35.2394775, lng: 149.0602031} | - { name: Cohen Street Bus Station,stop_code: Cohen Street Bus Station, lat: -35.2394775, lng: 149.0602031} |
- { name: Cohen Street Bus Station (Platform 1),stop_code: Cohen Street Bus Station (Platform 1), lat: -35.2394775, lng: 149.0602031} | - { name: Cohen Street Bus Station (Platform 1),stop_code: Cohen Street Bus Station (Platform 1), lat: -35.2394775, lng: 149.0602031} |
- { name: Cohen Street Bus Station (Platform 2),stop_code: Cohen Street Bus Station (Platform 2), lat: -35.2396467, lng: 149.0602152} | - { name: Cohen Street Bus Station (Platform 2),stop_code: Cohen Street Bus Station (Platform 2), lat: -35.2396467, lng: 149.0602152} |
- { name: Cohen Street Bus Station (Platform 3),stop_code: Cohen Street Bus Station (Platform 3), lat: -35.239764, lng: 149.0604531} | - { name: Cohen Street Bus Station (Platform 3),stop_code: Cohen Street Bus Station (Platform 3), lat: -35.239764, lng: 149.0604531} |
- { name: Cohen Street Bus Station (Platform 4),stop_code: Cohen Street Bus Station (Platform 4), lat: -35.239844, lng: 149.0600683} | - { name: Cohen Street Bus Station (Platform 4),stop_code: Cohen Street Bus Station (Platform 4), lat: -35.239844, lng: 149.0600683} |
- { name: Cohen Street Bus Station (Platform 5),stop_code: Cohen Street Bus Station (Platform 5), lat: -35.2401211, lng: 149.0597102} | - { name: Cohen Street Bus Station (Platform 5),stop_code: Cohen Street Bus Station (Platform 5), lat: -35.2401211, lng: 149.0597102} |
- { name: Cohen Street Bus Station (Platform 6),stop_code: Cohen Street Bus Station (Platform 6), lat: -35.2400028, lng: 149.060315} | - { name: Cohen Street Bus Station (Platform 6),stop_code: Cohen Street Bus Station (Platform 6), lat: -35.2400028, lng: 149.060315} |
- { name: Conder Primary,stop_code: Conder Primary, lat: -35.4643475, lng: 149.0986908} | - { name: Conder Primary,stop_code: Conder Primary, lat: -35.4643475, lng: 149.0986908} |
- { name: Cook,stop_code: Cook, lat: -35.2596, lng: 149.0638} | - { name: Cook,stop_code: Cook, lat: -35.2596, lng: 149.0638} |
- { name: Cook Shops,stop_code: Cook Shops, lat: -35.25898, lng: 149.06343} | |
- { name: Cooleman Court,stop_code: Cooleman Court, lat: -35.34147, lng: 149.05338} | - { name: Cooleman Court,stop_code: Cooleman Court, lat: -35.34147, lng: 149.05338} |
- { name: Copland College,stop_code: Copland College, lat: -35.2127018, lng: 149.0596387} | - { name: Copland College,stop_code: Copland College, lat: -35.2127018, lng: 149.0596387} |
- { name: Curtin,stop_code: Curtin, lat: -35.3248779, lng: 149.081441} | - { name: Curtin,stop_code: Curtin, lat: -35.3248779, lng: 149.081441} |
- { name: Curtin Shops,stop_code: Curtin Shops, lat: -35.32515, lng: 149.08224} | |
- { name: Deakin,stop_code: Deakin, lat: -35.3158608, lng: 149.1084563} | - { name: Deakin,stop_code: Deakin, lat: -35.3158608, lng: 149.1084563} |
- { name: Deakin Shops,stop_code: Deakin Shops, lat: -35.31473, lng: 149.10771} | |
- { name: Deamer / Clift Richardson,stop_code: Deamer / Clift Richardson, lat: -35.4319597, lng: 149.1187876} | - { name: Deamer / Clift Richardson,stop_code: Deamer / Clift Richardson, lat: -35.4319597, lng: 149.1187876} |
- { name: Dickson,stop_code: Dickson, lat: -35.2498434, lng: 149.1391218} | - { name: Dickson / Antill St,stop_code: Dickson / Antill St, lat: -35.2489, lng: 149.14012} |
- { name: Dickson College,stop_code: Dickson College, lat: -35.24923, lng: 149.15315} | - { name: Dickson College,stop_code: Dickson College, lat: -35.24923, lng: 149.15315} |
- { name: Dickson Cowper St,stop_code: Dickson Cowper St, lat: -35.250297, lng: 149.141336} | - { name: Dickson / Cowper St,stop_code: Dickson / Cowper St, lat: -35.250297, lng: 149.141336} |
- { name: Dickson Shops,stop_code: Dickson Shops, lat: -35.25045, lng: 149.14044} | |
- { name: Dickson Shops/Antill St,stop_code: Dickson Shops/Antill St, lat: -35.2251335, lng: 149.1658895} | |
- { name: Duffy,stop_code: Duffy, lat: -35.3366908, lng: 149.0324311} | - { name: Duffy,stop_code: Duffy, lat: -35.3366908, lng: 149.0324311} |
- { name: Duffy Primary,stop_code: Duffy Primary, lat: -35.334219, lng: 149.033656} | - { name: Duffy Primary,stop_code: Duffy Primary, lat: -35.334219, lng: 149.033656} |
- { name: Dunlop,stop_code: Dunlop, lat: -35.1942693, lng: 149.0206702} | - { name: Dunlop,stop_code: Dunlop, lat: -35.1942693, lng: 149.0206702} |
- { name: Erindale Centre,stop_code: Erindale Centre, lat: -35.4038881, lng: 149.0992283} | - { name: Erindale Centre,stop_code: Erindale Centre, lat: -35.4038881, lng: 149.0992283} |
- { name: Erindale Dr / Charleston St Monash,stop_code: Erindale Dr / Charleston St Monash, lat: -35.414616, lng: 149.07888} | - { name: Erindale Dr / Charleston St Monash,stop_code: Erindale Dr / Charleston St Monash, lat: -35.414616, lng: 149.07888} |
- { name: Erindale / Sternberg Cres,stop_code: Erindale / Sternberg Cres, lat: -35.4014472, lng: 149.0956545} | - { name: Erindale / Sternberg Cres,stop_code: Erindale / Sternberg Cres, lat: -35.4014472, lng: 149.0956545} |
- { name: Evatt,stop_code: Evatt, lat: -35.2091093, lng: 149.0735343} | - { name: Evatt,stop_code: Evatt, lat: -35.2091093, lng: 149.0735343} |
- { name: Evatt Shops,stop_code: Evatt Shops, lat: -35.21203, lng: 149.06505} | |
- { name: Eye Hospital,stop_code: Eye Hospital, lat: -35.3341884, lng: 149.1656213} | - { name: Eye Hospital,stop_code: Eye Hospital, lat: -35.3341884, lng: 149.1656213} |
- { name: Fairbairn Park,stop_code: Fairbairn Park, lat: -35.3001773, lng: 149.2041185} | - { name: Fairbairn Park,stop_code: Fairbairn Park, lat: -35.3001773, lng: 149.2041185} |
- { name: Farrer Primary School,stop_code: Farrer Primary School, lat: -35.37887, lng: 149.10641} | - { name: Farrer Primary School,stop_code: Farrer Primary School, lat: -35.37887, lng: 149.10641} |
- { name: Farrer Terminus,stop_code: Farrer Terminus, lat: -35.3771794, lng: 149.1046948} | - { name: Farrer Terminus,stop_code: Farrer Terminus, lat: -35.3771794, lng: 149.1046948} |
- { name: Federation Square,stop_code: Federation Square, lat: -35.1908726, lng: 149.0848153} | - { name: Federation Square,stop_code: Federation Square, lat: -35.1908726, lng: 149.0848153} |
- { name: Fisher,stop_code: Fisher, lat: -35.3605627, lng: 149.0576481} | - { name: Fisher,stop_code: Fisher, lat: -35.3605627, lng: 149.0576481} |
- { name: Fisher Shops,stop_code: Fisher Shops, lat: -35.36056, lng: 149.05765} | |
- { name: Flemington Rd,stop_code: Flemington Rd, lat: -35.20756, lng: 149.14778} | - { name: Flemington Rd,stop_code: Flemington Rd, lat: -35.20756, lng: 149.14778} |
- { name: Flemington Rd / Nullabor Ave,stop_code: Flemington Rd / Nullabor Ave, lat: -35.2008585, lng: 149.1493407} | - { name: Flemington Rd / Nullabor Ave,stop_code: Flemington Rd / Nullabor Ave, lat: -35.2008585, lng: 149.1493407} |
- { name: Flemington Rd / Sandford St,stop_code: Flemington Rd / Sandford St, lat: -35.221231, lng: 149.144645} | - { name: Flemington Rd / Sandford St,stop_code: Flemington Rd / Sandford St, lat: -35.221231, lng: 149.144645} |
- { name: Florey Shops,stop_code: Florey Shops, lat: -35.2258544, lng: 149.0546214} | - { name: Florey,stop_code: Florey, lat: -35.2258544, lng: 149.0546214} |
- { name: Flynn,stop_code: Flynn, lat: -35.2019283, lng: 149.0478356} | - { name: Flynn,stop_code: Flynn, lat: -35.2019283, lng: 149.0478356} |
- { name: Fraser,stop_code: Fraser, lat: -35.1896539, lng: 149.0435012} | - { name: Fraser,stop_code: Fraser, lat: -35.1896539, lng: 149.0435012} |
- { name: Fraser East Terminus,stop_code: Fraser East Terminus, lat: -35.1896539, lng: 149.0435012} | - { name: Fraser East Terminus,stop_code: Fraser East Terminus, lat: -35.1896539, lng: 149.0435012} |
- { name: Fraser Shops,stop_code: Fraser Shops, lat: -35.18966, lng: 149.0435} | |
- { name: Fraser West Terminus,stop_code: Fraser West Terminus, lat: -35.191513, lng: 149.038006} | - { name: Fraser West Terminus,stop_code: Fraser West Terminus, lat: -35.191513, lng: 149.038006} |
- { name: Fyshwick Direct Factory Outlet,stop_code: Fyshwick Direct Factory Outlet, lat: -35.3359862, lng: 149.1796322} | - { name: Fyshwick Direct Factory Outlet,stop_code: Fyshwick Direct Factory Outlet, lat: -35.3359862, lng: 149.1796322} |
- { name: Fyshwick Terminus,stop_code: Fyshwick Terminus, lat: -35.3285202, lng: 149.1785592} | - { name: Fyshwick Terminus,stop_code: Fyshwick Terminus, lat: -35.3285202, lng: 149.1785592} |
- { name: Garran,stop_code: Garran, lat: -35.3423286, lng: 149.10811} | - { name: Garran,stop_code: Garran, lat: -35.3423286, lng: 149.10811} |
- { name: Garran Shops,stop_code: Garran Shops, lat: -35.34236, lng: 149.1082} | |
- { name: Geoscience Australia,stop_code: Geoscience Australia, lat: -35.3429702, lng: 149.1583893} | - { name: Geoscience Australia,stop_code: Geoscience Australia, lat: -35.3429702, lng: 149.1583893} |
- { name: Giralang,stop_code: Giralang, lat: -35.2115608, lng: 149.0960692} | - { name: Giralang,stop_code: Giralang, lat: -35.2115608, lng: 149.0960692} |
- { name: Giralang Shops,stop_code: Giralang Shops, lat: -35.2115608, lng: 149.0960692} | |
- { name: Gordon Primary,stop_code: Gordon Primary, lat: -35.455517, lng: 149.086978} | - { name: Gordon Primary,stop_code: Gordon Primary, lat: -35.455517, lng: 149.086978} |
- { name: Gowrie,stop_code: Gowrie, lat: -35.4120264, lng: 149.1110804} | - { name: Gowrie,stop_code: Gowrie, lat: -35.4120264, lng: 149.1110804} |
- { name: Gowrie Shops,stop_code: Gowrie Shops, lat: -35.4120264, lng: 149.1110804} | |
- { name: Gungahlin Marketplace,stop_code: Gungahlin Marketplace, lat: -35.1769532, lng: 149.1319017} | - { name: Gungahlin Marketplace,stop_code: Gungahlin Marketplace, lat: -35.1769532, lng: 149.1319017} |
- { name: Gwydir Square Kaleen,stop_code: Gwydir Square Kaleen, lat: -35.2338677, lng: 149.1031998} | - { name: Gwydir Square Kaleen,stop_code: Gwydir Square Kaleen, lat: -35.2338677, lng: 149.1031998} |
- { name: Hackett,stop_code: Hackett, lat: -35.2481617, lng: 149.1626094} | - { name: Hackett,stop_code: Hackett, lat: -35.2481617, lng: 149.1626094} |
- { name: Hackett Shops,stop_code: Hackett Shops, lat: -35.24825, lng: 149.16271} | |
- { name: Hawker,stop_code: Hawker, lat: -35.2437386, lng: 149.0432804} | - { name: Hawker,stop_code: Hawker, lat: -35.2437386, lng: 149.0432804} |
- { name: Hawker College,stop_code: Hawker College, lat: -35.2454598, lng: 149.0324251} | - { name: Hawker College,stop_code: Hawker College, lat: -35.2454598, lng: 149.0324251} |
- { name: Hawker Shops,stop_code: Hawker Shops, lat: -35.24398, lng: 149.04361} | |
- { name: Heagney / Clift Richardson,stop_code: Heagney / Clift Richardson, lat: -35.4251299, lng: 149.11375} | - { name: Heagney / Clift Richardson,stop_code: Heagney / Clift Richardson, lat: -35.4251299, lng: 149.11375} |
- { name: Hibberson / Kate Crace,stop_code: Hibberson / Kate Crace, lat: -35.1861642, lng: 149.1391756} | - { name: Hibberson / Kate Crace,stop_code: Hibberson / Kate Crace, lat: -35.1861642, lng: 149.1391756} |
- { name: Higgins,stop_code: Higgins, lat: -35.2313901, lng: 149.0271811} | - { name: Higgins,stop_code: Higgins, lat: -35.2313901, lng: 149.0271811} |
- { name: Higgins Shops,stop_code: Higgins Shops, lat: -35.23136, lng: 149.02611} | |
- { name: Holder,stop_code: Holder, lat: -35.3378123, lng: 149.0449433} | - { name: Holder,stop_code: Holder, lat: -35.3378123, lng: 149.0449433} |
- { name: Holder Shops,stop_code: Holder Shops, lat: -35.33781, lng: 149.04494} | |
- { name: Holt,stop_code: Holt, lat: -35.223099, lng: 149.0126269} | - { name: Holt,stop_code: Holt, lat: -35.223099, lng: 149.0126269} |
- { name: Holt Shops,stop_code: Holt Shops, lat: -35.2231, lng: 149.01263} | |
- { name: Hoskins Street / Oodgeroo Ave,stop_code: Hoskins Street / Oodgeroo Ave, lat: -35.201095, lng: 149.139941} | - { name: Hoskins Street / Oodgeroo Ave,stop_code: Hoskins Street / Oodgeroo Ave, lat: -35.201095, lng: 149.139941} |
- { name: Hospice / Menindee Dr,stop_code: Hospice / Menindee Dr, lat: -35.303557, lng: 149.151627} | - { name: Hospice / Menindee Dr,stop_code: Hospice / Menindee Dr, lat: -35.303557, lng: 149.151627} |
- { name: Hughes,stop_code: Hughes, lat: -35.3339223, lng: 149.093854} | - { name: Hughes,stop_code: Hughes, lat: -35.3339223, lng: 149.093854} |
- { name: Hughes Shops,stop_code: Hughes Shops, lat: -35.3335, lng: 149.09392} | |
- { name: Isaacs,stop_code: Isaacs, lat: -35.3669823, lng: 149.1119217} | - { name: Isaacs,stop_code: Isaacs, lat: -35.3669823, lng: 149.1119217} |
- { name: Isaacs Shops,stop_code: Isaacs Shops, lat: -35.36698, lng: 149.11192} | - { name: Isabella,stop_code: Isabella, lat: -35.4285703, lng: 149.0916837} |
- { name: Isabella Shops,stop_code: Isabella Shops, lat: -35.4285703, lng: 149.0916837} | |
- { name: Jamison Centre,stop_code: Jamison Centre, lat: -35.2527268, lng: 149.0713712} | - { name: Jamison Centre,stop_code: Jamison Centre, lat: -35.2527268, lng: 149.0713712} |
- { name: John James Hospital,stop_code: John James Hospital, lat: -35.3200295, lng: 149.0955996} | - { name: John James Hospital,stop_code: John James Hospital, lat: -35.3200295, lng: 149.0955996} |
- { name: Kaleen Village / Marybrynong,stop_code: Kaleen Village / Marybrynong, lat: -35.2274031, lng: 149.1075421} | - { name: Kaleen Village / Marybrynong,stop_code: Kaleen Village / Marybrynong, lat: -35.2274031, lng: 149.1075421} |
- { name: Kambah High,stop_code: Kambah High, lat: -35.3847749, lng: 149.0720245} | - { name: Kambah High,stop_code: Kambah High, lat: -35.3847749, lng: 149.0720245} |
- { name: Kambah / Livingston St,stop_code: Kambah / Livingston St, lat: -35.3883359, lng: 149.0811471} | |
- { name: Kambah Village,stop_code: Kambah Village, lat: -35.3800314, lng: 149.0576581} | - { name: Kambah Village,stop_code: Kambah Village, lat: -35.3800314, lng: 149.0576581} |
- { name: Katherine Ave / Horse Park Drive,stop_code: Katherine Ave / Horse Park Drive, lat: -35.1680901, lng: 149.1321801} | - { name: Katherine Ave / Horse Park Drive,stop_code: Katherine Ave / Horse Park Drive, lat: -35.1680901, lng: 149.1321801} |
- { name: Kerrigan / Lhotsky,stop_code: Kerrigan / Lhotsky, lat: -35.193801, lng: 149.035689} | - { name: Kerrigan / Lhotsky,stop_code: Kerrigan / Lhotsky, lat: -35.193801, lng: 149.035689} |
- { name: Kings Ave / National Circuit,stop_code: Kings Ave / National Circuit, lat: -35.305004, lng: 149.13262} | - { name: Kings Ave / National Circuit,stop_code: Kings Ave / National Circuit, lat: -35.305004, lng: 149.13262} |
- { name: Kingston,stop_code: Kingston, lat: -35.3197448, lng: 149.1375261} | - { name: Kingston,stop_code: Kingston, lat: -35.3197448, lng: 149.1375261} |
- { name: Kippax,stop_code: Kippax, lat: -35.22225, lng: 149.0195627} | - { name: Kippax,stop_code: Kippax, lat: -35.22225, lng: 149.0195627} |
- { name: Kippax Centre,stop_code: Kippax Centre, lat: -35.22172, lng: 149.01995} | - { name: Kippax Centre,stop_code: Kippax Centre, lat: -35.22172, lng: 149.01995} |
- { name: Kosciuszko / Everard,stop_code: Kosciuszko / Everard, lat: -35.188901, lng: 149.1216937} | - { name: Kosciuszko / Everard,stop_code: Kosciuszko / Everard, lat: -35.188901, lng: 149.1216937} |
- { name: Lanyon Market Place,stop_code: Lanyon Market Place, lat: -35.4573, lng: 149.09199} | - { name: Lanyon Marketplace,stop_code: Lanyon Marketplace, lat: -35.4573, lng: 149.09199} |
- { name: Latham,stop_code: Latham, lat: -35.21848, lng: 149.03214} | |
- { name: Latham Post Office,stop_code: Latham Post Office, lat: -35.21906, lng: 149.03223} | - { name: Latham Post Office,stop_code: Latham Post Office, lat: -35.21906, lng: 149.03223} |
- { name: Latham Shops,stop_code: Latham Shops, lat: -35.21848, lng: 149.03214} | |
- { name: Lathlain St Bus Station,stop_code: Lathlain St Bus Station, lat: -35.2396657, lng: 149.0633993} | - { name: Lathlain St Bus Station,stop_code: Lathlain St Bus Station, lat: -35.2396657, lng: 149.0633993} |
- { name: Lathlain St Bus Station (Platform 1),stop_code: Lathlain St Bus Station (Platform 1), lat: -35.2408973, lng: 149.0639887} | - { name: Lathlain St Bus Station (Platform 1),stop_code: Lathlain St Bus Station (Platform 1), lat: -35.2408973, lng: 149.0639887} |
- { name: Lathlain St Bus Station (Platform 2),stop_code: Lathlain St Bus Station (Platform 2), lat: -35.2406038, lng: 149.0638922} | - { name: Lathlain St Bus Station (Platform 2),stop_code: Lathlain St Bus Station (Platform 2), lat: -35.2406038, lng: 149.0638922} |
- { name: Lathlain St Bus Station (Platform 3),stop_code: Lathlain St Bus Station (Platform 3), lat: -35.2400517, lng: 149.0637152} | - { name: Lathlain St Bus Station (Platform 3),stop_code: Lathlain St Bus Station (Platform 3), lat: -35.2400517, lng: 149.0637152} |
- { name: Lathlain St Bus Station (Platform 4),stop_code: Lathlain St Bus Station (Platform 4), lat: -35.2396657, lng: 149.0633993} | - { name: Lathlain St Bus Station (Platform 4),stop_code: Lathlain St Bus Station (Platform 4), lat: -35.2396657, lng: 149.0633993} |
- { name: Lathlain St Bus Station (Platform 5),stop_code: Lathlain St Bus Station (Platform 5), lat: -35.2405468, lng: 149.0636669} | - { name: Lathlain St Bus Station (Platform 5),stop_code: Lathlain St Bus Station (Platform 5), lat: -35.2405468, lng: 149.0636669} |
- { name: Lathlain St Bus Station (Platform 6),stop_code: Lathlain St Bus Station (Platform 6), lat: -35.2410486, lng: 149.0638326} | - { name: Lathlain St Bus Station (Platform 6),stop_code: Lathlain St Bus Station (Platform 6), lat: -35.2410486, lng: 149.0638326} |
- { name: Lewis Luxton/Woodcock Dr,stop_code: Lewis Luxton/Woodcock Dr, lat: -35.4422566, lng: 149.0854375} | - { name: Lewis Luxton/Woodcock Dr,stop_code: Lewis Luxton/Woodcock Dr, lat: -35.4422566, lng: 149.0854375} |
- { name: Lithgow St Terminus Fyshwick,stop_code: Lithgow St Terminus Fyshwick, lat: -35.3296912, lng: 149.1668153} | - { name: Lithgow St Terminus Fyshwick,stop_code: Lithgow St Terminus Fyshwick, lat: -35.3296912, lng: 149.1668153} |
- { name: Livingston Shops Kambah,stop_code: Livingston Shops Kambah, lat: -35.3883359, lng: 149.0811471} | |
- { name: Livingston Shops / Kambah,stop_code: Livingston Shops / Kambah, lat: -35.390246, lng: 149.07822} | |
- { name: Lyneham,stop_code: Lyneham, lat: -35.2523304, lng: 149.1246184} | - { name: Lyneham,stop_code: Lyneham, lat: -35.2523304, lng: 149.1246184} |
- { name: Lyneham High,stop_code: Lyneham High, lat: -35.2524016, lng: 149.130254} | - { name: Lyneham High,stop_code: Lyneham High, lat: -35.2524016, lng: 149.130254} |
- { name: Lyneham Shops Wattle Street,stop_code: Lyneham Shops Wattle Street, lat: -35.25205, lng: 149.12524} | - { name: Lyneham / Wattle St,stop_code: Lyneham / Wattle St, lat: -35.25205, lng: 149.12524} |
- { name: Lyons,stop_code: Lyons, lat: -35.3415779, lng: 149.0765703} | - { name: Lyons,stop_code: Lyons, lat: -35.3415779, lng: 149.0765703} |
- { name: Lyons Shops,stop_code: Lyons Shops, lat: -35.34019, lng: 149.0771} | |
- { name: Macarthur / Miller O'Connor,stop_code: Macarthur / Miller O'Connor, lat: -35.2587584, lng: 149.1153561} | - { name: Macarthur / Miller O'Connor,stop_code: Macarthur / Miller O'Connor, lat: -35.2587584, lng: 149.1153561} |
- { name: Macarthur / Northbourne Ave,stop_code: Macarthur / Northbourne Ave, lat: -35.26051, lng: 149.13224} | - { name: Macarthur / Northbourne Ave,stop_code: Macarthur / Northbourne Ave, lat: -35.26051, lng: 149.13224} |
- { name: Macgregor,stop_code: Macgregor, lat: -35.2100645, lng: 149.0122952} | - { name: Macgregor,stop_code: Macgregor, lat: -35.2100645, lng: 149.0122952} |
- { name: Macgregor Shops,stop_code: Macgregor Shops, lat: -35.2100645, lng: 149.0122952} | |
- { name: MacKillop College Isabella Campus,stop_code: MacKillop College Isabella Campus, lat: -35.42597, lng: 149.09172} | - { name: MacKillop College Isabella Campus,stop_code: MacKillop College Isabella Campus, lat: -35.42597, lng: 149.09172} |
- { name: MacKillop College Wanniassa Campus,stop_code: MacKillop College Wanniassa Campus, lat: -35.4056, lng: 149.089774} | - { name: MacKillop College Wanniassa Campus,stop_code: MacKillop College Wanniassa Campus, lat: -35.4056, lng: 149.089774} |
- { name: Macquarie,stop_code: Macquarie, lat: -35.2483414, lng: 149.0600666} | - { name: Macquarie,stop_code: Macquarie, lat: -35.2483414, lng: 149.0600666} |
- { name: Majura Business Park,stop_code: Majura Business Park, lat: -35.2987, lng: 149.18561} | - { name: Majura Business Park,stop_code: Majura Business Park, lat: -35.2987, lng: 149.18561} |
- { name: Manning Clarke / Oodgeroo,stop_code: Manning Clarke / Oodgeroo, lat: -35.193236, lng: 149.146534} | - { name: Manning Clarke / Oodgeroo,stop_code: Manning Clarke / Oodgeroo, lat: -35.193236, lng: 149.146534} |
- { name: Manuka,stop_code: Manuka, lat: -35.3200096, lng: 149.1341344} | - { name: Manuka,stop_code: Manuka, lat: -35.3200096, lng: 149.1341344} |
- { name: Manuka / Captain Cook Cres,stop_code: Manuka / Captain Cook Cres, lat: -35.3217, lng: 149.13445} | - { name: Manuka / Captain Cook Cres,stop_code: Manuka / Captain Cook Cres, lat: -35.3217, lng: 149.13445} |
- { name: McKellar,stop_code: McKellar, lat: -35.2174267, lng: 149.0742108} | - { name: McKellar,stop_code: McKellar, lat: -35.2174267, lng: 149.0742108} |
- { name: McKellar Shops,stop_code: McKellar Shops, lat: -35.2182, lng: 149.07555} | |
- { name: Melba,stop_code: Melba, lat: -35.2083104, lng: 149.0485366} | - { name: Melba,stop_code: Melba, lat: -35.2083104, lng: 149.0485366} |
- { name: Melba Shops,stop_code: Melba Shops, lat: -35.21004, lng: 149.05302} | |
- { name: Mentone View / Tharwa Drive,stop_code: Mentone View / Tharwa Drive, lat: -35.45144, lng: 149.0919} | - { name: Mentone View / Tharwa Drive,stop_code: Mentone View / Tharwa Drive, lat: -35.45144, lng: 149.0919} |
- { name: Merici College,stop_code: Merici College, lat: -35.266525, lng: 149.137037} | - { name: Merici College,stop_code: Merici College, lat: -35.266525, lng: 149.137037} |
- { name: Mirrabei Drive / Dam Wall,stop_code: Mirrabei Drive / Dam Wall, lat: -35.177453, lng: 149.124291} | - { name: Mirrabei Drive / Dam Wall,stop_code: Mirrabei Drive / Dam Wall, lat: -35.177453, lng: 149.124291} |
- { name: Monash,stop_code: Monash, lat: -35.4190254, lng: 149.0834805} | - { name: Monash,stop_code: Monash, lat: -35.4190254, lng: 149.0834805} |
- { name: Monash Goodwin Village,stop_code: Monash Goodwin Village, lat: -35.421084, lng: 149.097438} | - { name: Monash Goodwin Village,stop_code: Monash Goodwin Village, lat: -35.421084, lng: 149.097438} |
- { name: Monash Primary,stop_code: Monash Primary, lat: -35.414879, lng: 149.089411} | - { name: Monash Primary,stop_code: Monash Primary, lat: -35.414879, lng: 149.089411} |
- { name: Mount Neighbour School,stop_code: Mount Neighbour School, lat: -35.382445, lng: 149.051518} | - { name: Mount Neighbour School,stop_code: Mount Neighbour School, lat: -35.382445, lng: 149.051518} |
- { name: Narrabundah,stop_code: Narrabundah, lat: -35.332605, lng: 149.154049} | - { name: Narrabundah,stop_code: Narrabundah, lat: -35.332605, lng: 149.154049} |
- { name: Narrabundah College,stop_code: Narrabundah College, lat: -35.3362106, lng: 149.1471005} | - { name: Narrabundah College,stop_code: Narrabundah College, lat: -35.3362106, lng: 149.1471005} |
- { name: Narrabundah Terminus,stop_code: Narrabundah Terminus, lat: -35.332605, lng: 149.154049} | - { name: Narrabundah Terminus,stop_code: Narrabundah Terminus, lat: -35.332605, lng: 149.154049} |
- { name: National Circ / Canberra Ave,stop_code: National Circ / Canberra Ave, lat: -35.31407, lng: 149.13011} | - { name: National Circ / Canberra Ave,stop_code: National Circ / Canberra Ave, lat: -35.31407, lng: 149.13011} |
- { name: National Hockey Centre Lyneham,stop_code: National Hockey Centre Lyneham, lat: -35.2446729, lng: 149.1288303} | - { name: National Hockey Centre Lyneham,stop_code: National Hockey Centre Lyneham, lat: -35.2446729, lng: 149.1288303} |
- { name: National Museum of Australia,stop_code: National Museum of Australia, lat: -35.29248, lng: 149.1205367} | - { name: National Museum of Australia,stop_code: National Museum of Australia, lat: -35.29248, lng: 149.1205367} |
- { name: National Zoo and Aquarium,stop_code: National Zoo and Aquarium, lat: -35.29915, lng: 149.07025} | - { name: National Zoo and Aquarium,stop_code: National Zoo and Aquarium, lat: -35.29915, lng: 149.07025} |
- { name: Newcastle Street after Isa Street,stop_code: Newcastle Street after Isa Street, lat: -35.3255, lng: 149.173291} | - { name: Newcastle Street after Isa Street,stop_code: Newcastle Street after Isa Street, lat: -35.3255, lng: 149.173291} |
- { name: Ngunnawal Primary,stop_code: Ngunnawal Primary, lat: -35.1688551, lng: 149.1112569} | - { name: Ngunnawal Primary,stop_code: Ngunnawal Primary, lat: -35.1688551, lng: 149.1112569} |
- { name: Nicholls Primary,stop_code: Nicholls Primary, lat: -35.1905592, lng: 149.0876716} | - { name: Nicholls Primary,stop_code: Nicholls Primary, lat: -35.1905592, lng: 149.0876716} |
- { name: Northbourne Avenue / Antill St,stop_code: Northbourne Avenue / Antill St, lat: -35.248287, lng: 149.134241} | - { name: Northbourne Avenue / Antill St,stop_code: Northbourne Avenue / Antill St, lat: -35.248287, lng: 149.134241} |
- { name: North Lyneham,stop_code: North Lyneham, lat: -35.2385618, lng: 149.1221188} | - { name: North Lyneham,stop_code: North Lyneham, lat: -35.2385618, lng: 149.1221188} |
- { name: O'Connor,stop_code: O'Connor, lat: -35.2640376, lng: 149.1226107} | - { name: O'Connor,stop_code: O'Connor, lat: -35.2640376, lng: 149.1226107} |
- { name: O'Connor Shops,stop_code: O'Connor Shops, lat: -35.2640376, lng: 149.1226107} | |
- { name: Olims Hotel,stop_code: Olims Hotel, lat: -35.27597, lng: 149.1428} | - { name: Olims Hotel,stop_code: Olims Hotel, lat: -35.27597, lng: 149.1428} |
- { name: Outtrim / Duggan,stop_code: Outtrim / Duggan, lat: -35.435871, lng: 149.097692} | - { name: Outtrim / Duggan,stop_code: Outtrim / Duggan, lat: -35.435871, lng: 149.097692} |
- { name: Page Shops,stop_code: Page Shops, lat: -35.2360695, lng: 149.0536554} | - { name: Page,stop_code: Page, lat: -35.2360695, lng: 149.0536554} |
- { name: Parliament House,stop_code: Parliament House, lat: -35.3081571, lng: 149.1244592} | - { name: Parliament House,stop_code: Parliament House, lat: -35.3081571, lng: 149.1244592} |
- { name: Paul Coe / Mirrabei Dr,stop_code: Paul Coe / Mirrabei Dr, lat: -35.17467, lng: 149.12005} | - { name: Paul Coe / Mirrabei Dr,stop_code: Paul Coe / Mirrabei Dr, lat: -35.17467, lng: 149.12005} |
- { name: Pearce,stop_code: Pearce, lat: -35.3625413, lng: 149.0815935} | - { name: Pearce,stop_code: Pearce, lat: -35.3625413, lng: 149.0815935} |
- { name: Pearce Shops,stop_code: Pearce Shops, lat: -35.3625413, lng: 149.0815935} | |
- { name: Police College Weston,stop_code: Police College Weston, lat: -35.33018, lng: 149.05458} | - { name: Police College Weston,stop_code: Police College Weston, lat: -35.33018, lng: 149.05458} |
- { name: Proctor / Mead,stop_code: Proctor / Mead, lat: -35.415305, lng: 149.127204} | - { name: Proctor / Mead,stop_code: Proctor / Mead, lat: -35.415305, lng: 149.127204} |
- { name: Railway Station Kingston,stop_code: Railway Station Kingston, lat: -35.319602, lng: 149.149083} | - { name: Railway Station Kingston,stop_code: Railway Station Kingston, lat: -35.319602, lng: 149.149083} |
- { name: Red Hill,stop_code: Red Hill, lat: -35.336505, lng: 149.131645} | - { name: Red Hill,stop_code: Red Hill, lat: -35.336505, lng: 149.131645} |
- { name: Red Hill Shops,stop_code: Red Hill Shops, lat: -35.336505, lng: 149.131645} | |
- { name: Rivett,stop_code: Rivett, lat: -35.3473758, lng: 149.0365438} | - { name: Rivett,stop_code: Rivett, lat: -35.3473758, lng: 149.0365438} |
- { name: Rivett Shops,stop_code: Rivett Shops, lat: -35.34737, lng: 149.03654} | |
- { name: Russell Offices,stop_code: Russell Offices, lat: -35.2973294, lng: 149.1508803} | - { name: Russell Offices,stop_code: Russell Offices, lat: -35.2973294, lng: 149.1508803} |
- { name: Sainsbury Street,stop_code: Sainsbury Street, lat: -35.3885, lng: 149.09643} | - { name: Sainsbury Street,stop_code: Sainsbury Street, lat: -35.3885, lng: 149.09643} |
- { name: Saint Andrews Village Hughes,stop_code: Saint Andrews Village Hughes, lat: -35.328097, lng: 149.088685} | - { name: Saint Andrews Village Hughes,stop_code: Saint Andrews Village Hughes, lat: -35.328097, lng: 149.088685} |
- { name: Scullin Shops,stop_code: Scullin Shops, lat: -35.23356, lng: 149.04056} | - { name: Scullin,stop_code: Scullin, lat: -35.23356, lng: 149.04056} |
- { name: Shoalhaven / Katherine Ave,stop_code: Shoalhaven / Katherine Ave, lat: -35.16823, lng: 149.12791} | - { name: Shoalhaven / Katherine Ave,stop_code: Shoalhaven / Katherine Ave, lat: -35.16823, lng: 149.12791} |
- { name: Southlands Mawson,stop_code: Southlands Mawson, lat: -35.3650685, lng: 149.0945962} | - { name: Southlands Mawson,stop_code: Southlands Mawson, lat: -35.3650685, lng: 149.0945962} |
- { name: Southwell Park,stop_code: Southwell Park, lat: -35.24573, lng: 149.1321} | - { name: Southwell Park,stop_code: Southwell Park, lat: -35.24573, lng: 149.1321} |
- { name: Spence,stop_code: Spence, lat: -35.194735, lng: 149.062352} | - { name: Spence,stop_code: Spence, lat: -35.194735, lng: 149.062352} |
- { name: Spence Shops,stop_code: Spence Shops, lat: -35.19968, lng: 149.06763} | |
- { name: Spence Terminus,stop_code: Spence Terminus, lat: -35.199684, lng: 149.0676196} | - { name: Spence Terminus,stop_code: Spence Terminus, lat: -35.199684, lng: 149.0676196} |
- { name: St Clare of Assisi,stop_code: St Clare of Assisi, lat: -35.46063, lng: 149.09627} | |
- { name: St Clare of Assisi Primary,stop_code: St Clare of Assisi Primary, lat: -35.4606284, lng: 149.0962704} | - { name: St Clare of Assisi Primary,stop_code: St Clare of Assisi Primary, lat: -35.4606284, lng: 149.0962704} |
- { name: St Francis Xavier Florey,stop_code: St Francis Xavier Florey, lat: -35.223951, lng: 149.0406888} | - { name: St Francis Xavier Florey,stop_code: St Francis Xavier Florey, lat: -35.223951, lng: 149.0406888} |
- { name: Stromlo High Waramanga,stop_code: Stromlo High Waramanga, lat: -35.3551186, lng: 149.0547624} | - { name: Stromlo High Waramanga,stop_code: Stromlo High Waramanga, lat: -35.3551186, lng: 149.0547624} |
- { name: St Thomas More's Campbell,stop_code: St Thomas More's Campbell, lat: -35.286717, lng: 149.156836} | - { name: St Thomas More's Campbell,stop_code: St Thomas More's Campbell, lat: -35.286717, lng: 149.156836} |
- { name: Sydney Ave,stop_code: Sydney Ave, lat: -35.31193, lng: 149.13105} | - { name: Sydney Ave,stop_code: Sydney Ave, lat: -35.31193, lng: 149.13105} |
- { name: Taverner St / Erindale Dr,stop_code: Taverner St / Erindale Dr, lat: -35.4059104, lng: 149.0809317} | - { name: Taverner St / Erindale Dr,stop_code: Taverner St / Erindale Dr, lat: -35.4059104, lng: 149.0809317} |
- { name: Tharwa Drive,stop_code: Tharwa Drive, lat: -35.458251, lng: 149.091652} | - { name: Tharwa Drive,stop_code: Tharwa Drive, lat: -35.458251, lng: 149.091652} |
- { name: Tharwa Drive / Knoke Ave,stop_code: Tharwa Drive / Knoke Ave, lat: -35.47281, lng: 149.08926} | - { name: Tharwa Drive / Knoke Ave,stop_code: Tharwa Drive / Knoke Ave, lat: -35.47281, lng: 149.08926} |
- { name: Tharwa Dr / Pockett Ave,stop_code: Tharwa Dr / Pockett Ave, lat: -35.47348, lng: 149.09178} | - { name: Tharwa Drive / Pockett Ave,stop_code: Tharwa Drive / Pockett Ave, lat: -35.47348, lng: 149.09178} |
- { name: Theodore,stop_code: Theodore, lat: -35.4464808, lng: 149.1234651} | - { name: Theodore,stop_code: Theodore, lat: -35.4464808, lng: 149.1234651} |
- { name: Tillyard / Spalding,stop_code: Tillyard / Spalding, lat: -35.199204, lng: 149.044556} | - { name: Tillyard / Spalding,stop_code: Tillyard / Spalding, lat: -35.199204, lng: 149.044556} |
- { name: Torrens Shops,stop_code: Torrens Shops, lat: -35.3730889, lng: 149.087327} | - { name: Torrens,stop_code: Torrens, lat: -35.3730889, lng: 149.087327} |
- { name: Tuggeranong Bus Station,stop_code: Tuggeranong Bus Station, lat: -35.41465, lng: 149.06537} | - { name: Tuggeranong Bus Station,stop_code: Tuggeranong Bus Station, lat: -35.41465, lng: 149.06537} |
- { name: Tuggeranong Bus Station (Platform 3),stop_code: Tuggeranong Bus Station (Platform 3), lat: -35.4147569, lng: 149.0657435} | - { name: Tuggeranong Bus Station (Platform 3),stop_code: Tuggeranong Bus Station (Platform 3), lat: -35.4147569, lng: 149.0657435} |
- { name: Tuggeranong Bus Station (Platform 4),stop_code: Tuggeranong Bus Station (Platform 4), lat: -35.4144924, lng: 149.0655423} | - { name: Tuggeranong Bus Station (Platform 4),stop_code: Tuggeranong Bus Station (Platform 4), lat: -35.4144924, lng: 149.0655423} |
- { name: Tuggeranong Bus Station (Platform 5),stop_code: Tuggeranong Bus Station (Platform 5), lat: -35.414217, lng: 149.0653492} | - { name: Tuggeranong Bus Station (Platform 5),stop_code: Tuggeranong Bus Station (Platform 5), lat: -35.414217, lng: 149.0653492} |
- { name: Tuggeranong Bus Station (Platform 7),stop_code: Tuggeranong Bus Station (Platform 7), lat: -35.4146761, lng: 149.0654565} | - { name: Tuggeranong Bus Station (Platform 7),stop_code: Tuggeranong Bus Station (Platform 7), lat: -35.4146761, lng: 149.0654565} |
- { name: Tuggeranong Bus Station (Platform 8),stop_code: Tuggeranong Bus Station (Platform 8), lat: -35.4149428, lng: 149.0656523} | - { name: Tuggeranong Bus Station (Platform 8),stop_code: Tuggeranong Bus Station (Platform 8), lat: -35.4149428, lng: 149.0656523} |
- { name: University of Canberra,stop_code: University of Canberra, lat: -35.2423222, lng: 149.0831522} | - { name: University of Canberra,stop_code: University of Canberra, lat: -35.2423222, lng: 149.0831522} |
- { name: Wanniassa High,stop_code: Wanniassa High, lat: -35.3952462, lng: 149.0852655} | - { name: Wanniassa High,stop_code: Wanniassa High, lat: -35.3952462, lng: 149.0852655} |
- { name: Waramanga,stop_code: Waramanga, lat: -35.3526825, lng: 149.0594712} | - { name: Waramanga,stop_code: Waramanga, lat: -35.3526825, lng: 149.0594712} |
- { name: Waramanga Shops,stop_code: Waramanga Shops, lat: -35.35268, lng: 149.05948} | - { name: War Memorial / Limestone Ave,stop_code: War Memorial / Limestone Ave, lat: -35.280477, lng: 149.149085} |
- { name: War Memorial Limestone Ave,stop_code: War Memorial Limestone Ave, lat: -35.280477, lng: 149.149085} | |
- { name: Watson,stop_code: Watson, lat: -35.2389399, lng: 149.1535345} | - { name: Watson,stop_code: Watson, lat: -35.2389399, lng: 149.1535345} |
- { name: Watson Shops,stop_code: Watson Shops, lat: -35.2389399, lng: 149.1535345} | |
- { name: Watson Terminus,stop_code: Watson Terminus, lat: -35.2374698, lng: 149.1534553} | - { name: Watson Terminus,stop_code: Watson Terminus, lat: -35.2374698, lng: 149.1534553} |
- { name: Weetangera Shops,stop_code: Weetangera Shops, lat: -35.248393, lng: 149.0506342} | - { name: Weetangera,stop_code: Weetangera, lat: -35.248393, lng: 149.0506342} |
- { name: Westfield Bus Station,stop_code: Westfield Bus Station, lat: -35.23875, lng: 149.0638} | - { name: Westfield Bus Station,stop_code: Westfield Bus Station, lat: -35.23875, lng: 149.0638} |
- { name: Westfield Bus Station (Platform 1),stop_code: Westfield Bus Station (Platform 1), lat: -35.23872, lng: 149.06387} | - { name: Westfield Bus Station (Platform 1),stop_code: Westfield Bus Station (Platform 1), lat: -35.23872, lng: 149.06387} |
- { name: Westfield Bus Station (Platform 2),stop_code: Westfield Bus Station (Platform 2), lat: -35.23882, lng: 149.0637} | - { name: Westfield Bus Station (Platform 2),stop_code: Westfield Bus Station (Platform 2), lat: -35.23882, lng: 149.0637} |
- { name: West Macgregor,stop_code: West Macgregor, lat: -35.21207, lng: 149.00165} | - { name: West Macgregor,stop_code: West Macgregor, lat: -35.21207, lng: 149.00165} |
- { name: Weston Creek Terminus,stop_code: Weston Creek Terminus, lat: -35.342728, lng: 149.0524906} | - { name: Weston Creek Terminus,stop_code: Weston Creek Terminus, lat: -35.342728, lng: 149.0524906} |
- { name: Weston Primary,stop_code: Weston Primary, lat: -35.3305221, lng: 149.0524281} | - { name: Weston Primary,stop_code: Weston Primary, lat: -35.3305221, lng: 149.0524281} |
- { name: William Webb / Ginninderra Drive,stop_code: William Webb / Ginninderra Drive, lat: -35.222395, lng: 149.0706} | - { name: William Webb / Ginninderra Drive,stop_code: William Webb / Ginninderra Drive, lat: -35.222395, lng: 149.0706} |
- { name: Woden Bus Station,stop_code: Woden Bus Station, lat: -35.34433, lng: 149.08742} | - { name: Woden Bus Station,stop_code: Woden Bus Station, lat: -35.34433, lng: 149.08742} |
- { name: Woden Bus Station (Platform 10),stop_code: Woden Bus Station (Platform 10), lat: -35.3439501, lng: 149.0877369} | - { name: Woden Bus Station (Platform 10),stop_code: Woden Bus Station (Platform 10), lat: -35.3439501, lng: 149.0877369} |
- { name: Woden Bus Station (Platform 11),stop_code: Woden Bus Station (Platform 11), lat: -35.3439129, lng: 149.0876216} | - { name: Woden Bus Station (Platform 11),stop_code: Woden Bus Station (Platform 11), lat: -35.3439129, lng: 149.0876216} |
- { name: Woden Bus Station (Platform 12),stop_code: Woden Bus Station (Platform 12), lat: -35.3442094, lng: 149.0876444} | - { name: Woden Bus Station (Platform 12),stop_code: Woden Bus Station (Platform 12), lat: -35.3442094, lng: 149.0876444} |
- { name: Woden Bus Station (Platform 14),stop_code: Woden Bus Station (Platform 14), lat: -35.34438, lng: 149.0872662} | - { name: Woden Bus Station (Platform 14),stop_code: Woden Bus Station (Platform 14), lat: -35.34438, lng: 149.0872662} |
- { name: Woden Bus Station (Platform 15),stop_code: Woden Bus Station (Platform 15), lat: -35.3444271, lng: 149.0869631} | - { name: Woden Bus Station (Platform 15),stop_code: Woden Bus Station (Platform 15), lat: -35.3444271, lng: 149.0869631} |
- { name: Woden Bus Station (Platform 16),stop_code: Woden Bus Station (Platform 16), lat: -35.344484, lng: 149.0866144} | - { name: Woden Bus Station (Platform 16),stop_code: Woden Bus Station (Platform 16), lat: -35.344484, lng: 149.0866144} |
- { name: Woden Bus Station (Platform 2),stop_code: Woden Bus Station (Platform 2), lat: -35.3447574, lng: 149.0862912} | - { name: Woden Bus Station (Platform 2),stop_code: Woden Bus Station (Platform 2), lat: -35.3447574, lng: 149.0862912} |
- { name: Woden Bus Station (Platform 3),stop_code: Woden Bus Station (Platform 3), lat: -35.344566, lng: 149.086774} | - { name: Woden Bus Station (Platform 3),stop_code: Woden Bus Station (Platform 3), lat: -35.344566, lng: 149.086774} |
- { name: Woden Bus Station (Platform 4),stop_code: Woden Bus Station (Platform 4), lat: -35.3445222, lng: 149.0870436} | - { name: Woden Bus Station (Platform 4),stop_code: Woden Bus Station (Platform 4), lat: -35.3445222, lng: 149.0870436} |
- { name: Woden Bus Station (Platform 5),stop_code: Woden Bus Station (Platform 5), lat: -35.3444741, lng: 149.0873533} | - { name: Woden Bus Station (Platform 5),stop_code: Woden Bus Station (Platform 5), lat: -35.3444741, lng: 149.0873533} |
- { name: Woden Bus Station (Platform 6),stop_code: Woden Bus Station (Platform 6), lat: -35.34445, lng: 149.0875371} | - { name: Woden Bus Station (Platform 6),stop_code: Woden Bus Station (Platform 6), lat: -35.34445, lng: 149.0875371} |
- { name: Woden Bus Station (Platform 9),stop_code: Woden Bus Station (Platform 9), lat: -35.3442083, lng: 149.0877771} | - { name: Woden Bus Station (Platform 9),stop_code: Woden Bus Station (Platform 9), lat: -35.3442083, lng: 149.0877771} |
- { name: Woodcock / Clare Dennis,stop_code: Woodcock / Clare Dennis, lat: -35.4422566, lng: 149.0854375} | - { name: Woodcock / Clare Dennis,stop_code: Woodcock / Clare Dennis, lat: -35.4422566, lng: 149.0854375} |
- { name: Yarralumla Shops,stop_code: Yarralumla Shops, lat: -35.30725, lng: 149.0972} | - { name: Yarralumla,stop_code: Yarralumla, lat: -35.30725, lng: 149.0972} |
- { name: Andrea Place,stop_code: Wjz1ceG, lat: -35.4375289, lng: 149.0757996} | - { name: Andrea Place,stop_code: Wjz1ceG, lat: -35.4375289, lng: 149.0757996} |
- { name: Tarlton Place,stop_code: Wjz1kvl, lat: -35.4366017, lng: 149.0890756} | - { name: Tarlton Place,stop_code: Wjz1kvl, lat: -35.4366017, lng: 149.0890756} |
- { name: Don Dunstan Drive,stop_code: Wjz16U7, lat: -35.4302659, lng: 149.0722593} | - { name: Don Dunstan Drive,stop_code: Wjz16U7, lat: -35.4302659, lng: 149.0722593} |
- { name: Salmon Place,stop_code: WjrWY3_, lat: -35.3952466, lng: 149.0527528} | - { name: Salmon Place,stop_code: WjrWY3_, lat: -35.3952466, lng: 149.0527528} |
- { name: Crozier Circuit,stop_code: WjrWSUa, lat: -35.3867455, lng: 149.0504459} | - { name: Crozier Circuit,stop_code: WjrWSUa, lat: -35.3867455, lng: 149.0504459} |
- { name: Mouat Street,stop_code: Wjz5LYB, lat: -35.2464052, lng: 149.1278592} | - { name: Mouat Street,stop_code: Wjz5LYB, lat: -35.2464052, lng: 149.1278592} |
- { name: Mackennal Street,stop_code: Wjz5LsC, lat: -35.2463364, lng: 149.1223897} | - { name: Mackennal Street,stop_code: Wjz5LsC, lat: -35.2463364, lng: 149.1223897} |
- { name: Clianthus Street,stop_code: Wjz5Krx, lat: -35.2529666, lng: 149.1223781} | - { name: Clianthus Street,stop_code: Wjz5Krx, lat: -35.2529666, lng: 149.1223781} |
- { name: Way Street,stop_code: Wjz5BWh, lat: -35.2591172, lng: 149.1164155} | - { name: Way Street,stop_code: Wjz5BWh, lat: -35.2591172, lng: 149.1164155} |
- { name: Cockle Street,stop_code: Wjz5AGB, lat: -35.2642702, lng: 149.1141435} | - { name: Cockle Street,stop_code: Wjz5AGB, lat: -35.2642702, lng: 149.1141435} |
- { name: Froggatt Street,stop_code: Wjz5H0p, lat: -35.2714838, lng: 149.1180142} | - { name: Froggatt Street,stop_code: Wjz5H0p, lat: -35.2714838, lng: 149.1180142} |
- { name: McClintock Street,stop_code: Wjz6ElH, lat: -35.2404264, lng: 149.1210434} | - { name: McClintock Street,stop_code: Wjz6ElH, lat: -35.2404264, lng: 149.1210434} |
- { name: Cossington Smith Crescent,stop_code: Wjz6FEI, lat: -35.2382959, lng: 149.1252507} | - { name: Cossington Smith Crescent,stop_code: Wjz6FEI, lat: -35.2382959, lng: 149.1252507} |
- { name: Dumas Street,stop_code: Wjz6cz2, lat: -35.2199304, lng: 149.0791416} | - { name: Dumas Street,stop_code: Wjz6cz2, lat: -35.2199304, lng: 149.0791416} |
- { name: Buggy Crescent,stop_code: Wjz64OE, lat: -35.2207286, lng: 149.0717368} | - { name: Buggy Crescent,stop_code: Wjz64OE, lat: -35.2207286, lng: 149.0717368} |
- { name: Owen Dixon Drive,stop_code: Wjz6eWi, lat: -35.2096321, lng: 149.0835148} | - { name: Owen Dixon Drive,stop_code: Wjz6eWi, lat: -35.2096321, lng: 149.0835148} |
- { name: Baldwin Drive,stop_code: Wjz6kCT, lat: -35.217402, lng: 149.0910262} | - { name: Baldwin Drive,stop_code: Wjz6kCT, lat: -35.217402, lng: 149.0910262} |
- { name: Jacob Place,stop_code: Wjr-TRM, lat: -35.2021703, lng: 149.0498418} | - { name: Jacob Place,stop_code: Wjr-TRM, lat: -35.2021703, lng: 149.0498418} |
- { name: Love Street,stop_code: Wjr_MMi, lat: -35.200018, lng: 149.0491234} | - { name: Love Street,stop_code: Wjr_MMi, lat: -35.200018, lng: 149.0491234} |
- { name: Box Place,stop_code: Wjr-IeY, lat: -35.2176259, lng: 149.032238} | - { name: Box Place,stop_code: Wjr-IeY, lat: -35.2176259, lng: 149.032238} |
- { name: Macrossan Crescent,stop_code: Wjr-J8t, lat: -35.2161747, lng: 149.0315719} | - { name: Macrossan Crescent,stop_code: Wjr-J8t, lat: -35.2161747, lng: 149.0315719} |
- { name: Want Place,stop_code: Wjr-Jm9, lat: -35.2124379, lng: 149.0325045} | - { name: Want Place,stop_code: Wjr-Jm9, lat: -35.2124379, lng: 149.0325045} |
- { name: Fellows Street,stop_code: Wjr-J44, lat: -35.2135626, lng: 149.0296181} | - { name: Fellows Street,stop_code: Wjr-J44, lat: -35.2135626, lng: 149.0296181} |
- { name: Osburn Drive,stop_code: Wjr-BB3, lat: -35.2129096, lng: 149.0241561} | - { name: Osburn Drive,stop_code: Wjr-BB3, lat: -35.2129096, lng: 149.0241561} |
- { name: Solomon Crescent,stop_code: Wjr-AY4, lat: -35.2190044, lng: 149.0282415} | - { name: Solomon Crescent,stop_code: Wjr-AY4, lat: -35.2190044, lng: 149.0282415} |
- { name: Onslow Street,stop_code: Wjr-IcO, lat: -35.2191858, lng: 149.0319716} | - { name: Onslow Street,stop_code: Wjr-IcO, lat: -35.2191858, lng: 149.0319716} |
- { name: Onslow Street,stop_code: Wjr-IqS, lat: -35.2202741, lng: 149.034858} | - { name: Onslow Street,stop_code: Wjr-IqS, lat: -35.2202741, lng: 149.034858} |
- { name: Kingsford Smith Drive,stop_code: Wjr-H-a, lat: -35.2232851, lng: 149.039343} | - { name: Kingsford Smith Drive,stop_code: Wjr-H-a, lat: -35.2232851, lng: 149.039343} |
- { name: Krefft Street,stop_code: Wjr-Q4G, lat: -35.2192221, lng: 149.0415189} | - { name: Krefft Street,stop_code: Wjr-Q4G, lat: -35.2192221, lng: 149.0415189} |
- { name: Maribyrnong Avenue,stop_code: Wjz6zon, lat: -35.2269858, lng: 149.1109391} | - { name: Maribyrnong Avenue,stop_code: Wjz6zon, lat: -35.2269858, lng: 149.1109391} |
- { name: Maribyrnong Avenue,stop_code: Wjz6ytu, lat: -35.2291622, lng: 149.1110812} | - { name: Maribyrnong Avenue,stop_code: Wjz6ytu, lat: -35.2291622, lng: 149.1110812} |
- { name: Belconnen Way,stop_code: Wjz5mpm, lat: -35.2538531, lng: 149.0889493} | - { name: Belconnen Way,stop_code: Wjz5mpm, lat: -35.2538531, lng: 149.0889493} |
- { name: Belconnen Way,stop_code: Wjz5mxf, lat: -35.2538241, lng: 149.0902637} | - { name: Belconnen Way,stop_code: Wjz5mxf, lat: -35.2538241, lng: 149.0902637} |
- { name: Belconnen Way,stop_code: Wjr-MNh, lat: -35.2433401, lng: 149.0492618} | - { name: Belconnen Way,stop_code: Wjr-MNh, lat: -35.2433401, lng: 149.0492618} |
- { name: Belconnen Way,stop_code: Wjr-Mqd, lat: -35.2422956, lng: 149.0448568} | - { name: Belconnen Way,stop_code: Wjr-Mqd, lat: -35.2422956, lng: 149.0448568} |
- { name: Belconnen Way,stop_code: Wjr-EYe, lat: -35.2408449, lng: 149.0394925} | - { name: Belconnen Way,stop_code: Wjr-EYe, lat: -35.2408449, lng: 149.0394925} |
- { name: Belconnen Way,stop_code: Wjr-EA_, lat: -35.2407288, lng: 149.0362953} | - { name: Belconnen Way,stop_code: Wjr-EA_, lat: -35.2407288, lng: 149.0362953} |
- { name: Mackinolty Street,stop_code: Wjr-Fw4, lat: -35.2382916, lng: 149.035194} | - { name: Mackinolty Street,stop_code: Wjr-Fw4, lat: -35.2382916, lng: 149.035194} |
- { name: Challinor Crescent,stop_code: Wjr-Vnf, lat: -35.2331848, lng: 149.054555} | - { name: Challinor Crescent,stop_code: Wjr-Vnf, lat: -35.2331848, lng: 149.054555} |
- { name: Lightfoot Crescent,stop_code: Wjr-Ws2, lat: -35.230167, lng: 149.0557628} | - { name: Lightfoot Crescent,stop_code: Wjr-Ws2, lat: -35.230167, lng: 149.0557628} |
- { name: Nanson Place,stop_code: Wjr-PyX, lat: -35.2259882, lng: 149.0472724} | - { name: Nanson Place,stop_code: Wjr-PyX, lat: -35.2259882, lng: 149.0472724} |
- { name: Kulgera Street,stop_code: WjrZKZn, lat: -35.2510294, lng: 149.0396391} | - { name: Kulgera Street,stop_code: WjrZKZn, lat: -35.2510294, lng: 149.0396391} |
- { name: King Edward Terrace,stop_code: Wjz4S1U, lat: -35.2983385, lng: 149.1296979} | - { name: King Edward Terrace,stop_code: Wjz4S1U, lat: -35.2983385, lng: 149.1296979} |
- { name: King George Terrace,stop_code: Wjz4RbQ, lat: -35.3021238, lng: 149.1308574} | - { name: King George Terrace,stop_code: Wjz4RbQ, lat: -35.3021238, lng: 149.1308574} |
- { name: James Street,stop_code: Wjz3fCx, lat: -35.333256, lng: 149.0798309} | - { name: James Street,stop_code: Wjz3fCx, lat: -35.333256, lng: 149.0798309} |
- { name: Kent Street,stop_code: Wjz4peM, lat: -35.322342, lng: 149.0979263} | - { name: Kent Street,stop_code: Wjz4peM, lat: -35.322342, lng: 149.0979263} |
- { name: Fuller Street,stop_code: Wjz4qgy, lat: -35.3208475, lng: 149.098981} | - { name: Fuller Street,stop_code: Wjz4qgy, lat: -35.3208475, lng: 149.098981} |
- { name: Hopetoun Circuit,stop_code: Wjz4A7o, lat: -35.3052441, lng: 149.107042} | - { name: Hopetoun Circuit,stop_code: Wjz4A7o, lat: -35.3052441, lng: 149.107042} |
- { name: De Chair Street,stop_code: Wjz4qTw, lat: -35.3162151, lng: 149.1045086} | - { name: De Chair Street,stop_code: Wjz4qTw, lat: -35.3162151, lng: 149.1045086} |
- { name: Macgregor Street,stop_code: Wjz4qs0, lat: -35.3182278, lng: 149.09964} | - { name: Macgregor Street,stop_code: Wjz4qs0, lat: -35.3182278, lng: 149.09964} |
- { name: Stonehaven Crescent,stop_code: Wjz4yzk, lat: -35.3186155, lng: 149.1123352} | - { name: Stonehaven Crescent,stop_code: Wjz4yzk, lat: -35.3186155, lng: 149.1123352} |
- { name: Dominion Circuit,stop_code: Wjz4H0P, lat: -35.3152936, lng: 149.1185178} | - { name: Dominion Circuit,stop_code: Wjz4H0P, lat: -35.3152936, lng: 149.1185178} |
- { name: Schlich Street,stop_code: Wjz4tpE, lat: -35.3038329, lng: 149.1005569} | - { name: Schlich Street,stop_code: Wjz4tpE, lat: -35.3038329, lng: 149.1005569} |
- { name: Weston Street,stop_code: Wjz4z67, lat: -35.3107704, lng: 149.1065979} | - { name: Weston Street,stop_code: Wjz4z67, lat: -35.3107704, lng: 149.1065979} |
- { name: Musgrave Street,stop_code: Wjz4tUp, lat: -35.3044055, lng: 149.1056974} | - { name: Musgrave Street,stop_code: Wjz4tUp, lat: -35.3044055, lng: 149.1056974} |
- { name: Hopetoun Circuit,stop_code: Wjz4A2c, lat: -35.3082791, lng: 149.1066534} | - { name: Hopetoun Circuit,stop_code: Wjz4A2c, lat: -35.3082791, lng: 149.1066534} |
- { name: Lienhop Street,stop_code: Wjz1HTi, lat: -35.4423392, lng: 149.1260397} | - { name: Lienhop Street,stop_code: Wjz1HTi, lat: -35.4423392, lng: 149.1260397} |
- { name: Hartung Crescent,stop_code: Wjz1zN3, lat: -35.4464057, lng: 149.1147796} | - { name: Hartung Crescent,stop_code: Wjz1zN3, lat: -35.4464057, lng: 149.1147796} |
- { name: Lawrence Wackett Crescent,stop_code: Wjz1HEb, lat: -35.4471149, lng: 149.1245306} | - { name: Lawrence Wackett Crescent,stop_code: Wjz1HEb, lat: -35.4471149, lng: 149.1245306} |
- { name: Callister Crescent,stop_code: Wjz1xWZ, lat: -35.4565002, lng: 149.1174205} | - { name: Callister Crescent,stop_code: Wjz1xWZ, lat: -35.4565002, lng: 149.1174205} |
- { name: Chippindall Circuit,stop_code: Wjz1Gjj, lat: -35.4504956, lng: 149.1205257} | - { name: Chippindall Circuit,stop_code: Wjz1Gjj, lat: -35.4504956, lng: 149.1205257} |
- { name: Fidge Street,stop_code: Wjz1rQ6, lat: -35.4440887, lng: 149.1038388} | - { name: Fidge Street,stop_code: Wjz1rQ6, lat: -35.4440887, lng: 149.1038388} |
- { name: Weavers Crescent,stop_code: Wjz1xRC, lat: -35.4544199, lng: 149.1154761} | - { name: Weavers Crescent,stop_code: Wjz1xRC, lat: -35.4544199, lng: 149.1154761} |
- { name: Kiddle Crescent,stop_code: Wjz1CdY, lat: -35.4270927, lng: 149.1090734} | - { name: Kiddle Crescent,stop_code: Wjz1CdY, lat: -35.4270927, lng: 149.1090734} |
- { name: Fairley Crescent,stop_code: Wjz1G89, lat: -35.4527651, lng: 149.1190457} | - { name: Fairley Crescent,stop_code: Wjz1G89, lat: -35.4527651, lng: 149.1190457} |
- { name: Fairley Crescent,stop_code: Wjz1F5W, lat: -35.4547272, lng: 149.1186974} | - { name: Fairley Crescent,stop_code: Wjz1F5W, lat: -35.4547272, lng: 149.1186974} |
- { name: Muscio Place,stop_code: Wjz2EdX, lat: -35.416214, lng: 149.120065} | - { name: Muscio Place,stop_code: Wjz2EdX, lat: -35.416214, lng: 149.120065} |
- { name: Clift Crescent,stop_code: Wjz1CRl, lat: -35.4269745, lng: 149.1151677} | - { name: Clift Crescent,stop_code: Wjz1CRl, lat: -35.4269745, lng: 149.1151677} |
- { name: Southern Close,stop_code: Wjz1K49, lat: -35.428009, lng: 149.1176708} | - { name: Southern Close,stop_code: Wjz1K49, lat: -35.428009, lng: 149.1176708} |
- { name: Clift Crescent,stop_code: Wjz1J4T, lat: -35.4330044, lng: 149.1185777} | - { name: Clift Crescent,stop_code: Wjz1J4T, lat: -35.4330044, lng: 149.1185777} |
- { name: Prichard Circuit,stop_code: Wjz1K89, lat: -35.4308171, lng: 149.1191218} | - { name: Prichard Circuit,stop_code: Wjz1K89, lat: -35.4308171, lng: 149.1191218} |
- { name: Twamley Crescent,stop_code: Wjz1JD7, lat: -35.4309354, lng: 149.1230759} | - { name: Twamley Crescent,stop_code: Wjz1JD7, lat: -35.4309354, lng: 149.1230759} |
- { name: Monaro Highway,stop_code: Wjz1JTP, lat: -35.4312901, lng: 149.126776} | - { name: Monaro Highway,stop_code: Wjz1JTP, lat: -35.4312901, lng: 149.126776} |
- { name: Deamer Crescent,stop_code: Wjz1S5I, lat: -35.4271223, lng: 149.1292791} | - { name: Deamer Crescent,stop_code: Wjz1S5I, lat: -35.4271223, lng: 149.1292791} |
- { name: Monaro Highway,stop_code: Wjz1SfM, lat: -35.4260286, lng: 149.1309478} | - { name: Monaro Highway,stop_code: Wjz1SfM, lat: -35.4260286, lng: 149.1309478} |
- { name: Henry Melville Crescent,stop_code: Wjz1TLL, lat: -35.4199685, lng: 149.1361715} | - { name: Henry Melville Crescent,stop_code: Wjz1TLL, lat: -35.4199685, lng: 149.1361715} |
- { name: Muntz Street,stop_code: Wjz1Lxu, lat: -35.4241367, lng: 149.1234749} | - { name: Muntz Street,stop_code: Wjz1Lxu, lat: -35.4241367, lng: 149.1234749} |
- { name: Mofflin Street,stop_code: Wjz1Liw, lat: -35.4239889, lng: 149.1208993} | - { name: Mofflin Street,stop_code: Wjz1Liw, lat: -35.4239889, lng: 149.1208993} |
- { name: Tuck Place,stop_code: Wjz1DLm, lat: -35.4200572, lng: 149.1136804} | - { name: Tuck Place,stop_code: Wjz1DLm, lat: -35.4200572, lng: 149.1136804} |
- { name: Proctor Street,stop_code: Wjz2M5R, lat: -35.4160071, lng: 149.129533} | - { name: Proctor Street,stop_code: Wjz2M5R, lat: -35.4160071, lng: 149.129533} |
- { name: Hynes Place,stop_code: Wjz2wY-, lat: -35.4166279, lng: 149.1173443} | - { name: Hynes Place,stop_code: Wjz2wY-, lat: -35.4166279, lng: 149.1173443} |
- { name: Sweet Place,stop_code: Wjz2EL2, lat: -35.4149132, lng: 149.1244544} | - { name: Sweet Place,stop_code: Wjz2EL2, lat: -35.4149132, lng: 149.1244544} |
- { name: Schoales Place,stop_code: WjrXZiM, lat: -35.3470777, lng: 149.0553331} | - { name: Schoales Place,stop_code: WjrXZiM, lat: -35.3470777, lng: 149.0553331} |
- { name: Logue Place,stop_code: WjrXRW0, lat: -35.3471147, lng: 149.0502999} | - { name: Logue Place,stop_code: WjrXRW0, lat: -35.3471147, lng: 149.0502999} |
- { name: Finlayson Place,stop_code: Wjz2NPZ, lat: -35.4118681, lng: 149.1378765} | - { name: Finlayson Place,stop_code: Wjz2NPZ, lat: -35.4118681, lng: 149.1378765} |
- { name: Namatjira Drive,stop_code: WjrXZz3, lat: -35.3461161, lng: 149.0570563} | - { name: Namatjira Drive,stop_code: WjrXZz3, lat: -35.3461161, lng: 149.0570563} |
- { name: Wark Street,stop_code: Wjz3nLq, lat: -35.3325054, lng: 149.0919265} | - { name: Wark Street,stop_code: Wjz3nLq, lat: -35.3325054, lng: 149.0919265} |
- { name: McCulloch Street,stop_code: Wjz49Y5, lat: -35.3233291, lng: 149.0831296} | - { name: McCulloch Street,stop_code: Wjz49Y5, lat: -35.3233291, lng: 149.0831296} |
- { name: Novar Street,stop_code: Wjz4shf, lat: -35.3086912, lng: 149.0984092} | - { name: Novar Street,stop_code: Wjz4shf, lat: -35.3086912, lng: 149.0984092} |
- { name: Novar Street,stop_code: Wjz4rk2, lat: -35.3126013, lng: 149.0982349} | - { name: Novar Street,stop_code: Wjz4rk2, lat: -35.3126013, lng: 149.0982349} |
- { name: Denison Street,stop_code: Wjz4hPC, lat: -35.323921, lng: 149.0935136} | - { name: Denison Street,stop_code: Wjz4hPC, lat: -35.323921, lng: 149.0935136} |
- { name: Jensen Street,stop_code: Wjz4gou, lat: -35.3314972, lng: 149.0892541} | - { name: Jensen Street,stop_code: Wjz4gou, lat: -35.3314972, lng: 149.0892541} |
- { name: Denison Street,stop_code: Wjz4hMe, lat: -35.3259558, lng: 149.0929241} | - { name: Denison Street,stop_code: Wjz4hMe, lat: -35.3259558, lng: 149.0929241} |
- { name: Yarra Glen,stop_code: Wjz4gt5, lat: -35.3281248, lng: 149.0887511} | - { name: Yarra Glen,stop_code: Wjz4gt5, lat: -35.3281248, lng: 149.0887511} |
- { name: Carruthers Street,stop_code: Wjz49Wd, lat: -35.324698, lng: 149.0833563} | - { name: Carruthers Street,stop_code: Wjz49Wd, lat: -35.324698, lng: 149.0833563} |
- { name: Shiels Place,stop_code: Wjz4arc, lat: -35.3185933, lng: 149.0779149} | - { name: Shiels Place,stop_code: Wjz4arc, lat: -35.3185933, lng: 149.0779149} |
- { name: Heysen Street,stop_code: WjrYUG8, lat: -35.3306155, lng: 149.058622} | - { name: Heysen Street,stop_code: WjrYUG8, lat: -35.3306155, lng: 149.058622} |
- { name: Dunstan Street,stop_code: Wjz4aH6, lat: -35.3184453, lng: 149.0804542} | - { name: Dunstan Street,stop_code: Wjz4aH6, lat: -35.3184453, lng: 149.0804542} |
- { name: Mair Place,stop_code: Wjz48dZ, lat: -35.3281016, lng: 149.0761465} | - { name: Mair Place,stop_code: Wjz48dZ, lat: -35.3281016, lng: 149.0761465} |
- { name: Jennings Street,stop_code: Wjz499S, lat: -35.3252899, lng: 149.0759651} | - { name: Jennings Street,stop_code: Wjz499S, lat: -35.3252899, lng: 149.0759651} |
- { name: O'Loghlen Street,stop_code: Wjr-IMR, lat: -35.2216889, lng: 149.0389433} | - { name: O'Loghlen Street,stop_code: Wjr-IMR, lat: -35.2216889, lng: 149.0389433} |
- { name: Carruthers Street,stop_code: Wjz48qI, lat: -35.3302472, lng: 149.0785498} | - { name: Carruthers Street,stop_code: Wjz48qI, lat: -35.3302472, lng: 149.0785498} |
- { name: Heysen Street,stop_code: WjrYUj0, lat: -35.3299526, lng: 149.0543559} | - { name: Heysen Street,stop_code: WjrYUj0, lat: -35.3299526, lng: 149.0543559} |
- { name: Heysen Street,stop_code: Wjz37Lm, lat: -35.3321544, lng: 149.0697369} | - { name: Heysen Street,stop_code: Wjz37Lm, lat: -35.3321544, lng: 149.0697369} |
- { name: Burnie Street,stop_code: Wjz3d3K, lat: -35.3459087, lng: 149.0743512} | - { name: Burnie Street,stop_code: Wjz3d3K, lat: -35.3459087, lng: 149.0743512} |
- { name: Derwent Street,stop_code: Wjz3ee-, lat: -35.3383098, lng: 149.0761505} | - { name: Derwent Street,stop_code: Wjz3ee-, lat: -35.3383098, lng: 149.0761505} |
- { name: Anne Place,stop_code: Wjz3fa8, lat: -35.3360845, lng: 149.0750477} | - { name: Anne Place,stop_code: Wjz3fa8, lat: -35.3360845, lng: 149.0750477} |
- { name: McInnes Street,stop_code: WjrX-Lw, lat: -35.3381915, lng: 149.0592024} | - { name: McInnes Street,stop_code: WjrX-Lw, lat: -35.3381915, lng: 149.0592024} |
- { name: Lycett Street,stop_code: WjrX_xY, lat: -35.3364869, lng: 149.0583028} | - { name: Lycett Street,stop_code: WjrX_xY, lat: -35.3364869, lng: 149.0583028} |
- { name: Meldrum Street,stop_code: WjrX_iU, lat: -35.3361318, lng: 149.0556038} | - { name: Meldrum Street,stop_code: WjrX_iU, lat: -35.3361318, lng: 149.0556038} |
- { name: Namatjira Drive,stop_code: WjrX-m2, lat: -35.3386886, lng: 149.0543559} | - { name: Namatjira Drive,stop_code: WjrX-m2, lat: -35.3386886, lng: 149.0543559} |
- { name: Mather Street,stop_code: WjrX-sE, lat: -35.3402511, lng: 149.0565615} | - { name: Mather Street,stop_code: WjrX-sE, lat: -35.3402511, lng: 149.0565615} |
- { name: Buvelot Street,stop_code: Wjz354b, lat: -35.345459, lng: 149.062772} | - { name: Buvelot Street,stop_code: Wjz354b, lat: -35.345459, lng: 149.062772} |
- { name: Gask Place,stop_code: Wjz1et6, lat: -35.4269117, lng: 149.0777759} | - { name: Gask Place,stop_code: Wjz1et6, lat: -35.4269117, lng: 149.0777759} |
- { name: Drumston Street,stop_code: Wjz1nxQ, lat: -35.4243695, lng: 149.0911255} | - { name: Drumston Street,stop_code: Wjz1nxQ, lat: -35.4243695, lng: 149.0911255} |
- { name: Athllon Drive,stop_code: Wjz1f8Y, lat: -35.4250198, lng: 149.076216} | - { name: Athllon Drive,stop_code: Wjz1f8Y, lat: -35.4250198, lng: 149.076216} |
- { name: Anketell Street,stop_code: Wjz1f2H, lat: -35.4237487, lng: 149.0744748} | - { name: Anketell Street,stop_code: Wjz1f2H, lat: -35.4237487, lng: 149.0744748} |
- { name: Lake Tuggeranong cycle track,stop_code: Wjz1f7q, lat: -35.4203787, lng: 149.0740032} | - { name: Lake Tuggeranong cycle track,stop_code: Wjz1f7q, lat: -35.4203787, lng: 149.0740032} |
- { name: Forlonge Street,stop_code: Wjz2bHS, lat: -35.400824, lng: 149.0814035} | - { name: Forlonge Street,stop_code: Wjz2bHS, lat: -35.400824, lng: 149.0814035} |
- { name: Derham Court,stop_code: Wjz2aLs, lat: -35.4037395, lng: 149.081019} | - { name: Derham Court,stop_code: Wjz2aLs, lat: -35.4037395, lng: 149.081019} |
- { name: Mortimer Lewis Drive,stop_code: Wjz2a26, lat: -35.4069683, lng: 149.0736259} | - { name: Mortimer Lewis Drive,stop_code: Wjz2a26, lat: -35.4069683, lng: 149.0736259} |
- { name: Nunan Crescent,stop_code: Wjz29Ya, lat: -35.4114741, lng: 149.0833189} | - { name: Nunan Crescent,stop_code: Wjz29Ya, lat: -35.4114741, lng: 149.0833189} |
- { name: William Webb Drive,stop_code: Wjz6e8G, lat: -35.2110071, lng: 149.0758577} | - { name: William Webb Drive,stop_code: Wjz6e8G, lat: -35.2110071, lng: 149.0758577} |
- { name: Evelyn Owen Crescent,stop_code: Wjr_w0L, lat: -35.1995769, lng: 149.0194714} | - { name: Evelyn Owen Crescent,stop_code: Wjr_w0L, lat: -35.1995769, lng: 149.0194714} |
- { name: Cusack Place,stop_code: Wjr_Ow3, lat: -35.1889085, lng: 149.0461463} | - { name: Cusack Place,stop_code: Wjr_Ow3, lat: -35.1889085, lng: 149.0461463} |
- { name: Binns Street,stop_code: Wjr_GGq, lat: -35.1875953, lng: 149.0370811} | - { name: Binns Street,stop_code: Wjr_GGq, lat: -35.1875953, lng: 149.0370811} |
- { name: Clubbe Crescent,stop_code: Wjr-uUb, lat: -35.2108896, lng: 149.0174054} | - { name: Clubbe Crescent,stop_code: Wjr-uUb, lat: -35.2108896, lng: 149.0174054} |
- { name: Southern Cross Drive,stop_code: Wjr-s5D, lat: -35.2180783, lng: 149.0083939} | - { name: Southern Cross Drive,stop_code: Wjr-s5D, lat: -35.2180783, lng: 149.0083939} |
- { name: Higgins Place,stop_code: Wjr-yOB, lat: -35.2313222, lng: 149.0276235} | - { name: Higgins Place,stop_code: Wjr-yOB, lat: -35.2313222, lng: 149.0276235} |
- { name: Southern Cross Drive,stop_code: Wjr-Hoi, lat: -35.2274077, lng: 149.0341216} | - { name: Southern Cross Drive,stop_code: Wjr-Hoi, lat: -35.2274077, lng: 149.0341216} |
- { name: Wollongong Street,stop_code: WjzcgD0, lat: -35.3271927, lng: 149.1779495} | - { name: Wollongong Street,stop_code: WjzcgD0, lat: -35.3271927, lng: 149.1779495} |
- { name: Taubman Street,stop_code: Wjzbfpl, lat: -35.3363832, lng: 149.1658515} | - { name: Taubman Street,stop_code: Wjzbfpl, lat: -35.3363832, lng: 149.1658515} |
- { name: Wiluna Street,stop_code: Wjzc8l0, lat: -35.3285713, lng: 149.1642018} | - { name: Wiluna Street,stop_code: Wjzc8l0, lat: -35.3285713, lng: 149.1642018} |
- { name: Whyalla Street,stop_code: Wjzbnmb, lat: -35.3331064, lng: 149.1753196} | - { name: Whyalla Street,stop_code: Wjzbnmb, lat: -35.3331064, lng: 149.1753196} |
- { name: Allen Street,stop_code: Wjz3_3L, lat: -35.3347817, lng: 149.1404124} | - { name: Allen Street,stop_code: Wjz3_3L, lat: -35.3347817, lng: 149.1404124} |
- { name: Goyder Street,stop_code: Wjz3-aW, lat: -35.3414521, lng: 149.1420263} | - { name: Goyder Street,stop_code: Wjz3-aW, lat: -35.3414521, lng: 149.1420263} |
- { name: Alfred Place,stop_code: Wjza_-f, lat: -35.3767042, lng: 149.237157} | - { name: Alfred Place,stop_code: Wjza_-f, lat: -35.3767042, lng: 149.237157} |
- { name: Farrer Place,stop_code: WjzbXms, lat: -35.3550134, lng: 149.2306199} | - { name: Farrer Place,stop_code: WjzbXms, lat: -35.3550134, lng: 149.2306199} |
- { name: Bazley Street,stop_code: Wjr_Vbj, lat: -35.1923583, lng: 149.0533723} | - { name: Bazley Street,stop_code: Wjr_Vbj, lat: -35.1923583, lng: 149.0533723} |
- { name: Tuggeranong Parkway,stop_code: Wjz33GY, lat: -35.3577485, lng: 149.0706526} | - { name: Tuggeranong Parkway,stop_code: Wjz33GY, lat: -35.3577485, lng: 149.0706526} |
- { name: Kalgoorlie Crescent,stop_code: WjrXXFn, lat: -35.3581997, lng: 149.0587995} | - { name: Kalgoorlie Crescent,stop_code: WjrXXFn, lat: -35.3581997, lng: 149.0587995} |
- { name: Jarrahdale Street,stop_code: WjrXWQ8, lat: -35.3621767, lng: 149.0600261} | - { name: Jarrahdale Street,stop_code: WjrXWQ8, lat: -35.3621767, lng: 149.0600261} |
- { name: Kapunda Street,stop_code: WjrXW7A, lat: -35.3597972, lng: 149.0523061} | - { name: Kapunda Street,stop_code: WjrXW7A, lat: -35.3597972, lng: 149.0523061} |
- { name: Nannine Place,stop_code: WjrXXq3, lat: -35.3578077, lng: 149.0557251} | - { name: Nannine Place,stop_code: WjrXXq3, lat: -35.3578077, lng: 149.0557251} |
- { name: Greenvale Street,stop_code: WjrXXd0, lat: -35.3559956, lng: 149.0529772} | - { name: Greenvale Street,stop_code: WjrXXd0, lat: -35.3559956, lng: 149.0529772} |
- { name: Hindmarsh Drive,stop_code: Wjz35av, lat: -35.3464684, lng: 149.064395} | - { name: Hindmarsh Drive,stop_code: Wjz35av, lat: -35.3464684, lng: 149.064395} |
- { name: Bangalay Crescent,stop_code: WjrXIDX, lat: -35.348916, lng: 149.0363428} | - { name: Bangalay Crescent,stop_code: WjrXIDX, lat: -35.348916, lng: 149.0363428} |
- { name: Buvelot Street,stop_code: WjrX-FV, lat: -35.3422149, lng: 149.0596338} | - { name: Buvelot Street,stop_code: WjrX-FV, lat: -35.3422149, lng: 149.0596338} |
- { name: Chevalier Street,stop_code: Wjz356k, lat: -35.3440169, lng: 149.0629513} | - { name: Chevalier Street,stop_code: Wjz356k, lat: -35.3440169, lng: 149.0629513} |
- { name: Larakia Street,stop_code: Wjz358l, lat: -35.3480588, lng: 149.0643043} | - { name: Larakia Street,stop_code: Wjz358l, lat: -35.3480588, lng: 149.0643043} |
- { name: Tiwi Place,stop_code: Wjz348u, lat: -35.3534586, lng: 149.0644857} | - { name: Tiwi Place,stop_code: Wjz348u, lat: -35.3534586, lng: 149.0644857} |
- { name: Bidia Place,stop_code: Wjz337w, lat: -35.354642, lng: 149.0633068} | - { name: Bidia Place,stop_code: Wjz337w, lat: -35.354642, lng: 149.0633068} |
- { name: Dalabon Crescent,stop_code: WjrXXK9, lat: -35.355219, lng: 149.0585637} | - { name: Dalabon Crescent,stop_code: WjrXXK9, lat: -35.355219, lng: 149.0585637} |
- { name: Kalgoorlie Crescent,stop_code: WjrXXyQ, lat: -35.3576967, lng: 149.0580467} | - { name: Kalgoorlie Crescent,stop_code: WjrXXyQ, lat: -35.3576967, lng: 149.0580467} |
- { name: Tristania Street,stop_code: WjrXRks, lat: -35.3453958, lng: 149.0438991} | - { name: Tristania Street,stop_code: WjrXRks, lat: -35.3453958, lng: 149.0438991} |
- { name: Damala Street,stop_code: WjrXYL4, lat: -35.3488355, lng: 149.0584095} | - { name: Damala Street,stop_code: WjrXYL4, lat: -35.3488355, lng: 149.0584095} |
- { name: Somerset Street,stop_code: WjrXLaD, lat: -35.3355436, lng: 149.0316183} | - { name: Somerset Street,stop_code: WjrXLaD, lat: -35.3355436, lng: 149.0316183} |
- { name: Frayne Place,stop_code: WjrXQZX, lat: -35.3502779, lng: 149.0514717} | - { name: Frayne Place,stop_code: WjrXQZX, lat: -35.3502779, lng: 149.0514717} |
- { name: Dixon Drive,stop_code: WjrXTgl, lat: -35.3370298, lng: 149.0436997} | - { name: Dixon Drive,stop_code: WjrXTgl, lat: -35.3370298, lng: 149.0436997} |
- { name: Hyndes Crescent,stop_code: WjrXTqY, lat: -35.3357893, lng: 149.0460156} | - { name: Hyndes Crescent,stop_code: WjrXTqY, lat: -35.3357893, lng: 149.0460156} |
- { name: Nelumbo Street,stop_code: WjrXQ65, lat: -35.349419, lng: 149.040696} | - { name: Nelumbo Street,stop_code: WjrXQ65, lat: -35.349419, lng: 149.040696} |
- { name: Hindmarsh Drive,stop_code: WjrXKoe, lat: -35.3424911, lng: 149.0339533} | - { name: Hindmarsh Drive,stop_code: WjrXKoe, lat: -35.3424911, lng: 149.0339533} |
- { name: Burrinjuck Crescent,stop_code: WjrXLR-, lat: -35.3335487, lng: 149.0390846} | - { name: Burrinjuck Crescent,stop_code: WjrXLR-, lat: -35.3335487, lng: 149.0390846} |
- { name: Warragamba Avenue,stop_code: WjrYEpn, lat: -35.3306598, lng: 149.0341649} | - { name: Warragamba Avenue,stop_code: WjrYEpn, lat: -35.3306598, lng: 149.0341649} |
- { name: Tantangara Street,stop_code: WjrXKBE, lat: -35.3395611, lng: 149.0360582} | - { name: Tantangara Street,stop_code: WjrXKBE, lat: -35.3395611, lng: 149.0360582} |
- { name: Counsel Street,stop_code: WjrYMbF, lat: -35.3298385, lng: 149.0428712} | - { name: Counsel Street,stop_code: WjrYMbF, lat: -35.3298385, lng: 149.0428712} |
- { name: Hyndes Crescent,stop_code: WjrYMrj, lat: -35.3296313, lng: 149.0450622} | - { name: Hyndes Crescent,stop_code: WjrYMrj, lat: -35.3296313, lng: 149.0450622} |
- { name: Mulley Street,stop_code: WjrYMHm, lat: -35.3294538, lng: 149.0477466} | - { name: Mulley Street,stop_code: WjrYMHm, lat: -35.3294538, lng: 149.0477466} |
- { name: Mulley Street,stop_code: WjrYMGB, lat: -35.3301626, lng: 149.0481758} | - { name: Mulley Street,stop_code: WjrYMGB, lat: -35.3301626, lng: 149.0481758} |
- { name: Dixon Drive,stop_code: WjrXTSe, lat: -35.3328347, lng: 149.0489873} | - { name: Dixon Drive,stop_code: WjrXTSe, lat: -35.3328347, lng: 149.0489873} |
- { name: Calder Crescent,stop_code: WjrXTIp, lat: -35.3346742, lng: 149.0480789} | - { name: Calder Crescent,stop_code: WjrXTIp, lat: -35.3346742, lng: 149.0480789} |
- { name: Woodger Place,stop_code: Wjr_V2c, lat: -35.192985, lng: 149.0517177} | - { name: Woodger Place,stop_code: Wjr_V2c, lat: -35.192985, lng: 149.0517177} |
- { name: Watt Place,stop_code: Wjz2ve3, lat: -35.3770117, lng: 149.0968721} | - { name: Watt Place,stop_code: Wjz2ve3, lat: -35.3770117, lng: 149.0968721} |
- { name: Pearce Avenue,stop_code: WjzcBHZ, lat: -35.3020154, lng: 149.2024041} | - { name: Pearce Avenue,stop_code: WjzcBHZ, lat: -35.3020154, lng: 149.2024041} |
- { name: Duffy Place,stop_code: WjrXLgs, lat: -35.3371612, lng: 149.0328459} | - { name: Duffy Place,stop_code: WjrXLgs, lat: -35.3371612, lng: 149.0328459} |
- { name: Renmark Street,stop_code: WjrXKfG, lat: -35.338018, lng: 149.0318393} | - { name: Renmark Street,stop_code: WjrXKfG, lat: -35.338018, lng: 149.0318393} |
- { name: Anstey Street,stop_code: Wjz3aaB, lat: -35.3631322, lng: 149.0756066} | - { name: Anstey Street,stop_code: Wjz3aaB, lat: -35.3631322, lng: 149.0756066} |
- { name: Lhotsky Street,stop_code: Wjr-L1H, lat: -35.2046871, lng: 149.0304447} | - { name: Lhotsky Street,stop_code: Wjr-L1H, lat: -35.2046871, lng: 149.0304447} |
- { name: McCay Place,stop_code: Wjz39PE, lat: -35.3683683, lng: 149.0827167} | - { name: McCay Place,stop_code: Wjz39PE, lat: -35.3683683, lng: 149.0827167} |
- { name: Hodgson Crescent,stop_code: Wjz3h5c, lat: -35.3666525, lng: 149.0847118} | - { name: Hodgson Crescent,stop_code: Wjz3h5c, lat: -35.3666525, lng: 149.0847118} |
- { name: Collings Street,stop_code: Wjz3j2F, lat: -35.3580142, lng: 149.0853648} | - { name: Collings Street,stop_code: Wjz3j2F, lat: -35.3580142, lng: 149.0853648} |
- { name: Marr Street,stop_code: Wjz3it1, lat: -35.3614164, lng: 149.0886297} | - { name: Marr Street,stop_code: Wjz3it1, lat: -35.3614164, lng: 149.0886297} |
- { name: Pialligo Avenue,stop_code: Wjzcrp_, lat: -35.3142011, lng: 149.1887666} | - { name: Pialligo Avenue,stop_code: Wjzcrp_, lat: -35.3142011, lng: 149.1887666} |
- { name: Brindabella Circuit,stop_code: WjzcrK3, lat: -35.3111478, lng: 149.190364} | - { name: Brindabella Circuit,stop_code: WjzcrK3, lat: -35.3111478, lng: 149.190364} |
- { name: Dakota Drive,stop_code: Wjzcuw1, lat: -35.2989793, lng: 149.188937} | - { name: Dakota Drive,stop_code: Wjzcuw1, lat: -35.2989793, lng: 149.188937} |
- { name: Fairbairn Avenue,stop_code: WjzcJ0K, lat: -35.3040486, lng: 149.2062653} | - { name: Fairbairn Avenue,stop_code: WjzcJ0K, lat: -35.3040486, lng: 149.2062653} |
- { name: Anthony Rolfe Avenue,stop_code: Wjzf3oM, lat: -35.1836894, lng: 149.1556666} | - { name: Anthony Rolfe Avenue,stop_code: Wjzf3oM, lat: -35.1836894, lng: 149.1556666} |
- { name: Binns Street,stop_code: Wjr_Gxf, lat: -35.1878657, lng: 149.0352296} | - { name: Binns Street,stop_code: Wjr_Gxf, lat: -35.1878657, lng: 149.0352296} |
- { name: Lhotsky Street,stop_code: Wjr_Es4, lat: -35.1970405, lng: 149.0338265} | - { name: Lhotsky Street,stop_code: Wjr_Es4, lat: -35.1970405, lng: 149.0338265} |
- { name: Rogers Street,stop_code: Wjr_FTN, lat: -35.1897508, lng: 149.038952} | - { name: Rogers Street,stop_code: Wjr_FTN, lat: -35.1897508, lng: 149.038952} |
- { name: Kerrigan Street,stop_code: Wjr_xLL, lat: -35.1892698, lng: 149.0264062} | - { name: Kerrigan Street,stop_code: Wjr_xLL, lat: -35.1892698, lng: 149.0264062} |
- { name: Bandt Place,stop_code: Wjr_xnT, lat: -35.1892671, lng: 149.0223682} | - { name: Bandt Place,stop_code: Wjr_xnT, lat: -35.1892671, lng: 149.0223682} |
- { name: Filshie Close,stop_code: Wjr_FXR, lat: -35.1922038, lng: 149.0402464} | - { name: Filshie Close,stop_code: Wjr_FXR, lat: -35.1922038, lng: 149.0402464} |
- { name: Donnison Place,stop_code: Wjr_E1y, lat: -35.1992571, lng: 149.0303603} | - { name: Donnison Place,stop_code: Wjr_E1y, lat: -35.1992571, lng: 149.0303603} |
- { name: Edlington Street,stop_code: Wjr_NDY, lat: -35.1895167, lng: 149.04724} | - { name: Edlington Street,stop_code: Wjr_NDY, lat: -35.1895167, lng: 149.04724} |
- { name: Nish Place,stop_code: Wjr_Vt9, lat: -35.191134, lng: 149.055871} | - { name: Nish Place,stop_code: Wjr_Vt9, lat: -35.191134, lng: 149.055871} |
- { name: Shrivell Circuit,stop_code: Wjr_wm3, lat: -35.195762, lng: 149.0214528} | - { name: Shrivell Circuit,stop_code: Wjr_wm3, lat: -35.195762, lng: 149.0214528} |
- { name: O'Reilly Street,stop_code: Wjr-thp, lat: -35.2158247, lng: 149.0109263} | - { name: O'Reilly Street,stop_code: Wjr-thp, lat: -35.2158247, lng: 149.0109263} |
- { name: Eddison Place,stop_code: Wjr_NFt, lat: -35.1935465, lng: 149.0479464} | - { name: Eddison Place,stop_code: Wjr_NFt, lat: -35.1935465, lng: 149.0479464} |
- { name: Garrad Court,stop_code: Wjr_MjV, lat: -35.1979805, lng: 149.0445264} | - { name: Garrad Court,stop_code: Wjr_MjV, lat: -35.1979805, lng: 149.0445264} |
- { name: Covington Crescent,stop_code: Wjr-Tf_, lat: -35.2002734, lng: 149.0432168} | - { name: Covington Crescent,stop_code: Wjr-Tf_, lat: -35.2002734, lng: 149.0432168} |
- { name: Moyes Crescent,stop_code: Wjr-zOn, lat: -35.2256125, lng: 149.0272189} | - { name: Moyes Crescent,stop_code: Wjr-zOn, lat: -35.2256125, lng: 149.0272189} |
- { name: Noakes Court,stop_code: Wjr-Lzm, lat: -35.2030997, lng: 149.0354829} | - { name: Noakes Court,stop_code: Wjr-Lzm, lat: -35.2030997, lng: 149.0354829} |
- { name: Hirschfeld Crescent,stop_code: Wjr-tbm, lat: -35.2140927, lng: 149.0093105} | - { name: Hirschfeld Crescent,stop_code: Wjr-tbm, lat: -35.2140927, lng: 149.0093105} |
- { name: Florey Drive,stop_code: Wjr-DNK, lat: -35.2044788, lng: 149.0277602} | - { name: Florey Drive,stop_code: Wjr-DNK, lat: -35.2044788, lng: 149.0277602} |
- { name: Lhotsky Street,stop_code: Wjr-DQE, lat: -35.2029293, lng: 149.0277662} | - { name: Lhotsky Street,stop_code: Wjr-DQE, lat: -35.2029293, lng: 149.0277662} |
- { name: Ginninderra Drive,stop_code: Wjr_oP1, lat: -35.1980445, lng: 149.0158736} | - { name: Ginninderra Drive,stop_code: Wjr_oP1, lat: -35.1980445, lng: 149.0158736} |
- { name: Krefft Street,stop_code: Wjr-Pk6, lat: -35.2243699, lng: 149.0432872} | - { name: Krefft Street,stop_code: Wjr-Pk6, lat: -35.2243699, lng: 149.0432872} |
- { name: Kerrigan Street,stop_code: Wjr_o_j, lat: -35.1950629, lng: 149.0175978} | - { name: Kerrigan Street,stop_code: Wjr_o_j, lat: -35.1950629, lng: 149.0175978} |
- { name: Lance Hill Avenue,stop_code: Wjr_wjn, lat: -35.1975263, lng: 149.0216638} | - { name: Lance Hill Avenue,stop_code: Wjr_wjn, lat: -35.1975263, lng: 149.0216638} |
- { name: Florey Drive,stop_code: Wjr-CS2, lat: -35.2068071, lng: 149.0268212} | - { name: Florey Drive,stop_code: Wjr-CS2, lat: -35.2068071, lng: 149.0268212} |
- { name: Kerrigan Street,stop_code: Wjr_oJA, lat: -35.1964177, lng: 149.0152805} | - { name: Kerrigan Street,stop_code: Wjr_oJA, lat: -35.1964177, lng: 149.0152805} |
- { name: Rossell Place,stop_code: Wjr-KJQ, lat: -35.2073355, lng: 149.037506} | - { name: Rossell Place,stop_code: Wjr-KJQ, lat: -35.2073355, lng: 149.037506} |
- { name: O'Reilly Street,stop_code: Wjr-smi, lat: -35.2178617, lng: 149.0106876} | - { name: O'Reilly Street,stop_code: Wjr-smi, lat: -35.2178617, lng: 149.0106876} |
- { name: Archdall Street,stop_code: Wjr-vJY, lat: -35.2019113, lng: 149.0157184} | - { name: Archdall Street,stop_code: Wjr-vJY, lat: -35.2019113, lng: 149.0157184} |
- { name: Cumpston Place,stop_code: Wjr-BL8, lat: -35.2118565, lng: 149.025622} | - { name: Cumpston Place,stop_code: Wjr-BL8, lat: -35.2118565, lng: 149.025622} |
- { name: Nulsen Circuit,stop_code: Wjr-S6B, lat: -35.2066123, lng: 149.0412991} | - { name: Nulsen Circuit,stop_code: Wjr-S6B, lat: -35.2066123, lng: 149.0412991} |
- { name: Tulloch Place,stop_code: Wjr-RnT, lat: -35.2112095, lng: 149.0444601} | - { name: Tulloch Place,stop_code: Wjr-RnT, lat: -35.2112095, lng: 149.0444601} |
- { name: Grigson Place,stop_code: Wjr-s_F, lat: -35.2172009, lng: 149.0180976} | - { name: Grigson Place,stop_code: Wjr-s_F, lat: -35.2172009, lng: 149.0180976} |
- { name: Hampton Gardens,stop_code: Wjr-rQJ, lat: -35.2244007, lng: 149.0167658} | - { name: Hampton Gardens,stop_code: Wjr-rQJ, lat: -35.2244007, lng: 149.0167658} |
- { name: Rentoul Place,stop_code: Wjr-Rs8, lat: -35.2139046, lng: 149.0449606} | - { name: Rentoul Place,stop_code: Wjr-Rs8, lat: -35.2139046, lng: 149.0449606} |
- { name: Krefft Street,stop_code: Wjr-Q8c, lat: -35.2217975, lng: 149.042121} | - { name: Krefft Street,stop_code: Wjr-Q8c, lat: -35.2217975, lng: 149.042121} |
- { name: Dalley Crescent,stop_code: Wjr-AHx, lat: -35.2199899, lng: 149.0262529} | - { name: Dalley Crescent,stop_code: Wjr-AHx, lat: -35.2199899, lng: 149.0262529} |
- { name: Southern Cross Drive,stop_code: Wjr-z_L, lat: -35.222191, lng: 149.0291286} | - { name: Southern Cross Drive,stop_code: Wjr-z_L, lat: -35.222191, lng: 149.0291286} |
- { name: Starke Street,stop_code: Wjr-sV3, lat: -35.2212162, lng: 149.0172455} | - { name: Starke Street,stop_code: Wjr-sV3, lat: -35.2212162, lng: 149.0172455} |
- { name: Drake Brockman Drive,stop_code: Wjr-qcc, lat: -35.230013, lng: 149.0092125} | - { name: Drake Brockman Drive,stop_code: Wjr-qcc, lat: -35.230013, lng: 149.0092125} |
- { name: Southern Cross Drive,stop_code: Wjr-st9, lat: -35.2186471, lng: 149.0119654} | - { name: Southern Cross Drive,stop_code: Wjr-st9, lat: -35.2186471, lng: 149.0119654} |
- { name: Messenger Street,stop_code: Wjr-jRn, lat: -35.2235756, lng: 149.0053113} | - { name: Messenger Street,stop_code: Wjr-jRn, lat: -35.2235756, lng: 149.0053113} |
- { name: Armstrong Crescent,stop_code: Wjr-syd, lat: -35.2203046, lng: 149.0133355} | - { name: Armstrong Crescent,stop_code: Wjr-syd, lat: -35.2203046, lng: 149.0133355} |
- { name: Holt Place,stop_code: Wjr-rjD, lat: -35.2249706, lng: 149.0111289} | - { name: Holt Place,stop_code: Wjr-rjD, lat: -35.2249706, lng: 149.0111289} |
- { name: Drake Brockman Drive,stop_code: Wjr-qyr, lat: -35.2315106, lng: 149.0137011} | - { name: Drake Brockman Drive,stop_code: Wjr-qyr, lat: -35.2315106, lng: 149.0137011} |
- { name: Ashburner Street,stop_code: Wjr-yrh, lat: -35.2309899, lng: 149.0230231} | - { name: Ashburner Street,stop_code: Wjr-yrh, lat: -35.2309899, lng: 149.0230231} |
- { name: Grout Place,stop_code: Wjr-jNB, lat: -35.2265208, lng: 149.0056756} | - { name: Grout Place,stop_code: Wjr-jNB, lat: -35.2265208, lng: 149.0056756} |
- { name: Starke Street,stop_code: Wjr-yni, lat: -35.2281496, lng: 149.0217011} | - { name: Starke Street,stop_code: Wjr-yni, lat: -35.2281496, lng: 149.0217011} |
- { name: Hardwick Crescent,stop_code: Wjr-zom, lat: -35.2270626, lng: 149.0231771} | - { name: Hardwick Crescent,stop_code: Wjr-zom, lat: -35.2270626, lng: 149.0231771} |
- { name: Davidson Street,stop_code: Wjr-ywh, lat: -35.2330631, lng: 149.0245222} | - { name: Davidson Street,stop_code: Wjr-ywh, lat: -35.2330631, lng: 149.0245222} |
- { name: Kriewaldt Circuit,stop_code: Wjr-yJZ, lat: -35.2292857, lng: 149.0266955} | - { name: Kriewaldt Circuit,stop_code: Wjr-yJZ, lat: -35.2292857, lng: 149.0266955} |
- { name: Kriewaldt Circuit,stop_code: Wjr-ySy, lat: -35.228821, lng: 149.0276438} | - { name: Kriewaldt Circuit,stop_code: Wjr-ySy, lat: -35.228821, lng: 149.0276438} |
- { name: Starke Street,stop_code: Wjr-zWb, lat: -35.2259772, lng: 149.0283569} | - { name: Starke Street,stop_code: Wjr-zWb, lat: -35.2259772, lng: 149.0283569} |
- { name: Chave Street,stop_code: Wjr-zC9, lat: -35.2234474, lng: 149.0242983} | - { name: Chave Street,stop_code: Wjr-zC9, lat: -35.2234474, lng: 149.0242983} |
- { name: Dethridge Street,stop_code: Wjr-GeX, lat: -35.2287693, lng: 149.0321955} | - { name: Dethridge Street,stop_code: Wjr-GeX, lat: -35.2287693, lng: 149.0321955} |
- { name: Davidson Street,stop_code: Wjr-xLK, lat: -35.2332476, lng: 149.0263679} | - { name: Davidson Street,stop_code: Wjr-xLK, lat: -35.2332476, lng: 149.0263679} |
- { name: Drake Brockman Drive,stop_code: Wjr-xxu, lat: -35.2373929, lng: 149.0246092} | - { name: Drake Brockman Drive,stop_code: Wjr-xxu, lat: -35.2373929, lng: 149.0246092} |
- { name: Tanumbirini Street,stop_code: Wjr-Ekp, lat: -35.2412759, lng: 149.032879} | - { name: Tanumbirini Street,stop_code: Wjr-Ekp, lat: -35.2412759, lng: 149.032879} |
- { name: Crawford Street,stop_code: WjzbYue, lat: -35.3493054, lng: 149.2316145} | - { name: Crawford Street,stop_code: WjzbYue, lat: -35.3493054, lng: 149.2316145} |
- { name: Antill Street,stop_code: WjzbYD0, lat: -35.3491814, lng: 149.232803} | - { name: Antill Street,stop_code: WjzbYD0, lat: -35.3491814, lng: 149.232803} |
- { name: Alinga Street,stop_code: Wjz5FSY, lat: -35.2780524, lng: 149.1269928} | - { name: Alinga Street,stop_code: Wjz5FSY, lat: -35.2780524, lng: 149.1269928} |
- { name: Uriarra Road,stop_code: WjzbRdA, lat: -35.3446934, lng: 149.2184308} | - { name: Uriarra Road,stop_code: WjzbRdA, lat: -35.3446934, lng: 149.2184308} |
- { name: Pound Street,stop_code: Wjzj5cC, lat: -35.3451754, lng: 149.2404108} | - { name: Pound Street,stop_code: Wjzj5cC, lat: -35.3451754, lng: 149.2404108} |
- { name: Uriarra Road,stop_code: WjzbRBx, lat: -35.3449879, lng: 149.2226535} | - { name: Uriarra Road,stop_code: WjzbRBx, lat: -35.3449879, lng: 149.2226535} |
- { name: Alinga Street,stop_code: Wjz5Neo, lat: -35.27843, lng: 149.130345} | - { name: Alinga Street,stop_code: Wjz5Neo, lat: -35.27843, lng: 149.130345} |
- { name: Redwood Avenue,stop_code: WjzaJ9a, lat: -35.391582, lng: 149.2069701} | - { name: Redwood Avenue,stop_code: WjzaJ9a, lat: -35.391582, lng: 149.2069701} |
- { name: Canberra Avenue,stop_code: WjzbPQW, lat: -35.3565184, lng: 149.2259167} | - { name: Canberra Avenue,stop_code: WjzbPQW, lat: -35.3565184, lng: 149.2259167} |
- { name: Kenneth Place,stop_code: WjzbVBj, lat: -35.3667378, lng: 149.233235} | - { name: Kenneth Place,stop_code: WjzbVBj, lat: -35.3667378, lng: 149.233235} |
- { name: Cooma Street,stop_code: WjzbVCw, lat: -35.3663608, lng: 149.2335824} | - { name: Cooma Street,stop_code: WjzbVCw, lat: -35.3663608, lng: 149.2335824} |
- { name: Gibbs Place,stop_code: Wjz9JIL, lat: -35.4330525, lng: 149.2131844} | - { name: Gibbs Place,stop_code: Wjz9JIL, lat: -35.4330525, lng: 149.2131844} |
- { name: Parkview Crescent,stop_code: WjzaK0g, lat: -35.3868815, lng: 149.2056751} | - { name: Parkview Crescent,stop_code: WjzaK0g, lat: -35.3868815, lng: 149.2056751} |
- { name: Dixon Place,stop_code: WjzaDIK, lat: -35.3781802, lng: 149.2021825} | - { name: Dixon Place,stop_code: WjzaDIK, lat: -35.3781802, lng: 149.2021825} |
- { name: Rutledge Street,stop_code: WjzbXBT, lat: -35.3553953, lng: 149.2338714} | - { name: Rutledge Street,stop_code: WjzbXBT, lat: -35.3553953, lng: 149.2338714} |
- { name: Brindabella Circuit,stop_code: WjzcrrQ, lat: -35.3131274, lng: 149.188611} | - { name: Brindabella Circuit,stop_code: WjzcrrQ, lat: -35.3131274, lng: 149.188611} |
- { name: Benjamin Way,stop_code: Wjz57tg, lat: -35.2461188, lng: 149.0669661} | - { name: Benjamin Way,stop_code: Wjz57tg, lat: -35.2461188, lng: 149.0669661} |
- { name: Greene Place,stop_code: Wjz57T_, lat: -35.2441569, lng: 149.0719751} | - { name: Greene Place,stop_code: Wjz57T_, lat: -35.2441569, lng: 149.0719751} |
- { name: Gatehouse Place,stop_code: Wjz5f2j, lat: -35.2479775, lng: 149.0739202} | - { name: Gatehouse Place,stop_code: Wjz5f2j, lat: -35.2479775, lng: 149.0739202} |
- { name: Crisp Circuit,stop_code: Wjz688N, lat: -35.2439868, lng: 149.0759082} | - { name: Crisp Circuit,stop_code: Wjz688N, lat: -35.2439868, lng: 149.0759082} |
- { name: Cobbett Place,stop_code: Wjz68g-, lat: -35.2436119, lng: 149.0775571} | - { name: Cobbett Place,stop_code: Wjz68g-, lat: -35.2436119, lng: 149.0775571} |
- { name: Braybrooke Street,stop_code: Wjz5vjd, lat: -35.2470998, lng: 149.0983861} | - { name: Braybrooke Street,stop_code: Wjz5vjd, lat: -35.2470998, lng: 149.0983861} |
- { name: Watkin Street,stop_code: Wjz5v68, lat: -35.2454993, lng: 149.0956677} | - { name: Watkin Street,stop_code: Wjz5v68, lat: -35.2454993, lng: 149.0956677} |
- { name: Dunlop Court,stop_code: Wjz6gQ0, lat: -35.2413491, lng: 149.0928379} | - { name: Dunlop Court,stop_code: Wjz6gQ0, lat: -35.2413491, lng: 149.0928379} |
- { name: Eardley Street,stop_code: Wjz6gJc, lat: -35.2402968, lng: 149.0916132} | - { name: Eardley Street,stop_code: Wjz6gJc, lat: -35.2402968, lng: 149.0916132} |
- { name: Leverrier Crescent,stop_code: Wjz6oEz, lat: -35.243821, lng: 149.1030282} | - { name: Leverrier Crescent,stop_code: Wjz6oEz, lat: -35.243821, lng: 149.1030282} |
- { name: Krantzcke Circuit,stop_code: Wjz7pfP, lat: -35.189616, lng: 149.0978803} | - { name: Krantzcke Circuit,stop_code: Wjz7pfP, lat: -35.189616, lng: 149.0978803} |
- { name: Temperley Street,stop_code: Wjz7p2n, lat: -35.1926501, lng: 149.0958323} | - { name: Temperley Street,stop_code: Wjz7p2n, lat: -35.1926501, lng: 149.0958323} |
- { name: Temperley Street,stop_code: Wjz7iV0, lat: -35.1885169, lng: 149.0941253} | - { name: Temperley Street,stop_code: Wjz7iV0, lat: -35.1885169, lng: 149.0941253} |
- { name: Temperley Street,stop_code: Wjz7iG_, lat: -35.1872252, lng: 149.0926713} | - { name: Temperley Street,stop_code: Wjz7iG_, lat: -35.1872252, lng: 149.0926713} |
- { name: Curran Drive,stop_code: Wjz7ilp, lat: -35.1856235, lng: 149.0877402} | - { name: Curran Drive,stop_code: Wjz7ilp, lat: -35.1856235, lng: 149.0877402} |
- { name: Ayers Fowler Street,stop_code: Wjz7i7r, lat: -35.1841251, lng: 149.0850218} | - { name: Ayers Fowler Street,stop_code: Wjz7i7r, lat: -35.1841251, lng: 149.0850218} |
- { name: McClelland Avenue,stop_code: Wjz7jsi, lat: -35.1807665, lng: 149.0890046} | - { name: McClelland Avenue,stop_code: Wjz7jsi, lat: -35.1807665, lng: 149.0890046} |
- { name: Whiteside Court,stop_code: Wjz7qfu, lat: -35.1838151, lng: 149.0974127} | - { name: Whiteside Court,stop_code: Wjz7qfu, lat: -35.1838151, lng: 149.0974127} |
- { name: Oldershaw Court,stop_code: Wjz7qvq, lat: -35.1841768, lng: 149.1001944} | - { name: Oldershaw Court,stop_code: Wjz7qvq, lat: -35.1841768, lng: 149.1001944} |
- { name: Ryder Place,stop_code: Wjz7qkM, lat: -35.1864502, lng: 149.0992461} | - { name: Ryder Place,stop_code: Wjz7qkM, lat: -35.1864502, lng: 149.0992461} |
- { name: Lexcen Avenue,stop_code: Wjz7qwq, lat: -35.1890336, lng: 149.101522} | - { name: Lexcen Avenue,stop_code: Wjz7qwq, lat: -35.1890336, lng: 149.101522} |
- { name: Anne Clark Avenue,stop_code: Wjz7rOj, lat: -35.1820066, lng: 149.104114} | - { name: Anne Clark Avenue,stop_code: Wjz7rOj, lat: -35.1820066, lng: 149.104114} |
- { name: Biddell Place,stop_code: Wjz7rMm, lat: -35.1831434, lng: 149.104114} | - { name: Biddell Place,stop_code: Wjz7rMm, lat: -35.1831434, lng: 149.104114} |
- { name: Lexcen Avenue,stop_code: Wjz7q-_, lat: -35.1844351, lng: 149.1063899} | - { name: Lexcen Avenue,stop_code: Wjz7q-_, lat: -35.1844351, lng: 149.1063899} |
- { name: Quist Place,stop_code: Wjz7yfG, lat: -35.1841768, lng: 149.108729} | - { name: Quist Place,stop_code: Wjz7yfG, lat: -35.1841768, lng: 149.108729} |
- { name: Kelleway Avenue,stop_code: Wjz7r-a, lat: -35.1793714, lng: 149.1053784} | - { name: Kelleway Avenue,stop_code: Wjz7r-a, lat: -35.1793714, lng: 149.1053784} |
- { name: Wanganeen Avenue,stop_code: Wjz7Add, lat: -35.1743073, lng: 149.10816} | - { name: Wanganeen Avenue,stop_code: Wjz7Add, lat: -35.1743073, lng: 149.10816} |
- { name: Bimbiang Crescent,stop_code: Wjz7tOr, lat: -35.1710517, lng: 149.1042404} | - { name: Bimbiang Crescent,stop_code: Wjz7tOr, lat: -35.1710517, lng: 149.1042404} |
- { name: Bargang Crescent,stop_code: Wjz7txI, lat: -35.1716718, lng: 149.1018381} | - { name: Bargang Crescent,stop_code: Wjz7txI, lat: -35.1716718, lng: 149.1018381} |
- { name: Horse Park Drive,stop_code: Wjz7tug, lat: -35.1685711, lng: 149.0999415} | - { name: Horse Park Drive,stop_code: Wjz7tug, lat: -35.1685711, lng: 149.0999415} |
- { name: Horse Park Drive,stop_code: Wjz7tvK, lat: -35.1673308, lng: 149.1005105} | - { name: Horse Park Drive,stop_code: Wjz7tvK, lat: -35.1673308, lng: 149.1005105} |
- { name: Warabin Crescent,stop_code: Wjz7tLG, lat: -35.1677443, lng: 149.1032921} | - { name: Warabin Crescent,stop_code: Wjz7tLG, lat: -35.1677443, lng: 149.1032921} |
- { name: Wanganeen Avenue,stop_code: Wjz7Bg7, lat: -35.1720853, lng: 149.109298} | - { name: Wanganeen Avenue,stop_code: Wjz7Bg7, lat: -35.1720853, lng: 149.109298} |
- { name: Bunburung Close,stop_code: Wjz7BqG, lat: -35.1711551, lng: 149.1115106} | - { name: Bunburung Close,stop_code: Wjz7BqG, lat: -35.1711551, lng: 149.1115106} |
- { name: Unaipon Avenue,stop_code: Wjz7BC3, lat: -35.1683127, lng: 149.1120164} | - { name: Unaipon Avenue,stop_code: Wjz7BC3, lat: -35.1683127, lng: 149.1120164} |
- { name: Gurubun Close,stop_code: Wjz7BJK, lat: -35.1687262, lng: 149.1142923} | - { name: Gurubun Close,stop_code: Wjz7BJK, lat: -35.1687262, lng: 149.1142923} |
- { name: Deumonga Court,stop_code: Wjz7BED, lat: -35.1720853, lng: 149.1141026} | - { name: Deumonga Court,stop_code: Wjz7BED, lat: -35.1720853, lng: 149.1141026} |
- { name: Mirrabei Drive,stop_code: Wjz7BWN, lat: -35.1712067, lng: 149.1171372} | - { name: Mirrabei Drive,stop_code: Wjz7BWN, lat: -35.1712067, lng: 149.1171372} |
- { name: Ferguson Circuit,stop_code: Wjz7AGv, lat: -35.1762193, lng: 149.113913} | - { name: Ferguson Circuit,stop_code: Wjz7AGv, lat: -35.1762193, lng: 149.113913} |
- { name: Taggerty Street,stop_code: Wjz7AEw, lat: -35.1781829, lng: 149.1141659} | - { name: Taggerty Street,stop_code: Wjz7AEw, lat: -35.1781829, lng: 149.1141659} |
- { name: Tipiloura Street,stop_code: Wjz7CqJ, lat: -35.1654186, lng: 149.1114474} | - { name: Tipiloura Street,stop_code: Wjz7CqJ, lat: -35.1654186, lng: 149.1114474} |
- { name: Windradyne Street,stop_code: Wjz7CA3, lat: -35.16423, lng: 149.1119532} | - { name: Windradyne Street,stop_code: Wjz7CA3, lat: -35.16423, lng: 149.1119532} |
- { name: Mirrabei Drive,stop_code: Wjz7CKg, lat: -35.1630413, lng: 149.1137233} | - { name: Mirrabei Drive,stop_code: Wjz7CKg, lat: -35.1630413, lng: 149.1137233} |
- { name: Naas Close,stop_code: Wjz7IDY, lat: -35.1730154, lng: 149.1242809} | - { name: Naas Close,stop_code: Wjz7IDY, lat: -35.1730154, lng: 149.1242809} |
- { name: Paul Coe Crescent,stop_code: Wjz7Ikc, lat: -35.1750825, lng: 149.1204878} | - { name: Paul Coe Crescent,stop_code: Wjz7Ikc, lat: -35.1750825, lng: 149.1204878} |
- { name: Milari Street,stop_code: Wjz7HfF, lat: -35.178803, lng: 149.1197924} | - { name: Milari Street,stop_code: Wjz7HfF, lat: -35.178803, lng: 149.1197924} |
- { name: Paul Coe Crescent,stop_code: Wjz7IoZ, lat: -35.1777695, lng: 149.1227637} | - { name: Paul Coe Crescent,stop_code: Wjz7IoZ, lat: -35.1777695, lng: 149.1227637} |
- { name: Shoalhaven Avenue,stop_code: Wjz7IuJ, lat: -35.1736356, lng: 149.1225108} | - { name: Shoalhaven Avenue,stop_code: Wjz7IuJ, lat: -35.1736356, lng: 149.1225108} |
- { name: Tyenna Close,stop_code: Wjz7JP1, lat: -35.1705349, lng: 149.1257982} | - { name: Tyenna Close,stop_code: Wjz7JP1, lat: -35.1705349, lng: 149.1257982} |
- { name: Katherine Avenue,stop_code: Wjz7R6d, lat: -35.1681577, lng: 149.1286431} | - { name: Katherine Avenue,stop_code: Wjz7R6d, lat: -35.1681577, lng: 149.1286431} |
- { name: Timboram Street,stop_code: Wjz7R5z, lat: -35.1690363, lng: 149.1291488} | - { name: Timboram Street,stop_code: Wjz7R5z, lat: -35.1690363, lng: 149.1291488} |
- { name: Carstairs Circuit,stop_code: Wjz7RHe, lat: -35.1700698, lng: 149.135534} | - { name: Carstairs Circuit,stop_code: Wjz7RHe, lat: -35.1700698, lng: 149.135534} |
- { name: Horse Park Drive,stop_code: Wjz7SN-, lat: -35.1660013, lng: 149.1378981} | - { name: Horse Park Drive,stop_code: Wjz7SN-, lat: -35.1660013, lng: 149.1378981} |
- { name: Boreham Lane,stop_code: Wjz7PIc, lat: -35.1805599, lng: 149.135534} | - { name: Boreham Lane,stop_code: Wjz7PIc, lat: -35.1805599, lng: 149.135534} |
- { name: Swain Street,stop_code: Wjz7Pjj, lat: -35.1813349, lng: 149.1316144} | - { name: Swain Street,stop_code: Wjz7Pjj, lat: -35.1813349, lng: 149.1316144} |
- { name: Gundaroo Drive,stop_code: Wjz7yNW, lat: -35.1883262, lng: 149.1159763} | - { name: Gundaroo Drive,stop_code: Wjz7yNW, lat: -35.1883262, lng: 149.1159763} |
- { name: Hibberson Street,stop_code: Wjz7OBc, lat: -35.1853732, lng: 149.1341431} | - { name: Hibberson Street,stop_code: Wjz7OBc, lat: -35.1853732, lng: 149.1341431} |
- { name: Sarre Street,stop_code: Wjz7PNV, lat: -35.1828992, lng: 149.1380246} | - { name: Sarre Street,stop_code: Wjz7PNV, lat: -35.1828992, lng: 149.1380246} |
- { name: Gundaroo Drive,stop_code: Wjz7X3O, lat: -35.1814007, lng: 149.1404901} | - { name: Gundaroo Drive,stop_code: Wjz7X3O, lat: -35.1814007, lng: 149.1404901} |
- { name: Tesselaar Street,stop_code: Wjz7Xiv, lat: -35.1817108, lng: 149.1427028} | - { name: Tesselaar Street,stop_code: Wjz7Xiv, lat: -35.1817108, lng: 149.1427028} |
- { name: Sarson Street,stop_code: Wjzf31y, lat: -35.1828475, lng: 149.151111} | - { name: Sarson Street,stop_code: Wjzf31y, lat: -35.1828475, lng: 149.151111} |
- { name: Kalianna Street,stop_code: Wjzf2hJ, lat: -35.1880144, lng: 149.154019} | - { name: Kalianna Street,stop_code: Wjzf2hJ, lat: -35.1880144, lng: 149.154019} |
- { name: Nimbera Street,stop_code: Wjzf1X3, lat: -35.1923543, lng: 149.1600249} | - { name: Nimbera Street,stop_code: Wjzf1X3, lat: -35.1923543, lng: 149.1600249} |
- { name: Mapleton Avenue,stop_code: Wjzf91m, lat: -35.1934909, lng: 149.1618582} | - { name: Mapleton Avenue,stop_code: Wjzf91m, lat: -35.1934909, lng: 149.1618582} |
- { name: Elabana Street,stop_code: Wjzf0EJ, lat: -35.1997419, lng: 149.1581283} | - { name: Elabana Street,stop_code: Wjzf0EJ, lat: -35.1997419, lng: 149.1581283} |
- { name: Cudgewa Lane,stop_code: Wjze7Cp, lat: -35.2014466, lng: 149.1565478} | - { name: Cudgewa Lane,stop_code: Wjze7Cp, lat: -35.2014466, lng: 149.1565478} |
- { name: Oodgeroo Avenue,stop_code: Wjz6_7M, lat: -35.2008784, lng: 149.1404901} | - { name: Oodgeroo Avenue,stop_code: Wjz6_7M, lat: -35.2008784, lng: 149.1404901} |
- { name: Hoskins Street,stop_code: Wjz6TZN, lat: -35.2021182, lng: 149.1392257} | - { name: Hoskins Street,stop_code: Wjz6TZN, lat: -35.2021182, lng: 149.1392257} |
- { name: The Valley Avenue,stop_code: Wjz7GPB, lat: -35.1867085, lng: 149.1264936} | - { name: The Valley Avenue,stop_code: Wjz7GPB, lat: -35.1867085, lng: 149.1264936} |
- { name: The Valley Avenue,stop_code: Wjz7Gxm, lat: -35.188002, lng: 149.1234035} | - { name: The Valley Avenue,stop_code: Wjz7Gxm, lat: -35.188002, lng: 149.1234035} |
- { name: Kosciuszko Avenue,stop_code: Wjz7F5C, lat: -35.1906966, lng: 149.118141} | - { name: Kosciuszko Avenue,stop_code: Wjz7F5C, lat: -35.1906966, lng: 149.118141} |
- { name: Burrowa Street,stop_code: Wjz7xJz, lat: -35.191011, lng: 149.1141277} | - { name: Burrowa Street,stop_code: Wjz7xJz, lat: -35.191011, lng: 149.1141277} |
- { name: Kosciuszko Avenue,stop_code: Wjz7wZg, lat: -35.1967555, lng: 149.1165529} | - { name: Kosciuszko Avenue,stop_code: Wjz7wZg, lat: -35.1967555, lng: 149.1165529} |
- { name: Kosciuszko Avenue,stop_code: Wjz7EjH, lat: -35.1978404, lng: 149.1211679} | - { name: Kosciuszko Avenue,stop_code: Wjz7EjH, lat: -35.1978404, lng: 149.1211679} |
- { name: Kosciuszko Avenue,stop_code: Wjz7Ezf, lat: -35.1975304, lng: 149.1231277} | - { name: Kosciuszko Avenue,stop_code: Wjz7Ezf, lat: -35.1975304, lng: 149.1231277} |
- { name: Everard Street,stop_code: Wjz7FNw, lat: -35.193955, lng: 149.126474} | - { name: Everard Street,stop_code: Wjz7FNw, lat: -35.193955, lng: 149.126474} |
- { name: Vicars Street,stop_code: Wjz6-16, lat: -35.20994, lng: 149.1394383} | - { name: Vicars Street,stop_code: Wjz6-16, lat: -35.20994, lng: 149.1394383} |
- { name: McEacharn Place,stop_code: Wjz6Zb2, lat: -35.214395, lng: 149.1408607} | - { name: McEacharn Place,stop_code: Wjz6Zb2, lat: -35.214395, lng: 149.1408607} |
- { name: Brookes Street,stop_code: Wjz6Z8D, lat: -35.216009, lng: 149.1414929} | - { name: Brookes Street,stop_code: Wjz6Z8D, lat: -35.216009, lng: 149.1414929} |
- { name: Grimwade Street,stop_code: Wjz6QPM, lat: -35.2200763, lng: 149.1377788} | - { name: Grimwade Street,stop_code: Wjz6QPM, lat: -35.2200763, lng: 149.1377788} |
- { name: Brookes Street,stop_code: Wjz6Yc1, lat: -35.2193016, lng: 149.1407817} | - { name: Brookes Street,stop_code: Wjz6Yc1, lat: -35.2193016, lng: 149.1407817} |
- { name: Darling Street,stop_code: Wjz6YiM, lat: -35.2207864, lng: 149.1433105} | - { name: Darling Street,stop_code: Wjz6YiM, lat: -35.2207864, lng: 149.1433105} |
- { name: Flemington Road,stop_code: Wjz6XiO, lat: -35.226071, lng: 149.143256} | - { name: Flemington Road,stop_code: Wjz6XiO, lat: -35.226071, lng: 149.143256} |
- { name: Well Station Road,stop_code: Wjze2eG, lat: -35.2288072, lng: 149.1527323} | - { name: Well Station Road,stop_code: Wjze2eG, lat: -35.2288072, lng: 149.1527323} |
- { name: Well Station Road,stop_code: Wjze3gN, lat: -35.2275265, lng: 149.154199} | - { name: Well Station Road,stop_code: Wjze3gN, lat: -35.2275265, lng: 149.154199} |
- { name: Federal Highway,stop_code: Wjze3Vq, lat: -35.2267416, lng: 149.1606727} | - { name: Federal Highway,stop_code: Wjze3Vq, lat: -35.2267416, lng: 149.1606727} |
- { name: Federal Highway,stop_code: Wjzebjj, lat: -35.2253369, lng: 149.1645164} | - { name: Federal Highway,stop_code: Wjzebjj, lat: -35.2253369, lng: 149.1645164} |
- { name: Antill Street,stop_code: Wjze8v0, lat: -35.2393099, lng: 149.1654981} | - { name: Antill Street,stop_code: Wjze8v0, lat: -35.2393099, lng: 149.1654981} |
- { name: Fison Street,stop_code: Wjze8bf, lat: -35.2414165, lng: 149.1630705} | - { name: Fison Street,stop_code: Wjze8bf, lat: -35.2414165, lng: 149.1630705} |
- { name: Dobbie Place,stop_code: Wjze0Pi, lat: -35.2418709, lng: 149.1591256} | - { name: Dobbie Place,stop_code: Wjze0Pi, lat: -35.2418709, lng: 149.1591256} |
- { name: Knox Street,stop_code: Wjze0vR, lat: -35.2388968, lng: 149.1555853} | - { name: Knox Street,stop_code: Wjze0vR, lat: -35.2388968, lng: 149.1555853} |
- { name: Dickinson Street,stop_code: Wjze1c2, lat: -35.2356747, lng: 149.1518427} | - { name: Dickinson Street,stop_code: Wjze1c2, lat: -35.2356747, lng: 149.1518427} |
- { name: Harvey Street,stop_code: Wjze1gi, lat: -35.2384424, lng: 149.1535117} | - { name: Harvey Street,stop_code: Wjze1gi, lat: -35.2384424, lng: 149.1535117} |
- { name: Bradfield Street,stop_code: Wjz6UYK, lat: -35.2407969, lng: 149.1499714} | - { name: Bradfield Street,stop_code: Wjz6UYK, lat: -35.2407969, lng: 149.1499714} |
- { name: Atherton Street,stop_code: Wjz6Upu, lat: -35.2429035, lng: 149.1442058} | - { name: Atherton Street,stop_code: Wjz6Upu, lat: -35.2429035, lng: 149.1442058} |
- { name: Melba Street,stop_code: Wjz6Ugw, lat: -35.2441014, lng: 149.142992} | - { name: Melba Street,stop_code: Wjz6Ugw, lat: -35.2441014, lng: 149.142992} |
- { name: Melba Street,stop_code: Wjz5_ie, lat: -35.2476948, lng: 149.1423851} | - { name: Melba Street,stop_code: Wjz5_ie, lat: -35.2476948, lng: 149.1423851} |
- { name: Antill Street,stop_code: Wjz5_y0, lat: -35.2482318, lng: 149.1449139} | - { name: Antill Street,stop_code: Wjz5_y0, lat: -35.2482318, lng: 149.1449139} |
- { name: Antill Street,stop_code: Wjzd73N, lat: -35.2474057, lng: 149.1515393} | - { name: Antill Street,stop_code: Wjzd73N, lat: -35.2474057, lng: 149.1515393} |
- { name: Antill Street,stop_code: Wjzd7sL, lat: -35.2462079, lng: 149.1554841} | - { name: Antill Street,stop_code: Wjzd7sL, lat: -35.2462079, lng: 149.1554841} |
- { name: Madigan Street,stop_code: Wjzd7_6, lat: -35.2443079, lng: 149.1601371} | - { name: Madigan Street,stop_code: Wjzd7_6, lat: -35.2443079, lng: 149.1601371} |
- { name: Madigan Street,stop_code: Wjzdfaz, lat: -35.2479426, lng: 149.1635256} | - { name: Madigan Street,stop_code: Wjzdfaz, lat: -35.2479426, lng: 149.1635256} |
- { name: Madigan Street,stop_code: Wjzd6XP, lat: -35.2527713, lng: 149.1610527} | - { name: Madigan Street,stop_code: Wjzd6XP, lat: -35.2527713, lng: 149.1610527} |
- { name: Phillip Avenue,stop_code: Wjzd6Pn, lat: -35.2524079, lng: 149.1590701} | - { name: Phillip Avenue,stop_code: Wjzd6Pn, lat: -35.2524079, lng: 149.1590701} |
- { name: Salomons Place,stop_code: Wjzd6lW, lat: -35.2515158, lng: 149.1544172} | - { name: Salomons Place,stop_code: Wjzd6lW, lat: -35.2515158, lng: 149.1544172} |
- { name: Agnew Street,stop_code: Wjzd6iW, lat: -35.2535643, lng: 149.1544576} | - { name: Agnew Street,stop_code: Wjzd6iW, lat: -35.2535643, lng: 149.1544576} |
- { name: Bourke Street,stop_code: Wjz4Pt5, lat: -35.3116531, lng: 149.1326324} | - { name: Bourke Street,stop_code: Wjz4Pt5, lat: -35.3116531, lng: 149.1326324} |
- { name: Nyrang Street,stop_code: Wjzc1qE, lat: -35.3251161, lng: 149.1555115} | - { name: Nyrang Street,stop_code: Wjzc1qE, lat: -35.3251161, lng: 149.1555115} |
- { name: Bunda Street,stop_code: Wjz5NeC, lat: -35.2778798, lng: 149.1305995} | - { name: Bunda Street,stop_code: Wjz5NeC, lat: -35.2778798, lng: 149.1305995} |
- { name: Justinian Street,stop_code: Wjz3mWn, lat: -35.3409621, lng: 149.0945298} | - { name: Justinian Street,stop_code: Wjz3mWn, lat: -35.3409621, lng: 149.0945298} |
- { name: Wisdom Street,stop_code: Wjz3mQ4, lat: -35.3398419, lng: 149.0928819} | - { name: Wisdom Street,stop_code: Wjz3mQ4, lat: -35.3398419, lng: 149.0928819} |
- { name: Robson Street,stop_code: Wjz3C9Q, lat: -35.3419855, lng: 149.108934} | - { name: Robson Street,stop_code: Wjz3C9Q, lat: -35.3419855, lng: 149.108934} |
- { name: Ingamells Street,stop_code: Wjz3uJV, lat: -35.339486, lng: 149.1035524} | - { name: Ingamells Street,stop_code: Wjz3uJV, lat: -35.339486, lng: 149.1035524} |
- { name: Robson Street,stop_code: Wjz3C9J, lat: -35.3418945, lng: 149.1087966} | - { name: Robson Street,stop_code: Wjz3C9J, lat: -35.3418945, lng: 149.1087966} |
- { name: Wisdom Street,stop_code: Wjz3n-4, lat: -35.3330183, lng: 149.0941258} | - { name: Wisdom Street,stop_code: Wjz3n-4, lat: -35.3330183, lng: 149.0941258} |
- { name: Kent Street,stop_code: Wjz4qia, lat: -35.3194535, lng: 149.0984183} | - { name: Kent Street,stop_code: Wjz4qia, lat: -35.3194535, lng: 149.0984183} |
- { name: Kent Street,stop_code: Wjz4gXk, lat: -35.3296011, lng: 149.0945736} | - { name: Kent Street,stop_code: Wjz4gXk, lat: -35.3296011, lng: 149.0945736} |
- { name: McCaughey Street,stop_code: Wjz5Guy, lat: -35.2727878, lng: 149.1223747} | - { name: McCaughey Street,stop_code: Wjz5Guy, lat: -35.2727878, lng: 149.1223747} |
- { name: McCaughey Street,stop_code: Wjz5Iw8, lat: -35.2660466, lng: 149.1231132} | - { name: McCaughey Street,stop_code: Wjz5Iw8, lat: -35.2660466, lng: 149.1231132} |
- { name: Macpherson Street,stop_code: Wjz5Imu, lat: -35.2614148, lng: 149.1208459} | - { name: Macpherson Street,stop_code: Wjz5Imu, lat: -35.2614148, lng: 149.1208459} |
- { name: Macarthur Avenue,stop_code: Wjz5Jpu, lat: -35.2594072, lng: 149.1221624} | - { name: Macarthur Avenue,stop_code: Wjz5Jpu, lat: -35.2594072, lng: 149.1221624} |
- { name: Karri Street,stop_code: Wjz5JuJ, lat: -35.2560391, lng: 149.1225279} | - { name: Karri Street,stop_code: Wjz5JuJ, lat: -35.2560391, lng: 149.1225279} |
- { name: Jarrah Street,stop_code: Wjz5KgT, lat: -35.2544701, lng: 149.1213129} | - { name: Jarrah Street,stop_code: Wjz5KgT, lat: -35.2544701, lng: 149.1213129} |
- { name: Fawkner Street,stop_code: Wjz5OIf, lat: -35.2737328, lng: 149.1354944} | - { name: Fawkner Street,stop_code: Wjz5OIf, lat: -35.2737328, lng: 149.1354944} |
- { name: Ainslie Avenue,stop_code: Wjz5V64, lat: -35.2780918, lng: 149.1394963} | - { name: Ainslie Avenue,stop_code: Wjz5V64, lat: -35.2780918, lng: 149.1394963} |
- { name: Ainslie Avenue,stop_code: Wjz5NRJ, lat: -35.2787111, lng: 149.1375365} | - { name: Ainslie Avenue,stop_code: Wjz5NRJ, lat: -35.2787111, lng: 149.1375365} |
- { name: Gooreen Street,stop_code: Wjz5Vls, lat: -35.2787911, lng: 149.1427895} | - { name: Gooreen Street,stop_code: Wjz5Vls, lat: -35.2787911, lng: 149.1427895} |
- { name: Limestone Avenue,stop_code: Wjz5VAq, lat: -35.2796604, lng: 149.14553} | - { name: Limestone Avenue,stop_code: Wjz5VAq, lat: -35.2796604, lng: 149.14553} |
- { name: Fairbairn Avenue,stop_code: Wjz5VUU, lat: -35.2825429, lng: 149.15037} | - { name: Fairbairn Avenue,stop_code: Wjz5VUU, lat: -35.2825429, lng: 149.15037} |
- { name: Fairbairn Avenue,stop_code: Wjzd8br, lat: -35.2857037, lng: 149.16333} | - { name: Fairbairn Avenue,stop_code: Wjzd8br, lat: -35.2857037, lng: 149.16333} |
- { name: Glossop Crescent,stop_code: Wjzd0yM, lat: -35.2866868, lng: 149.1570161} | - { name: Glossop Crescent,stop_code: Wjzd0yM, lat: -35.2866868, lng: 149.1570161} |
- { name: Savige Street,stop_code: Wjzd02s, lat: -35.286331, lng: 149.1509776} | - { name: Savige Street,stop_code: Wjzd02s, lat: -35.286331, lng: 149.1509776} |
- { name: Chowne Street,stop_code: Wjz5UHK, lat: -35.2854924, lng: 149.1472635} | - { name: Chowne Street,stop_code: Wjz5UHK, lat: -35.2854924, lng: 149.1472635} |
- { name: Euree Street,stop_code: Wjz5Vg4, lat: -35.2821666, lng: 149.1422877} | - { name: Euree Street,stop_code: Wjz5Vg4, lat: -35.2821666, lng: 149.1422877} |
- { name: White Crescent,stop_code: Wjzd0EU, lat: -35.2880133, lng: 149.158501} | - { name: White Crescent,stop_code: Wjzd0EU, lat: -35.2880133, lng: 149.158501} |
- { name: Chauvel Street,stop_code: Wjzc7si, lat: -35.2905765, lng: 149.1549056} | - { name: Chauvel Street,stop_code: Wjzc7si, lat: -35.2905765, lng: 149.1549056} |
- { name: Bungey Street,stop_code: Wjzc7bs, lat: -35.2911202, lng: 149.1523397} | - { name: Bungey Street,stop_code: Wjzc7bs, lat: -35.2911202, lng: 149.1523397} |
- { name: Constitution Avenue,stop_code: Wjz4_wS, lat: -35.2930129, lng: 149.145973} | - { name: Constitution Avenue,stop_code: Wjz4_wS, lat: -35.2930129, lng: 149.145973} |
- { name: Wendouree Drive,stop_code: Wjz4_jm, lat: -35.2909901, lng: 149.1425844} | - { name: Wendouree Drive,stop_code: Wjz4_jm, lat: -35.2909901, lng: 149.1425844} |
- { name: Parkes Way,stop_code: Wjz5MEL, lat: -35.2874399, lng: 149.1362625} | - { name: Parkes Way,stop_code: Wjz5MEL, lat: -35.2874399, lng: 149.1362625} |
- { name: General Bridges Drive,stop_code: Wjzce4H, lat: -35.2960675, lng: 149.1623594} | - { name: General Bridges Drive,stop_code: Wjzce4H, lat: -35.2960675, lng: 149.1623594} |
- { name: Vowels Road,stop_code: WjzceFT, lat: -35.2977187, lng: 149.1693894} | - { name: Vowels Road,stop_code: WjzceFT, lat: -35.2977187, lng: 149.1693894} |
- { name: Vowels Road,stop_code: WjzcdDs, lat: -35.299411, lng: 149.1675181} | - { name: Vowels Road,stop_code: WjzcdDs, lat: -35.299411, lng: 149.1675181} |
- { name: Morshead Drive,stop_code: Wjzcdi7, lat: -35.3025893, lng: 149.1642813} | - { name: Morshead Drive,stop_code: Wjzcdi7, lat: -35.3025893, lng: 149.1642813} |
- { name: Morshead Drive,stop_code: Wjzcd8D, lat: -35.3039101, lng: 149.1635732} | - { name: Morshead Drive,stop_code: Wjzcd8D, lat: -35.3039101, lng: 149.1635732} |
- { name: Menindee Drive,stop_code: Wjzc59p, lat: -35.3037863, lng: 149.1523455} | - { name: Menindee Drive,stop_code: Wjzc59p, lat: -35.3037863, lng: 149.1523455} |
- { name: Menindee Drive,stop_code: Wjzc45R, lat: -35.3061389, lng: 149.1514351} | - { name: Menindee Drive,stop_code: Wjzc45R, lat: -35.3061389, lng: 149.1514351} |
- { name: Canberra Avenue,stop_code: Wjz4VKr, lat: -35.3221513, lng: 149.1468833} | - { name: Canberra Avenue,stop_code: Wjz4VKr, lat: -35.3221513, lng: 149.1468833} |
- { name: Canberra Avenue,stop_code: Wjz4VRQ, lat: -35.3226878, lng: 149.148704} | - { name: Canberra Avenue,stop_code: Wjz4VRQ, lat: -35.3226878, lng: 149.148704} |
- { name: Wickham Crescent,stop_code: Wjz4FEJ, lat: -35.3260887, lng: 149.125286} | - { name: Wickham Crescent,stop_code: Wjz4FEJ, lat: -35.3260887, lng: 149.125286} |
- { name: Vancouver Street,stop_code: Wjz4ECF, lat: -35.3278218, lng: 149.1238193} | - { name: Vancouver Street,stop_code: Wjz4ECF, lat: -35.3278218, lng: 149.1238193} |
- { name: Friendship Street,stop_code: Wjz3LP9, lat: -35.3353724, lng: 149.1259941} | - { name: Friendship Street,stop_code: Wjz3LP9, lat: -35.3353724, lng: 149.1259941} |
- { name: Quiros Street,stop_code: Wjz3LN9, lat: -35.3367339, lng: 149.1259435} | - { name: Quiros Street,stop_code: Wjz3LN9, lat: -35.3367339, lng: 149.1259435} |
- { name: Bremer Street,stop_code: Wjz4MAz, lat: -35.3290192, lng: 149.1346333} | - { name: Bremer Street,stop_code: Wjz4MAz, lat: -35.3290192, lng: 149.1346333} |
- { name: Favenc Circle,stop_code: Wjz4Ue5, lat: -35.327397, lng: 149.140921} | - { name: Favenc Circle,stop_code: Wjz4Ue5, lat: -35.327397, lng: 149.140921} |
- { name: Stuart Street,stop_code: Wjz4Ujk, lat: -35.3295839, lng: 149.1425394} | - { name: Stuart Street,stop_code: Wjz4Ujk, lat: -35.3295839, lng: 149.1425394} |
- { name: Captain Cook Crescent,stop_code: Wjz3_Ji, lat: -35.3339111, lng: 149.146681} | - { name: Captain Cook Crescent,stop_code: Wjz3_Ji, lat: -35.3339111, lng: 149.146681} |
- { name: McKinlay Place,stop_code: Wjz4UwD, lat: -35.3313913, lng: 149.1456952} | - { name: McKinlay Place,stop_code: Wjz4UwD, lat: -35.3313913, lng: 149.1456952} |
- { name: McKinlay Street,stop_code: Wjz4VEF, lat: -35.3264205, lng: 149.1472235} | - { name: McKinlay Street,stop_code: Wjz4VEF, lat: -35.3264205, lng: 149.1472235} |
- { name: Leeton Street,stop_code: Wjzc1n0, lat: -35.3216636, lng: 149.1532292} | - { name: Leeton Street,stop_code: Wjzc1n0, lat: -35.3216636, lng: 149.1532292} |
- { name: Boolimba Crescent,stop_code: Wjzc090, lat: -35.3312849, lng: 149.15186} | - { name: Boolimba Crescent,stop_code: Wjzc090, lat: -35.3312849, lng: 149.15186} |
- { name: Iluka Street,stop_code: Wjzb7nW, lat: -35.3324815, lng: 149.1544899} | - { name: Iluka Street,stop_code: Wjzb7nW, lat: -35.3324815, lng: 149.1544899} |
- { name: Mugga Way,stop_code: Wjz3Kxb, lat: -35.342056, lng: 149.1231366} | - { name: Mugga Way,stop_code: Wjz3Kxb, lat: -35.342056, lng: 149.1231366} |
- { name: Mugga Way,stop_code: Wjz3JDp, lat: -35.3435515, lng: 149.1235159} | - { name: Mugga Way,stop_code: Wjz3JDp, lat: -35.3435515, lng: 149.1235159} |
- { name: Mugga Way,stop_code: Wjz3JJs, lat: -35.344686, lng: 149.1248435} | - { name: Mugga Way,stop_code: Wjz3JJs, lat: -35.344686, lng: 149.1248435} |
- { name: Beagle Street,stop_code: Wjz3Rdo, lat: -35.3450469, lng: 149.1304068} | - { name: Beagle Street,stop_code: Wjz3Rdo, lat: -35.3450469, lng: 149.1304068} |
- { name: Monaro Crescent,stop_code: Wjz3ShE, lat: -35.3422498, lng: 149.1321257} | - { name: Monaro Crescent,stop_code: Wjz3ShE, lat: -35.3422498, lng: 149.1321257} |
- { name: Astrolabe Street,stop_code: Wjz3T8Z, lat: -35.337043, lng: 149.1311337} | - { name: Astrolabe Street,stop_code: Wjz3T8Z, lat: -35.337043, lng: 149.1311337} |
- { name: Bell Street,stop_code: Wjz4MpW, lat: -35.3311406, lng: 149.1338209} | - { name: Bell Street,stop_code: Wjz4MpW, lat: -35.3311406, lng: 149.1338209} |
- { name: Goyder Street,stop_code: Wjz3-Jb, lat: -35.3392754, lng: 149.1466095} | - { name: Goyder Street,stop_code: Wjz3-Jb, lat: -35.3392754, lng: 149.1466095} |
- { name: Narupai Street,stop_code: Wjzb6cp, lat: -35.3401203, lng: 149.1523581} | - { name: Narupai Street,stop_code: Wjzb6cp, lat: -35.3401203, lng: 149.1523581} |
- { name: Kyeema Street,stop_code: Wjzb7wf, lat: -35.3368722, lng: 149.1561338} | - { name: Kyeema Street,stop_code: Wjzb7wf, lat: -35.3368722, lng: 149.1561338} |
- { name: Matina Street,stop_code: Wjzb7HN, lat: -35.335349, lng: 149.1583716} | - { name: Matina Street,stop_code: Wjzb7HN, lat: -35.335349, lng: 149.1583716} |
- { name: Kootara Crescent,stop_code: Wjzb7S4, lat: -35.3330282, lng: 149.1586877} | - { name: Kootara Crescent,stop_code: Wjzb7S4, lat: -35.3330282, lng: 149.1586877} |
- { name: Goyder Street,stop_code: Wjz3SUA, lat: -35.3426508, lng: 149.1388551} | - { name: Goyder Street,stop_code: Wjz3SUA, lat: -35.3426508, lng: 149.1388551} |
- { name: Narrabundah Lane,stop_code: Wjzb4vx, lat: -35.3490259, lng: 149.1553622} | - { name: Narrabundah Lane,stop_code: Wjzb4vx, lat: -35.3490259, lng: 149.1553622} |
- { name: Dalby Street,stop_code: Wjzc1tq, lat: -35.3228774, lng: 149.1550358} | - { name: Dalby Street,stop_code: Wjzc1tq, lat: -35.3228774, lng: 149.1550358} |
- { name: Canberra Avenue,stop_code: Wjzbfnr, lat: -35.332383, lng: 149.1647873} | - { name: Canberra Avenue,stop_code: Wjzbfnr, lat: -35.332383, lng: 149.1647873} |
- { name: Newcastle Street,stop_code: Wjzc9WV, lat: -35.3250576, lng: 149.1722805} | - { name: Newcastle Street,stop_code: Wjzc9WV, lat: -35.3250576, lng: 149.1722805} |
- { name: Albany Street,stop_code: WjzchQP, lat: -35.3235189, lng: 149.1817987} | - { name: Albany Street,stop_code: WjzchQP, lat: -35.3235189, lng: 149.1817987} |
- { name: Townsville Street,stop_code: Wjzcod5, lat: -35.3281204, lng: 149.1848684} | - { name: Townsville Street,stop_code: Wjzcod5, lat: -35.3281204, lng: 149.1848684} |
- { name: Townsville Street,stop_code: Wjzcoab, lat: -35.3303968, lng: 149.1849583} | - { name: Townsville Street,stop_code: Wjzcoab, lat: -35.3303968, lng: 149.1849583} |
- { name: Townsville Street,stop_code: WjzcgX_, lat: -35.3293219, lng: 149.1833416} | - { name: Townsville Street,stop_code: WjzcgX_, lat: -35.3293219, lng: 149.1833416} |
- { name: Jindalee Crescent,stop_code: Wjz3r_u, lat: -35.3540946, lng: 149.1057023} | - { name: Jindalee Crescent,stop_code: Wjz3r_u, lat: -35.3540946, lng: 149.1057023} |
- { name: Arrellah Place,stop_code: Wjz3rQi, lat: -35.3565695, lng: 149.104185} | - { name: Arrellah Place,stop_code: Wjz3rQi, lat: -35.3565695, lng: 149.104185} |
- { name: Coreen Place,stop_code: Wjz3z0c, lat: -35.3591474, lng: 149.106777} | - { name: Coreen Place,stop_code: Wjz3z0c, lat: -35.3591474, lng: 149.106777} |
- { name: Bromby Street,stop_code: Wjz3y4z, lat: -35.3619315, lng: 149.1072828} | - { name: Bromby Street,stop_code: Wjz3y4z, lat: -35.3619315, lng: 149.1072828} |
- { name: Yamba Drive,stop_code: Wjz3pZQ, lat: -35.366623, lng: 149.1062713} | - { name: Yamba Drive,stop_code: Wjz3pZQ, lat: -35.366623, lng: 149.1062713} |
- { name: Beasley Street,stop_code: Wjz3x3A, lat: -35.3680664, lng: 149.1072196} | - { name: Beasley Street,stop_code: Wjz3x3A, lat: -35.3680664, lng: 149.1072196} |
- { name: Bee Place,stop_code: Wjz3xwa, lat: -35.3702316, lng: 149.1122771} | - { name: Bee Place,stop_code: Wjz3xwa, lat: -35.3702316, lng: 149.1122771} |
- { name: Yamba Drive,stop_code: Wjz3wrK, lat: -35.3733761, lng: 149.1115817} | - { name: Yamba Drive,stop_code: Wjz3wrK, lat: -35.3733761, lng: 149.1115817} |
- { name: Dookie Street,stop_code: Wjz3woC, lat: -35.3754381, lng: 149.1112656} | - { name: Dookie Street,stop_code: Wjz3woC, lat: -35.3754381, lng: 149.1112656} |
- { name: Shepherdson Place,stop_code: Wjz2DPD, lat: -35.378737, lng: 149.1155013} | - { name: Shepherdson Place,stop_code: Wjz2DPD, lat: -35.378737, lng: 149.1155013} |
- { name: Pudney Street,stop_code: Wjz2DEs, lat: -35.3811081, lng: 149.1139208} | - { name: Pudney Street,stop_code: Wjz2DEs, lat: -35.3811081, lng: 149.1139208} |
- { name: Woodgate Street,stop_code: Wjz2C5I, lat: -35.3831852, lng: 149.1074202} | - { name: Woodgate Street,stop_code: Wjz2C5I, lat: -35.3831852, lng: 149.1074202} |
- { name: Muresk Street,stop_code: Wjz2uSZ, lat: -35.3823742, lng: 149.1050643} | - { name: Muresk Street,stop_code: Wjz2uSZ, lat: -35.3823742, lng: 149.1050643} |
- { name: Longerenong Street,stop_code: Wjz2vL4, lat: -35.3762782, lng: 149.1023627} | - { name: Longerenong Street,stop_code: Wjz2vL4, lat: -35.3762782, lng: 149.1023627} |
- { name: Pridham Street,stop_code: Wjz3oih, lat: -35.3744422, lng: 149.0986886} | - { name: Pridham Street,stop_code: Wjz3oih, lat: -35.3744422, lng: 149.0986886} |
- { name: Lambrigg Street,stop_code: Wjz3oeM, lat: -35.3718451, lng: 149.0980006} | - { name: Lambrigg Street,stop_code: Wjz3oeM, lat: -35.3718451, lng: 149.0980006} |
- { name: Beasley Street,stop_code: Wjz3hXO, lat: -35.3681696, lng: 149.0952079} | - { name: Beasley Street,stop_code: Wjz3hXO, lat: -35.3681696, lng: 149.0952079} |
- { name: Wilkins Street,stop_code: Wjz3peD, lat: -35.3657466, lng: 149.0976102} | - { name: Wilkins Street,stop_code: Wjz3peD, lat: -35.3657466, lng: 149.0976102} |
- { name: Prior Place,stop_code: Wjz3oge, lat: -35.3754535, lng: 149.0983799} | - { name: Prior Place,stop_code: Wjz3oge, lat: -35.3754535, lng: 149.0983799} |
- { name: Athllon Drive,stop_code: Wjz2nLE, lat: -35.3766237, lng: 149.0922366} | - { name: Athllon Drive,stop_code: Wjz2nLE, lat: -35.3766237, lng: 149.0922366} |
- { name: Brookman Street,stop_code: Wjz2nug, lat: -35.3773453, lng: 149.0890124} | - { name: Brookman Street,stop_code: Wjz2nug, lat: -35.3773453, lng: 149.0890124} |
- { name: Batchelor Street,stop_code: Wjz3gcu, lat: -35.3726637, lng: 149.0864364} | - { name: Batchelor Street,stop_code: Wjz3gcu, lat: -35.3726637, lng: 149.0864364} |
- { name: Gouger Street,stop_code: Wjz3gB5, lat: -35.3720623, lng: 149.0900243} | - { name: Gouger Street,stop_code: Wjz3gB5, lat: -35.3720623, lng: 149.0900243} |
- { name: Garratt Street,stop_code: Wjz2k5E, lat: -35.3945084, lng: 149.0853457} | - { name: Garratt Street,stop_code: Wjz2k5E, lat: -35.3945084, lng: 149.0853457} |
- { name: Sternberg Crescent,stop_code: Wjz2cKo, lat: -35.3937869, lng: 149.0809204} | - { name: Sternberg Crescent,stop_code: Wjz2cKo, lat: -35.3937869, lng: 149.0809204} |
- { name: Fincham Crescent,stop_code: Wjz2crQ, lat: -35.3954875, lng: 149.0787077} | - { name: Fincham Crescent,stop_code: Wjz2crQ, lat: -35.3954875, lng: 149.0787077} |
- { name: Byrne Street,stop_code: Wjz2kbO, lat: -35.3956421, lng: 149.0869894} | - { name: Byrne Street,stop_code: Wjz2kbO, lat: -35.3956421, lng: 149.0869894} |
- { name: Athllon Drive,stop_code: Wjz2lDC, lat: -35.3870716, lng: 149.090679} | - { name: Athllon Drive,stop_code: Wjz2lDC, lat: -35.3870716, lng: 149.090679} |
- { name: Sulwood Drive,stop_code: Wjz2u2j, lat: -35.3853192, lng: 149.095863} | - { name: Sulwood Drive,stop_code: Wjz2u2j, lat: -35.3853192, lng: 149.095863} |
- { name: Sulwood Drive,stop_code: Wjz2ugd, lat: -35.3865047, lng: 149.0985182} | - { name: Sulwood Drive,stop_code: Wjz2ugd, lat: -35.3865047, lng: 149.0985182} |
- { name: Sulwood Drive,stop_code: Wjz2tyn, lat: -35.3904732, lng: 149.1013631} | - { name: Sulwood Drive,stop_code: Wjz2tyn, lat: -35.3904732, lng: 149.1013631} |
- { name: Sulwood Drive,stop_code: Wjz2sLr, lat: -35.3928439, lng: 149.1028803} | - { name: Sulwood Drive,stop_code: Wjz2sLr, lat: -35.3928439, lng: 149.1028803} |
- { name: Lansell Circuit,stop_code: Wjz2qJ7, lat: -35.4048663, lng: 149.1024781} | - { name: Lansell Circuit,stop_code: Wjz2qJ7, lat: -35.4048663, lng: 149.1024781} |
- { name: Grattan Court,stop_code: Wjz2r9X, lat: -35.4024569, lng: 149.098142} | - { name: Grattan Court,stop_code: Wjz2r9X, lat: -35.4024569, lng: 149.098142} |
- { name: Wheeler Crescent,stop_code: Wjz2jFF, lat: -35.4026479, lng: 149.0922959} | - { name: Wheeler Crescent,stop_code: Wjz2jFF, lat: -35.4026479, lng: 149.0922959} |
- { name: Snowden Place,stop_code: Wjz2isR, lat: -35.4057431, lng: 149.0896883} | - { name: Snowden Place,stop_code: Wjz2isR, lat: -35.4057431, lng: 149.0896883} |
- { name: Sturdee Crescent,stop_code: Wjz2iVd, lat: -35.4077519, lng: 149.0942596} | - { name: Sturdee Crescent,stop_code: Wjz2iVd, lat: -35.4077519, lng: 149.0942596} |
- { name: Crocker Place,stop_code: Wjz2q9z, lat: -35.4079064, lng: 149.0976735} | - { name: Crocker Place,stop_code: Wjz2q9z, lat: -35.4079064, lng: 149.0976735} |
- { name: Bugden Avenue,stop_code: Wjz2F6d, lat: -35.4098598, lng: 149.1177053} | - { name: Bugden Avenue,stop_code: Wjz2F6d, lat: -35.4098598, lng: 149.1177053} |
- { name: Bugden Avenue,stop_code: Wjz2xyM, lat: -35.4130074, lng: 149.113099} | - { name: Bugden Avenue,stop_code: Wjz2xyM, lat: -35.4130074, lng: 149.113099} |
- { name: Woods Place,stop_code: Wjz2pVO, lat: -35.4135227, lng: 149.1062081} | - { name: Woods Place,stop_code: Wjz2pVO, lat: -35.4135227, lng: 149.1062081} |
- { name: Stacy Street,stop_code: Wjz2oQE, lat: -35.4171292, lng: 149.1046908} | - { name: Stacy Street,stop_code: Wjz2oQE, lat: -35.4171292, lng: 149.1046908} |
- { name: Gilday Place,stop_code: Wjz2Gff, lat: -35.403475, lng: 149.1191048} | - { name: Gilday Place,stop_code: Wjz2Gff, lat: -35.403475, lng: 149.1191048} |
- { name: Demaine Crescent,stop_code: Wjz2Gu5, lat: -35.404351, lng: 149.1216336} | - { name: Demaine Crescent,stop_code: Wjz2Gu5, lat: -35.404351, lng: 149.1216336} |
- { name: Coyne Street,stop_code: Wjz2FDo, lat: -35.4095553, lng: 149.1235301} | - { name: Coyne Street,stop_code: Wjz2FDo, lat: -35.4095553, lng: 149.1235301} |
- { name: Coyne Street,stop_code: Wjz2F_q, lat: -35.4093651, lng: 149.1276548} | - { name: Coyne Street,stop_code: Wjz2F_q, lat: -35.4093651, lng: 149.1276548} |
- { name: Akhurst Grove,stop_code: Wjz1cz3, lat: -35.4395376, lng: 149.079087} | - { name: Akhurst Grove,stop_code: Wjz1cz3, lat: -35.4395376, lng: 149.079087} |
- { name: Andrea Place,stop_code: Wjz1d0X, lat: -35.4360866, lng: 149.0748513} | - { name: Andrea Place,stop_code: Wjz1d0X, lat: -35.4360866, lng: 149.0748513} |
- { name: Andrea Place,stop_code: Wjz15Xb, lat: -35.4340778, lng: 149.0723858} | - { name: Andrea Place,stop_code: Wjz15Xb, lat: -35.4340778, lng: 149.0723858} |
- { name: Harcus Close,stop_code: Wjz1klr, lat: -35.4381985, lng: 149.087748} | - { name: Harcus Close,stop_code: Wjz1klr, lat: -35.4381985, lng: 149.087748} |
- { name: Woodcock Drive,stop_code: Wjz1kyn, lat: -35.4398982, lng: 149.0904032} | - { name: Woodcock Drive,stop_code: Wjz1kyn, lat: -35.4398982, lng: 149.0904032} |
- { name: Stella Hume Street,stop_code: Wjz16Q9, lat: -35.4280509, lng: 149.0709317} | - { name: Stella Hume Street,stop_code: Wjz16Q9, lat: -35.4280509, lng: 149.0709317} |
- { name: Ragless Circuit,stop_code: WjrWXL8, lat: -35.3985958, lng: 149.0586576} | - { name: Ragless Circuit,stop_code: WjrWXL8, lat: -35.3985958, lng: 149.0586576} |
- { name: Learmonth Drive,stop_code: WjrWXIP, lat: -35.4004264, lng: 149.0594265} | - { name: Learmonth Drive,stop_code: WjrWXIP, lat: -35.4004264, lng: 149.0594265} |
- { name: Meredith Circuit,stop_code: WjrWQRL, lat: -35.3938608, lng: 149.049706} | - { name: Meredith Circuit,stop_code: WjrWQRL, lat: -35.3938608, lng: 149.049706} |
- { name: Bateman Street,stop_code: WjrWRWi, lat: -35.3908805, lng: 149.0506492} | - { name: Bateman Street,stop_code: WjrWRWi, lat: -35.3908805, lng: 149.0506492} |
- { name: Boddington Crescent,stop_code: WjrWSX9, lat: -35.3847561, lng: 149.0504459} | - { name: Boddington Crescent,stop_code: WjrWSX9, lat: -35.3847561, lng: 149.0504459} |
- { name: Eagle Circuit,stop_code: WjrWSBZ, lat: -35.383041, lng: 149.0472484} | - { name: Eagle Circuit,stop_code: WjrWSBZ, lat: -35.383041, lng: 149.0472484} |
- { name: Archibald Street,stop_code: Wjz5LLF, lat: -35.2446872, lng: 149.1252507} | - { name: Archibald Street,stop_code: Wjz5LLF, lat: -35.2446872, lng: 149.1252507} |
- { name: Archibald Street,stop_code: Wjz5LDv, lat: -35.2442061, lng: 149.1235678} | - { name: Archibald Street,stop_code: Wjz5LDv, lat: -35.2442061, lng: 149.1235678} |
- { name: Tharwa Drive,stop_code: Wjz1gBy, lat: -35.4601891, lng: 149.0907826} | - { name: Tharwa Drive,stop_code: Wjz1gBy, lat: -35.4601891, lng: 149.0907826} |
- { name: Pocket Avenue,stop_code: Wjz0v3X, lat: -35.4670374, lng: 149.0967252} | - { name: Pocket Avenue,stop_code: Wjz0v3X, lat: -35.4670374, lng: 149.0967252} |
- { name: Troughton Street,stop_code: Wjz0unz, lat: -35.4697663, lng: 149.0990011} | - { name: Troughton Street,stop_code: Wjz0unz, lat: -35.4697663, lng: 149.0990011} |
- { name: Paperbark Street,stop_code: Wjz0uQv, lat: -35.4714653, lng: 149.1043747} | - { name: Paperbark Street,stop_code: Wjz0uQv, lat: -35.4714653, lng: 149.1043747} |
- { name: Wollemi Place,stop_code: Wjz0C4B, lat: -35.4716198, lng: 149.1071563} | - { name: Wollemi Place,stop_code: Wjz0C4B, lat: -35.4716198, lng: 149.1071563} |
- { name: Kallista Place,stop_code: Wjz0Cpn, lat: -35.4735247, lng: 149.1110759} | - { name: Kallista Place,stop_code: Wjz0Cpn, lat: -35.4735247, lng: 149.1110759} |
- { name: Wollemi Place,stop_code: Wjz0Bv9, lat: -35.4753782, lng: 149.1107598} | - { name: Wollemi Place,stop_code: Wjz0Bv9, lat: -35.4753782, lng: 149.1107598} |
- { name: Galbraith Close,stop_code: Wjz0t_T, lat: -35.4749148, lng: 149.1061448} | - { name: Galbraith Close,stop_code: Wjz0t_T, lat: -35.4749148, lng: 149.1061448} |
- { name: Bellchambers Crescent,stop_code: Wjz0tno, lat: -35.4754811, lng: 149.0988746} | - { name: Bellchambers Crescent,stop_code: Wjz0tno, lat: -35.4754811, lng: 149.0988746} |
- { name: Forsythe Street,stop_code: Wjz0u92, lat: -35.4739881, lng: 149.0969148} | - { name: Forsythe Street,stop_code: Wjz0u92, lat: -35.4739881, lng: 149.0969148} |
- { name: Menzies Court,stop_code: Wjz0lYC, lat: -35.4770256, lng: 149.0948286} | - { name: Menzies Court,stop_code: Wjz0lYC, lat: -35.4770256, lng: 149.0948286} |
- { name: Olive Pink Crescent,stop_code: Wjz0t9g, lat: -35.4795997, lng: 149.0972309} | - { name: Olive Pink Crescent,stop_code: Wjz0t9g, lat: -35.4795997, lng: 149.0972309} |
- { name: Tharwa Drive,stop_code: Wjz0kHU, lat: -35.4837695, lng: 149.0925527} | - { name: Tharwa Drive,stop_code: Wjz0kHU, lat: -35.4837695, lng: 149.0925527} |
- { name: Tharwa Drive,stop_code: Wjz0klX, lat: -35.4821222, lng: 149.0884434} | - { name: Tharwa Drive,stop_code: Wjz0klX, lat: -35.4821222, lng: 149.0884434} |
- { name: Tharwa Drive,stop_code: Wjz0lcW, lat: -35.477386, lng: 149.0870526} | - { name: Tharwa Drive,stop_code: Wjz0lcW, lat: -35.477386, lng: 149.0870526} |
- { name: McVilly Close,stop_code: Wjz0eVg, lat: -35.4740911, lng: 149.0835756} | - { name: McVilly Close,stop_code: Wjz0eVg, lat: -35.4740911, lng: 149.0835756} |
- { name: Robert Lewis Court,stop_code: Wjz0m65, lat: -35.4702811, lng: 149.0845871} | - { name: Robert Lewis Court,stop_code: Wjz0m65, lat: -35.4702811, lng: 149.0845871} |
- { name: Hickenbotham Street,stop_code: Wjz0n3A, lat: -35.4669344, lng: 149.0852193} | - { name: Hickenbotham Street,stop_code: Wjz0n3A, lat: -35.4669344, lng: 149.0852193} |
- { name: Oxenham Circuit,stop_code: Wjz1gnx, lat: -35.4589532, lng: 149.0880641} | - { name: Oxenham Circuit,stop_code: Wjz1gnx, lat: -35.4589532, lng: 149.0880641} |
- { name: Knoke Avenue,stop_code: Wjz1h9y, lat: -35.4574599, lng: 149.0866733} | - { name: Knoke Avenue,stop_code: Wjz1h9y, lat: -35.4574599, lng: 149.0866733} |
- { name: McGilvray Close,stop_code: Wjz1h4G, lat: -35.4554516, lng: 149.0853457} | - { name: McGilvray Close,stop_code: Wjz1h4G, lat: -35.4554516, lng: 149.0853457} |
- { name: Woodcock Drive,stop_code: Wjz1heN, lat: -35.4541126, lng: 149.0869262} | - { name: Woodcock Drive,stop_code: Wjz1heN, lat: -35.4541126, lng: 149.0869262} |
- { name: Donohoe Place,stop_code: Wjz1ic5, lat: -35.4496838, lng: 149.0858515} | - { name: Donohoe Place,stop_code: Wjz1ic5, lat: -35.4496838, lng: 149.0858515} |
- { name: Dempsey Place,stop_code: Wjz1bTA, lat: -35.4422159, lng: 149.0824376} | - { name: Dempsey Place,stop_code: Wjz1bTA, lat: -35.4422159, lng: 149.0824376} |
- { name: Akhurst Grove,stop_code: Wjz1cI3, lat: -35.438868, lng: 149.0804778} | - { name: Akhurst Grove,stop_code: Wjz1cI3, lat: -35.438868, lng: 149.0804778} |
- { name: Mackennal Street,stop_code: Wjz5Lh-, lat: -35.248398, lng: 149.12138} | - { name: Mackennal Street,stop_code: Wjz5Lh-, lat: -35.248398, lng: 149.12138} |
- { name: Dyson Street,stop_code: Wjz5Kve, lat: -35.2497723, lng: 149.1218849} | - { name: Dyson Street,stop_code: Wjz5Kve, lat: -35.2497723, lng: 149.1218849} |
- { name: Miller Street,stop_code: Wjz5CW3, lat: -35.2534813, lng: 149.1160707} | - { name: Miller Street,stop_code: Wjz5CW3, lat: -35.2534813, lng: 149.1160707} |
- { name: Miller Street,stop_code: Wjz5BPB, lat: -35.2580866, lng: 149.1154899} | - { name: Miller Street,stop_code: Wjz5BPB, lat: -35.2580866, lng: 149.1154899} |
- { name: Fairfax Street,stop_code: Wjz5BaH, lat: -35.2589798, lng: 149.1087583} | - { name: Fairfax Street,stop_code: Wjz5BaH, lat: -35.2589798, lng: 149.1087583} |
- { name: Miller Street,stop_code: Wjz5ASf, lat: -35.2613846, lng: 149.1149009} | - { name: Miller Street,stop_code: Wjz5ASf, lat: -35.2613846, lng: 149.1149009} |
- { name: David Street,stop_code: Wjz5zJi, lat: -35.2679801, lng: 149.113807} | - { name: David Street,stop_code: Wjz5zJi, lat: -35.2679801, lng: 149.113807} |
- { name: Nicholson Crescent,stop_code: Wjz5zOq, lat: -35.2700411, lng: 149.1153216} | - { name: Nicholson Crescent,stop_code: Wjz5zOq, lat: -35.2700411, lng: 149.1153216} |
- { name: Boldrewood Street,stop_code: Wjz5GeU, lat: -35.2729264, lng: 149.1200337} | - { name: Boldrewood Street,stop_code: Wjz5GeU, lat: -35.2729264, lng: 149.1200337} |
- { name: Colville Street,stop_code: Wjz6EBY, lat: -35.2403577, lng: 149.1242409} | - { name: Colville Street,stop_code: Wjz6EBY, lat: -35.2403577, lng: 149.1242409} |
- { name: Northbourne Avenue,stop_code: Wjz6Myj, lat: -35.2424881, lng: 149.1344225} | - { name: Northbourne Avenue,stop_code: Wjz6Myj, lat: -35.2424881, lng: 149.1344225} |
- { name: Federal Highway,stop_code: Wjz6Vj2, lat: -35.2363715, lng: 149.1421638} | - { name: Federal Highway,stop_code: Wjz6Vj2, lat: -35.2363715, lng: 149.1421638} |
- { name: Claxton Crescent,stop_code: Wjz6Fze, lat: -35.2360279, lng: 149.123147} | - { name: Claxton Crescent,stop_code: Wjz6Fze, lat: -35.2360279, lng: 149.123147} |
- { name: Barsdell Place,stop_code: Wjz6cjg, lat: -35.2200412, lng: 149.0766172} | - { name: Barsdell Place,stop_code: Wjz6cjg, lat: -35.2200412, lng: 149.0766172} |
- { name: Bean Crescent,stop_code: Wjz6c8c, lat: -35.2217598, lng: 149.0751026} | - { name: Bean Crescent,stop_code: Wjz6c8c, lat: -35.2217598, lng: 149.0751026} |
- { name: Grover Crescent,stop_code: Wjz64Yc, lat: -35.2190101, lng: 149.0723258} | - { name: Grover Crescent,stop_code: Wjz64Yc, lat: -35.2190101, lng: 149.0723258} |
- { name: Bennetts Close,stop_code: Wjz6c7A, lat: -35.2169478, lng: 149.074177} | - { name: Bennetts Close,stop_code: Wjz6c7A, lat: -35.2169478, lng: 149.074177} |
- { name: Pirani Place,stop_code: Wjz6eGq, lat: -35.2096321, lng: 149.0809063} | - { name: Pirani Place,stop_code: Wjz6eGq, lat: -35.2096321, lng: 149.0809063} |
- { name: William Webb Drive,stop_code: Wjz6eoG, lat: -35.2110071, lng: 149.0784661} | - { name: William Webb Drive,stop_code: Wjz6eoG, lat: -35.2110071, lng: 149.0784661} |
- { name: Gleadow Street,stop_code: Wjz65_2, lat: -35.2116258, lng: 149.0722394} | - { name: Gleadow Street,stop_code: Wjz65_2, lat: -35.2116258, lng: 149.0722394} |
- { name: William Webb Drive,stop_code: Wjz64CB, lat: -35.2176067, lng: 149.0687895} | - { name: William Webb Drive,stop_code: Wjz64CB, lat: -35.2176067, lng: 149.0687895} |
- { name: Kerrigan Street,stop_code: Wjr_F9a, lat: -35.1938253, lng: 149.031231} | - { name: Kerrigan Street,stop_code: Wjr_F9a, lat: -35.1938253, lng: 149.031231} |
- { name: Tillyard Drive,stop_code: Wjr_NaX, lat: -35.1930428, lng: 149.043112} | - { name: Tillyard Drive,stop_code: Wjr_NaX, lat: -35.1930428, lng: 149.043112} |
- { name: Reuther Street,stop_code: Wjr_M6A, lat: -35.1956738, lng: 149.0413435} | - { name: Reuther Street,stop_code: Wjr_M6A, lat: -35.1956738, lng: 149.0413435} |
- { name: Shakespeare Crescent,stop_code: Wjr_FV4, lat: -35.1935916, lng: 149.039268} | - { name: Shakespeare Crescent,stop_code: Wjr_FV4, lat: -35.1935916, lng: 149.039268} |
- { name: Lawrence Close,stop_code: Wjr-CnE, lat: -35.206318, lng: 149.0223041} | - { name: Lawrence Close,stop_code: Wjr-CnE, lat: -35.206318, lng: 149.0223041} |
- { name: Pockley Close,stop_code: Wjr-D1B, lat: -35.2045158, lng: 149.0193788} | - { name: Pockley Close,stop_code: Wjr-D1B, lat: -35.2045158, lng: 149.0193788} |
- { name: Osburn Drive,stop_code: Wjr-ux-, lat: -35.2099601, lng: 149.0143872} | - { name: Osburn Drive,stop_code: Wjr-ux-, lat: -35.2099601, lng: 149.0143872} |
- { name: Spofforth Street,stop_code: Wjr-kZV, lat: -35.2186221, lng: 149.0075381} | - { name: Spofforth Street,stop_code: Wjr-kZV, lat: -35.2186221, lng: 149.0075381} |
- { name: Fullagar Crescent,stop_code: Wjr-yDR, lat: -35.2278849, lng: 149.0252438} | - { name: Fullagar Crescent,stop_code: Wjr-yDR, lat: -35.2278849, lng: 149.0252438} |
- { name: Dethridge Street,stop_code: Wjr-G49, lat: -35.2302721, lng: 149.0298424} | - { name: Dethridge Street,stop_code: Wjr-G49, lat: -35.2302721, lng: 149.0298424} |
- { name: Hodges Street,stop_code: Wjr-GcG, lat: -35.2301944, lng: 149.0319226} | - { name: Hodges Street,stop_code: Wjr-GcG, lat: -35.2301944, lng: 149.0319226} |
- { name: Southern Cross Drive,stop_code: Wjr-Hi1, lat: -35.2261454, lng: 149.032398} | - { name: Southern Cross Drive,stop_code: Wjr-Hi1, lat: -35.2261454, lng: 149.032398} |
- { name: Albany Street,stop_code: WjzcgLt, lat: -35.3267279, lng: 149.1797667} | - { name: Albany Street,stop_code: WjzcgLt, lat: -35.3267279, lng: 149.1797667} |
- { name: Collie Street,stop_code: Wjzcgzn, lat: -35.3293028, lng: 149.178368} | - { name: Collie Street,stop_code: Wjzcgzn, lat: -35.3293028, lng: 149.178368} |
- { name: Faulding Street,stop_code: WjzbfzE, lat: -35.3354178, lng: 149.1678599} | - { name: Faulding Street,stop_code: WjzbfzE, lat: -35.3354178, lng: 149.1678599} |
- { name: Wormald Street,stop_code: Wjzbfr6, lat: -35.3349204, lng: 149.1655287} | - { name: Wormald Street,stop_code: Wjzbfr6, lat: -35.3349204, lng: 149.1655287} |
- { name: Lithgow Street,stop_code: Wjzc8im, lat: -35.3300635, lng: 149.1644887} | - { name: Lithgow Street,stop_code: Wjzc8im, lat: -35.3300635, lng: 149.1644887} |
- { name: Ipswich Street,stop_code: Wjzc8c1, lat: -35.3291272, lng: 149.1628031} | - { name: Ipswich Street,stop_code: Wjzc8c1, lat: -35.3291272, lng: 149.1628031} |
- { name: Whyalla Street,stop_code: Wjzbn5y, lat: -35.3338671, lng: 149.1730601} | - { name: Whyalla Street,stop_code: Wjzbn5y, lat: -35.3338671, lng: 149.1730601} |
- { name: Hamelin Crescent,stop_code: Wjz3TZj, lat: -35.3338162, lng: 149.1384399} | - { name: Hamelin Crescent,stop_code: Wjz3TZj, lat: -35.3338162, lng: 149.1384399} |
- { name: Sprent Street,stop_code: Wjz3_o2, lat: -35.3372978, lng: 149.1435685} | - { name: Sprent Street,stop_code: Wjz3_o2, lat: -35.3372978, lng: 149.1435685} |
- { name: Goyder Street,stop_code: Wjz3-r-, lat: -35.3403989, lng: 149.1448954} | - { name: Goyder Street,stop_code: Wjz3-r-, lat: -35.3403989, lng: 149.1448954} |
- { name: Jerrabomberra Avenue,stop_code: Wjzb5vw, lat: -35.3436462, lng: 149.155296} | - { name: Jerrabomberra Avenue,stop_code: Wjzb5vw, lat: -35.3436462, lng: 149.155296} |
- { name: Northbourne Avenue,stop_code: Wjz5N7c, lat: -35.2774279, lng: 149.1287001} | - { name: Northbourne Avenue,stop_code: Wjz5N7c, lat: -35.2774279, lng: 149.1287001} |
- { name: Crawford Street,stop_code: WjzbYnD, lat: -35.3485475, lng: 149.2307657} | - { name: Crawford Street,stop_code: WjzbYnD, lat: -35.3485475, lng: 149.2307657} |
- { name: Uriarra Road,stop_code: WjzbZ3m, lat: -35.3459335, lng: 149.227726} | - { name: Uriarra Road,stop_code: WjzbZ3m, lat: -35.3459335, lng: 149.227726} |
- { name: Farrer Place,stop_code: WjzbXmQ, lat: -35.3550126, lng: 149.2311068} | - { name: Farrer Place,stop_code: WjzbXmQ, lat: -35.3550126, lng: 149.2311068} |
- { name: Crawford Street,stop_code: WjzbYzg, lat: -35.3519226, lng: 149.2332104} | - { name: Crawford Street,stop_code: WjzbYzg, lat: -35.3519226, lng: 149.2332104} |
- { name: Yass Road,stop_code: Wjzj5BH, lat: -35.3447463, lng: 149.2446946} | - { name: Yass Road,stop_code: Wjzj5BH, lat: -35.3447463, lng: 149.2446946} |
- { name: Endurance Avenue,stop_code: Wjzj6z9, lat: -35.3407864, lng: 149.2440483} | - { name: Endurance Avenue,stop_code: Wjzj6z9, lat: -35.3407864, lng: 149.2440483} |
- { name: Erin Street,stop_code: WjzbZqS, lat: -35.3465484, lng: 149.2325494} | - { name: Erin Street,stop_code: WjzbZqS, lat: -35.3465484, lng: 149.2325494} |
- { name: Alinga Street,stop_code: Wjz5F-1, lat: -35.2783161, lng: 149.1271286} | - { name: Alinga Street,stop_code: Wjz5F-1, lat: -35.2783161, lng: 149.1271286} |
- { name: Crawford Street,stop_code: WjzbZ77, lat: -35.3430401, lng: 149.2274615} | - { name: Crawford Street,stop_code: WjzbZ77, lat: -35.3430401, lng: 149.2274615} |
- { name: Alinga Street,stop_code: Wjz5N6V, lat: -35.2783725, lng: 149.1297843} | - { name: Alinga Street,stop_code: Wjz5N6V, lat: -35.2783725, lng: 149.1297843} |
- { name: Uriarra Road,stop_code: WjzbRdl, lat: -35.3446304, lng: 149.2181472} | - { name: Uriarra Road,stop_code: WjzbRdl, lat: -35.3446304, lng: 149.2181472} |
- { name: Uriarra Road,stop_code: WjzbJSj, lat: -35.3441148, lng: 149.2140644} | - { name: Uriarra Road,stop_code: WjzbJSj, lat: -35.3441148, lng: 149.2140644} |
- { name: Uriarra Road,stop_code: WjzbZ3n, lat: -35.3458022, lng: 149.2277877} | - { name: Uriarra Road,stop_code: WjzbZ3n, lat: -35.3458022, lng: 149.2277877} |
- { name: Uriarra Road,stop_code: WjzbRBs, lat: -35.344722, lng: 149.2224303} | - { name: Uriarra Road,stop_code: WjzbRBs, lat: -35.344722, lng: 149.2224303} |
- { name: Alinga Street,stop_code: Wjz5N5_, lat: -35.2785242, lng: 149.1297348} | - { name: Alinga Street,stop_code: Wjz5N5_, lat: -35.2785242, lng: 149.1297348} |
- { name: Alinga Street,stop_code: Wjz5Ndm, lat: -35.2785658, lng: 149.1301727} | - { name: Alinga Street,stop_code: Wjz5Ndm, lat: -35.2785658, lng: 149.1301727} |
- { name: Woodhill Link,stop_code: WjzaArS, lat: -35.3953167, lng: 149.1995002} | - { name: Woodhill Link,stop_code: WjzaArS, lat: -35.3953167, lng: 149.1995002} |
- { name: Nicholii Loop,stop_code: WjzaAXA, lat: -35.3954806, lng: 149.2047447} | - { name: Nicholii Loop,stop_code: WjzaAXA, lat: -35.3954806, lng: 149.2047447} |
- { name: Mariners Court,stop_code: WjzaAdv, lat: -35.3938794, lng: 149.1962366} | - { name: Mariners Court,stop_code: WjzaAdv, lat: -35.3938794, lng: 149.1962366} |
- { name: Canberra Avenue,stop_code: WjzbBu_, lat: -35.3437537, lng: 149.1997253} | - { name: Canberra Avenue,stop_code: WjzbBu_, lat: -35.3437537, lng: 149.1997253} |
- { name: Broughton Place,stop_code: WjzbPXf, lat: -35.3567667, lng: 149.2261434} | - { name: Broughton Place,stop_code: WjzbPXf, lat: -35.3567667, lng: 149.2261434} |
- { name: Tharwa Road,stop_code: WjzbPpi, lat: -35.3586252, lng: 149.2208441} | - { name: Tharwa Road,stop_code: WjzbPpi, lat: -35.3586252, lng: 149.2208441} |
- { name: Hayes Street,stop_code: WjzbWDe, lat: -35.3596366, lng: 149.2330229} | - { name: Hayes Street,stop_code: WjzbWDe, lat: -35.3596366, lng: 149.2330229} |
- { name: Cooma Street,stop_code: WjzbXwk, lat: -35.3591416, lng: 149.2331706} | - { name: Cooma Street,stop_code: WjzbXwk, lat: -35.3591416, lng: 149.2331706} |
- { name: Cooma Street,stop_code: WjzbVxf, lat: -35.369131, lng: 149.233084} | - { name: Cooma Street,stop_code: WjzbVxf, lat: -35.369131, lng: 149.233084} |
- { name: Cooma Street,stop_code: WjzbVy2, lat: -35.3689098, lng: 149.232863} | - { name: Cooma Street,stop_code: WjzbVy2, lat: -35.3689098, lng: 149.232863} |
- { name: Old Cooma Road,stop_code: Wjz9JdV, lat: -35.4328562, lng: 149.2080577} | - { name: Old Cooma Road,stop_code: Wjz9JdV, lat: -35.4328562, lng: 149.2080577} |
- { name: Cooma Street,stop_code: WjzbXAb, lat: -35.3564366, lng: 149.2330826} | - { name: Cooma Street,stop_code: WjzbXAb, lat: -35.3564366, lng: 149.2330826} |
- { name: Kinlyside Avenue,stop_code: WjzbwuF, lat: -35.3717405, lng: 149.1994726} | - { name: Kinlyside Avenue,stop_code: WjzbwuF, lat: -35.3717405, lng: 149.1994726} |
- { name: Darmody Place,stop_code: WjzbwDR, lat: -35.37069, lng: 149.2008683} | - { name: Darmody Place,stop_code: WjzbwDR, lat: -35.37069, lng: 149.2008683} |
- { name: Halloran Drive,stop_code: WjzbwMd, lat: -35.3755316, lng: 149.2028602} | - { name: Halloran Drive,stop_code: WjzbwMd, lat: -35.3755316, lng: 149.2028602} |
- { name: Maloney Street,stop_code: WjzbG5c, lat: -35.3611934, lng: 149.2054955} | - { name: Maloney Street,stop_code: WjzbG5c, lat: -35.3611934, lng: 149.2054955} |
- { name: Kendall Avenue North,stop_code: WjzbJRl, lat: -35.3445935, lng: 149.2139248} | - { name: Kendall Avenue North,stop_code: WjzbJRl, lat: -35.3445935, lng: 149.2139248} |
- { name: Canberra Avenue,stop_code: WjzbfPy, lat: -35.3352335, lng: 149.1703836} | - { name: Canberra Avenue,stop_code: WjzbfPy, lat: -35.3352335, lng: 149.1703836} |
- { name: Flinders Way,stop_code: Wjz4OqF, lat: -35.3195494, lng: 149.1335622} | - { name: Flinders Way,stop_code: Wjz4OqF, lat: -35.3195494, lng: 149.1335622} |
- { name: Burbury Close,stop_code: Wjz4Pk_, lat: -35.3121631, lng: 149.1324213} | - { name: Burbury Close,stop_code: Wjz4Pk_, lat: -35.3121631, lng: 149.1324213} |
- { name: Mort Street,stop_code: Wjz5NeF, lat: -35.2783224, lng: 149.130726} | - { name: Mort Street,stop_code: Wjz5NeF, lat: -35.2783224, lng: 149.130726} |
- { name: East Row,stop_code: Wjz5Ndz, lat: -35.2788601, lng: 149.130649} | - { name: East Row,stop_code: Wjz5Ndz, lat: -35.2788601, lng: 149.130649} |
- { name: East Row,stop_code: Wjz5NcA, lat: -35.2794346, lng: 149.1305879} | - { name: East Row,stop_code: Wjz5NcA, lat: -35.2794346, lng: 149.1305879} |
- { name: East Row,stop_code: Wjz5Nds, lat: -35.2787886, lng: 149.1304779} | - { name: East Row,stop_code: Wjz5Nds, lat: -35.2787886, lng: 149.1304779} |
- { name: Justinian Street,stop_code: Wjz3mPO, lat: -35.3407241, lng: 149.0937831} | - { name: Justinian Street,stop_code: Wjz3mPO, lat: -35.3407241, lng: 149.0937831} |
- { name: Wisdom Street,stop_code: Wjz3mI_, lat: -35.3396179, lng: 149.0925471} | - { name: Wisdom Street,stop_code: Wjz3mI_, lat: -35.3396179, lng: 149.0925471} |
- { name: Birdwood Street,stop_code: Wjz3vrf, lat: -35.3348497, lng: 149.099817} | - { name: Birdwood Street,stop_code: Wjz3vrf, lat: -35.3348497, lng: 149.099817} |
- { name: McNicoll Street,stop_code: Wjz3vqN, lat: -35.3360119, lng: 149.1006409} | - { name: McNicoll Street,stop_code: Wjz3vqN, lat: -35.3360119, lng: 149.1006409} |
- { name: Ingamells Street,stop_code: Wjz3C4O, lat: -35.3400601, lng: 149.1074834} | - { name: Ingamells Street,stop_code: Wjz3C4O, lat: -35.3400601, lng: 149.1074834} |
- { name: Ingamells Street,stop_code: Wjz3uQf, lat: -35.339661, lng: 149.1040329} | - { name: Ingamells Street,stop_code: Wjz3uQf, lat: -35.339661, lng: 149.1040329} |
- { name: Ingamells Street,stop_code: Wjz3C4q, lat: -35.3400391, lng: 149.106977} | - { name: Ingamells Street,stop_code: Wjz3C4q, lat: -35.3400391, lng: 149.106977} |
- { name: Dennis Street,stop_code: Wjz3B5o, lat: -35.344996, lng: 149.1070285} | - { name: Dennis Street,stop_code: Wjz3B5o, lat: -35.344996, lng: 149.1070285} |
- { name: Yamba Drive,stop_code: Wjz3lVM, lat: -35.3477625, lng: 149.0952366} | - { name: Yamba Drive,stop_code: Wjz3lVM, lat: -35.3477625, lng: 149.0952366} |
- { name: Yamba Drive,stop_code: Wjz3lVG, lat: -35.3476365, lng: 149.095065} | - { name: Yamba Drive,stop_code: Wjz3lVG, lat: -35.3476365, lng: 149.095065} |
- { name: Kent Street,stop_code: Wjz3n-H, lat: -35.3331304, lng: 149.0950356} | - { name: Kent Street,stop_code: Wjz3n-H, lat: -35.3331304, lng: 149.0950356} |
- { name: Yamba Drive,stop_code: Wjz3mAg, lat: -35.3402021, lng: 149.0903851} | - { name: Yamba Drive,stop_code: Wjz3mAg, lat: -35.3402021, lng: 149.0903851} |
- { name: Kent Street,stop_code: Wjz4q8_, lat: -35.3203709, lng: 149.0981179} | - { name: Kent Street,stop_code: Wjz4q8_, lat: -35.3203709, lng: 149.0981179} |
- { name: Kent Street,stop_code: Wjz4p1K, lat: -35.325336, lng: 149.0963669} | - { name: Kent Street,stop_code: Wjz4p1K, lat: -35.325336, lng: 149.0963669} |
- { name: Kent Street,stop_code: Wjz4p2R, lat: -35.3247128, lng: 149.0966244} | - { name: Kent Street,stop_code: Wjz4p2R, lat: -35.3247128, lng: 149.0966244} |
- { name: Kent Street,stop_code: Wjz4gYg, lat: -35.329258, lng: 149.0944878} | - { name: Kent Street,stop_code: Wjz4gYg, lat: -35.329258, lng: 149.0944878} |
- { name: Barry Drive,stop_code: Wjz5G6U, lat: -35.2729086, lng: 149.1187429} | - { name: Barry Drive,stop_code: Wjz5G6U, lat: -35.2729086, lng: 149.1187429} |
- { name: McCaughey Street,stop_code: Wjz5Hw8, lat: -35.2715996, lng: 149.1231371} | - { name: McCaughey Street,stop_code: Wjz5Hw8, lat: -35.2715996, lng: 149.1231371} |
- { name: McCaughey Street,stop_code: Wjz5HDd, lat: -35.2662951, lng: 149.1231711} | - { name: McCaughey Street,stop_code: Wjz5HDd, lat: -35.2662951, lng: 149.1231711} |
- { name: Macpherson Street,stop_code: Wjz5Iqp, lat: -35.2646152, lng: 149.1221727} | - { name: Macpherson Street,stop_code: Wjz5Iqp, lat: -35.2646152, lng: 149.1221727} |
- { name: Bluebell Street,stop_code: Wjz5IjX, lat: -35.2637604, lng: 149.1215219} | - { name: Bluebell Street,stop_code: Wjz5IjX, lat: -35.2637604, lng: 149.1215219} |
- { name: Macarthur Avenue,stop_code: Wjz5Jpp, lat: -35.2597672, lng: 149.1221194} | - { name: Macarthur Avenue,stop_code: Wjz5Jpp, lat: -35.2597672, lng: 149.1221194} |
- { name: Hovea Street,stop_code: Wjz5Jyz, lat: -35.258945, lng: 149.123718} | - { name: Hovea Street,stop_code: Wjz5Jyz, lat: -35.258945, lng: 149.123718} |
- { name: Hovea Street,stop_code: Wjz5JzP, lat: -35.2582197, lng: 149.123961} | - { name: Hovea Street,stop_code: Wjz5JzP, lat: -35.2582197, lng: 149.123961} |
- { name: Scrivener Street,stop_code: Wjz5Juf, lat: -35.2558204, lng: 149.1217923} | - { name: Scrivener Street,stop_code: Wjz5Juf, lat: -35.2558204, lng: 149.1217923} |
- { name: Brigalow Street,stop_code: Wjz5KgQ, lat: -35.2547172, lng: 149.1212395} | - { name: Brigalow Street,stop_code: Wjz5KgQ, lat: -35.2547172, lng: 149.1212395} |
- { name: Northbourne Avenue,stop_code: Wjz5N5k, lat: -35.2787905, lng: 149.1288627} | - { name: Northbourne Avenue,stop_code: Wjz5N5k, lat: -35.2787905, lng: 149.1288627} |
- { name: Northbourne Avenue,stop_code: Wjz5N4J, lat: -35.2793571, lng: 149.1293659} | - { name: Northbourne Avenue,stop_code: Wjz5N4J, lat: -35.2793571, lng: 149.1293659} |
- { name: Tillyard Drive,stop_code: Wjr-LNq, lat: -35.2048275, lng: 149.0383141} | - { name: Tillyard Drive,stop_code: Wjr-LNq, lat: -35.2048275, lng: 149.0383141} |
- { name: College Street,stop_code: Wjz68W5, lat: -35.2423221, lng: 149.0831522} | - { name: College Street,stop_code: Wjz68W5, lat: -35.2423221, lng: 149.0831522} |
- { name: College Street,stop_code: Wjz6gia, lat: -35.2425616, lng: 149.0874888} | - { name: College Street,stop_code: Wjz6gia, lat: -35.2425616, lng: 149.0874888} |
- { name: Haydon Drive,stop_code: Wjz5maK, lat: -35.2532079, lng: 149.0867657} | - { name: Haydon Drive,stop_code: Wjz5maK, lat: -35.2532079, lng: 149.0867657} |
- { name: Marcus Clarke Street,stop_code: Wjz5GMT, lat: -35.2764151, lng: 149.1267199} | - { name: Marcus Clarke Street,stop_code: Wjz5GMT, lat: -35.2764151, lng: 149.1267199} |
- { name: Flynn Drive,stop_code: Wjz4KNu, lat: -35.2978611, lng: 149.1263289} | - { name: Flynn Drive,stop_code: Wjz4KNu, lat: -35.2978611, lng: 149.1263289} |
- { name: Beaconsfield Street,stop_code: WjzbnGh, lat: -35.3359862, lng: 149.1796321} | - { name: Beaconsfield Street,stop_code: WjzbnGh, lat: -35.3359862, lng: 149.1796321} |
- { name: Flinders Way,stop_code: Wjz4Ox0, lat: -35.3203301, lng: 149.1339648} | - { name: Flinders Way,stop_code: Wjz4Ox0, lat: -35.3203301, lng: 149.1339648} |
- { name: Flinders Way,stop_code: Wjz4OpP, lat: -35.320064, lng: 149.1335699} | - { name: Flinders Way,stop_code: Wjz4OpP, lat: -35.320064, lng: 149.1335699} |
- { name: Captain Cook Crescent,stop_code: Wjz4NDP, lat: -35.3214366, lng: 149.1350462} | - { name: Captain Cook Crescent,stop_code: Wjz4NDP, lat: -35.3214366, lng: 149.1350462} |
- { name: Dominion Circuit,stop_code: Wjz4Pa9, lat: -35.314076, lng: 149.1301281} | - { name: Dominion Circuit,stop_code: Wjz4Pa9, lat: -35.314076, lng: 149.1301281} |
- { name: Summit Track,stop_code: Wjz5qbi, lat: -35.2748058, lng: 149.0972461} | - { name: Summit Track,stop_code: Wjz5qbi, lat: -35.2748058, lng: 149.0972461} |
- { name: Alpen Street,stop_code: Wjr-_Ua, lat: -35.2054509, lng: 149.0613315} | - { name: Alpen Street,stop_code: Wjr-_Ua, lat: -35.2054509, lng: 149.0613315} |
- { name: Keenan Street,stop_code: Wjz66kP, lat: -35.2081588, lng: 149.066382} | - { name: Keenan Street,stop_code: Wjz66kP, lat: -35.2081588, lng: 149.066382} |
- { name: Copland Drive,stop_code: Wjz66lY, lat: -35.2073806, lng: 149.0665685} | - { name: Copland Drive,stop_code: Wjz66lY, lat: -35.2073806, lng: 149.0665685} |
- { name: Meagher Place,stop_code: Wjz664q, lat: -35.2082119, lng: 149.0631086} | - { name: Meagher Place,stop_code: Wjz664q, lat: -35.2082119, lng: 149.0631086} |
- { name: Meagher Place,stop_code: Wjz664g, lat: -35.2083936, lng: 149.0629132} | - { name: Meagher Place,stop_code: Wjz664g, lat: -35.2083936, lng: 149.0629132} |
- { name: Parkes Place,stop_code: Wjz4Rs-, lat: -35.3012441, lng: 149.1338254} | - { name: Parkes Place,stop_code: Wjz4Rs-, lat: -35.3012441, lng: 149.1338254} |
- { name: Alpen Street,stop_code: Wjr-_Uj, lat: -35.2054305, lng: 149.0615985} | - { name: Alpen Street,stop_code: Wjr-_Uj, lat: -35.2054305, lng: 149.0615985} |
- { name: Lennox Crossing,stop_code: Wjz4Lh5, lat: -35.2924038, lng: 149.1201999} | - { name: Lennox Crossing,stop_code: Wjz4Lh5, lat: -35.2924038, lng: 149.1201999} |
- { name: Russell Drive,stop_code: Wjzc54R, lat: -35.3013866, lng: 149.1515283} | - { name: Russell Drive,stop_code: Wjzc54R, lat: -35.3013866, lng: 149.1515283} |
- { name: Russell Drive,stop_code: Wjzc60A, lat: -35.2986953, lng: 149.151155} | - { name: Russell Drive,stop_code: Wjzc60A, lat: -35.2986953, lng: 149.151155} |
- { name: Russell Drive,stop_code: Wjz4-WZ, lat: -35.2972194, lng: 149.1503113} | - { name: Russell Drive,stop_code: Wjz4-WZ, lat: -35.2972194, lng: 149.1503113} |
- { name: Catchpole Street,stop_code: Wjz56Hh, lat: -35.25291, lng: 149.0697814} | - { name: Catchpole Street,stop_code: Wjz56Hh, lat: -35.25291, lng: 149.0697814} |
- { name: Russell Drive,stop_code: Wjz4-WL, lat: -35.2970826, lng: 149.149927} | - { name: Russell Drive,stop_code: Wjz4-WL, lat: -35.2970826, lng: 149.149927} |
- { name: Kings Avenue,stop_code: Wjz4RFJ, lat: -35.3034224, lng: 149.1361467} | - { name: Kings Avenue,stop_code: Wjz4RFJ, lat: -35.3034224, lng: 149.1361467} |
- { name: Kings Avenue,stop_code: Wjz4RwH, lat: -35.3042846, lng: 149.1348585} | - { name: Kings Avenue,stop_code: Wjz4RwH, lat: -35.3042846, lng: 149.1348585} |
- { name: Bourke Street,stop_code: Wjz4PuC, lat: -35.3109115, lng: 149.1332413} | - { name: Bourke Street,stop_code: Wjz4PuC, lat: -35.3109115, lng: 149.1332413} |
- { name: Sydney Avenue,stop_code: Wjz4P6x, lat: -35.3112617, lng: 149.1291119} | - { name: Sydney Avenue,stop_code: Wjz4P6x, lat: -35.3112617, lng: 149.1291119} |
- { name: Waldock Street,stop_code: Wjz3bdj, lat: -35.3557447, lng: 149.0753424} | - { name: Waldock Street,stop_code: Wjz3bdj, lat: -35.3557447, lng: 149.0753424} |
- { name: Russell Drive,stop_code: Wjz4-Rc, lat: -35.2952651, lng: 149.1479687} | - { name: Russell Drive,stop_code: Wjz4-Rc, lat: -35.2952651, lng: 149.1479687} |
- { name: Keenan Street,stop_code: Wjr--W0, lat: -35.2097244, lng: 149.0611869} | - { name: Keenan Street,stop_code: Wjr--W0, lat: -35.2097244, lng: 149.0611869} |
- { name: Keenan Street,stop_code: Wjr--W9, lat: -35.2096897, lng: 149.061394} | - { name: Keenan Street,stop_code: Wjr--W9, lat: -35.2096897, lng: 149.061394} |
- { name: Chifley Place,stop_code: Wjz3cal, lat: -35.3521568, lng: 149.0752845} | - { name: Chifley Place,stop_code: Wjz3cal, lat: -35.3521568, lng: 149.0752845} |
- { name: Waldock Street,stop_code: Wjz3bdl, lat: -35.3556201, lng: 149.075221} | - { name: Waldock Street,stop_code: Wjz3bdl, lat: -35.3556201, lng: 149.075221} |
- { name: Wilsmore Crescent,stop_code: Wjz3b9v, lat: -35.3581498, lng: 149.0754026} | - { name: Wilsmore Crescent,stop_code: Wjz3b9v, lat: -35.3581498, lng: 149.0754026} |
- { name: Brinsmead Street,stop_code: Wjz39RI, lat: -35.3666487, lng: 149.0827357} | - { name: Brinsmead Street,stop_code: Wjz39RI, lat: -35.3666487, lng: 149.0827357} |
- { name: McDonald Street,stop_code: Wjz3ceV, lat: -35.3497899, lng: 149.0761589} | - { name: McDonald Street,stop_code: Wjz3ceV, lat: -35.3497899, lng: 149.0761589} |
- { name: Kingsford Smith Drive,stop_code: Wjr-RKi, lat: -35.2123821, lng: 149.0478391} | - { name: Kingsford Smith Drive,stop_code: Wjr-RKi, lat: -35.2123821, lng: 149.0478391} |
- { name: Conley Drive,stop_code: Wjr-RZx, lat: -35.213153, lng: 149.050965} | - { name: Conley Drive,stop_code: Wjr-RZx, lat: -35.213153, lng: 149.050965} |
- { name: Grainger Circuit,stop_code: Wjr-RT-, lat: -35.2113153, lng: 149.0500244} | - { name: Grainger Circuit,stop_code: Wjr-RT-, lat: -35.2113153, lng: 149.0500244} |
- { name: Horsley Crescent,stop_code: Wjr-Zk3, lat: -35.2136037, lng: 149.0543575} | - { name: Horsley Crescent,stop_code: Wjr-Zk3, lat: -35.2136037, lng: 149.0543575} |
- { name: Horsley Crescent,stop_code: Wjr-Zk5, lat: -35.2134943, lng: 149.0543506} | - { name: Horsley Crescent,stop_code: Wjr-Zk5, lat: -35.2134943, lng: 149.0543506} |
- { name: Verbrugghen Street,stop_code: Wjr-ZJc, lat: -35.2128875, lng: 149.0586429} | - { name: Verbrugghen Street,stop_code: Wjr-ZJc, lat: -35.2128875, lng: 149.0586429} |
- { name: Copland Drive,stop_code: Wjr-ZRJ, lat: -35.2127453, lng: 149.0607491} | - { name: Copland Drive,stop_code: Wjr-ZRJ, lat: -35.2127453, lng: 149.0607491} |
- { name: Clifford Crescent,stop_code: Wjz66fw, lat: -35.2063185, lng: 149.0646037} | - { name: Clifford Crescent,stop_code: Wjz66fw, lat: -35.2063185, lng: 149.0646037} |
- { name: Clifford Crescent,stop_code: Wjz66fx, lat: -35.2062629, lng: 149.0647145} | - { name: Clifford Crescent,stop_code: Wjz66fx, lat: -35.2062629, lng: 149.0647145} |
- { name: Crossley Close,stop_code: Wjr--Lw, lat: -35.2063011, lng: 149.059093} | - { name: Crossley Close,stop_code: Wjr--Lw, lat: -35.2063011, lng: 149.059093} |
- { name: Crossley Close,stop_code: Wjr--Ki, lat: -35.2068427, lng: 149.0588291} | - { name: Crossley Close,stop_code: Wjr--Ki, lat: -35.2068427, lng: 149.0588291} |
- { name: Le Gallienne Street,stop_code: Wjr--md, lat: -35.2066211, lng: 149.0544526} | - { name: Le Gallienne Street,stop_code: Wjr--md, lat: -35.2066211, lng: 149.0544526} |
- { name: Henslowe Place,stop_code: Wjr--6k, lat: -35.2066759, lng: 149.0519744} | - { name: Henslowe Place,stop_code: Wjr--6k, lat: -35.2066759, lng: 149.0519744} |
- { name: Pattinson Crescent,stop_code: Wjr-SS5, lat: -35.2065999, lng: 149.0489353} | - { name: Pattinson Crescent,stop_code: Wjr-SS5, lat: -35.2065999, lng: 149.0489353} |
- { name: Lathlain Street,stop_code: Wjz60d1, lat: -35.2406019, lng: 149.0638958} | - { name: Lathlain Street,stop_code: Wjz60d1, lat: -35.2406019, lng: 149.0638958} |
- { name: Weedon Close,stop_code: Wjz60c5, lat: -35.2408972, lng: 149.0639885} | - { name: Weedon Close,stop_code: Wjz60c5, lat: -35.2408972, lng: 149.0639885} |
- { name: Lathlain Street,stop_code: Wjz605_, lat: -35.2400517, lng: 149.0637152} | - { name: Lathlain Street,stop_code: Wjz605_, lat: -35.2400517, lng: 149.0637152} |
- { name: Lathlain Street,stop_code: Wjz606I, lat: -35.2396656, lng: 149.0633992} | - { name: Lathlain Street,stop_code: Wjz606I, lat: -35.2396656, lng: 149.0633992} |
- { name: Daley Road,stop_code: Wjz5yXo, lat: -35.2749982, lng: 149.1166312} | - { name: Daley Road,stop_code: Wjz5yXo, lat: -35.2749982, lng: 149.1166312} |
- { name: Macarthur Avenue,stop_code: Wjz5Jaa, lat: -35.2590481, lng: 149.1191164} | - { name: Macarthur Avenue,stop_code: Wjz5Jaa, lat: -35.2590481, lng: 149.1191164} |
- { name: Bimbimbie Street,stop_code: Wjz68Yy, lat: -35.2411603, lng: 149.0838439} | - { name: Bimbimbie Street,stop_code: Wjz68Yy, lat: -35.2411603, lng: 149.0838439} |
- { name: Carandini Street,stop_code: Wjr-_3A, lat: -35.2032823, lng: 149.0522538} | - { name: Carandini Street,stop_code: Wjr-_3A, lat: -35.2032823, lng: 149.0522538} |
- { name: Kingsford Smith Drive,stop_code: Wjr-_Hp, lat: -35.2034703, lng: 149.0589653} | - { name: Kingsford Smith Drive,stop_code: Wjr-_Hp, lat: -35.2034703, lng: 149.0589653} |
- { name: Alpen Street,stop_code: Wjr-_Og, lat: -35.2042571, lng: 149.0602273} | - { name: Alpen Street,stop_code: Wjr-_Og, lat: -35.2042571, lng: 149.0602273} |
- { name: Colborne Place,stop_code: Wjz670_, lat: -35.205061, lng: 149.0637667} | - { name: Colborne Place,stop_code: Wjz670_, lat: -35.205061, lng: 149.0637667} |
- { name: Hancock Street,stop_code: Wjz67k1, lat: -35.2028461, lng: 149.0653269} | - { name: Hancock Street,stop_code: Wjz67k1, lat: -35.2028461, lng: 149.0653269} |
- { name: Hancock Street,stop_code: Wjz67kk, lat: -35.2025967, lng: 149.0657125} | - { name: Hancock Street,stop_code: Wjz67kk, lat: -35.2025967, lng: 149.0657125} |
- { name: Copland Drive,stop_code: Wjr-YdU, lat: -35.2186771, lng: 149.0542242} | - { name: Copland Drive,stop_code: Wjr-YdU, lat: -35.2186771, lng: 149.0542242} |
- { name: Copland Drive,stop_code: Wjr-YcT, lat: -35.2187393, lng: 149.0539932} | - { name: Copland Drive,stop_code: Wjr-YcT, lat: -35.2187393, lng: 149.0539932} |
- { name: John Cleland Crescent,stop_code: Wjr-Xno, lat: -35.2227935, lng: 149.0548844} | - { name: John Cleland Crescent,stop_code: Wjr-Xno, lat: -35.2227935, lng: 149.0548844} |
- { name: John Cleland Crescent,stop_code: Wjr-Xky, lat: -35.2247107, lng: 149.0549856} | - { name: John Cleland Crescent,stop_code: Wjr-Xky, lat: -35.2247107, lng: 149.0549856} |
- { name: Coulter Drive,stop_code: WjrZ_tn, lat: -35.2455787, lng: 149.0560808} | - { name: Coulter Drive,stop_code: WjrZ_tn, lat: -35.2455787, lng: 149.0560808} |
- { name: Coulter Drive,stop_code: WjrZ_so, lat: -35.2468109, lng: 149.0562979} | - { name: Coulter Drive,stop_code: WjrZ_so, lat: -35.2468109, lng: 149.0562979} |
- { name: Wiseman Street,stop_code: Wjz56XB, lat: -35.2526099, lng: 149.0728793} | - { name: Wiseman Street,stop_code: Wjz56XB, lat: -35.2526099, lng: 149.0728793} |
- { name: Fulton Street,stop_code: Wjz5711, lat: -35.2488233, lng: 149.0625779} | - { name: Fulton Street,stop_code: Wjz5711, lat: -35.2488233, lng: 149.0625779} |
- { name: Melrose Drive,stop_code: Wjz3eRR, lat: -35.3390911, lng: 149.082759} | - { name: Melrose Drive,stop_code: Wjz3eRR, lat: -35.3390911, lng: 149.082759} |
- { name: Furzer Street,stop_code: Wjz3m31, lat: -35.3408061, lng: 149.0844784} | - { name: Furzer Street,stop_code: Wjz3m31, lat: -35.3408061, lng: 149.0844784} |
- { name: Barton Highway,stop_code: Wjz79-a, lat: -35.1903384, lng: 149.0833628} | - { name: Barton Highway,stop_code: Wjz79-a, lat: -35.1903384, lng: 149.0833628} |
- { name: Akuna Street,stop_code: Wjz5Nht, lat: -35.281465, lng: 149.131837} | - { name: Akuna Street,stop_code: Wjz5Nht, lat: -35.281465, lng: 149.131837} |
- { name: College Street,stop_code: Wjz6giR, lat: -35.2422899, lng: 149.0883846} | - { name: College Street,stop_code: Wjz6giR, lat: -35.2422899, lng: 149.0883846} |
- { name: Wisdom Street,stop_code: Wjz3mQ5, lat: -35.339761, lng: 149.0927558} | - { name: Wisdom Street,stop_code: Wjz3mQ5, lat: -35.339761, lng: 149.0927558} |
- { name: Sharwood Crescent,stop_code: Wjr-ZXo, lat: -35.214551, lng: 149.0617978} | - { name: Sharwood Crescent,stop_code: Wjr-ZXo, lat: -35.214551, lng: 149.0617978} |
- { name: Deffell Street,stop_code: Wjz652H, lat: -35.2150139, lng: 149.0634241} | - { name: Deffell Street,stop_code: Wjz652H, lat: -35.2150139, lng: 149.0634241} |
- { name: Callaghan Street,stop_code: Wjz65ik, lat: -35.2149321, lng: 149.0656677} | - { name: Callaghan Street,stop_code: Wjz65ik, lat: -35.2149321, lng: 149.0656677} |
- { name: Alderman Street,stop_code: Wjz65rA, lat: -35.2142446, lng: 149.0673143} | - { name: Alderman Street,stop_code: Wjz65rA, lat: -35.2142446, lng: 149.0673143} |
- { name: Norton Street,stop_code: Wjz65Hy, lat: -35.2143691, lng: 149.0701627} | - { name: Norton Street,stop_code: Wjz65Hy, lat: -35.2143691, lng: 149.0701627} |
- { name: Norton Street,stop_code: Wjz65GS, lat: -35.2147682, lng: 149.0705542} | - { name: Norton Street,stop_code: Wjz65GS, lat: -35.2147682, lng: 149.0705542} |
- { name: Stenhouse Close,stop_code: Wjz66oO, lat: -35.2109547, lng: 149.067737} | - { name: Stenhouse Close,stop_code: Wjz66oO, lat: -35.2109547, lng: 149.067737} |
- { name: Pitcairn Street,stop_code: Wjz66Fg, lat: -35.2104421, lng: 149.0698018} | - { name: Pitcairn Street,stop_code: Wjz66Fg, lat: -35.2104421, lng: 149.0698018} |
- { name: Clancy Street,stop_code: Wjz66XM, lat: -35.2090851, lng: 149.0732672} | - { name: Clancy Street,stop_code: Wjz66XM, lat: -35.2090851, lng: 149.0732672} |
- { name: Kissane Crescent,stop_code: Wjz6ec7, lat: -35.2077712, lng: 149.0749969} | - { name: Kissane Crescent,stop_code: Wjz6ec7, lat: -35.2077712, lng: 149.0749969} |
- { name: Primmer Court,stop_code: WjrW_zy, lat: -35.3792073, lng: 149.0577944} | - { name: Primmer Court,stop_code: WjrW_zy, lat: -35.3792073, lng: 149.0577944} |
- { name: Marconi Crescent,stop_code: WjrW_Qk, lat: -35.3783254, lng: 149.0600973} | - { name: Marconi Crescent,stop_code: WjrW_Qk, lat: -35.3783254, lng: 149.0600973} |
- { name: Marconi Crescent,stop_code: Wjz27d3, lat: -35.3777767, lng: 149.064033} | - { name: Marconi Crescent,stop_code: Wjz27d3, lat: -35.3777767, lng: 149.064033} |
- { name: Sinclair Street,stop_code: Wjz27dd, lat: -35.3775909, lng: 149.0640777} | - { name: Sinclair Street,stop_code: Wjz27dd, lat: -35.3775909, lng: 149.0640777} |
- { name: Marconi Crescent,stop_code: Wjz27k8, lat: -35.3787048, lng: 149.065524} | - { name: Marconi Crescent,stop_code: Wjz27k8, lat: -35.3787048, lng: 149.065524} |
- { name: Lascelles Circuit,stop_code: Wjz26n5, lat: -35.3816653, lng: 149.0653041} | - { name: Lascelles Circuit,stop_code: Wjz26n5, lat: -35.3816653, lng: 149.0653041} |
- { name: Summerland Circuit,stop_code: Wjz26tG, lat: -35.3833338, lng: 149.0674908} | - { name: Summerland Circuit,stop_code: Wjz26tG, lat: -35.3833338, lng: 149.0674908} |
- { name: Summerland Circuit,stop_code: Wjz26P8, lat: -35.3848854, lng: 149.0709314} | - { name: Summerland Circuit,stop_code: Wjz26P8, lat: -35.3848854, lng: 149.0709314} |
- { name: Summerland Circuit,stop_code: Wjz26Om, lat: -35.385045, lng: 149.0711386} | - { name: Summerland Circuit,stop_code: Wjz26Om, lat: -35.385045, lng: 149.0711386} |
- { name: Mason Street,stop_code: Wjz26WN, lat: -35.3854988, lng: 149.073226} | - { name: Mason Street,stop_code: Wjz26WN, lat: -35.3854988, lng: 149.073226} |
- { name: Lee Steere Crescent,stop_code: Wjz2def, lat: -35.3876959, lng: 149.0750942} | - { name: Lee Steere Crescent,stop_code: Wjz2def, lat: -35.3876959, lng: 149.0750942} |
- { name: Kingsmill Street,stop_code: Wjz2d34, lat: -35.3900029, lng: 149.0734943} | - { name: Kingsmill Street,stop_code: Wjz2d34, lat: -35.3900029, lng: 149.0734943} |
- { name: Summerland Circuit,stop_code: Wjz25Ox, lat: -35.3909341, lng: 149.0714764} | - { name: Summerland Circuit,stop_code: Wjz25Ox, lat: -35.3909341, lng: 149.0714764} |
- { name: Summerland Circuit,stop_code: Wjz25NL, lat: -35.3911118, lng: 149.0716052} | - { name: Summerland Circuit,stop_code: Wjz25NL, lat: -35.3911118, lng: 149.0716052} |
- { name: O'Halloran Circuit,stop_code: Wjz24vP, lat: -35.3928088, lng: 149.0677265} | - { name: O'Halloran Circuit,stop_code: Wjz24vP, lat: -35.3928088, lng: 149.0677265} |
- { name: O'Halloran Circuit,stop_code: Wjz24lu, lat: -35.3939542, lng: 149.0657865} | - { name: O'Halloran Circuit,stop_code: Wjz24lu, lat: -35.3939542, lng: 149.0657865} |
- { name: O'Halloran Circuit,stop_code: Wjz24cK, lat: -35.3946419, lng: 149.0647484} | - { name: O'Halloran Circuit,stop_code: Wjz24cK, lat: -35.3946419, lng: 149.0647484} |
- { name: Pinkerton Circuit,stop_code: Wjz248n, lat: -35.3972727, lng: 149.064345} | - { name: Pinkerton Circuit,stop_code: Wjz248n, lat: -35.3972727, lng: 149.064345} |
- { name: Ragless Circuit,stop_code: Wjz2347, lat: -35.4000362, lng: 149.0625} | - { name: Ragless Circuit,stop_code: Wjz2347, lat: -35.4000362, lng: 149.0625} |
- { name: Learmonth Drive,stop_code: WjrWXON, lat: -35.4019182, lng: 149.060886} | - { name: Learmonth Drive,stop_code: WjrWXON, lat: -35.4019182, lng: 149.060886} |
- { name: Learmonth Drive,stop_code: WjrWXNL, lat: -35.4020721, lng: 149.0607315} | - { name: Learmonth Drive,stop_code: WjrWXNL, lat: -35.4020721, lng: 149.0607315} |
- { name: Learmonth Drive,stop_code: Wjz230G, lat: -35.4032475, lng: 149.0634951} | - { name: Learmonth Drive,stop_code: Wjz230G, lat: -35.4032475, lng: 149.0634951} |
- { name: Driver Place,stop_code: Wjz66Cd, lat: -35.2065831, lng: 149.0682105} | - { name: Driver Place,stop_code: Wjz66Cd, lat: -35.2065831, lng: 149.0682105} |
- { name: Willis Street,stop_code: Wjz67xQ, lat: -35.2046532, lng: 149.0691406} | - { name: Willis Street,stop_code: Wjz67xQ, lat: -35.2046532, lng: 149.0691406} |
- { name: Kellway Street,stop_code: Wjz66KO, lat: -35.2068138, lng: 149.0704302} | - { name: Kellway Street,stop_code: Wjz66KO, lat: -35.2068138, lng: 149.0704302} |
- { name: Copland Drive,stop_code: Wjz67yW, lat: -35.2040813, lng: 149.0692143} | - { name: Copland Drive,stop_code: Wjz67yW, lat: -35.2040813, lng: 149.0692143} |
- { name: Edmunds Place,stop_code: Wjz67nz, lat: -35.2006201, lng: 149.0659965} | - { name: Edmunds Place,stop_code: Wjz67nz, lat: -35.2006201, lng: 149.0659965} |
- { name: Crofts Crescent,stop_code: Wjz701y, lat: -35.1992909, lng: 149.0633518} | - { name: Crofts Crescent,stop_code: Wjz701y, lat: -35.1992909, lng: 149.0633518} |
- { name: Standbridge Place,stop_code: Wjz701a, lat: -35.1992794, lng: 149.0628172} | - { name: Standbridge Place,stop_code: Wjz701a, lat: -35.1992794, lng: 149.0628172} |
- { name: Baddeley Crescent,stop_code: Wjr_UUU, lat: -35.2001327, lng: 149.0624944} | - { name: Baddeley Crescent,stop_code: Wjr_UUU, lat: -35.2001327, lng: 149.0624944} |
- { name: Goyder Street,stop_code: Wjzb705, lat: -35.3370433, lng: 149.1505109} | - { name: Goyder Street,stop_code: Wjzb705, lat: -35.3370433, lng: 149.1505109} |
- { name: Kingsford Smith Drive,stop_code: Wjr_UPA, lat: -35.1977713, lng: 149.0605874} | - { name: Kingsford Smith Drive,stop_code: Wjr_UPA, lat: -35.1977713, lng: 149.0605874} |
- { name: Kingsford Smith Drive,stop_code: Wjr_UTL, lat: -35.1947749, lng: 149.060646} | - { name: Kingsford Smith Drive,stop_code: Wjr_UTL, lat: -35.1947749, lng: 149.060646} |
- { name: Clarey Crescent,stop_code: Wjz707-, lat: -35.1947883, lng: 149.0637942} | - { name: Clarey Crescent,stop_code: Wjz707-, lat: -35.1947883, lng: 149.0637942} |
- { name: Clarey Crescent,stop_code: Wjz707Z, lat: -35.1948745, lng: 149.0637273} | - { name: Clarey Crescent,stop_code: Wjz707Z, lat: -35.1948745, lng: 149.0637273} |
- { name: Healy Street,stop_code: Wjz70lp, lat: -35.1966753, lng: 149.0658519} | - { name: Healy Street,stop_code: Wjz70lp, lat: -35.1966753, lng: 149.0658519} |
- { name: Boote Street,stop_code: Wjz70zB, lat: -35.1976784, lng: 149.0688026} | - { name: Boote Street,stop_code: Wjz70zB, lat: -35.1976784, lng: 149.0688026} |
- { name: Scattergood Place,stop_code: Wjz70zz, lat: -35.1978567, lng: 149.0687555} | - { name: Scattergood Place,stop_code: Wjz70zz, lat: -35.1978567, lng: 149.0687555} |
- { name: Owen Dixon Drive,stop_code: Wjz70IY, lat: -35.1970964, lng: 149.0706179} | - { name: Owen Dixon Drive,stop_code: Wjz70IY, lat: -35.1970964, lng: 149.0706179} |
- { name: Douglass Street,stop_code: Wjz70Wx, lat: -35.1986717, lng: 149.0728065} | - { name: Douglass Street,stop_code: Wjz70Wx, lat: -35.1986717, lng: 149.0728065} |
- { name: Copland Drive,stop_code: Wjz67_t, lat: -35.200411, lng: 149.0727116} | - { name: Copland Drive,stop_code: Wjz67_t, lat: -35.200411, lng: 149.0727116} |
- { name: Emerton Street,stop_code: Wjz67BD, lat: -35.2015929, lng: 149.0686908} | - { name: Emerton Street,stop_code: Wjz67BD, lat: -35.2015929, lng: 149.0686908} |
- { name: Scattergood Place,stop_code: Wjz67Dq, lat: -35.2006561, lng: 149.0686086} | - { name: Scattergood Place,stop_code: Wjz67Dq, lat: -35.2006561, lng: 149.0686086} |
- { name: Milne Bay Road,stop_code: Wjzce7O, lat: -35.2940494, lng: 149.162512} | - { name: Milne Bay Road,stop_code: Wjzce7O, lat: -35.2940494, lng: 149.162512} |
- { name: Bimbimbie Street,stop_code: Wjz68Y0, lat: -35.2413091, lng: 149.0832098} | - { name: Bimbimbie Street,stop_code: Wjz68Y0, lat: -35.2413091, lng: 149.0832098} |
- { name: Bimbimbie Street,stop_code: Wjz68IH, lat: -35.2411129, lng: 149.0812786} | - { name: Bimbimbie Street,stop_code: Wjz68IH, lat: -35.2411129, lng: 149.0812786} |
- { name: Bimbimbie Street,stop_code: Wjz68Ip, lat: -35.2412881, lng: 149.0809439} | - { name: Bimbimbie Street,stop_code: Wjz68Ip, lat: -35.2412881, lng: 149.0809439} |
- { name: Drakeford Drive,stop_code: WjrXUoV, lat: -35.3758661, lng: 149.0568376} | - { name: Drakeford Drive,stop_code: WjrXUoV, lat: -35.3758661, lng: 149.0568376} |
- { name: Tuggeranong Parkway,stop_code: WjrXUsW, lat: -35.3730527, lng: 149.0568719} | - { name: Tuggeranong Parkway,stop_code: WjrXUsW, lat: -35.3730527, lng: 149.0568719} |
- { name: Banambila Street,stop_code: Wjz5dQt, lat: -35.2573605, lng: 149.0822652} | - { name: Banambila Street,stop_code: Wjz5dQt, lat: -35.2573605, lng: 149.0822652} |
- { name: Bindaga Street,stop_code: Wjz5dcJ, lat: -35.2573868, lng: 149.075852} | - { name: Bindaga Street,stop_code: Wjz5dcJ, lat: -35.2573868, lng: 149.075852} |
- { name: Bandjalong Crescent,stop_code: Wjz5d81, lat: -35.2605056, lng: 149.0749293} | - { name: Bandjalong Crescent,stop_code: Wjz5d81, lat: -35.2605056, lng: 149.0749293} |
- { name: Cooyong Street,stop_code: Wjz5NAQ, lat: -35.2794375, lng: 149.1349942} | - { name: Cooyong Street,stop_code: Wjz5NAQ, lat: -35.2794375, lng: 149.1349942} |
- { name: Kambah pool Road,stop_code: WjrXMN9, lat: -35.3751239, lng: 149.0489789} | - { name: Kambah pool Road,stop_code: WjrXMN9, lat: -35.3751239, lng: 149.0489789} |
- { name: Brierly Street,stop_code: WjrX-3w, lat: -35.340876, lng: 149.0522964} | - { name: Brierly Street,stop_code: WjrX-3w, lat: -35.340876, lng: 149.0522964} |
- { name: Atkinson Street,stop_code: Wjzj4ju, lat: -35.351369, lng: 149.2416919} | - { name: Atkinson Street,stop_code: Wjzj4ju, lat: -35.351369, lng: 149.2416919} |
- { name: Gungurra Crescent,stop_code: WjrXJ-g, lat: -35.3443528, lng: 149.0396647} | - { name: Gungurra Crescent,stop_code: WjrXJ-g, lat: -35.3443528, lng: 149.0396647} |
- { name: Comrie Street,stop_code: Wjz2qnG, lat: -35.4038881, lng: 149.0992283} | - { name: Comrie Street,stop_code: Wjz2qnG, lat: -35.4038881, lng: 149.0992283} |
- { name: Pethebridge Street,stop_code: Wjz3i6e, lat: -35.3603188, lng: 149.084779} | - { name: Pethebridge Street,stop_code: Wjz3i6e, lat: -35.3603188, lng: 149.084779} |
- { name: Colbee Court,stop_code: Wjz3k1J, lat: -35.3528521, lng: 149.0854118} | - { name: Colbee Court,stop_code: Wjz3k1J, lat: -35.3528521, lng: 149.0854118} |
- { name: Divine Court,stop_code: Wjz3kcA, lat: -35.3508773, lng: 149.0866243} | - { name: Divine Court,stop_code: Wjz3kcA, lat: -35.3508773, lng: 149.0866243} |
- { name: Amy Ackman Street,stop_code: Wjz7ZaH, lat: -35.171087, lng: 149.1418054} | - { name: Amy Ackman Street,stop_code: Wjz7ZaH, lat: -35.171087, lng: 149.1418054} |
- { name: Amy Ackman Street,stop_code: Wjz7ZaP, lat: -35.1710474, lng: 149.141884} | - { name: Amy Ackman Street,stop_code: Wjz7ZaP, lat: -35.1710474, lng: 149.141884} |
- { name: Amy Ackman Street,stop_code: Wjz7-xb, lat: -35.1662448, lng: 149.1450965} | - { name: Amy Ackman Street,stop_code: Wjz7-xb, lat: -35.1662448, lng: 149.1450965} |
- { name: Molonglo Drive,stop_code: WjzcrEu, lat: -35.3150059, lng: 149.190788} | - { name: Molonglo Drive,stop_code: WjzcrEu, lat: -35.3150059, lng: 149.190788} |
- { name: Lochiel Street,stop_code: WjzbUQX, lat: -35.3729581, lng: 149.2368028} | - { name: Lochiel Street,stop_code: WjzbUQX, lat: -35.3729581, lng: 149.2368028} |
- { name: Noonan Street,stop_code: Wjzi7mf, lat: -35.3766831, lng: 149.2412565} | - { name: Noonan Street,stop_code: Wjzi7mf, lat: -35.3766831, lng: 149.2412565} |
- { name: Cooma Street,stop_code: WjzbUCp, lat: -35.3717241, lng: 149.2334526} | - { name: Cooma Street,stop_code: WjzbUCp, lat: -35.3717241, lng: 149.2334526} |
- { name: Cooma Street,stop_code: WjzbWBs, lat: -35.3611492, lng: 149.2334303} | - { name: Cooma Street,stop_code: WjzbWBs, lat: -35.3611492, lng: 149.2334303} |
- { name: Cooma Street,stop_code: WjzbWzE, lat: -35.3628765, lng: 149.2337473} | - { name: Cooma Street,stop_code: WjzbWzE, lat: -35.3628765, lng: 149.2337473} |
- { name: Hambly Place,stop_code: WjzbWyW, lat: -35.363411, lng: 149.2340547} | - { name: Hambly Place,stop_code: WjzbWyW, lat: -35.363411, lng: 149.2340547} |
- { name: Gundaroo Drive,stop_code: Wjz7oZp, lat: -35.1966204, lng: 149.1057315} | - { name: Gundaroo Drive,stop_code: Wjz7oZp, lat: -35.1966204, lng: 149.1057315} |
- { name: Gundaroo Drive,stop_code: Wjz7xp9, lat: -35.193896, lng: 149.1108506} | - { name: Gundaroo Drive,stop_code: Wjz7xp9, lat: -35.193896, lng: 149.1108506} |
- { name: Cowper Street,stop_code: Wjz5-6R, lat: -35.2505265, lng: 149.1404751} | - { name: Cowper Street,stop_code: Wjz5-6R, lat: -35.2505265, lng: 149.1404751} |
- { name: David Walsh Avenue,stop_code: Wjz7YIc, lat: -35.1751298, lng: 149.1466086} | - { name: David Walsh Avenue,stop_code: Wjz7YIc, lat: -35.1751298, lng: 149.1466086} |
- { name: Barritt Street,stop_code: WjrWTWO, lat: -35.3798917, lng: 149.0512179} | - { name: Barritt Street,stop_code: WjrWTWO, lat: -35.3798917, lng: 149.0512179} |
- { name: Barritt Street,stop_code: WjrWTJo, lat: -35.3779591, lng: 149.0479511} | - { name: Barritt Street,stop_code: WjrWTJo, lat: -35.3779591, lng: 149.0479511} |
- { name: Constitution Avenue,stop_code: Wjz5MsT, lat: -35.2846782, lng: 149.133671} | - { name: Constitution Avenue,stop_code: Wjz5MsT, lat: -35.2846782, lng: 149.133671} |
- { name: Hindmarsh Drive,stop_code: WjrXBSS, lat: -35.3438051, lng: 149.0278253} | - { name: Hindmarsh Drive,stop_code: WjrXBSS, lat: -35.3438051, lng: 149.0278253} |
- { name: Hindmarsh Drive,stop_code: WjrXBSJ, lat: -35.3439387, lng: 149.0276931} | - { name: Hindmarsh Drive,stop_code: WjrXBSJ, lat: -35.3439387, lng: 149.0276931} |
- { name: Mort Street,stop_code: Wjz5Oj2, lat: -35.2748472, lng: 149.131256} | - { name: Mort Street,stop_code: Wjz5Oj2, lat: -35.2748472, lng: 149.131256} |
- { name: Northbourne Avenue,stop_code: Wjz5P8K, lat: -35.2710632, lng: 149.1307122} | - { name: Northbourne Avenue,stop_code: Wjz5P8K, lat: -35.2710632, lng: 149.1307122} |
- { name: Northbourne Avenue,stop_code: Wjz5SrO, lat: -35.2528485, lng: 149.1336705} | - { name: Northbourne Avenue,stop_code: Wjz5SrO, lat: -35.2528485, lng: 149.1336705} |
- { name: Northbourne Avenue,stop_code: Wjz5Rsi, lat: -35.2576771, lng: 149.132889} | - { name: Northbourne Avenue,stop_code: Wjz5Rsi, lat: -35.2576771, lng: 149.132889} |
- { name: Northbourne Avenue,stop_code: Wjz5QmR, lat: -35.2615172, lng: 149.1322602} | - { name: Northbourne Avenue,stop_code: Wjz5QmR, lat: -35.2615172, lng: 149.1322602} |
- { name: Northbourne Avenue,stop_code: Wjz5Pl0, lat: -35.2681201, lng: 149.1312} | - { name: Northbourne Avenue,stop_code: Wjz5Pl0, lat: -35.2681201, lng: 149.1312} |
- { name: Northbourne Avenue,stop_code: Wjz5N5h, lat: -35.2790396, lng: 149.1288222} | - { name: Northbourne Avenue,stop_code: Wjz5N5h, lat: -35.2790396, lng: 149.1288222} |
- { name: Northbourne Avenue,stop_code: Wjz5O3Q, lat: -35.274617, lng: 149.1295599} | - { name: Northbourne Avenue,stop_code: Wjz5O3Q, lat: -35.274617, lng: 149.1295599} |
- { name: Northbourne Avenue,stop_code: Wjz5P8n, lat: -35.2710038, lng: 149.1301486} | - { name: Northbourne Avenue,stop_code: Wjz5P8n, lat: -35.2710038, lng: 149.1301486} |
- { name: Northbourne Avenue,stop_code: Wjz5Qi2, lat: -35.2645608, lng: 149.1311834} | - { name: Northbourne Avenue,stop_code: Wjz5Qi2, lat: -35.2645608, lng: 149.1311834} |
- { name: Northbourne Avenue,stop_code: Wjz5RkN, lat: -35.2577065, lng: 149.1322899} | - { name: Northbourne Avenue,stop_code: Wjz5RkN, lat: -35.2577065, lng: 149.1322899} |
- { name: Morisset Street,stop_code: WjzbYAM, lat: -35.3512052, lng: 149.2339748} | - { name: Morisset Street,stop_code: WjzbYAM, lat: -35.3512052, lng: 149.2339748} |
- { name: Kitchener Street,stop_code: Wjz3uDU, lat: -35.338154, lng: 149.1022456} | - { name: Kitchener Street,stop_code: Wjz3uDU, lat: -35.338154, lng: 149.1022456} |
- { name: Kitchener Street,stop_code: Wjz3uK7, lat: -35.3382669, lng: 149.1024969} | - { name: Kitchener Street,stop_code: Wjz3uK7, lat: -35.3382669, lng: 149.1024969} |
- { name: Black Mountain Summit Walk,stop_code: Wjz5xl6, lat: -35.278643, lng: 149.1093237} | - { name: Black Mountain Summit Walk,stop_code: Wjz5xl6, lat: -35.278643, lng: 149.1093237} |
- { name: Athllon Drive,stop_code: Wjz2mTK, lat: -35.3815863, lng: 149.0936139} | - { name: Athllon Drive,stop_code: Wjz2mTK, lat: -35.3815863, lng: 149.0936139} |
- { name: Baldwin Drive,stop_code: Wjz6keB, lat: -35.2175697, lng: 149.0866478} | - { name: Baldwin Drive,stop_code: Wjz6keB, lat: -35.2175697, lng: 149.0866478} |
- { name: Flierl Place,stop_code: Wjr_Mxy, lat: -35.1992913, lng: 149.0468658} | - { name: Flierl Place,stop_code: Wjr_Mxy, lat: -35.1992913, lng: 149.0468658} |
- { name: Fellows Street,stop_code: Wjr-InZ, lat: -35.2169003, lng: 149.0335258} | - { name: Fellows Street,stop_code: Wjr-InZ, lat: -35.2169003, lng: 149.0335258} |
- { name: Moyes Crescent,stop_code: Wjr-Alc, lat: -35.2183514, lng: 149.021625} | - { name: Moyes Crescent,stop_code: Wjr-Alc, lat: -35.2183514, lng: 149.021625} |
- { name: Solomon Crescent,stop_code: Wjr-I4P, lat: -35.2191133, lng: 149.0306838} | - { name: Solomon Crescent,stop_code: Wjr-I4P, lat: -35.2191133, lng: 149.0306838} |
- { name: Chambers Street,stop_code: Wjr-IGJ, lat: -35.2203467, lng: 149.0373003} | - { name: Chambers Street,stop_code: Wjr-IGJ, lat: -35.2203467, lng: 149.0373003} |
- { name: Maribyrnong Avenue,stop_code: Wjz6zth, lat: -35.2241129, lng: 149.1109391} | - { name: Maribyrnong Avenue,stop_code: Wjz6zth, lat: -35.2241129, lng: 149.1109391} |
- { name: Macumba Place,stop_code: Wjz6yir, lat: -35.2314837, lng: 149.1098378} | - { name: Macumba Place,stop_code: Wjz6yir, lat: -35.2314837, lng: 149.1098378} |
- { name: Glossop Crescent,stop_code: Wjzd0oD, lat: -35.2874406, lng: 149.1552177} | - { name: Glossop Crescent,stop_code: Wjzd0oD, lat: -35.2874406, lng: 149.1552177} |
- { name: Chewings Street,stop_code: Wjr-N9a, lat: -35.2377693, lng: 149.0421213} | - { name: Chewings Street,stop_code: Wjr-N9a, lat: -35.2377693, lng: 149.0421213} |
- { name: Hinkler Street,stop_code: Wjr-EuB, lat: -35.2395683, lng: 149.034448} | - { name: Hinkler Street,stop_code: Wjr-EuB, lat: -35.2395683, lng: 149.034448} |
- { name: Ratcliffe Crescent,stop_code: Wjr-VdI, lat: -35.2348097, lng: 149.0539156} | - { name: Ratcliffe Crescent,stop_code: Wjr-VdI, lat: -35.2348097, lng: 149.0539156} |
- { name: Krefft Street,stop_code: Wjr-PWf, lat: -35.225611, lng: 149.0504341} | - { name: Krefft Street,stop_code: Wjr-PWf, lat: -35.225611, lng: 149.0504341} |
- { name: Dungowan Street,stop_code: WjrZKnY, lat: -35.2498968, lng: 149.0336595} | - { name: Dungowan Street,stop_code: WjrZKnY, lat: -35.2498968, lng: 149.0336595} |
- { name: Capital Circle,stop_code: Wjz4IrL, lat: -35.307326, lng: 149.1225503} | - { name: Capital Circle,stop_code: Wjz4IrL, lat: -35.307326, lng: 149.1225503} |
- { name: National Circuit,stop_code: Wjz4INj, lat: -35.3091118, lng: 149.1261312} | - { name: National Circuit,stop_code: Wjz4INj, lat: -35.3091118, lng: 149.1261312} |
- { name: Theodore Street,stop_code: Wjz3fO2, lat: -35.3359729, lng: 149.0817737} | - { name: Theodore Street,stop_code: Wjz3fO2, lat: -35.3359729, lng: 149.0817737} |
- { name: Newdegate Street,stop_code: Wjz4qtY, lat: -35.3172423, lng: 149.100878} | - { name: Newdegate Street,stop_code: Wjz4qtY, lat: -35.3172423, lng: 149.100878} |
- { name: Hannah Place,stop_code: Wjz4y7z, lat: -35.3159129, lng: 149.1072689} | - { name: Hannah Place,stop_code: Wjz4y7z, lat: -35.3159129, lng: 149.1072689} |
- { name: Hopetoun Circuit,stop_code: Wjz4yng, lat: -35.316172, lng: 149.1095953} | - { name: Hopetoun Circuit,stop_code: Wjz4yng, lat: -35.316172, lng: 149.1095953} |
- { name: Stonehaven Crescent,stop_code: Wjz4yGG, lat: -35.3194308, lng: 149.1142224} | - { name: Stonehaven Crescent,stop_code: Wjz4yGG, lat: -35.3194308, lng: 149.1142224} |
- { name: Melbourne Avenue,stop_code: Wjz4yQ-, lat: -35.3177825, lng: 149.1159796} | - { name: Melbourne Avenue,stop_code: Wjz4yQ-, lat: -35.3177825, lng: 149.1159796} |
- { name: Melbourne Avenue,stop_code: Wjz4Hbx, lat: -35.3133913, lng: 149.1195724} | - { name: Melbourne Avenue,stop_code: Wjz4Hbx, lat: -35.3133913, lng: 149.1195724} |
- { name: Freda Gibson Circuit,stop_code: Wjz1HOf, lat: -35.4453654, lng: 149.1258946} | - { name: Freda Gibson Circuit,stop_code: Wjz1HOf, lat: -35.4453654, lng: 149.1258946} |
- { name: Burdett Crescent,stop_code: Wjz1GsO, lat: -35.4499519, lng: 149.1226442} | - { name: Burdett Crescent,stop_code: Wjz1GsO, lat: -35.4499519, lng: 149.1226442} |
- { name: Hartung Crescent,stop_code: Wjz1zWz, lat: -35.4457437, lng: 149.1168111} | - { name: Hartung Crescent,stop_code: Wjz1zWz, lat: -35.4457437, lng: 149.1168111} |
- { name: Cochrane Crescent,stop_code: Wjz1ySn, lat: -35.4481315, lng: 149.1151569} | - { name: Cochrane Crescent,stop_code: Wjz1ySn, lat: -35.4481315, lng: 149.1151569} |
- { name: Conlon Crescent,stop_code: Wjz1G32, lat: -35.4506139, lng: 149.1174495} | - { name: Conlon Crescent,stop_code: Wjz1G32, lat: -35.4506139, lng: 149.1174495} |
- { name: Clift Crescent,stop_code: Wjz1CD8, lat: -35.4260286, lng: 149.1122294} | - { name: Clift Crescent,stop_code: Wjz1CD8, lat: -35.4260286, lng: 149.1122294} |
- { name: Meeson Street,stop_code: Wjz1Kiu, lat: -35.4289549, lng: 149.1207905} | - { name: Meeson Street,stop_code: Wjz1Kiu, lat: -35.4289549, lng: 149.1207905} |
- { name: Nina Jones Crescent,stop_code: Wjz1S2v, lat: -35.4289254, lng: 149.1290251} | - { name: Nina Jones Crescent,stop_code: Wjz1S2v, lat: -35.4289254, lng: 149.1290251} |
- { name: Monaro Highway,stop_code: Wjz1TgM, lat: -35.4253782, lng: 149.1323625} | - { name: Monaro Highway,stop_code: Wjz1TgM, lat: -35.4253782, lng: 149.1323625} |
- { name: Baskerville Street,stop_code: Wjz1LBV, lat: -35.4218605, lng: 149.1241279} | - { name: Baskerville Street,stop_code: Wjz1LBV, lat: -35.4218605, lng: 149.1241279} |
- { name: McLorinan Street,stop_code: Wjz1DWq, lat: -35.4238411, lng: 149.1166188} | - { name: McLorinan Street,stop_code: Wjz1DWq, lat: -35.4238411, lng: 149.1166188} |
- { name: Barry Drive,stop_code: Wjz5G6B, lat: -35.2724804, lng: 149.1181797} | - { name: Barry Drive,stop_code: Wjz5G6B, lat: -35.2724804, lng: 149.1181797} |
- { name: Chinner Crescent,stop_code: Wjr-SAW, lat: -35.2081966, lng: 149.0473834} | - { name: Chinner Crescent,stop_code: Wjr-SAW, lat: -35.2081966, lng: 149.0473834} |
- { name: O'Halloran Circuit,stop_code: WjrWYDO, lat: -35.3929049, lng: 149.058196} | - { name: O'Halloran Circuit,stop_code: WjrWYDO, lat: -35.3929049, lng: 149.058196} |
- { name: Chuculba Crescent,stop_code: Wjz6sdJ, lat: -35.21822, lng: 149.09782} | - { name: Chuculba Crescent,stop_code: Wjz6sdJ, lat: -35.21822, lng: 149.09782} |
- { name: Tucana Street,stop_code: Wjz6t8_, lat: -35.21601, lng: 149.09817} | - { name: Tucana Street,stop_code: Wjz6t8_, lat: -35.21601, lng: 149.09817} |
- { name: Tucana Street,stop_code: Wjz6t9w, lat: -35.21597, lng: 149.09763} | - { name: Tucana Street,stop_code: Wjz6t9w, lat: -35.21597, lng: 149.09763} |
- { name: Canopus Crescent,stop_code: Wjz6t4U, lat: -35.21388, lng: 149.09676} | - { name: Canopus Crescent,stop_code: Wjz6t4U, lat: -35.21388, lng: 149.09676} |
- { name: Purdie Street,stop_code: Wjz5nw6, lat: -35.2491082, lng: 149.0900504} | - { name: Purdie Street,stop_code: Wjz5nw6, lat: -35.2491082, lng: 149.0900504} |
- { name: Haydon Drive,stop_code: Wjz6hxB, lat: -35.2374959, lng: 149.0907853} | - { name: Haydon Drive,stop_code: Wjz6hxB, lat: -35.2374959, lng: 149.0907853} |
- { name: Baldwin Drive,stop_code: Wjz6rsL, lat: -35.2242562, lng: 149.1005043} | - { name: Baldwin Drive,stop_code: Wjz6rsL, lat: -35.2242562, lng: 149.1005043} |
- { name: Baldwin Drive,stop_code: Wjz6rrI, lat: -35.2252509, lng: 149.1005016} | - { name: Baldwin Drive,stop_code: Wjz6rrI, lat: -35.2252509, lng: 149.1005016} |
- { name: Bindubi Street,stop_code: Wjz5eb2, lat: -35.252833, lng: 149.0749872} | - { name: Bindubi Street,stop_code: Wjz5eb2, lat: -35.252833, lng: 149.0749872} |
- { name: Bindubi Street,stop_code: Wjz5ec7, lat: -35.2517641, lng: 149.0750194} | - { name: Bindubi Street,stop_code: Wjz5ec7, lat: -35.2517641, lng: 149.0750194} |
- { name: Bindubi Street,stop_code: Wjz5d57, lat: -35.256585, lng: 149.0734919} | - { name: Bindubi Street,stop_code: Wjz5d57, lat: -35.256585, lng: 149.0734919} |
- { name: College Street,stop_code: Wjz681S, lat: -35.2428905, lng: 149.0745728} | - { name: College Street,stop_code: Wjz681S, lat: -35.2428905, lng: 149.0745728} |
- { name: College Street,stop_code: Wjz689c, lat: -35.2430767, lng: 149.0750449} | - { name: College Street,stop_code: Wjz689c, lat: -35.2430767, lng: 149.0750449} |
- { name: Gwydir Square,stop_code: Wjz6pLi, lat: -35.2336222, lng: 149.1026958} | - { name: Gwydir Square,stop_code: Wjz6pLi, lat: -35.2336222, lng: 149.1026958} |
- { name: Maribyrnong Avenue,stop_code: Wjz6y90, lat: -35.2324006, lng: 149.1079069} | - { name: Maribyrnong Avenue,stop_code: Wjz6y90, lat: -35.2324006, lng: 149.1079069} |
- { name: Moruya Circuit,stop_code: Wjz6Apq, lat: -35.2212504, lng: 149.1111434} | - { name: Moruya Circuit,stop_code: Wjz6Apq, lat: -35.2212504, lng: 149.1111434} |
- { name: Ellenborough Street,stop_code: Wjz6yzQ, lat: -35.2307289, lng: 149.1130906} | - { name: Ellenborough Street,stop_code: Wjz6yzQ, lat: -35.2307289, lng: 149.1130906} |
- { name: Mouat Street,stop_code: Wjz5L_c, lat: -35.2444385, lng: 149.1272473} | - { name: Mouat Street,stop_code: Wjz5L_c, lat: -35.2444385, lng: 149.1272473} |
- { name: Mouat Street,stop_code: Wjz5Ti2, lat: -35.2480353, lng: 149.1313351} | - { name: Mouat Street,stop_code: Wjz5Ti2, lat: -35.2480353, lng: 149.1313351} |
- { name: Aikman Drive,stop_code: Wjz69ht, lat: -35.2375061, lng: 149.0768646} | - { name: Aikman Drive,stop_code: Wjz69ht, lat: -35.2375061, lng: 149.0768646} |
- { name: Aikman Drive,stop_code: Wjz69gA, lat: -35.2382334, lng: 149.0769344} | - { name: Aikman Drive,stop_code: Wjz69gA, lat: -35.2382334, lng: 149.0769344} |
- { name: Broad Place,stop_code: WjrWZsS, lat: -35.3891768, lng: 149.0567055} | - { name: Broad Place,stop_code: WjrWZsS, lat: -35.3891768, lng: 149.0567055} |
- { name: Boddington Crescent,stop_code: WjrWZA3, lat: -35.3893963, lng: 149.0571767} | - { name: Boddington Crescent,stop_code: WjrWZA3, lat: -35.3893963, lng: 149.0571767} |
- { name: Baldwin Drive,stop_code: Wjz6iYm, lat: -35.2298806, lng: 149.0944438} | - { name: Baldwin Drive,stop_code: Wjz6iYm, lat: -35.2298806, lng: 149.0944438} |
- { name: Baldwin Drive,stop_code: Wjz6iYk, lat: -35.2300583, lng: 149.0945448} | - { name: Baldwin Drive,stop_code: Wjz6iYk, lat: -35.2300583, lng: 149.0945448} |
- { name: Athllon Drive,stop_code: Wjz239F, lat: -35.4026063, lng: 149.0647649} | - { name: Athllon Drive,stop_code: Wjz239F, lat: -35.4026063, lng: 149.0647649} |
- { name: Anketell Street,stop_code: Wjz213w, lat: -35.4123171, lng: 149.0633299} | - { name: Anketell Street,stop_code: Wjz213w, lat: -35.4123171, lng: 149.0633299} |
- { name: Anketell Street,stop_code: Wjz20ut, lat: -35.415325, lng: 149.0672593} | - { name: Anketell Street,stop_code: Wjz20ut, lat: -35.415325, lng: 149.0672593} |
- { name: Athllon Drive,stop_code: Wjz3hL_, lat: -35.3650156, lng: 149.0926464} | - { name: Athllon Drive,stop_code: Wjz3hL_, lat: -35.3650156, lng: 149.0926464} |
- { name: Athllon Drive,stop_code: Wjz3gQn, lat: -35.3725942, lng: 149.0931105} | - { name: Athllon Drive,stop_code: Wjz3gQn, lat: -35.3725942, lng: 149.0931105} |
- { name: Athllon Drive,stop_code: Wjz3gMq, lat: -35.3757982, lng: 149.0932419} | - { name: Athllon Drive,stop_code: Wjz3gMq, lat: -35.3757982, lng: 149.0932419} |
- { name: Athllon Drive,stop_code: Wjz238T, lat: -35.4027681, lng: 149.0650277} | - { name: Athllon Drive,stop_code: Wjz238T, lat: -35.4027681, lng: 149.0650277} |
- { name: Athllon Drive,stop_code: Wjz3kwU, lat: -35.3539843, lng: 149.0913052} | - { name: Athllon Drive,stop_code: Wjz3kwU, lat: -35.3539843, lng: 149.0913052} |
- { name: Neales Street,stop_code: Wjz6rp1, lat: -35.2268254, lng: 149.0996755} | - { name: Neales Street,stop_code: Wjz6rp1, lat: -35.2268254, lng: 149.0996755} |
- { name: Neales Street,stop_code: Wjz6rhW, lat: -35.2267553, lng: 149.0994502} | - { name: Neales Street,stop_code: Wjz6rhW, lat: -35.2267553, lng: 149.0994502} |
- { name: Maribyrnong Avenue,stop_code: Wjz6qea, lat: -35.2288148, lng: 149.0970523} | - { name: Maribyrnong Avenue,stop_code: Wjz6qea, lat: -35.2288148, lng: 149.0970523} |
- { name: Marcus Clarke Street,stop_code: Wjz5GNG, lat: -35.2762093, lng: 149.1265723} | - { name: Marcus Clarke Street,stop_code: Wjz5GNG, lat: -35.2762093, lng: 149.1265723} |
- { name: Liversidge Street,stop_code: Wjz5E4O, lat: -35.2851023, lng: 149.1186022} | - { name: Liversidge Street,stop_code: Wjz5E4O, lat: -35.2851023, lng: 149.1186022} |
- { name: McDonald Place,stop_code: Wjz5w_S, lat: -35.2827048, lng: 149.117182} | - { name: McDonald Place,stop_code: Wjz5w_S, lat: -35.2827048, lng: 149.117182} |
- { name: Bowes Street,stop_code: Wjz3leq, lat: -35.344135, lng: 149.0864401} | - { name: Bowes Street,stop_code: Wjz3leq, lat: -35.344135, lng: 149.0864401} |
- { name: Bradley Street,stop_code: Wjz3ldj, lat: -35.3447574, lng: 149.0862912} | - { name: Bradley Street,stop_code: Wjz3ldj, lat: -35.3447574, lng: 149.0862912} |
- { name: Bradley Street,stop_code: Wjz3ldh, lat: -35.3449697, lng: 149.0863328} | - { name: Bradley Street,stop_code: Wjz3ldh, lat: -35.3449697, lng: 149.0863328} |
- { name: Pitman,stop_code: Wjz20ni, lat: -35.4149428, lng: 149.0656523} | - { name: Pitman,stop_code: Wjz20ni, lat: -35.4149428, lng: 149.0656523} |
- { name: Pitman,stop_code: Wjz20nk, lat: -35.4147569, lng: 149.0657435} | - { name: Pitman,stop_code: Wjz20nk, lat: -35.4147569, lng: 149.0657435} |
- { name: Callam Street,stop_code: Wjz3lmt, lat: -35.3439501, lng: 149.0877369} | - { name: Callam Street,stop_code: Wjz3lmt, lat: -35.3439501, lng: 149.0877369} |
- { name: Bowes Street,stop_code: Wjz3ldC, lat: -35.344484, lng: 149.0866144} | - { name: Bowes Street,stop_code: Wjz3ldC, lat: -35.344484, lng: 149.0866144} |
- { name: Bradley Street,stop_code: Wjz3lm0, lat: -35.34438, lng: 149.0872661} | - { name: Bradley Street,stop_code: Wjz3lm0, lat: -35.34438, lng: 149.0872661} |
- { name: Bradley Street,stop_code: Wjz3ll7, lat: -35.3444741, lng: 149.0873533} | - { name: Bradley Street,stop_code: Wjz3ll7, lat: -35.3444741, lng: 149.0873533} |
- { name: Bowes Street,stop_code: Wjz3lml, lat: -35.3439129, lng: 149.0876216} | - { name: Bowes Street,stop_code: Wjz3lml, lat: -35.3439129, lng: 149.0876216} |
- { name: Callam Street,stop_code: Wjz3lmi, lat: -35.3442093, lng: 149.0876443} | - { name: Callam Street,stop_code: Wjz3lmi, lat: -35.3442093, lng: 149.0876443} |
- { name: Bowes Street,stop_code: Wjz3leo, lat: -35.344368, lng: 149.0864991} | - { name: Bowes Street,stop_code: Wjz3leo, lat: -35.344368, lng: 149.0864991} |
- { name: Callam Street,stop_code: Wjz3lmq, lat: -35.3442083, lng: 149.0877771} | - { name: Callam Street,stop_code: Wjz3lmq, lat: -35.3442083, lng: 149.0877771} |
- { name: Eileen Good Street,stop_code: Wjz21g2, lat: -35.414217, lng: 149.0653492} | - { name: Eileen Good Street,stop_code: Wjz21g2, lat: -35.414217, lng: 149.0653492} |
- { name: Cohen Street,stop_code: Wjr-UJ-, lat: -35.240121, lng: 149.0597101} | - { name: Cohen Street,stop_code: Wjr-UJ-, lat: -35.240121, lng: 149.0597101} |
- { name: Pitman,stop_code: Wjz20nd, lat: -35.4146761, lng: 149.0654565} | - { name: Pitman,stop_code: Wjz20nd, lat: -35.4146761, lng: 149.0654565} |
- { name: Cohen Street,stop_code: Wjr-USa, lat: -35.2398454, lng: 149.0600442} | - { name: Cohen Street,stop_code: Wjr-USa, lat: -35.2398454, lng: 149.0600442} |
- { name: David Walsh Avenue,stop_code: Wjz7YzW, lat: -35.1759253, lng: 149.1462691} | - { name: David Walsh Avenue,stop_code: Wjz7YzW, lat: -35.1759253, lng: 149.1462691} |
- { name: Kathner Street,stop_code: WjrXBWn, lat: -35.3465295, lng: 149.0286032} | - { name: Kathner Street,stop_code: WjrXBWn, lat: -35.3465295, lng: 149.0286032} |
- { name: Cohen Street,stop_code: Wjr-USy, lat: -35.2397639, lng: 149.0604531} | - { name: Cohen Street,stop_code: Wjr-USy, lat: -35.2397639, lng: 149.0604531} |
- { name: Rene Street,stop_code: WjrXHvw, lat: -35.3546272, lng: 149.0344542} | - { name: Rene Street,stop_code: WjrXHvw, lat: -35.3546272, lng: 149.0344542} |
- { name: Perry Drive,stop_code: WjrXPbD, lat: -35.356823, lng: 149.0426424} | - { name: Perry Drive,stop_code: WjrXPbD, lat: -35.356823, lng: 149.0426424} |
- { name: Darwinia Terrace,stop_code: WjrXIbT, lat: -35.351342, lng: 149.0321099} | - { name: Darwinia Terrace,stop_code: WjrXIbT, lat: -35.351342, lng: 149.0321099} |
- { name: Darwinia Terrace,stop_code: WjrXIqp, lat: -35.352473, lng: 149.0342718} | - { name: Darwinia Terrace,stop_code: WjrXIqp, lat: -35.352473, lng: 149.0342718} |
- { name: Rafferty Street,stop_code: WjrXIbK, lat: -35.3514081, lng: 149.0319332} | - { name: Rafferty Street,stop_code: WjrXIbK, lat: -35.3514081, lng: 149.0319332} |
- { name: Kathner Street,stop_code: WjrXBWu, lat: -35.3466197, lng: 149.0287455} | - { name: Kathner Street,stop_code: WjrXBWu, lat: -35.3466197, lng: 149.0287455} |
- { name: Darwinia Terrace,stop_code: WjrXI5u, lat: -35.3499839, lng: 149.0301495} | - { name: Darwinia Terrace,stop_code: WjrXI5u, lat: -35.3499839, lng: 149.0301495} |
- { name: Rene Street,stop_code: WjrXHuL, lat: -35.3547054, lng: 149.0346008} | - { name: Rene Street,stop_code: WjrXHuL, lat: -35.3547054, lng: 149.0346008} |
- { name: Musgrove street,stop_code: WjrXHH7, lat: -35.3568349, lng: 149.0364585} | - { name: Musgrove street,stop_code: WjrXHH7, lat: -35.3568349, lng: 149.0364585} |
- { name: Musgrove street,stop_code: WjrXHHk, lat: -35.3570187, lng: 149.0369096} | - { name: Musgrove street,stop_code: WjrXHHk, lat: -35.3570187, lng: 149.0369096} |
- { name: Perry Drive,stop_code: WjrXHYJ, lat: -35.356246, lng: 149.0401055} | - { name: Perry Drive,stop_code: WjrXHYJ, lat: -35.356246, lng: 149.0401055} |
- { name: Bertel Crescent,stop_code: WjrXPgO, lat: -35.3592839, lng: 149.0444246} | - { name: Bertel Crescent,stop_code: WjrXPgO, lat: -35.3592839, lng: 149.0444246} |
- { name: Namatjira Drive,stop_code: WjrXPFr, lat: -35.3585046, lng: 149.0479415} | - { name: Namatjira Drive,stop_code: WjrXPFr, lat: -35.3585046, lng: 149.0479415} |
- { name: Namatjira Drive,stop_code: WjrXPFn, lat: -35.358206, lng: 149.0478792} | - { name: Namatjira Drive,stop_code: WjrXPFn, lat: -35.358206, lng: 149.0478792} |
- { name: Streeton Drive,stop_code: WjrXPJX, lat: -35.3557253, lng: 149.0486263} | - { name: Streeton Drive,stop_code: WjrXPJX, lat: -35.3557253, lng: 149.0486263} |
- { name: Fremantle Drive,stop_code: WjrXQO9, lat: -35.352521, lng: 149.0490119} | - { name: Fremantle Drive,stop_code: WjrXQO9, lat: -35.352521, lng: 149.0490119} |
- { name: Bunbury Street,stop_code: WjrXQTq, lat: -35.348941, lng: 149.0494159} | - { name: Bunbury Street,stop_code: WjrXQTq, lat: -35.348941, lng: 149.0494159} |
- { name: Bunbury Street,stop_code: WjrXQTy, lat: -35.3489683, lng: 149.0495709} | - { name: Bunbury Street,stop_code: WjrXQTy, lat: -35.3489683, lng: 149.0495709} |
- { name: McKail Crescent,stop_code: WjrXRFB, lat: -35.3473864, lng: 149.048202} | - { name: McKail Crescent,stop_code: WjrXRFB, lat: -35.3473864, lng: 149.048202} |
- { name: McKail Crescent,stop_code: WjrXRyK, lat: -35.3465911, lng: 149.0470392} | - { name: McKail Crescent,stop_code: WjrXRyK, lat: -35.3465911, lng: 149.0470392} |
- { name: Streeton Drive,stop_code: WjrXRBQ, lat: -35.3446963, lng: 149.0471083} | - { name: Streeton Drive,stop_code: WjrXRBQ, lat: -35.3446963, lng: 149.0471083} |
- { name: Streeton Drive,stop_code: WjrXRBJ, lat: -35.344588, lng: 149.0469995} | - { name: Streeton Drive,stop_code: WjrXRBJ, lat: -35.344588, lng: 149.0469995} |
- { name: Whitney Place,stop_code: WjrX-90, lat: -35.3423165, lng: 149.0529937} | - { name: Whitney Place,stop_code: WjrX-90, lat: -35.3423165, lng: 149.0529937} |
- { name: Parkinson Street,stop_code: WjrXZv3, lat: -35.3434037, lng: 149.0557375} | - { name: Parkinson Street,stop_code: WjrXZv3, lat: -35.3434037, lng: 149.0557375} |
- { name: Corinna Street,stop_code: Wjz3dXS, lat: -35.3459117, lng: 149.0842511} | - { name: Corinna Street,stop_code: Wjz3dXS, lat: -35.3459117, lng: 149.0842511} |
- { name: Clode Crescent,stop_code: Wjr-uhM, lat: -35.2104818, lng: 149.0114129} | - { name: Clode Crescent,stop_code: Wjr-uhM, lat: -35.2104818, lng: 149.0114129} |
- { name: Gilmore Crescent,stop_code: Wjz3Bea, lat: -35.3442178, lng: 149.1080098} | - { name: Gilmore Crescent,stop_code: Wjz3Bea, lat: -35.3442178, lng: 149.1080098} |
- { name: Gonzaga Place,stop_code: Wjz2wGU, lat: -35.4184904, lng: 149.1145873} | - { name: Gonzaga Place,stop_code: Wjz2wGU, lat: -35.4184904, lng: 149.1145873} |
- { name: Rischbieth Crescent,stop_code: Wjz2MYC, lat: -35.4166279, lng: 149.1388559} | - { name: Rischbieth Crescent,stop_code: Wjz2MYC, lat: -35.4166279, lng: 149.1388559} |
- { name: Penton Place,stop_code: Wjz2Npv, lat: -35.4131394, lng: 149.1331606} | - { name: Penton Place,stop_code: Wjz2Npv, lat: -35.4131394, lng: 149.1331606} |
- { name: Carruthers Street,stop_code: Wjz4h1X, lat: -35.3255489, lng: 149.0857143} | - { name: Carruthers Street,stop_code: Wjz4h1X, lat: -35.3255489, lng: 149.0857143} |
- { name: Bunny Street,stop_code: WjrX_SL, lat: -35.3327937, lng: 149.0607695} | - { name: Bunny Street,stop_code: WjrX_SL, lat: -35.3327937, lng: 149.0607695} |
- { name: Davenport Street,stop_code: Wjz37Zc, lat: -35.3337407, lng: 149.0723488} | - { name: Davenport Street,stop_code: Wjz37Zc, lat: -35.3337407, lng: 149.0723488} |
- { name: Isabella Drive,stop_code: Wjz1nzY, lat: -35.4229506, lng: 149.0912343} | - { name: Isabella Drive,stop_code: Wjz1nzY, lat: -35.4229506, lng: 149.0912343} |
- { name: Lake Tuggeranong cycle track,stop_code: Wjz20Vv, lat: -35.4185754, lng: 149.072661} | - { name: Lake Tuggeranong cycle track,stop_code: Wjz20Vv, lat: -35.4185754, lng: 149.072661} |
- { name: Taverner Street,stop_code: Wjz2b8J, lat: -35.4029944, lng: 149.0757807} | - { name: Taverner Street,stop_code: Wjz2b8J, lat: -35.4029944, lng: 149.0757807} |
- { name: Nunan Crescent,stop_code: Wjz29-5, lat: -35.4098244, lng: 149.083123} | - { name: Nunan Crescent,stop_code: Wjz29-5, lat: -35.4098244, lng: 149.083123} |
- { name: Laurens Street,stop_code: Wjz2i3o, lat: -35.4068322, lng: 149.0850166} | - { name: Laurens Street,stop_code: Wjz2i3o, lat: -35.4068322, lng: 149.0850166} |
- { name: Taverner Street,stop_code: Wjz2aGG, lat: -35.4073408, lng: 149.0812511} | - { name: Taverner Street,stop_code: Wjz2aGG, lat: -35.4073408, lng: 149.0812511} |
- { name: Taverner Street,stop_code: Wjz2azE, lat: -35.4068027, lng: 149.0799162} | - { name: Taverner Street,stop_code: Wjz2azE, lat: -35.4068027, lng: 149.0799162} |
- { name: Clutterbuck Crescent,stop_code: Wjz2arg, lat: -35.4068086, lng: 149.0779936} | - { name: Clutterbuck Crescent,stop_code: Wjz2arg, lat: -35.4068086, lng: 149.0779936} |
- { name: Connibere Crescent,stop_code: Wjz2aaw, lat: -35.4075241, lng: 149.0756429} | - { name: Connibere Crescent,stop_code: Wjz2aaw, lat: -35.4075241, lng: 149.0756429} |
- { name: Singleton Crescent,stop_code: Wjz29ea, lat: -35.4101319, lng: 149.0751278} | - { name: Singleton Crescent,stop_code: Wjz29ea, lat: -35.4101319, lng: 149.0751278} |
- { name: Maconochie Crescent,stop_code: Wjz29yh, lat: -35.4129642, lng: 149.0794301} | - { name: Maconochie Crescent,stop_code: Wjz29yh, lat: -35.4129642, lng: 149.0794301} |
- { name: Checchi Place,stop_code: Wjz28Yv, lat: -35.4165651, lng: 149.0836163} | - { name: Checchi Place,stop_code: Wjz28Yv, lat: -35.4165651, lng: 149.0836163} |
- { name: Forwood Street,stop_code: Wjz2haF, lat: -35.4129406, lng: 149.0867361} | - { name: Forwood Street,stop_code: Wjz2haF, lat: -35.4129406, lng: 149.0867361} |
- { name: Harricks Crescent,stop_code: Wjz2hlp, lat: -35.4109006, lng: 149.0878896} | - { name: Harricks Crescent,stop_code: Wjz2hlp, lat: -35.4109006, lng: 149.0878896} |
- { name: Michell Street,stop_code: Wjz2hBQ, lat: -35.4106404, lng: 149.0911182} | - { name: Michell Street,stop_code: Wjz2hBQ, lat: -35.4106404, lng: 149.0911182} |
- { name: Beirne Street,stop_code: Wjz2iEO, lat: -35.40876, lng: 149.0925039} | - { name: Beirne Street,stop_code: Wjz2iEO, lat: -35.40876, lng: 149.0925039} |
- { name: Amsinck Street,stop_code: Wjz2iPv, lat: -35.4062172, lng: 149.093302} | - { name: Amsinck Street,stop_code: Wjz2iPv, lat: -35.4062172, lng: 149.093302} |
- { name: Mackinnon Street,stop_code: Wjz2izK, lat: -35.4062764, lng: 149.0909078} | - { name: Mackinnon Street,stop_code: Wjz2izK, lat: -35.4062764, lng: 149.0909078} |
- { name: Tuggeranong Parkway,stop_code: Wjz34Gq, lat: -35.352423, lng: 149.0699271} | - { name: Tuggeranong Parkway,stop_code: Wjz34Gq, lat: -35.352423, lng: 149.0699271} |
- { name: Tuggeranong Parkway Onramp,stop_code: Wjz33LB, lat: -35.3542352, lng: 149.0701992} | - { name: Tuggeranong Parkway Onramp,stop_code: Wjz33LB, lat: -35.3542352, lng: 149.0701992} |
- { name: Tuggeranong Parkway,stop_code: Wjz33EK, lat: -35.3589689, lng: 149.0702445} | - { name: Tuggeranong Parkway,stop_code: Wjz33EK, lat: -35.3589689, lng: 149.0702445} |
- { name: Yambina Crescent,stop_code: WjrXXMe, lat: -35.3589023, lng: 149.0599784} | - { name: Yambina Crescent,stop_code: WjrXXMe, lat: -35.3589023, lng: 149.0599784} |
- { name: Araluen Street,stop_code: WjrXWsn, lat: -35.3616093, lng: 149.055979} | - { name: Araluen Street,stop_code: WjrXWsn, lat: -35.3616093, lng: 149.055979} |
- { name: Guinness Place,stop_code: WjrXGDF, lat: -35.3600413, lng: 149.0360091} | - { name: Guinness Place,stop_code: WjrXGDF, lat: -35.3600413, lng: 149.0360091} |
- { name: Gulgong Place,stop_code: WjrXXb4, lat: -35.3570754, lng: 149.0530316} | - { name: Gulgong Place,stop_code: WjrXXb4, lat: -35.3570754, lng: 149.0530316} |
- { name: Larakia Street,stop_code: Wjz34c4, lat: -35.3508697, lng: 149.0639869} | - { name: Larakia Street,stop_code: Wjz34c4, lat: -35.3508697, lng: 149.0639869} |
- { name: Cedrela Place,stop_code: WjrXR3f, lat: -35.3458397, lng: 149.040861} | - { name: Cedrela Place,stop_code: WjrXR3f, lat: -35.3458397, lng: 149.040861} |
- { name: Blowering Street,stop_code: WjrXLtK, lat: -35.3335671, lng: 149.0346289} | - { name: Blowering Street,stop_code: WjrXLtK, lat: -35.3335671, lng: 149.0346289} |
- { name: Mt Taylor Zig Zag,stop_code: Wjz39sA, lat: -35.3673329, lng: 149.0783636} | - { name: Mt Taylor Zig Zag,stop_code: Wjz39sA, lat: -35.3673329, lng: 149.0783636} |
- { name: Beasley Street,stop_code: Wjz3hu6, lat: -35.3658261, lng: 149.0887408} | - { name: Beasley Street,stop_code: Wjz3hu6, lat: -35.3658261, lng: 149.0887408} |
- { name: Marr Street,stop_code: Wjz3iuk, lat: -35.3604697, lng: 149.0889561} | - { name: Marr Street,stop_code: Wjz3iuk, lat: -35.3604697, lng: 149.0889561} |
- { name: Catalina Drive,stop_code: Wjzcuop, lat: -35.2989647, lng: 149.1881172} | - { name: Catalina Drive,stop_code: Wjzcuop, lat: -35.2989647, lng: 149.1881172} |
- { name: Laverton Avenue,stop_code: WjzcJ38, lat: -35.3024713, lng: 149.2056109} | - { name: Laverton Avenue,stop_code: WjzcJ38, lat: -35.3024713, lng: 149.2056109} |
- { name: Horse Park Drive,stop_code: Wjz7smv, lat: -35.1734671, lng: 149.0988597} | - { name: Horse Park Drive,stop_code: Wjz7smv, lat: -35.1734671, lng: 149.0988597} |
- { name: Kerrigan Street,stop_code: Wjr_xY9, lat: -35.1918291, lng: 149.028508} | - { name: Kerrigan Street,stop_code: Wjr_xY9, lat: -35.1918291, lng: 149.028508} |
- { name: Yabsley Place,stop_code: Wjr_Ej0, lat: -35.1981116, lng: 149.0323079} | - { name: Yabsley Place,stop_code: Wjr_Ej0, lat: -35.1981116, lng: 149.0323079} |
- { name: Rogers Street,stop_code: Wjr_GVA, lat: -35.188117, lng: 149.0399446} | - { name: Rogers Street,stop_code: Wjr_GVA, lat: -35.188117, lng: 149.0399446} |
- { name: Foskett Street,stop_code: Wjr_N-q, lat: -35.1903433, lng: 149.0507803} | - { name: Foskett Street,stop_code: Wjr_N-q, lat: -35.1903433, lng: 149.0507803} |
- { name: Nott Street,stop_code: Wjr_NpJ, lat: -35.1935127, lng: 149.0455536} | - { name: Nott Street,stop_code: Wjr_NpJ, lat: -35.1935127, lng: 149.0455536} |
- { name: Osburn Drive,stop_code: Wjr-uUL, lat: -35.210513, lng: 149.0180445} | - { name: Osburn Drive,stop_code: Wjr-uUL, lat: -35.210513, lng: 149.0180445} |
- { name: Commonwealth Avenue,stop_code: Wjz4KO9, lat: -35.2975962, lng: 149.1259252} | - { name: Commonwealth Avenue,stop_code: Wjz4KO9, lat: -35.2975962, lng: 149.1259252} |
- { name: Cowper Street,stop_code: Wjz5_0v, lat: -35.2490065, lng: 149.1400861} | - { name: Cowper Street,stop_code: Wjz5_0v, lat: -35.2490065, lng: 149.1400861} |
- { name: Captain Cook Crescent,stop_code: Wjz4NDo, lat: -35.3217168, lng: 149.1344712} | - { name: Captain Cook Crescent,stop_code: Wjz4NDo, lat: -35.3217168, lng: 149.1344712} |
- { name: Marcus Clarke Street,stop_code: Wjz5FIS, lat: -35.279312, lng: 149.1254166} | - { name: Marcus Clarke Street,stop_code: Wjz5FIS, lat: -35.279312, lng: 149.1254166} |
- { name: Keenan Street,stop_code: Wjz66kG, lat: -35.2081931, lng: 149.0662542} | - { name: Keenan Street,stop_code: Wjz66kG, lat: -35.2081931, lng: 149.0662542} |
- { name: Moor Place,stop_code: Wjz66t3, lat: -35.2074684, lng: 149.0667796} | - { name: Moor Place,stop_code: Wjz66t3, lat: -35.2074684, lng: 149.0667796} |
- { name: Connah Street,stop_code: Wjr-Xhh, lat: -35.2268712, lng: 149.0546156} | - { name: Connah Street,stop_code: Wjr-Xhh, lat: -35.2268712, lng: 149.0546156} |
- { name: Linger Place,stop_code: Wjr--r_, lat: -35.2084885, lng: 149.0569758} | - { name: Linger Place,stop_code: Wjr--r_, lat: -35.2084885, lng: 149.0569758} |
- { name: Russell Drive,stop_code: Wjzc55s, lat: -35.3007195, lng: 149.1509863} | - { name: Russell Drive,stop_code: Wjzc55s, lat: -35.3007195, lng: 149.1509863} |
- { name: Reg Saunders Way,stop_code: Wjz4-YV, lat: -35.2961803, lng: 149.1503194} | - { name: Reg Saunders Way,stop_code: Wjz4-YV, lat: -35.2961803, lng: 149.1503194} |
- { name: Russell Drive,stop_code: Wjzc60i, lat: -35.2988201, lng: 149.1508684} | - { name: Russell Drive,stop_code: Wjzc60i, lat: -35.2988201, lng: 149.1508684} |
- { name: National Circuit,stop_code: Wjz4Quk, lat: -35.3055692, lng: 149.1330442} | - { name: National Circuit,stop_code: Wjz4Quk, lat: -35.3055692, lng: 149.1330442} |
- { name: Melrose Drive,stop_code: Wjz3eZ4, lat: -35.3392098, lng: 149.0831308} | - { name: Melrose Drive,stop_code: Wjz3eZ4, lat: -35.3392098, lng: 149.0831308} |
- { name: Russell Drive,stop_code: Wjz4-KO, lat: -35.2946955, lng: 149.147399} | - { name: Russell Drive,stop_code: Wjz4-KO, lat: -35.2946955, lng: 149.147399} |
- { name: Chifley Place,stop_code: Wjz3caw, lat: -35.3525528, lng: 149.0755688} | - { name: Chifley Place,stop_code: Wjz3caw, lat: -35.3525528, lng: 149.0755688} |
- { name: Carslaw Street,stop_code: Wjz3ceY, lat: -35.3495185, lng: 149.0761236} | - { name: Carslaw Street,stop_code: Wjz3ceY, lat: -35.3495185, lng: 149.0761236} |
- { name: Threlfall Street,stop_code: Wjz3b9L, lat: -35.3581358, lng: 149.0757975} | - { name: Threlfall Street,stop_code: Wjz3b9L, lat: -35.3581358, lng: 149.0757975} |
- { name: Boult Place,stop_code: Wjr-SHc, lat: -35.2086969, lng: 149.0476925} | - { name: Boult Place,stop_code: Wjr-SHc, lat: -35.2086969, lng: 149.0476925} |
- { name: Conley Drive,stop_code: Wjr-RZE, lat: -35.2132014, lng: 149.0511677} | - { name: Conley Drive,stop_code: Wjr-RZE, lat: -35.2132014, lng: 149.0511677} |
- { name: Grainger Circuit,stop_code: Wjr-R_3, lat: -35.2115401, lng: 149.0502887} | - { name: Grainger Circuit,stop_code: Wjr-R_3, lat: -35.2115401, lng: 149.0502887} |
- { name: Verbrugghen Street,stop_code: Wjr-ZBY, lat: -35.2128526, lng: 149.0583185} | - { name: Verbrugghen Street,stop_code: Wjr-ZBY, lat: -35.2128526, lng: 149.0583185} |
- { name: Copland Drive,stop_code: Wjr-ZSE, lat: -35.2124829, lng: 149.0606716} | - { name: Copland Drive,stop_code: Wjr-ZSE, lat: -35.2124829, lng: 149.0606716} |
- { name: Linger Place,stop_code: Wjr--sV, lat: -35.2083253, lng: 149.0568878} | - { name: Linger Place,stop_code: Wjr--sV, lat: -35.2083253, lng: 149.0568878} |
- { name: Bishop Place,stop_code: Wjr--m3, lat: -35.2067416, lng: 149.0543264} | - { name: Bishop Place,stop_code: Wjr--m3, lat: -35.2067416, lng: 149.0543264} |
- { name: Henslowe Place,stop_code: Wjr--6t, lat: -35.2065912, lng: 149.0521439} | - { name: Henslowe Place,stop_code: Wjr--6t, lat: -35.2065912, lng: 149.0521439} |
- { name: Lathlain Street,stop_code: Wjz605N, lat: -35.2405467, lng: 149.0636668} | - { name: Lathlain Street,stop_code: Wjz605N, lat: -35.2405467, lng: 149.0636668} |
- { name: Lathlain Street,stop_code: Wjz604Y, lat: -35.2410486, lng: 149.0638326} | - { name: Lathlain Street,stop_code: Wjz604Y, lat: -35.2410486, lng: 149.0638326} |
- { name: Daley Road,stop_code: Wjz5xHC, lat: -35.2799871, lng: 149.1141335} | - { name: Daley Road,stop_code: Wjz5xHC, lat: -35.2799871, lng: 149.1141335} |
- { name: Macarthur Avenue,stop_code: Wjz5J9d, lat: -35.2594616, lng: 149.1190821} | - { name: Macarthur Avenue,stop_code: Wjz5J9d, lat: -35.2594616, lng: 149.1190821} |
- { name: Bainton Crescent,stop_code: Wjr-_kG, lat: -35.2027328, lng: 149.0551853} | - { name: Bainton Crescent,stop_code: Wjr-_kG, lat: -35.2027328, lng: 149.0551853} |
- { name: Alpen Street,stop_code: Wjr-_Nn, lat: -35.2043934, lng: 149.0601598} | - { name: Alpen Street,stop_code: Wjr-_Nn, lat: -35.2043934, lng: 149.0601598} |
- { name: Broadby Close,stop_code: Wjz671V, lat: -35.204864, lng: 149.0637204} | - { name: Broadby Close,stop_code: Wjz671V, lat: -35.204864, lng: 149.0637204} |
- { name: Kingsford Smith Drive,stop_code: Wjr-_zv, lat: -35.2030129, lng: 149.0575605} | - { name: Kingsford Smith Drive,stop_code: Wjr-_zv, lat: -35.2030129, lng: 149.0575605} |
- { name: John Cleland Crescent,stop_code: Wjr-Yg7, lat: -35.2215188, lng: 149.0543538} | - { name: John Cleland Crescent,stop_code: Wjr-Yg7, lat: -35.2215188, lng: 149.0543538} |
- { name: John Cleland Crescent,stop_code: Wjr-XyN, lat: -35.226202, lng: 149.0581637} | - { name: John Cleland Crescent,stop_code: Wjr-XyN, lat: -35.226202, lng: 149.0581637} |
- { name: Wiseman Street,stop_code: Wjz56Xu, lat: -35.2524925, lng: 149.0726439} | - { name: Wiseman Street,stop_code: Wjz56Xu, lat: -35.2524925, lng: 149.0726439} |
- { name: Fulton Street,stop_code: Wjz571j, lat: -35.2486364, lng: 149.0628845} | - { name: Fulton Street,stop_code: Wjz571j, lat: -35.2486364, lng: 149.0628845} |
- { name: Launceston Street,stop_code: Wjz3m3b, lat: -35.3406241, lng: 149.0847703} | - { name: Launceston Street,stop_code: Wjz3m3b, lat: -35.3406241, lng: 149.0847703} |
- { name: O'Hanlon Place,stop_code: Wjz79ZQ, lat: -35.190906, lng: 149.0842116} | - { name: O'Hanlon Place,stop_code: Wjz79ZQ, lat: -35.190906, lng: 149.0842116} |
- { name: O'Hanlon Place,stop_code: Wjz7hb5, lat: -35.1921368, lng: 149.0859491} | - { name: O'Hanlon Place,stop_code: Wjz7hb5, lat: -35.1921368, lng: 149.0859491} |
- { name: O'Hanlon Place,stop_code: Wjz7hbe, lat: -35.1921183, lng: 149.0860955} | - { name: O'Hanlon Place,stop_code: Wjz7hbe, lat: -35.1921183, lng: 149.0860955} |
- { name: Jalanga Crescent,stop_code: Wjz5dCr, lat: -35.2561978, lng: 149.0795805} | - { name: Jalanga Crescent,stop_code: Wjz5dCr, lat: -35.2561978, lng: 149.0795805} |
- { name: Lyttleton Crescent,stop_code: Wjz54_B, lat: -35.2608235, lng: 149.0728514} | - { name: Lyttleton Crescent,stop_code: Wjz54_B, lat: -35.2608235, lng: 149.0728514} |
- { name: Lyttleton Crescent,stop_code: Wjz54_n, lat: -35.2606623, lng: 149.072551} | - { name: Lyttleton Crescent,stop_code: Wjz54_n, lat: -35.2606623, lng: 149.072551} |
- { name: Cambridge Street,stop_code: Wjz54CS, lat: -35.2614333, lng: 149.0690577} | - { name: Cambridge Street,stop_code: Wjz54CS, lat: -35.2614333, lng: 149.0690577} |
- { name: Templeton Street,stop_code: Wjz551Q, lat: -35.2595831, lng: 149.0636761} | - { name: Templeton Street,stop_code: Wjz551Q, lat: -35.2595831, lng: 149.0636761} |
- { name: Templeton Street,stop_code: Wjz5592, lat: -35.2596812, lng: 149.0639679} | - { name: Templeton Street,stop_code: Wjz5592, lat: -35.2596812, lng: 149.0639679} |
- { name: Redfern Street,stop_code: WjrZZB7, lat: -35.2565133, lng: 149.0570071} | - { name: Redfern Street,stop_code: WjrZZB7, lat: -35.2565133, lng: 149.0570071} |
- { name: Coulter Drive,stop_code: WjrZ_o2, lat: -35.2493991, lng: 149.055711} | - { name: Coulter Drive,stop_code: WjrZ_o2, lat: -35.2493991, lng: 149.055711} |
- { name: Coulter Drive,stop_code: WjrZ_o4, lat: -35.2492379, lng: 149.0556338} | - { name: Coulter Drive,stop_code: WjrZ_o4, lat: -35.2492379, lng: 149.0556338} |
- { name: Weetangera Place,stop_code: WjrZTMv, lat: -35.2489575, lng: 149.0493939} | - { name: Weetangera Place,stop_code: WjrZTMv, lat: -35.2489575, lng: 149.0493939} |
- { name: Gillespie Street,stop_code: WjrZTua, lat: -35.2452775, lng: 149.0448362} | - { name: Gillespie Street,stop_code: WjrZTua, lat: -35.2452775, lng: 149.0448362} |
- { name: Gillespie Street,stop_code: WjrZTu1, lat: -35.2453967, lng: 149.044759} | - { name: Gillespie Street,stop_code: WjrZTu1, lat: -35.2453967, lng: 149.044759} |
- { name: Hawker Place,stop_code: Wjr-Mg6, lat: -35.2436162, lng: 149.0432913} | - { name: Hawker Place,stop_code: Wjr-Mg6, lat: -35.2436162, lng: 149.0432913} |
- { name: Hawker Place,stop_code: Wjr-Mgt, lat: -35.2436863, lng: 149.0438835} | - { name: Hawker Place,stop_code: Wjr-Mgt, lat: -35.2436863, lng: 149.0438835} |
- { name: Murranji Street,stop_code: WjrZT5e, lat: -35.245649, lng: 149.0408365} | - { name: Murranji Street,stop_code: WjrZT5e, lat: -35.245649, lng: 149.0408365} |
- { name: Erldunda Circuit,stop_code: WjrZLXY, lat: -35.2471491, lng: 149.0403988} | - { name: Erldunda Circuit,stop_code: WjrZLXY, lat: -35.2471491, lng: 149.0403988} |
- { name: Murranji Street,stop_code: WjrZT6b, lat: -35.2452004, lng: 149.0407936} | - { name: Murranji Street,stop_code: WjrZT6b, lat: -35.2452004, lng: 149.0407936} |
- { name: Wisdom Street,stop_code: Wjz3mI-, lat: -35.3396854, lng: 149.092654} | - { name: Wisdom Street,stop_code: Wjz3mI-, lat: -35.3396854, lng: 149.092654} |
- { name: Hardwick Crescent,stop_code: Wjr-z7J, lat: -35.2223574, lng: 149.0195037} | - { name: Hardwick Crescent,stop_code: Wjr-z7J, lat: -35.2223574, lng: 149.0195037} |
- { name: Ligertwood Street,stop_code: Wjz65aB, lat: -35.2148653, lng: 149.0646456} | - { name: Ligertwood Street,stop_code: Wjz65aB, lat: -35.2148653, lng: 149.0646456} |
- { name: Alderman Street,stop_code: Wjz65rQ, lat: -35.2142653, lng: 149.0676927} | - { name: Alderman Street,stop_code: Wjz65rQ, lat: -35.2142653, lng: 149.0676927} |
- { name: Hatfield Street,stop_code: Wjz66oJ, lat: -35.2107077, lng: 149.0674989} | - { name: Hatfield Street,stop_code: Wjz66oJ, lat: -35.2107077, lng: 149.0674989} |
- { name: Clancy Street,stop_code: Wjz66WS, lat: -35.2092634, lng: 149.0731992} | - { name: Clancy Street,stop_code: Wjz66WS, lat: -35.2092634, lng: 149.0731992} |
- { name: Marconi Crescent,stop_code: WjrW_zu, lat: -35.3788924, lng: 149.0576496} | - { name: Marconi Crescent,stop_code: WjrW_zu, lat: -35.3788924, lng: 149.0576496} |
- { name: Marconi Crescent,stop_code: WjrW_RH, lat: -35.3777568, lng: 149.0607135} | - { name: Marconi Crescent,stop_code: WjrW_RH, lat: -35.3777568, lng: 149.0607135} |
- { name: Marconi Crescent,stop_code: Wjz27k0, lat: -35.3786939, lng: 149.0653235} | - { name: Marconi Crescent,stop_code: Wjz27k0, lat: -35.3786939, lng: 149.0653235} |
- { name: Lascelles Circuit,stop_code: Wjz27gg, lat: -35.3814094, lng: 149.0656219} | - { name: Lascelles Circuit,stop_code: Wjz27gg, lat: -35.3814094, lng: 149.0656219} |
- { name: Summerland Circuit,stop_code: Wjz26tw, lat: -35.38347, lng: 149.0674733} | - { name: Summerland Circuit,stop_code: Wjz26tw, lat: -35.38347, lng: 149.0674733} |
- { name: Mason Street,stop_code: Wjz26WW, lat: -35.3853577, lng: 149.0733293} | - { name: Mason Street,stop_code: Wjz26WW, lat: -35.3853577, lng: 149.0733293} |
- { name: Lee Steere Crescent,stop_code: Wjz2df1, lat: -35.3875049, lng: 149.0748933} | - { name: Lee Steere Crescent,stop_code: Wjz2df1, lat: -35.3875049, lng: 149.0748933} |
- { name: Kingsmill Street,stop_code: Wjz2d32, lat: -35.3901917, lng: 149.0734943} | - { name: Kingsmill Street,stop_code: Wjz2d32, lat: -35.3901917, lng: 149.0734943} |
- { name: Jenke Circuit,stop_code: Wjz24uT, lat: -35.3931517, lng: 149.0676751} | - { name: Jenke Circuit,stop_code: Wjz24uT, lat: -35.3931517, lng: 149.0676751} |
- { name: O'Halloran Circuit,stop_code: Wjz24lA, lat: -35.3941231, lng: 149.0659575} | - { name: O'Halloran Circuit,stop_code: Wjz24lA, lat: -35.3941231, lng: 149.0659575} |
- { name: Pinkerton Circuit,stop_code: Wjz2498, lat: -35.3972167, lng: 149.0640703} | - { name: Pinkerton Circuit,stop_code: Wjz2498, lat: -35.3972167, lng: 149.0640703} |
- { name: Ragless Circuit,stop_code: Wjz234e, lat: -35.4001412, lng: 149.0627055} | - { name: Ragless Circuit,stop_code: Wjz234e, lat: -35.4001412, lng: 149.0627055} |
- { name: Learmonth Drive,stop_code: Wjz230Q, lat: -35.4030936, lng: 149.0635466} | - { name: Learmonth Drive,stop_code: Wjz230Q, lat: -35.4030936, lng: 149.0635466} |
- { name: Lavan Place,stop_code: Wjz66C2, lat: -35.2068343, lng: 149.0681005} | - { name: Lavan Place,stop_code: Wjz66C2, lat: -35.2068343, lng: 149.0681005} |
- { name: Clancy Street,stop_code: Wjz66Lx, lat: -35.2062279, lng: 149.0700922} | - { name: Clancy Street,stop_code: Wjz66Lx, lat: -35.2062279, lng: 149.0700922} |
- { name: Edmunds Place,stop_code: Wjz70go, lat: -35.2001419, lng: 149.0658463} | - { name: Edmunds Place,stop_code: Wjz70go, lat: -35.2001419, lng: 149.0658463} |
- { name: Baddeley Crescent,stop_code: Wjr_UUM, lat: -35.2001188, lng: 149.062303} | - { name: Baddeley Crescent,stop_code: Wjr_UUM, lat: -35.2001188, lng: 149.062303} |
- { name: Captain Cook Crescent,stop_code: Wjz3_z-, lat: -35.3349223, lng: 149.1461306} | - { name: Captain Cook Crescent,stop_code: Wjz3_z-, lat: -35.3349223, lng: 149.1461306} |
- { name: Kingsford Smith Drive,stop_code: Wjr_UPL, lat: -35.1975228, lng: 149.0606273} | - { name: Kingsford Smith Drive,stop_code: Wjr_UPL, lat: -35.1975228, lng: 149.0606273} |
- { name: Kingsford Smith Drive,stop_code: Wjr_UTJ, lat: -35.1949558, lng: 149.0607434} | - { name: Kingsford Smith Drive,stop_code: Wjr_UTJ, lat: -35.1949558, lng: 149.0607434} |
- { name: Healy Street,stop_code: Wjz70kD, lat: -35.196836, lng: 149.0659887} | - { name: Healy Street,stop_code: Wjz70kD, lat: -35.196836, lng: 149.0659887} |
- { name: Heagney Crescent,stop_code: Wjz2EXs, lat: -35.4174557, lng: 149.1275741} | - { name: Heagney Crescent,stop_code: Wjz2EXs, lat: -35.4174557, lng: 149.1275741} |
- { name: Monaro Highway,stop_code: Wjz2V0k, lat: -35.4140263, lng: 149.1397991} | - { name: Monaro Highway,stop_code: Wjz2V0k, lat: -35.4140263, lng: 149.1397991} |
- { name: Willoughby Crescent,stop_code: Wjz2NH0, lat: -35.4123115, lng: 149.1353734} | - { name: Willoughby Crescent,stop_code: Wjz2NH0, lat: -35.4123115, lng: 149.1353734} |
- { name: Theodore Street,stop_code: Wjz48Q1, lat: -35.3291744, lng: 149.0818599} | - { name: Theodore Street,stop_code: Wjz48Q1, lat: -35.3291744, lng: 149.0818599} |
- { name: Martin Street,stop_code: Wjz49Ui, lat: -35.3262888, lng: 149.0835377} | - { name: Martin Street,stop_code: Wjz49Ui, lat: -35.3262888, lng: 149.0835377} |
- { name: Morgan Crescent,stop_code: Wjz4aMo, lat: -35.3209613, lng: 149.082268} | - { name: Morgan Crescent,stop_code: Wjz4aMo, lat: -35.3209613, lng: 149.082268} |
- { name: Jenkins Street,stop_code: Wjz49dp, lat: -35.3229961, lng: 149.075421} | - { name: Jenkins Street,stop_code: Wjz49dp, lat: -35.3229961, lng: 149.075421} |
- { name: Launceston Street,stop_code: Wjz3e8l, lat: -35.3425473, lng: 149.0752509} | - { name: Launceston Street,stop_code: Wjz3e8l, lat: -35.3425473, lng: 149.0752509} |
- { name: McCubbin Street,stop_code: WjrX_bF, lat: -35.3353506, lng: 149.0538045} | - { name: McCubbin Street,stop_code: WjrX_bF, lat: -35.3353506, lng: 149.0538045} |
- { name: Namatjira Drive,stop_code: WjrX-oT, lat: -35.3424053, lng: 149.0567937} | - { name: Namatjira Drive,stop_code: WjrX-oT, lat: -35.3424053, lng: 149.0567937} |
- { name: Mather Street,stop_code: WjrX-zT, lat: -35.3402984, lng: 149.0581286} | - { name: Mather Street,stop_code: WjrX-zT, lat: -35.3402984, lng: 149.0581286} |
- { name: Nambir Court,stop_code: Wjz1edz, lat: -35.4271482, lng: 149.0757082} | - { name: Nambir Court,stop_code: Wjz1edz, lat: -35.4271482, lng: 149.0757082} |
- { name: Anketell Street,stop_code: Wjz20Eo, lat: -35.4198466, lng: 149.0699766} | - { name: Anketell Street,stop_code: Wjz20Eo, lat: -35.4198466, lng: 149.0699766} |
- { name: Laurens Street,stop_code: Wjz2aVu, lat: -35.4076897, lng: 149.0836236} | - { name: Laurens Street,stop_code: Wjz2aVu, lat: -35.4076897, lng: 149.0836236} |
- { name: Charleston Street,stop_code: Wjz28DH, lat: -35.4148504, lng: 149.0799887} | - { name: Charleston Street,stop_code: Wjz28DH, lat: -35.4148504, lng: 149.0799887} |
- { name: Mault Place,stop_code: Wjz2g6U, lat: -35.4157965, lng: 149.0857566} | - { name: Mault Place,stop_code: Wjz2g6U, lat: -35.4157965, lng: 149.0857566} |
- { name: Corlette Crescent,stop_code: Wjz2gvd, lat: -35.4146612, lng: 149.0888256} | - { name: Corlette Crescent,stop_code: Wjz2gvd, lat: -35.4146612, lng: 149.0888256} |
- { name: Nemarang Crescent,stop_code: Wjz33CI, lat: -35.3549749, lng: 149.0689295} | - { name: Nemarang Crescent,stop_code: Wjz33CI, lat: -35.3549749, lng: 149.0689295} |
- { name: Tuggeranong Parkway Onramp,stop_code: Wjz33KX, lat: -35.3550858, lng: 149.070698} | - { name: Tuggeranong Parkway Onramp,stop_code: Wjz33KX, lat: -35.3550858, lng: 149.070698} |
- { name: Wambaya Street,stop_code: Wjz33nk, lat: -35.3543462, lng: 149.0657554} | - { name: Wambaya Street,stop_code: Wjz33nk, lat: -35.3543462, lng: 149.0657554} |
- { name: Wirangu Place,stop_code: WjrXXI2, lat: -35.3565059, lng: 149.058473} | - { name: Wirangu Place,stop_code: WjrXXI2, lat: -35.3565059, lng: 149.058473} |
- { name: Walpiri Place,stop_code: WjrXYtm, lat: -35.3499821, lng: 149.0560969} | - { name: Walpiri Place,stop_code: WjrXYtm, lat: -35.3499821, lng: 149.0560969} |
- { name: Bangalay Crescent,stop_code: WjrXIKK, lat: -35.3493279, lng: 149.0374035} | - { name: Bangalay Crescent,stop_code: WjrXIKK, lat: -35.3493279, lng: 149.0374035} |
- { name: Hindmarsh Drive,stop_code: WjrXJfw, lat: -35.3436463, lng: 149.031771} | - { name: Hindmarsh Drive,stop_code: WjrXJfw, lat: -35.3436463, lng: 149.031771} |
- { name: Eppalock Street,stop_code: WjrYEg0, lat: -35.3320285, lng: 149.0323493} | - { name: Eppalock Street,stop_code: WjrYEg0, lat: -35.3320285, lng: 149.0323493} |
- { name: Warragamba Avenue,stop_code: WjrYEWc, lat: -35.3302839, lng: 149.0394086} | - { name: Warragamba Avenue,stop_code: WjrYEWc, lat: -35.3302839, lng: 149.0394086} |
- { name: Streeton Drive,stop_code: WjrX_1g, lat: -35.336799, lng: 149.0519909} | - { name: Streeton Drive,stop_code: WjrX_1g, lat: -35.336799, lng: 149.0519909} |
- { name: Hellyer Street,stop_code: WjrXLY1, lat: -35.3346674, lng: 149.0391656} | - { name: Hellyer Street,stop_code: WjrXLY1, lat: -35.3346674, lng: 149.0391656} |
- { name: Paloona Place,stop_code: WjrXLEL, lat: -35.3369076, lng: 149.0374236} | - { name: Paloona Place,stop_code: WjrXLEL, lat: -35.3369076, lng: 149.0374236} |
- { name: Leighton Street,stop_code: Wjz39GV, lat: -35.369019, lng: 149.0816284} | - { name: Leighton Street,stop_code: Wjz39GV, lat: -35.369019, lng: 149.0816284} |
- { name: Foskett Street,stop_code: Wjr_V6V, lat: -35.1904467, lng: 149.0528033} | - { name: Foskett Street,stop_code: Wjr_V6V, lat: -35.1904467, lng: 149.0528033} |
- { name: Tillyard Drive,stop_code: Wjr_McO, lat: -35.1972013, lng: 149.0429389} | - { name: Tillyard Drive,stop_code: Wjr_McO, lat: -35.1972013, lng: 149.0429389} |
- { name: Spalding Street,stop_code: Wjr_MhY, lat: -35.1991196, lng: 149.0445095} | - { name: Spalding Street,stop_code: Wjr_MhY, lat: -35.1991196, lng: 149.0445095} |
- { name: O'Shanassy Street,stop_code: Wjz4a9o, lat: -35.3203323, lng: 149.0754663} | - { name: O'Shanassy Street,stop_code: Wjz4a9o, lat: -35.3203323, lng: 149.0754663} |
- { name: Owen Dixon Drive,stop_code: Wjz70IW, lat: -35.197242, lng: 149.0706277} | - { name: Owen Dixon Drive,stop_code: Wjz70IW, lat: -35.197242, lng: 149.0706277} |
- { name: Sport Way,stop_code: Wjr-DTC, lat: -35.2002855, lng: 149.0276101} | - { name: Sport Way,stop_code: Wjr-DTC, lat: -35.2002855, lng: 149.0276101} |
- { name: Lance Hill Avenue,stop_code: Wjr_wf4, lat: -35.1950004, lng: 149.0199737} | - { name: Lance Hill Avenue,stop_code: Wjr_wf4, lat: -35.1950004, lng: 149.0199737} |
- { name: Kerrigan Street,stop_code: Wjr_pVW, lat: -35.1938099, lng: 149.0184155} | - { name: Kerrigan Street,stop_code: Wjr_pVW, lat: -35.1938099, lng: 149.0184155} |
- { name: Douglass Street,stop_code: Wjz70Wi, lat: -35.1986355, lng: 149.0725952} | - { name: Douglass Street,stop_code: Wjz70Wi, lat: -35.1986355, lng: 149.0725952} |
- { name: Copland Drive,stop_code: Wjz67_v, lat: -35.2002563, lng: 149.0727607} | - { name: Copland Drive,stop_code: Wjz67_v, lat: -35.2002563, lng: 149.0727607} |
- { name: Gallipoli Road,stop_code: Wjzcend, lat: -35.2937972, lng: 149.1643403} | - { name: Gallipoli Road,stop_code: Wjzcend, lat: -35.2937972, lng: 149.1643403} |
- { name: Mileham Street,stop_code: Wjr-vNL, lat: -35.2043835, lng: 149.0167621} | - { name: Mileham Street,stop_code: Wjr-vNL, lat: -35.2043835, lng: 149.0167621} |
- { name: Ginninderra Drive,stop_code: Wjr-Df8, lat: -35.2008175, lng: 149.0201835} | - { name: Ginninderra Drive,stop_code: Wjr-Df8, lat: -35.2008175, lng: 149.0201835} |
- { name: Clode Crescent,stop_code: Wjr-te3, lat: -35.2122382, lng: 149.0090273} | - { name: Clode Crescent,stop_code: Wjr-te3, lat: -35.2122382, lng: 149.0090273} |
- { name: Handcock Crescent,stop_code: Wjr-CsO, lat: -35.2082115, lng: 149.0237453} | - { name: Handcock Crescent,stop_code: Wjr-CsO, lat: -35.2082115, lng: 149.0237453} |
- { name: Prevost Place,stop_code: Wjr-sKW, lat: -35.2178207, lng: 149.0156953} | - { name: Prevost Place,stop_code: Wjr-sKW, lat: -35.2178207, lng: 149.0156953} |
- { name: Plowman Place,stop_code: Wjr-S9y, lat: -35.2102797, lng: 149.0426899} | - { name: Plowman Place,stop_code: Wjr-S9y, lat: -35.2102797, lng: 149.0426899} |
- { name: O'Loghlen Street,stop_code: Wjr-HbC, lat: -35.2250302, lng: 149.0316399} | - { name: O'Loghlen Street,stop_code: Wjr-HbC, lat: -35.2250302, lng: 149.0316399} |
- { name: Southern Cross Drive,stop_code: Wjr-sQ8, lat: -35.2193706, lng: 149.0159919} | - { name: Southern Cross Drive,stop_code: Wjr-sQ8, lat: -35.2193706, lng: 149.0159919} |
- { name: Armstrong Crescent,stop_code: Wjr-rv7, lat: -35.2221818, lng: 149.0117611} | - { name: Armstrong Crescent,stop_code: Wjr-rv7, lat: -35.2221818, lng: 149.0117611} |
- { name: Spofforth Street,stop_code: Wjr-kVk, lat: -35.2210905, lng: 149.0066193} | - { name: Spofforth Street,stop_code: Wjr-kVk, lat: -35.2210905, lng: 149.0066193} |
- { name: Pickworth Street,stop_code: Wjr-rxG, lat: -35.2267918, lng: 149.0140227} | - { name: Pickworth Street,stop_code: Wjr-rxG, lat: -35.2267918, lng: 149.0140227} |
- { name: Macnaughton Street,stop_code: Wjr-qZg, lat: -35.2296561, lng: 149.0176617} | - { name: Macnaughton Street,stop_code: Wjr-qZg, lat: -35.2296561, lng: 149.0176617} |
- { name: Powell Street,stop_code: Wjr-rUs, lat: -35.2272548, lng: 149.0178319} | - { name: Powell Street,stop_code: Wjr-rUs, lat: -35.2272548, lng: 149.0178319} |
- { name: Beaurepaire Crescent,stop_code: Wjr-rNr, lat: -35.226697, lng: 149.016389} | - { name: Beaurepaire Crescent,stop_code: Wjr-rNr, lat: -35.226697, lng: 149.016389} |
- { name: Hardwick Crescent,stop_code: Wjr-zcC, lat: -35.2243517, lng: 149.0207165} | - { name: Hardwick Crescent,stop_code: Wjr-zcC, lat: -35.2243517, lng: 149.0207165} |
- { name: Brazel Street,stop_code: Wjr-G5f, lat: -35.2290792, lng: 149.0298564} | - { name: Brazel Street,stop_code: Wjr-G5f, lat: -35.2290792, lng: 149.0298564} |
- { name: Wearing Street,stop_code: Wjr-xRd, lat: -35.2347078, lng: 149.0270748} | - { name: Wearing Street,stop_code: Wjr-xRd, lat: -35.2347078, lng: 149.0270748} |
- { name: Drake Brockman Drive,stop_code: Wjr-wDP, lat: -35.2389936, lng: 149.0252414} | - { name: Drake Brockman Drive,stop_code: Wjr-wDP, lat: -35.2389936, lng: 149.0252414} |
- { name: Castieau Street,stop_code: Wjr-Gsq, lat: -35.2301636, lng: 149.0342818} | - { name: Castieau Street,stop_code: Wjr-Gsq, lat: -35.2301636, lng: 149.0342818} |
- { name: Ulm Street,stop_code: Wjr-GyJ, lat: -35.2312775, lng: 149.0359574} | - { name: Ulm Street,stop_code: Wjr-GyJ, lat: -35.2312775, lng: 149.0359574} |
- { name: Wirraway Crescent,stop_code: Wjr-GFM, lat: -35.2324613, lng: 149.03753} | - { name: Wirraway Crescent,stop_code: Wjr-GFM, lat: -35.2324613, lng: 149.03753} |
- { name: Ross Smith Crescent,stop_code: Wjr-F_m, lat: -35.233261, lng: 149.039515} | - { name: Ross Smith Crescent,stop_code: Wjr-F_m, lat: -35.233261, lng: 149.039515} |
- { name: Ross Smith Crescent,stop_code: Wjr-FCU, lat: -35.2344506, lng: 149.0363984} | - { name: Ross Smith Crescent,stop_code: Wjr-FCU, lat: -35.2344506, lng: 149.0363984} |
- { name: Hinkler Street,stop_code: Wjr-Fzd, lat: -35.2360739, lng: 149.0353153} | - { name: Hinkler Street,stop_code: Wjr-Fzd, lat: -35.2360739, lng: 149.0353153} |
- { name: Delamere Street,stop_code: Wjr-E8A, lat: -35.2437543, lng: 149.031741} | - { name: Delamere Street,stop_code: Wjr-E8A, lat: -35.2437543, lng: 149.031741} |
- { name: Tanumbirini Street,stop_code: WjrZLdA, lat: -35.245805, lng: 149.0316615} | - { name: Tanumbirini Street,stop_code: WjrZLdA, lat: -35.245805, lng: 149.0316615} |
- { name: Southwell Street,stop_code: WjrZSKp, lat: -35.2509203, lng: 149.0480636} | - { name: Southwell Street,stop_code: WjrZSKp, lat: -35.2509203, lng: 149.0480636} |
- { name: De Salis Street,stop_code: WjrZSWs, lat: -35.2533983, lng: 149.050782} | - { name: De Salis Street,stop_code: WjrZSWs, lat: -35.2533983, lng: 149.050782} |
- { name: Hannaford Street,stop_code: Wjr-MCk, lat: -35.2396029, lng: 149.0464162} | - { name: Hannaford Street,stop_code: Wjr-MCk, lat: -35.2396029, lng: 149.0464162} |
- { name: Hannaford Street,stop_code: Wjr-M-x, lat: -35.2399127, lng: 149.0508416} | - { name: Hannaford Street,stop_code: Wjr-M-x, lat: -35.2399127, lng: 149.0508416} |
- { name: Shumack Street,stop_code: WjrZ-aT, lat: -35.2531402, lng: 149.053943} | - { name: Shumack Street,stop_code: WjrZ-aT, lat: -35.2531402, lng: 149.053943} |
- { name: Coulter Drive,stop_code: WjrZZeD, lat: -35.2558247, lng: 149.0536901} | - { name: Coulter Drive,stop_code: WjrZZeD, lat: -35.2558247, lng: 149.0536901} |
- { name: Redfern Street,stop_code: WjrZZlR, lat: -35.2567539, lng: 149.055397} | - { name: Redfern Street,stop_code: WjrZZlR, lat: -35.2567539, lng: 149.055397} |
- { name: Atkinson Street,stop_code: WjrZZH3, lat: -35.2583026, lng: 149.0584315} | - { name: Atkinson Street,stop_code: WjrZZH3, lat: -35.2583026, lng: 149.0584315} |
- { name: Skinner Street,stop_code: Wjz54mj, lat: -35.2617096, lng: 149.0656385} | - { name: Skinner Street,stop_code: Wjz54mj, lat: -35.2617096, lng: 149.0656385} |
- { name: Allman Circuit,stop_code: Wjz55vN, lat: -35.2557214, lng: 149.0677248} | - { name: Allman Circuit,stop_code: Wjz55vN, lat: -35.2557214, lng: 149.0677248} |
- { name: Redfern Street,stop_code: Wjz557P, lat: -35.2555149, lng: 149.0636155} | - { name: Redfern Street,stop_code: Wjz557P, lat: -35.2555149, lng: 149.0636155} |
- { name: Goulburn Street,stop_code: WjrZ-WW, lat: -35.2535016, lng: 149.0623511} | - { name: Goulburn Street,stop_code: WjrZ-WW, lat: -35.2535016, lng: 149.0623511} |
- { name: Roberts Street,stop_code: WjrZ-GZ, lat: -35.2532951, lng: 149.0596327} | - { name: Roberts Street,stop_code: WjrZ-GZ, lat: -35.2532951, lng: 149.0596327} |
- { name: Erskine Street,stop_code: WjrZ-Jc, lat: -35.2513107, lng: 149.058664} | - { name: Erskine Street,stop_code: WjrZ-Jc, lat: -35.2513107, lng: 149.058664} |
- { name: Erskine Street,stop_code: WjrZ_Fk, lat: -35.2485228, lng: 149.0588536} | - { name: Erskine Street,stop_code: WjrZ_Fk, lat: -35.2485228, lng: 149.0588536} |
- { name: Thurlow Place,stop_code: Wjz57Q7, lat: -35.2462221, lng: 149.0708857} | - { name: Thurlow Place,stop_code: Wjz57Q7, lat: -35.2462221, lng: 149.0708857} |
- { name: Maddison Close,stop_code: Wjz5fm2, lat: -35.2452775, lng: 149.0763507} | - { name: Maddison Close,stop_code: Wjz5fm2, lat: -35.2452775, lng: 149.0763507} |
- { name: Vowels Crescent,stop_code: Wjz5nUz, lat: -35.2493715, lng: 149.094909} | - { name: Vowels Crescent,stop_code: Wjz5nUz, lat: -35.2493715, lng: 149.094909} |
- { name: Thynne Street,stop_code: Wjz6gUM, lat: -35.2441052, lng: 149.0951619} | - { name: Thynne Street,stop_code: Wjz6gUM, lat: -35.2441052, lng: 149.0951619} |
- { name: Leverrier Crescent,stop_code: Wjz5vrT, lat: -35.2469189, lng: 149.1007523} | - { name: Leverrier Crescent,stop_code: Wjz5vrT, lat: -35.2469189, lng: 149.1007523} |
- { name: Braybrooke Street,stop_code: Wjz6oJz, lat: -35.2403705, lng: 149.1030403} | - { name: Braybrooke Street,stop_code: Wjz6oJz, lat: -35.2403705, lng: 149.1030403} |
- { name: Temperley Street,stop_code: Wjz7hZW, lat: -35.1910485, lng: 149.0953265} | - { name: Temperley Street,stop_code: Wjz7hZW, lat: -35.1910485, lng: 149.0953265} |
- { name: Dobbin Circuit,stop_code: Wjz7iKx, lat: -35.1849518, lng: 149.0920391} | - { name: Dobbin Circuit,stop_code: Wjz7iKx, lat: -35.1849518, lng: 149.0920391} |
- { name: Fitzsimmons Street,stop_code: Wjz7jaJ, lat: -35.1819033, lng: 149.0868551} | - { name: Fitzsimmons Street,stop_code: Wjz7jaJ, lat: -35.1819033, lng: 149.0868551} |
- { name: Kelleway Avenue,stop_code: Wjz7jW4, lat: -35.181955, lng: 149.0941886} | - { name: Kelleway Avenue,stop_code: Wjz7jW4, lat: -35.181955, lng: 149.0941886} |
- { name: Whatmore Court,stop_code: Wjz7rzg, lat: -35.1815933, lng: 149.1014588} | - { name: Whatmore Court,stop_code: Wjz7rzg, lat: -35.1815933, lng: 149.1014588} |
- { name: Whitfield Circuit,stop_code: Wjz7pkV, lat: -35.1918235, lng: 149.0995622} | - { name: Whitfield Circuit,stop_code: Wjz7pkV, lat: -35.1918235, lng: 149.0995622} |
- { name: Lexcen Avenue,stop_code: Wjz7qSX, lat: -35.1847968, lng: 149.1050623} | - { name: Lexcen Avenue,stop_code: Wjz7qSX, lat: -35.1847968, lng: 149.1050623} |
- { name: Kelleway Avenue,stop_code: Wjz7rRa, lat: -35.1800948, lng: 149.1039243} | - { name: Kelleway Avenue,stop_code: Wjz7rRa, lat: -35.1800948, lng: 149.1039243} |
- { name: Jabanungga Avenue,stop_code: Wjz7B0w, lat: -35.1727054, lng: 149.107275} | - { name: Jabanungga Avenue,stop_code: Wjz7B0w, lat: -35.1727054, lng: 149.107275} |
- { name: Newlop Street,stop_code: Wjz7thn, lat: -35.1713618, lng: 149.0985507} | - { name: Newlop Street,stop_code: Wjz7thn, lat: -35.1713618, lng: 149.0985507} |
- { name: Bicentennial National Trail,stop_code: Wjz7uxi, lat: -35.1663489, lng: 149.1013956} | - { name: Bicentennial National Trail,stop_code: Wjz7uxi, lat: -35.1663489, lng: 149.1013956} |
- { name: Mundang Crescent,stop_code: Wjz7tIt, lat: -35.169553, lng: 149.1029128} | - { name: Mundang Crescent,stop_code: Wjz7tIt, lat: -35.169553, lng: 149.1029128} |
- { name: Wanganeen Avenue,stop_code: Wjz7BsE, lat: -35.1699148, lng: 149.1115106} | - { name: Wanganeen Avenue,stop_code: Wjz7BsE, lat: -35.1699148, lng: 149.1115106} |
- { name: College Street,stop_code: Wjz68W3, lat: -35.2425008, lng: 149.0831669} | - { name: College Street,stop_code: Wjz68W3, lat: -35.2425008, lng: 149.0831669} |
- { name: Drakeford Drive,stop_code: WjrW_uo, lat: -35.3773291, lng: 149.056161} | - { name: Drakeford Drive,stop_code: WjrW_uo, lat: -35.3773291, lng: 149.056161} |
- { name: Tuggeranong Parkway,stop_code: WjrXUAm, lat: -35.3726375, lng: 149.0574471} | - { name: Tuggeranong Parkway,stop_code: WjrXUAm, lat: -35.3726375, lng: 149.0574471} |
- { name: Banambila Street,stop_code: Wjz5l2U, lat: -35.2592266, lng: 149.0857332} | - { name: Banambila Street,stop_code: Wjz5l2U, lat: -35.2592266, lng: 149.0857332} |
- { name: Bindel Street,stop_code: Wjz5e8Y, lat: -35.2547235, lng: 149.0761202} | - { name: Bindel Street,stop_code: Wjz5e8Y, lat: -35.2547235, lng: 149.0761202} |
- { name: Kambah pool Road,stop_code: WjrXMFM, lat: -35.3752866, lng: 149.0485475} | - { name: Kambah pool Road,stop_code: WjrXMFM, lat: -35.3752866, lng: 149.0485475} |
- { name: Carbeen Street,stop_code: WjrXJZ6, lat: -35.3445279, lng: 149.0392999} | - { name: Carbeen Street,stop_code: WjrXJZ6, lat: -35.3445279, lng: 149.0392999} |
- { name: Collings Street,stop_code: Wjz3jaF, lat: -35.3579826, lng: 149.0867102} | - { name: Collings Street,stop_code: Wjz3jaF, lat: -35.3579826, lng: 149.0867102} |
- { name: Paramatta Street,stop_code: Wjz3jei, lat: -35.3551755, lng: 149.0862349} | - { name: Paramatta Street,stop_code: Wjz3jei, lat: -35.3551755, lng: 149.0862349} |
- { name: Aikman Drive,stop_code: Wjz69uI, lat: -35.2341477, lng: 149.0784965} | - { name: Aikman Drive,stop_code: Wjz69uI, lat: -35.2341477, lng: 149.0784965} |
- { name: Amy Ackman Street,stop_code: Wjz7-oI, lat: -35.1668191, lng: 149.1443901} | - { name: Amy Ackman Street,stop_code: Wjz7-oI, lat: -35.1668191, lng: 149.1443901} |
- { name: Barracks Flat Drive,stop_code: WjzbUGB, lat: -35.3740947, lng: 149.2349556} | - { name: Barracks Flat Drive,stop_code: WjzbUGB, lat: -35.3740947, lng: 149.2349556} |
- { name: Ling Place,stop_code: Wjzj0yX, lat: -35.3742978, lng: 149.2450265} | - { name: Ling Place,stop_code: Wjzj0yX, lat: -35.3742978, lng: 149.2450265} |
- { name: Knowles Place,stop_code: Wjz5FOn, lat: -35.2806054, lng: 149.1260452} | - { name: Knowles Place,stop_code: Wjz5FOn, lat: -35.2806054, lng: 149.1260452} |
- { name: Gundaroo Drive,stop_code: Wjz7oYv, lat: -35.196789, lng: 149.1057064} | - { name: Gundaroo Drive,stop_code: Wjz7oYv, lat: -35.196789, lng: 149.1057064} |
- { name: Gundaroo Drive,stop_code: Wjz7xpa, lat: -35.1938349, lng: 149.1107761} | - { name: Gundaroo Drive,stop_code: Wjz7xpa, lat: -35.1938349, lng: 149.1107761} |
- { name: Barritt Street,stop_code: WjrW_1f, lat: -35.3801683, lng: 149.051853} | - { name: Barritt Street,stop_code: WjrW_1f, lat: -35.3801683, lng: 149.051853} |
- { name: Barritt Street,stop_code: WjrWTJq, lat: -35.3778081, lng: 149.0480034} | - { name: Barritt Street,stop_code: WjrWTJq, lat: -35.3778081, lng: 149.0480034} |
- { name: Constitution Avenue,stop_code: Wjz5MsD, lat: -35.2847121, lng: 149.1333531} | - { name: Constitution Avenue,stop_code: Wjz5MsD, lat: -35.2847121, lng: 149.1333531} |
- { name: Mort Street,stop_code: Wjz5Ok1, lat: -35.2742265, lng: 149.1312268} | - { name: Mort Street,stop_code: Wjz5Ok1, lat: -35.2742265, lng: 149.1312268} |
- { name: Northbourne Avenue,stop_code: Wjz5SDc, lat: -35.2499285, lng: 149.1341368} | - { name: Northbourne Avenue,stop_code: Wjz5SDc, lat: -35.2499285, lng: 149.1341368} |
- { name: Northbourne Avenue,stop_code: Wjz5Qgn, lat: -35.2655006, lng: 149.1316277} | - { name: Northbourne Avenue,stop_code: Wjz5Qgn, lat: -35.2655006, lng: 149.1316277} |
- { name: Northbourne Avenue,stop_code: Wjz5Sqk, lat: -35.2533948, lng: 149.1329835} | - { name: Northbourne Avenue,stop_code: Wjz5Sqk, lat: -35.2533948, lng: 149.1329835} |
- { name: Coranderrk Street,stop_code: Wjz5MI3, lat: -35.2850249, lng: 149.1353935} | - { name: Coranderrk Street,stop_code: Wjz5MI3, lat: -35.2850249, lng: 149.1353935} |
- { name: Launceston Street,stop_code: Wjz3eje, lat: -35.3403963, lng: 149.0765097} | - { name: Launceston Street,stop_code: Wjz3eje, lat: -35.3403963, lng: 149.0765097} |
- { name: Streeton Drive,stop_code: WjrXQ2W, lat: -35.3523853, lng: 149.0417814} | - { name: Streeton Drive,stop_code: WjrXQ2W, lat: -35.3523853, lng: 149.0417814} |
- { name: Bangalay Crescent,stop_code: WjrXQeH, lat: -35.3495777, lng: 149.0428125} | - { name: Bangalay Crescent,stop_code: WjrXQeH, lat: -35.3495777, lng: 149.0428125} |
- { name: Sidaway Street,stop_code: WjrXHZU, lat: -35.3560382, lng: 149.0404158} | - { name: Sidaway Street,stop_code: WjrXHZU, lat: -35.3560382, lng: 149.0404158} |
- { name: Mirrabei Drive,stop_code: Wjz7BST, lat: -35.167951, lng: 149.1157463} | - { name: Mirrabei Drive,stop_code: Wjz7BST, lat: -35.167951, lng: 149.1157463} |
- { name: Saunders Street,stop_code: Wjz7AJS, lat: -35.174204, lng: 149.1143555} | - { name: Saunders Street,stop_code: Wjz7AJS, lat: -35.174204, lng: 149.1143555} |
- { name: Amagula Avenue,stop_code: Wjz7zzB, lat: -35.1811799, lng: 149.1126486} | - { name: Amagula Avenue,stop_code: Wjz7zzB, lat: -35.1811799, lng: 149.1126486} |
- { name: Windradyne Street,stop_code: Wjz7CD7, lat: -35.1617492, lng: 149.1119532} | - { name: Windradyne Street,stop_code: Wjz7CD7, lat: -35.1617492, lng: 149.1119532} |
- { name: Mirrabei Drive,stop_code: Wjz7If2, lat: -35.1732221, lng: 149.1188441} | - { name: Mirrabei Drive,stop_code: Wjz7If2, lat: -35.1732221, lng: 149.1188441} |
- { name: Paul Coe Crescent,stop_code: Wjz7Iax, lat: -35.1766844, lng: 149.1196027} | - { name: Paul Coe Crescent,stop_code: Wjz7Iax, lat: -35.1766844, lng: 149.1196027} |
- { name: Mirrabei Drive,stop_code: Wjz7IFg, lat: -35.1774595, lng: 149.1246602} | - { name: Mirrabei Drive,stop_code: Wjz7IFg, lat: -35.1774595, lng: 149.1246602} |
- { name: Shoalhaven Avenue,stop_code: Wjz7J-7, lat: -35.167951, lng: 149.1270626} | - { name: Shoalhaven Avenue,stop_code: Wjz7J-7, lat: -35.167951, lng: 149.1270626} |
- { name: Proserpine Circuit,stop_code: Wjz7RdE, lat: -35.169243, lng: 149.1307293} | - { name: Proserpine Circuit,stop_code: Wjz7RdE, lat: -35.169243, lng: 149.1307293} |
- { name: Inglewood Street,stop_code: Wjz7Y0J, lat: -35.177732, lng: 149.1403005} | - { name: Inglewood Street,stop_code: Wjz7Y0J, lat: -35.177732, lng: 149.1403005} |
- { name: Obrien Place,stop_code: Wjz7GSc, lat: -35.1847451, lng: 149.1258614} | - { name: Obrien Place,stop_code: Wjz7GSc, lat: -35.1847451, lng: 149.1258614} |
- { name: Anthony Rolfe Avenue,stop_code: Wjz7Ppw, lat: -35.1829884, lng: 149.1332581} | - { name: Anthony Rolfe Avenue,stop_code: Wjz7Ppw, lat: -35.1829884, lng: 149.1332581} |
- { name: Swain Street,stop_code: Wjz7X2n, lat: -35.1817108, lng: 149.1398579} | - { name: Swain Street,stop_code: Wjz7X2n, lat: -35.1817108, lng: 149.1398579} |
- { name: Petersilka Street,stop_code: Wjz7XxD, lat: -35.1823825, lng: 149.1457373} | - { name: Petersilka Street,stop_code: Wjz7XxD, lat: -35.1823825, lng: 149.1457373} |
- { name: Thistle Lane,stop_code: Wjzf2rm, lat: -35.1865677, lng: 149.1549041} | - { name: Thistle Lane,stop_code: Wjzf2rm, lat: -35.1865677, lng: 149.1549041} |
- { name: Horse Park Drive,stop_code: Wjzf0ZL, lat: -35.1961257, lng: 149.1609099} | - { name: Horse Park Drive,stop_code: Wjzf0ZL, lat: -35.1961257, lng: 149.1609099} |
- { name: Morris West Street,stop_code: Wjz6_vY, lat: -35.2004651, lng: 149.1448522} | - { name: Morris West Street,stop_code: Wjz6_vY, lat: -35.2004651, lng: 149.1448522} |
- { name: The Valley Avenue,stop_code: Wjz7Oal, lat: -35.1873286, lng: 149.1301603} | - { name: The Valley Avenue,stop_code: Wjz7Oal, lat: -35.1873286, lng: 149.1301603} |
- { name: Gungahlin Drive,stop_code: Wjz7Fmf, lat: -35.1899217, lng: 149.1203537} | - { name: Gungahlin Drive,stop_code: Wjz7Fmf, lat: -35.1899217, lng: 149.1203537} |
- { name: Freeling Crescent,stop_code: Wjz7xO6, lat: -35.1928051, lng: 149.1147348} | - { name: Freeling Crescent,stop_code: Wjz7xO6, lat: -35.1928051, lng: 149.1147348} |
- { name: Kosciuszko Avenue,stop_code: Wjz7E3Z, lat: -35.1976337, lng: 149.1187656} | - { name: Kosciuszko Avenue,stop_code: Wjz7E3Z, lat: -35.1976337, lng: 149.1187656} |
- { name: Kosciuszko Avenue,stop_code: Wjz7EJ7, lat: -35.1960839, lng: 149.1244553} | - { name: Kosciuszko Avenue,stop_code: Wjz7EJ7, lat: -35.1960839, lng: 149.1244553} |
- { name: Hoskins Street,stop_code: Wjz6RQW, lat: -35.2136848, lng: 149.1379368} | - { name: Hoskins Street,stop_code: Wjz6RQW, lat: -35.2136848, lng: 149.1379368} |
- { name: Hoskins Street,stop_code: Wjz6QTd, lat: -35.2168483, lng: 149.1369095} | - { name: Hoskins Street,stop_code: Wjz6QTd, lat: -35.2168483, lng: 149.1369095} |
- { name: Sandford Street,stop_code: Wjz6Yaq, lat: -35.2205928, lng: 149.1414139} | - { name: Sandford Street,stop_code: Wjz6Yaq, lat: -35.2205928, lng: 149.1414139} |
- { name: Flemington Road,stop_code: Wjz6Wse, lat: -35.2298796, lng: 149.1438091} | - { name: Flemington Road,stop_code: Wjz6Wse, lat: -35.2298796, lng: 149.1438091} |
- { name: Federal Highway,stop_code: Wjze3Fa, lat: -35.2267416, lng: 149.1575876} | - { name: Federal Highway,stop_code: Wjze3Fa, lat: -35.2267416, lng: 149.1575876} |
- { name: Aspinall Street,stop_code: Wjzeaq_, lat: -35.2311306, lng: 149.1668636} | - { name: Aspinall Street,stop_code: Wjzeaq_, lat: -35.2311306, lng: 149.1668636} |
- { name: Antill Street,stop_code: Wjze0VY, lat: -35.2430274, lng: 149.1613003} | - { name: Antill Street,stop_code: Wjze0VY, lat: -35.2430274, lng: 149.1613003} |
- { name: Knox Street,stop_code: Wjze1hB, lat: -35.2374923, lng: 149.1539669} | - { name: Knox Street,stop_code: Wjze1hB, lat: -35.2374923, lng: 149.1539669} |
- { name: Molesworth Street,stop_code: Wjze17N, lat: -35.2336919, lng: 149.1515898} | - { name: Molesworth Street,stop_code: Wjze17N, lat: -35.2336919, lng: 149.1515898} |
- { name: Phillip Avenue,stop_code: Wjz6UQw, lat: -35.2413339, lng: 149.1484036} | - { name: Phillip Avenue,stop_code: Wjz6UQw, lat: -35.2413339, lng: 149.1484036} |
- { name: Melba Street,stop_code: Wjz5_mg, lat: -35.2454644, lng: 149.1425874} | - { name: Melba Street,stop_code: Wjz5_mg, lat: -35.2454644, lng: 149.1425874} |
- { name: Antill Street,stop_code: Wjz5_O4, lat: -35.24786, lng: 149.147645} | - { name: Antill Street,stop_code: Wjz5_O4, lat: -35.24786, lng: 149.147645} |
- { name: Antill Street,stop_code: Wjzd7LX, lat: -35.2445144, lng: 149.1586198} | - { name: Antill Street,stop_code: Wjzd7LX, lat: -35.2445144, lng: 149.1586198} |