|  |  | 
 |  |  | <!-- | 
 |  |  | URLs: | 
 |  |  |  | 
 |  |  | MODE=arrival,departure | 
 |  |  |  | 
 |  |  | http://www.ttss.krakow.pl | 
 |  |  |  | 
 |  |  | /internetservice/services/passageInfo/stopPassages/stop?stop=84&mode=MODE | 
 |  |  | /internetservice/services/passageInfo/stopPassages/stopPoint?stopPoint=stopPoint&mode=MODE | 
 |  |  |  | 
 |  |  | /internetservice/services/routeInfo/routeStops?routeId= | 
 |  |  |  | 
 |  |  | /internetservice/services/lookup/autocomplete/nearStops/json?lat=&lon= | 
 |  |  | /internetservice/services/lookup/autocomplete/json?query= | 
 |  |  | --> | 
 |  |  | <!DOCTYPE html> | 
 |  |  | <html lang="en"> | 
 |  |  |    <head> | 
 |  |  |       <title>TTSS Cracow</title> | 
 |  |  |       <title>TTSS Kraków - Real-time tram departures</title> | 
 |  |  |       <meta charset="utf-8"> | 
 |  |  |       <meta http-equiv="X-UA-Compatible" content="IE=edge"> | 
 |  |  |       <meta name="viewport" content="width=device-width, initial-scale=1"> | 
 |  |  |       <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> | 
 |  |  |       <style type="text/css"> | 
 |  |  |          tr.active { | 
 |  |  |             color: gray; | 
 |  |  |          } | 
 |  |  |          .form-round-left { | 
 |  |  |             border-top-left-radius: 4px !important; | 
 |  |  |             border-bottom-left-radius: 4px !important; | 
 |  |  |             border-right: 0; | 
 |  |  |          } | 
 |  |  |          .navbar-text { | 
 |  |  |             margin-right: 15px; | 
 |  |  |             margin-left: 15px; | 
 |  |  |          } | 
 |  |  |          .input-group-btn:first-child { | 
 |  |  |             width: 50%; | 
 |  |  |          } | 
 |  |  |       </style> | 
 |  |  |       <link rel="stylesheet" type="text/css" href="index.css"> | 
 |  |  |    </head> | 
 |  |  |    <body> | 
 |  |  |       <nav class="navbar navbar-default"> | 
 |  |  |          <div class="container-fluid"> | 
 |  |  |             <div class="navbar-header"> | 
 |  |  |                <a class="navbar-brand" href="#">TTSS KRK</a> | 
 |  |  |                <a class="navbar-brand" style="display:inline-block" href="#" data-translate="page_name">TTSS Kraków</a> | 
 |  |  |             </div> | 
 |  |  | 				 | 
 |  |  |             <form class="navbar-form navbar-left"> | 
 |  |  |                <select class="form-control" id="lang-select"> | 
 |  |  |                   <option value="en">EN</option> | 
 |  |  |                   <option value="pl">PL</option> | 
 |  |  |                </select> | 
 |  |  |             </form> | 
 |  |  | 				 | 
 |  |  |             <form class="navbar-form navbar-left"> | 
 |  |  |                <div class="input-group"> | 
 |  |  |                   <span class="input-group-btn"> | 
 |  |  |                      <input type="text" class="form-control form-round-left" id="stop-name" placeholder="Stop name" /> | 
 |  |  |                      <input type="text" class="form-control form-round-left" id="stop-name" placeholder="Stop name" autofocus="autofocus" /> | 
 |  |  |                   </span> | 
 |  |  |                   <select class="form-control" id="stop-name-autocomplete"> | 
 |  |  |                   </select> | 
 |  |  |                   <span class="input-group-btn"> | 
 |  |  |                      <button type="submit" class="btn btn-default">Go</button> | 
 |  |  |                      <button type="submit" class="btn btn-default" data-translate="go_button">Go</button> | 
 |  |  |                   </span> | 
 |  |  |                </div> | 
 |  |  |             </form> | 
 |  |  |              | 
 |  |  |             <button type="button" class="btn btn-default navbar-btn pull-right" id="refresh" disabled="disabled"> | 
 |  |  |                <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> | 
 |  |  |                Refresh | 
 |  |  |             </button> | 
 |  |  | 				 | 
 |  |  |             <button type="button" class="btn btn-default navbar-btn pull-right" id="refresh" disabled="disabled" data-translate="refresh_button">⟳ Refresh</button> | 
 |  |  |             <p class="navbar-text pull-right" id="refresh-text">Initializing...</p> | 
 |  |  |          </div> | 
 |  |  |       </nav> | 
 |  |  | 		 | 
 |  |  |       <div class="container-fluid"> | 
 |  |  |          <div id="alert" class="alert alert-danger alert-dismissible" style="display:none"> | 
 |  |  |             <a href="#" class="close" id="alert-close" aria-label="close">×</a> | 
 |  |  |             <strong>Error occured!</strong> <span id="alert-text"></span> | 
 |  |  |             <strong data-translate="error_title">Error occured!</strong> <span id="alert-text"></span> | 
 |  |  |          </div> | 
 |  |  |           | 
 |  |  |          <div class="row"> | 
 |  |  | 
 |  |  |                <table class="table table-striped table-condensed"> | 
 |  |  |                   <thead> | 
 |  |  |                      <tr> | 
 |  |  |                         <th>Line</th> | 
 |  |  |                         <th>Direction</th> | 
 |  |  |                         <th>Time</th> | 
 |  |  |                         <th>Delay</th> | 
 |  |  |                         <th data-translate="header_line">Line</th> | 
 |  |  |                         <th data-translate="header_direction">Direction</th> | 
 |  |  |                         <th data-translate="header_time">Time</th> | 
 |  |  |                         <th data-translate="header_delay">Delay</th> | 
 |  |  |                      </tr> | 
 |  |  |                   </thead> | 
 |  |  |                   <tbody id="times-table"> | 
 |  |  | 
 |  |  |                </table> | 
 |  |  |             </div> | 
 |  |  |             <div class="col-md-6"> | 
 |  |  |                <h3>Lines</h3> | 
 |  |  |                <!-- | 
 |  |  |                <h3 data-translate="header_lines">Lines</h3> | 
 |  |  |                 | 
 |  |  |                <table class="table table-condensed"> | 
 |  |  |                   <thead> | 
 |  |  |                      <tr> | 
 |  |  |                         <th>Line</th> | 
 |  |  |                         <th>Route</th> | 
 |  |  |                         <th>Carrier</th> | 
 |  |  |                         <th data-translate="header_line">Line</th> | 
 |  |  |                         <th data-translate="header_route">Route</th> | 
 |  |  |                         <th data-translate="header_carrier">Carrier</th> | 
 |  |  |                      </tr> | 
 |  |  |                   </thead> | 
 |  |  |                   <tbody id="times-lines"> | 
 |  |  | 							 | 
 |  |  |                   </tbody> | 
 |  |  |                </table> | 
 |  |  |                --> | 
 |  |  |                 | 
 |  |  |                <!-- | 
 |  |  |                <p data-translate="help_click_for_schedule">Click on an entry in the departures timetable to see the tram's schedule.</p> | 
 |  |  | 					 | 
 |  |  |                <h3 id="route-line"></h3> | 
 |  |  |                 | 
 |  |  |                <table class="table table-condensed"> | 
 |  |  |                   <thead> | 
 |  |  |                      <tr> | 
 |  |  |                         <th>Stop</th> | 
 |  |  |                         <th data-translate="header_time">Time</th> | 
 |  |  |                         <th data-translate="header_stop">Stop</th> | 
 |  |  |                      </tr> | 
 |  |  |                   </thead> | 
 |  |  |                   <tbody id="route-table"> | 
 |  |  | 							 | 
 |  |  |                   </tbody> | 
 |  |  |                </table> | 
 |  |  |                --> | 
 |  |  | 					 | 
 |  |  |                <p class="small"> | 
 |  |  |                   <span data-translate="help_legend">Legend:</span> | 
 |  |  |                   <span class="label bg-active" data-translate="status_departed">Departed</span> | 
 |  |  |                   <span class="label bg-success" data-translate="status_stopped">At stop</span> | 
 |  |  |                   <span class="label bg-default" data-translate="status_default">En route</span> | 
 |  |  |                   <span class="label bg-warning" data-translate="status_delayed_4">Delayed 4′+</span> | 
 |  |  |                   <span class="label bg-danger" data-translate="status_delayed_10">Delayed 10′+</span> | 
 |  |  |                </p> | 
 |  |  | 					 | 
 |  |  |                <p class="small"> | 
 |  |  |                   <span class="bigger" title="Bombardier NGT6, Bombardier NGT8, PESA 2014N Krakowiak, Newag Nevelo 126N" data-translate="low_floor_sign">♿</span> - <span data-translate="low_floor_description">low-floor tram</span>. | 
 |  |  |                   <span class="bigger" title="Düwag/Man/MPK N8C-NF, Düwag/MPK GT8C, Bombardier-Rotax/MPK EU8N, Protram 405N-Kr" data-translate="partially_low_floor_sign">*♿</span> - <span data-translate="partially_low_floor_description">partially low-floor tram</span>. | 
 |  |  |                   <span class="bigger" title="other tram types" data-translate="high_floor_sign">‐</span> - <span data-translate="high_floor_description">high-floor tram</span>. | 
 |  |  |                   <span data-translate="help_hover_for_more">Hover the icon for more details.</span> | 
 |  |  |                </p> | 
 |  |  | 					 | 
 |  |  |                <p class="small" data-translate="help_text">Relative times (eg. 3 min) are real-time arrivals based on tram location data. Absolute times (eg. 8:01) are scheduled departures, shown when the tram cannot be located. "?" means unknown delay.</p> | 
 |  |  | 					 | 
 |  |  |                <p class="small">© 2016-2017 Jacek Kowalski - <a href="https://github.com/jacekkow/mpk-ttss" data-translate="help_source">Source</a> - <a href="https://raw.githubusercontent.com/jacekkow/mpk-ttss/master/LICENSE" data-translate="help_license">License</a></p> | 
 |  |  |             </div> | 
 |  |  |          </div> | 
 |  |  |       </div> | 
 |  |  |       <script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha384-3ceskX3iaEnIogmQchP8opvBy3Mi7Ce34nWjpBIwVTHfGYWQS9jwHDVRnpKKHJg7"  crossorigin="anonymous"></script> | 
 |  |  |       <script type="text/javascript"> | 
 |  |  |          //var ttss_base = 'http://www.ttss.krakow.pl/internetservice/services'; | 
 |  |  |          var ttss_base = '/proxy.php'; | 
 |  |  |          var ttss_refresh = 20000; // 20 seconds | 
 |  |  | 			 | 
 |  |  |          var stop_id; | 
 |  |  |          var stop_name = document.getElementById('stop-name'); | 
 |  |  |          var stop_name_form = stop_name.form; | 
 |  |  |          var stop_name_autocomplete = document.getElementById('stop-name-autocomplete'); | 
 |  |  |          var stop_name_autocomplete_xhr; | 
 |  |  | 			 | 
 |  |  |          var times_xhr; | 
 |  |  |          var times_timer; | 
 |  |  |          var times_stop_name = document.getElementById('times-stop-name'); | 
 |  |  |          var times_alerts = document.getElementById('times-alerts'); | 
 |  |  |          var times_table = document.getElementById('times-table'); | 
 |  |  |          var times_lines = document.getElementById('times-lines'); | 
 |  |  | 			 | 
 |  |  |          /* | 
 |  |  |          var route_xhr; | 
 |  |  |          var route_line = document.getElementById('route-line'); | 
 |  |  |          var route_table = document.getElementById('route-table'); | 
 |  |  |          */ | 
 |  |  | 			 | 
 |  |  |          var refresh_button = document.getElementById('refresh'); | 
 |  |  |          var refresh_text = document.getElementById('refresh-text'); | 
 |  |  |          var refresh_time; | 
 |  |  |          var refresh_timer; | 
 |  |  | 			 | 
 |  |  |          var alert = document.getElementById('alert'); | 
 |  |  |          var alert_text = document.getElementById('alert-text'); | 
 |  |  |          var alert_close = document.getElementById('alert-close'); | 
 |  |  | 			 | 
 |  |  |          function parseStatus(status) { | 
 |  |  |             switch(status.status) { | 
 |  |  |                case 'STOPPING': | 
 |  |  |                   return '<<<'; | 
 |  |  |                case 'PREDICTED': | 
 |  |  |                   if(status.actualRelativeTime <= 0) | 
 |  |  |                      return '<<<'; | 
 |  |  |                   if(status.actualRelativeTime >= 60) | 
 |  |  |                      return Math.floor(status.actualRelativeTime / 60) + ' min'; | 
 |  |  |                   return status.actualRelativeTime + ' s'; | 
 |  |  |                case 'DEPARTED': | 
 |  |  |                   return Math.floor(-status.actualRelativeTime / 60) + ' min ago'; | 
 |  |  |                default: | 
 |  |  |                   return status.mixedTime; | 
 |  |  |             } | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function parseTime(date, time) { | 
 |  |  |             var result = new Date(date.getFullYear(), date.getMonth(), date.getDay()); | 
 |  |  |             var time_split = time.split(':'); | 
 |  |  |             result.setHours(time_split[0]); | 
 |  |  |             result.setMinutes(time_split[1]); | 
 |  |  | 				 | 
 |  |  |             if(result.getTime() - date.getTime() > 72000000) { | 
 |  |  |                result.setTime(result.getTime() - 86400000); | 
 |  |  |             } | 
 |  |  | 				 | 
 |  |  |             if(date.getTime() - result.getTime() > 72000000) { | 
 |  |  |                result.setTime(result.getTime() + 86400000); | 
 |  |  |             } | 
 |  |  | 				 | 
 |  |  |             return result; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function parseDelay(status) { | 
 |  |  |             if(!status.actualTime) return '?'; | 
 |  |  |             if(!status.plannedTime) return '?'; | 
 |  |  | 				 | 
 |  |  |             var now = new Date(); | 
 |  |  |             var actual = parseTime(now, status.actualTime); | 
 |  |  |             var planned = parseTime(now, status.plannedTime); | 
 |  |  | 				 | 
 |  |  |             return ((actual.getTime() - planned.getTime()) / 1000 / 60) + ' min'; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function deleteChildren(element) { | 
 |  |  |             while(element.lastChild) element.removeChild(element.lastChild); | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function addElementWithText(parent, element, text) { | 
 |  |  |             var elem = document.createElement(element); | 
 |  |  |             elem.appendChild(document.createTextNode(text)); | 
 |  |  |             parent.appendChild(elem); | 
 |  |  |             return elem; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function addCellWithText(parent, text) { | 
 |  |  |             addElementWithText(parent, 'td', text); | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function addParaWithText(parent, text) { | 
 |  |  |             addElementWithText(parent, 'p', text); | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function setText(element, text) { | 
 |  |  |             deleteChildren(element); | 
 |  |  |             element.appendChild(document.createTextNode(text)); | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function fail(message, more) { | 
 |  |  |             if(refresh_timer) clearInterval(refresh_timer); | 
 |  |  |             if(times_timer) clearTimeout(times_timer); | 
 |  |  | 				 | 
 |  |  |             setText(alert_text, message); | 
 |  |  |             alert.style.display = 'block'; | 
 |  |  | 				 | 
 |  |  |             console.log(message + ' More details follow.'); | 
 |  |  |             if(more) console.log(more); | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function fail_ajax(data) { | 
 |  |  |             // abort() is not a failure | 
 |  |  |             if(data.readyState == 0 && data.statusText == 'abort') return; | 
 |  |  | 				 | 
 |  |  |             if(data.status == 0) { | 
 |  |  |                fail('Request failed - please check your network connectivity.', data); | 
 |  |  |             } else if (data.statusText) { | 
 |  |  |                fail('Internet request failed with error: ' + data.statusText + '.', data); | 
 |  |  |             } else { | 
 |  |  |                fail('Internet request failed.', data); | 
 |  |  |             } | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function loadTimes(stopId = null, clearRoute = false) { | 
 |  |  |             if(!stopId) stopId = stop_id; | 
 |  |  |             if(!stopId) return; | 
 |  |  | 				 | 
 |  |  |             if(times_timer) clearTimeout(times_timer); | 
 |  |  |             if(times_xhr) times_xhr.abort(); | 
 |  |  | 				 | 
 |  |  |             refresh_button.removeAttribute('disabled'); | 
 |  |  | 				 | 
 |  |  |             times_xhr = $.get( | 
 |  |  |                ttss_base + '/passageInfo/stopPassages/stop'  | 
 |  |  |                   + '?stop=' + encodeURIComponent(stopId) | 
 |  |  |                   + '&mode=departure' | 
 |  |  |             ).done(function(data) { | 
 |  |  |                setText(times_stop_name, data.stopName); | 
 |  |  |                deleteChildren(times_alerts); | 
 |  |  |                deleteChildren(times_table); | 
 |  |  |                deleteChildren(times_lines); | 
 |  |  |                /* | 
 |  |  |                if(clearRoute) { | 
 |  |  |                   deleteChildren(route_line); | 
 |  |  |                   deleteChildren(route_table); | 
 |  |  |                } | 
 |  |  |                */ | 
 |  |  | 					 | 
 |  |  |                for(var i = 0, il = data.generalAlerts.length; i < il; i++) { | 
 |  |  |                   addParaWithText(times_alerts, data.generalAlerts[i]); | 
 |  |  |                } | 
 |  |  | 					 | 
 |  |  |                for(var i = 0, il = data.old.length; i < il; i++) { | 
 |  |  |                   var tr = document.createElement('tr'); | 
 |  |  |                   addCellWithText(tr, data.old[i].patternText); | 
 |  |  |                   addCellWithText(tr, data.old[i].direction); | 
 |  |  |                   var status = parseStatus(data.old[i]); | 
 |  |  |                   addCellWithText(tr, status); | 
 |  |  |                   addCellWithText(tr, ''); | 
 |  |  | 						 | 
 |  |  |                   tr.className = 'active'; | 
 |  |  |                   times_table.appendChild(tr); | 
 |  |  |                } | 
 |  |  | 					 | 
 |  |  |                for(var i = 0, il = data.actual.length; i < il; i++) { | 
 |  |  |                   var tr = document.createElement('tr'); | 
 |  |  |                   addCellWithText(tr, data.actual[i].patternText); | 
 |  |  |                   addCellWithText(tr, data.actual[i].direction); | 
 |  |  |                   var status = parseStatus(data.actual[i]); | 
 |  |  |                   addCellWithText(tr, status); | 
 |  |  |                   var delay = parseDelay(data.actual[i]); | 
 |  |  |                   addCellWithText(tr, delay); | 
 |  |  | 						 | 
 |  |  |                   if(status == '<<<') tr.className = 'success'; | 
 |  |  |                   else if(parseInt(delay) > 9) tr.className = 'danger'; | 
 |  |  |                   else if(parseInt(delay) > 3) tr.className = 'warning'; | 
 |  |  |                   times_table.appendChild(tr); | 
 |  |  |                } | 
 |  |  | 					 | 
 |  |  |                for(var i = 0, il = data.routes.length; i < il; i++) { | 
 |  |  |                   var tr = document.createElement('tr'); | 
 |  |  |                   addCellWithText(tr, data.routes[i].name); | 
 |  |  |                   addCellWithText(tr, data.routes[i].directions.join(' - ')); | 
 |  |  |                   addCellWithText(tr, data.routes[i].authority); | 
 |  |  | 						 | 
 |  |  |                   /* | 
 |  |  |                   tr.addEventListener('click', function(routeId, routeTr){ return function(e) { | 
 |  |  |                      var trs = tr.parentNode; | 
 |  |  |                      for(var i = 0; i < trs.childNodes.length; i++) { | 
 |  |  |                         trs.childNodes[i].removeAttribute('class'); | 
 |  |  |                      } | 
 |  |  |                      routeTr.className = 'warning'; | 
 |  |  | 							 | 
 |  |  |                      if(route_xhr) route_xhr.abort(); | 
 |  |  |                      route_xhr = $.get( | 
 |  |  |                         ttss_base + '/routeInfo/routeStops' | 
 |  |  |                            + '?routeId=' + encodeURIComponent(routeId) | 
 |  |  |                      ).done(function(data) { | 
 |  |  |                         setText(route_line, data.route.name + ': ' | 
 |  |  |                            + data.route.directions.join(' - ')); | 
 |  |  |                         deleteChildren(route_table); | 
 |  |  | 								 | 
 |  |  |                         routeTr.className = 'success'; | 
 |  |  | 								 | 
 |  |  |                         for(var i = 0, il = data.stops.length; i < il; i++) { | 
 |  |  |                            var tr = document.createElement('tr'); | 
 |  |  |                            addCellWithText(tr, data.stops[i].name); | 
 |  |  |                            route_table.appendChild(tr); | 
 |  |  |                         } | 
 |  |  |                      }).fail(fail_ajax); | 
 |  |  |                   }}(data.routes[i].id, tr)); | 
 |  |  |                   */ | 
 |  |  | 						 | 
 |  |  |                   times_lines.appendChild(tr); | 
 |  |  | 						 | 
 |  |  |                   for(var j = 0, jl = data.routes[i].alerts.length; j < jl; j++) { | 
 |  |  |                      addParaWithText( | 
 |  |  |                         times_alerts, | 
 |  |  |                         'Line ' +  data.routes[i].name + ': ' | 
 |  |  |                            + data.routes[i].alerts[j] | 
 |  |  |                      ); | 
 |  |  |                   } | 
 |  |  |                } | 
 |  |  | 					 | 
 |  |  |                startTimer(new Date()); | 
 |  |  | 					 | 
 |  |  |                times_timer = setTimeout(function(){ loadTimes(); }, ttss_refresh); | 
 |  |  |             }).fail(fail_ajax); | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function declinate(num, singular, plural) { | 
 |  |  |             if(num == 1) return num + ' ' + singular; | 
 |  |  |             return num + ' ' + plural; | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function startTimer(date) { | 
 |  |  |             if(date) { | 
 |  |  |                setText(refresh_text, 'Last refreshed: just now') | 
 |  |  |                refresh_time = date; | 
 |  |  |             } | 
 |  |  |             if(!refresh_time) return; | 
 |  |  |             if(refresh_timer) clearInterval(refresh_timer); | 
 |  |  | 				 | 
 |  |  |             var now = new Date(); | 
 |  |  |             var ms = now.getTime() - refresh_time.getTime(); | 
 |  |  | 				 | 
 |  |  |             var interval = 1000; | 
 |  |  |             if(ms >= 120000) interval = 60000; | 
 |  |  | 				 | 
 |  |  |             refresh_timer = setInterval(function() { | 
 |  |  |                var now = new Date(); | 
 |  |  |                var ms = now.getTime() - refresh_time.getTime(); | 
 |  |  | 					 | 
 |  |  |                if(ms >= 120000) { | 
 |  |  |                   setText(refresh_text, 'Last refreshed: ' | 
 |  |  |                      + declinate(Math.floor(ms / 60000), 'minute ago', 'minutes ago')); | 
 |  |  |                   startTimer(); | 
 |  |  |                } else { | 
 |  |  |                   setText(refresh_text, 'Last refreshed: ' | 
 |  |  |                      + declinate(Math.floor(ms / 1000), 'second ago', 'seconds ago')); | 
 |  |  |                } | 
 |  |  |             }, interval); | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          function init() { | 
 |  |  |             if(!window.jQuery) { | 
 |  |  |                fail('Required JavaScript jQuery library failed to load. You may try refreshing the page.'); | 
 |  |  |                return; | 
 |  |  |             } | 
 |  |  | 				 | 
 |  |  |             $.ajaxSetup({ | 
 |  |  |                dataType: 'json', | 
 |  |  |                timeout: 3000, | 
 |  |  |             }); | 
 |  |  | 				 | 
 |  |  |             stop_name.addEventListener('input', function(e) { | 
 |  |  |                if(!stop_name.value) return; | 
 |  |  |                if(stop_name_autocomplete_xhr) stop_name_autocomplete_xhr.abort(); | 
 |  |  | 					 | 
 |  |  |                stop_name_autocomplete_xhr = $.get( | 
 |  |  |                   ttss_base + '/lookup/autocomplete/json' | 
 |  |  |                      + '?query=' + encodeURIComponent(stop_name.value) | 
 |  |  |                ).done(function(data) { | 
 |  |  |                   deleteChildren(stop_name_autocomplete); | 
 |  |  |                   for(var i = 1, il = data.length; i < il; i++) { | 
 |  |  |                      var opt = document.createElement('option'); | 
 |  |  |                      opt.value = data[i].id; | 
 |  |  |                      opt.appendChild(document.createTextNode(data[i].name)); | 
 |  |  |                      stop_name_autocomplete.appendChild(opt); | 
 |  |  |                   } | 
 |  |  | 						 | 
 |  |  |                   if(!stop_id) setText(refresh_text, 'Select the stop and click "Go"'); | 
 |  |  |                }).fail(fail_ajax); | 
 |  |  |             }); | 
 |  |  | 				 | 
 |  |  |             setText(refresh_text, 'Enter the stop name to begin'); | 
 |  |  | 				 | 
 |  |  |             stop_name_form.addEventListener('submit', function(e) { | 
 |  |  |                e.preventDefault(); | 
 |  |  |                if(!stop_name_autocomplete.value) return; | 
 |  |  |                stop_id = stop_name_autocomplete.value; | 
 |  |  |                loadTimes(stop_id, true); | 
 |  |  |             }); | 
 |  |  | 				 | 
 |  |  |             refresh_button.addEventListener('click', function(e) { | 
 |  |  |                loadTimes(stop_id); | 
 |  |  |             }); | 
 |  |  | 				 | 
 |  |  |             alert_close.addEventListener('click', function(e) { | 
 |  |  |                alert.style.display = 'none'; | 
 |  |  |             }); | 
 |  |  |          } | 
 |  |  | 			 | 
 |  |  |          init(); | 
 |  |  |       </script> | 
 |  |  |       <script tyle="text/javascript" src="lang_en.js" id="lang_script"></script> | 
 |  |  |       <script tyle="text/javascript" src="common.js"></script> | 
 |  |  |       <script type="text/javascript" src="index.js"></script> | 
 |  |  |    </body> | 
 |  |  | </html> |