|  |  | 
 |  |  | }; | 
 |  |  | var ttss_types = ['t', 'b']; | 
 |  |  |  | 
 |  |  | // Special directions | 
 |  |  | var special_directions = { | 
 |  |  |     'Zajezdnia Nowa Huta' : 'ZH', | 
 |  |  |     'Zajezdnia Podgórze' : 'ZP', | 
 |  |  | 
 |  |  |     'Przejazd techniczny' : 'PT', | 
 |  |  | }; | 
 |  |  |  | 
 |  |  |  | 
 |  |  | /******** | 
 |  |  |  * AJAX * | 
 |  |  |  ********/ | 
 |  |  |  | 
 |  |  | function Deferred(promise, request) { | 
 |  |  |     return { | 
 |  |  |         promise: promise, | 
 |  |  |         request: request, | 
 |  |  |         abort: function() { | 
 |  |  |             request.abort.bind(request) | 
 |  |  |             return Deferred(promise, request); | 
 |  |  |         }, | 
 |  |  |         done: function(func) { | 
 |  |  |             return Deferred(promise.then(func), request); | 
 |  |  |         }, | 
 |  |  |         fail: function(func) { | 
 |  |  |             return Deferred(promise.catch(func), request); | 
 |  |  |         }, | 
 |  |  |         always: function(func) { | 
 |  |  |             return Deferred(promise.finally(func), request); | 
 |  |  |         }, | 
 |  |  |     }; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | Deferred.all = function(iterable) { | 
 |  |  |     return Deferred( | 
 |  |  |         Promise.all( | 
 |  |  |             iterable.map(x => x.promise) | 
 |  |  |         ) | 
 |  |  |     ); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | var $ = { | 
 |  |  |     timeout: 10000, | 
 |  |  |     dataType: 'json', | 
 |  |  |     get: function(url) { | 
 |  |  |         var self = this; | 
 |  |  |         var request = new XMLHttpRequest(); | 
 |  |  |         var promise = new Promise(function(resolve, reject) { | 
 |  |  |             request.timeout = self.timeout; | 
 |  |  |             request.onreadystatechange = function() { | 
 |  |  |                 if(this.readyState == 4) { | 
 |  |  |                     if(this.status == 200) { | 
 |  |  |                         if(self.dataType == 'json') { | 
 |  |  |                             resolve(JSON.parse(this.responseText)); | 
 |  |  |                         } else { | 
 |  |  |                             resolve(this.responseText); | 
 |  |  |                         } | 
 |  |  |                     } else { | 
 |  |  |                         reject(request); | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |             }; | 
 |  |  |             request.open("GET", url, true); | 
 |  |  |             request.send(); | 
 |  |  |         }); | 
 |  |  |         return Deferred(promise, request); | 
 |  |  |     }, | 
 |  |  | }; | 
 |  |  |  | 
 |  |  |  | 
 |  |  | /*********** | 
 |  |  |  * VERSION * | 
 |  |  |  ***********/ | 
 |  |  |  | 
 |  |  | var script_version; | 
 |  |  | var script_version_xhr; | 
 |  |  |  | 
 |  |  | var vehicles_info = {}; | 
 |  |  |  | 
 |  |  | // Check for website updates | 
 |  |  | function checkVersion() { | 
 |  |  |     if(script_version_xhr) script_version_xhr.abort(); | 
 |  |  |      | 
 |  |  | 
 |  |  |     setInterval(checkVersion, 3600000); | 
 |  |  | } | 
 |  |  |  | 
 |  |  | /* Parsing of received JSON parts */ | 
 |  |  |  | 
 |  |  | /*********** | 
 |  |  |  * PARSING * | 
 |  |  |  ***********/ | 
 |  |  |  | 
 |  |  | function parseStatus(status) { | 
 |  |  |     switch(status.status) { | 
 |  |  |         case 'STOPPING': | 
 |  |  | 
 |  |  |     return lang.time_minutes_prefix + ((actual.getTime() - planned.getTime()) / 1000 / 60) + lang.time_minutes_suffix; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | // Webservice-related functions | 
 |  |  | function parseVehicle(vehicleId) { | 
 |  |  |     if(!vehicleId) return false; | 
 |  |  |     if(!vehicles_info || !vehicles_info[vehicleId]) { | 
 |  |  | 
 |  |  |     return span; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | // Element mangling | 
 |  |  |  | 
 |  |  | /******* | 
 |  |  |  * DOM * | 
 |  |  |  *******/ | 
 |  |  |  | 
 |  |  | function deleteChildren(element) { | 
 |  |  |     while(element.lastChild) element.removeChild(element.lastChild); | 
 |  |  | } | 
 
 |  |  | 
 |  |  |                 </div> | 
 |  |  |             </div> | 
 |  |  |         </div> | 
 |  |  |         <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT" crossorigin="anonymous"></script> | 
 |  |  |         <script type="text/javascript" src="lang_pl.js?v4" id="lang_script"></script> | 
 |  |  |         <script type="text/javascript" src="common.js?v7"></script> | 
 |  |  |         <script type="text/javascript" src="index.js?v3"></script> | 
 |  |  |         <script src="https://polyfill.io/v3/polyfill.min.js?features=Promise,XMLHttpRequest"></script> | 
 |  |  |         <script type="text/javascript" src="lang_pl.js?v7" id="lang_script"></script> | 
 |  |  |         <script type="text/javascript" src="common.js?v8"></script> | 
 |  |  |         <script type="text/javascript" src="index.js?v6"></script> | 
 |  |  |     </body> | 
 |  |  | </html> | 
 
 |  |  | 
 |  |  |          | 
 |  |  |         times_timer = setTimeout(function(){ loadTimes(); loadRoute(); }, ttss_refresh); | 
 |  |  |     }).fail(fail_ajax).always(loading_end); | 
 |  |  |     return times_xhr; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | function loadRoute(tripId, vehicleInfo) { | 
 |  |  | 
 |  |  |             route_table.appendChild(tr); | 
 |  |  |         } | 
 |  |  |     }).fail(fail_ajax); | 
 |  |  |     return route_xhr; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | function startTimer(date) { | 
 |  |  | 
 |  |  |     var text_name; | 
 |  |  |     for(var i = 0; i < elements.length; i++) { | 
 |  |  |         text_name = elements[i].dataset.translate; | 
 |  |  |         if(lang[text_name] == undefined) { | 
 |  |  |         if(typeof lang[text_name] === 'undefined') { | 
 |  |  |             console.log('Missing translation: ' + text_name); | 
 |  |  |             continue; | 
 |  |  |         } | 
 |  |  | 
 |  |  |     } | 
 |  |  |     language = lang; | 
 |  |  |      | 
 |  |  |     var old_script = document.getElementById('lang_script'); | 
 |  |  |     var old_version = old_script.src.match(/\?v[0-9]+/)[0]; | 
 |  |  |     var script = document.createElement('script'); | 
 |  |  |     script.type = 'text/javascript'; | 
 |  |  |     script.src = 'lang_' + lang + '.js'; | 
 |  |  |     script.src = 'lang_' + lang + '.js' + (old_version ? old_version : ''); | 
 |  |  |     script.id = 'lang_script'; | 
 |  |  |     script.onload = translate; | 
 |  |  |      | 
 |  |  |     document.body.removeChild(document.getElementById('lang_script')); | 
 |  |  |     document.body.removeChild(old_script); | 
 |  |  |     document.body.appendChild(script); | 
 |  |  |      | 
 |  |  |     ignore_hashchange = true; | 
 |  |  | 
 |  |  |         for(var i = 0, il = data.length; i < il; i++) { | 
 |  |  |             var opt = document.createElement('option'); | 
 |  |  |             opt.value = data[i].id; | 
 |  |  |             setText(opt, data[i].id.substr(0,1) == 'b' ? lang.select_stop_bus.replace('$stop', data[i].name) : lang.select_stop_tram.replace('$stop', data[i].name)); | 
 |  |  |             setText(opt, lang.select_stop_type[data[i].id.substr(0,1)].replace('$stop', data[i].name)); | 
 |  |  |             stop_name_autocomplete.appendChild(opt); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |         if(!stop_id) setText(refresh_text, lang.select_stop_click_go); | 
 |  |  |     }).fail(fail_ajax); | 
 |  |  |     return stop_name_autocomplete_xhr; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | function init() { | 
 |  |  |     if(!window.jQuery) { | 
 |  |  |         fail(lang.jquery_not_loaded); | 
 |  |  |         return; | 
 |  |  |     } | 
 |  |  | 	 | 
 |  |  |     $.ajaxSetup({ | 
 |  |  |         dataType: 'json', | 
 |  |  |         timeout: 10000, | 
 |  |  |     }); | 
 |  |  | 	 | 
 |  |  |     lang_select.addEventListener('input', function(e) { | 
 |  |  |         change_language(lang_select.value); | 
 |  |  |     }); | 
 
 |  |  | 
 |  |  |     action_expand: 'Expand', | 
 |  |  |     action_collapse: 'Collapse', | 
 |  |  |      | 
 |  |  |     jquery_not_loaded: 'Required JavaScript jQuery library failed to load. You may try refreshing the page.', | 
 |  |  |     enter_stop_name_to_begin: 'Enter the stop name to begin.', | 
 |  |  |     select_stop_click_go: 'Select the stop and click "Go".', | 
 |  |  |     select_stop_tram: '$stop (tram)', | 
 |  |  |     select_stop_bus: '$stop (bus)', | 
 |  |  |     select_stop_type: { | 
 |  |  |         'b': '$stop (bus)', | 
 |  |  |         't': '$stop (tram)', | 
 |  |  |     }, | 
 |  |  |     stop_name_placeholder: 'Stop name', | 
 |  |  |     go_button: 'Go', | 
 |  |  |     refresh_button: '\u27f3 Refresh', | 
 |  |  | 
 |  |  |     time_minutes_ago_prefix: '', | 
 |  |  |     time_minutes_ago_suffix: ' min ago', | 
 |  |  |      | 
 |  |  |     type_vehicle: 'Vehicle', | 
 |  |  |     type_bus: 'Bus', | 
 |  |  |     type_tram: 'Tram', | 
 |  |  |     type_stop: 'Stop', | 
 |  |  |     type_stop_bus: 'Bus stop', | 
 |  |  |     type_stop_tram: 'Tram stop', | 
 |  |  |     type_stoppoint: 'Stop point', | 
 |  |  |     type_stoppoint_bus: 'Bus stop point', | 
 |  |  |     type_stoppoint_tram: 'Tram stop point', | 
 |  |  |     type_location: 'Your location', | 
 |  |  |     types: { | 
 |  |  |         v: 'Vehicle', | 
 |  |  |         b: 'Bus', | 
 |  |  |         t: 'Tram', | 
 |  |  |         s: 'Stop', | 
 |  |  |         sb: 'Bus stop', | 
 |  |  |         st: 'Tram stop', | 
 |  |  |         p: 'Stop point', | 
 |  |  |         pb: 'Bus stop point', | 
 |  |  |         pt: 'Tram stop point', | 
 |  |  |         l: 'Your location', | 
 |  |  |     }, | 
 |  |  |      | 
 |  |  |     select_feature: 'There is more than one feature here. Select the proper one:', | 
 |  |  |     departures_for_stop: 'Click for stop departures (and not only this stop point).', | 
 
 |  |  | 
 |  |  |     action_expand: 'Rozwiń', | 
 |  |  |     action_collapse: 'Zwiń', | 
 |  |  |      | 
 |  |  |     jquery_not_loaded: 'Wymagana biblioteka jQuery nie została poprawnie załadowana. Spróbuj odświeżyć stronę.', | 
 |  |  |     enter_stop_name_to_begin: 'Zacznij wpisywać nazwę przystanku.', | 
 |  |  |     select_stop_click_go: 'Wyierz przystanek i kliknij "Dalej".', | 
 |  |  |     select_stop_tram: '$stop (tramwaj)', | 
 |  |  |     select_stop_bus: '$stop (autobus)', | 
 |  |  |     select_stop_type: { | 
 |  |  |         'b': '$stop (autobus)', | 
 |  |  |         't': '$stop (tramwaj)', | 
 |  |  |     }, | 
 |  |  |     stop_name_placeholder: 'Nazwa przystanku', | 
 |  |  |     go_button: 'Dalej', | 
 |  |  |     refresh_button: '\u27f3 Odśwież', | 
 |  |  | 
 |  |  |     header_line: 'Linia', | 
 |  |  |     header_direction: 'Kierunek', | 
 |  |  |     header_vehicle: 'Pojazd', | 
 |  |  |     header_bus: 'Autobus', | 
 |  |  |     header_tram: 'Tramwaj', | 
 |  |  |     header_time: 'Odjazd', | 
 |  |  |     header_delay: 'Opóźn.', | 
 |  |  |     header_lines: 'Linie', | 
 |  |  | 
 |  |  |     time_minutes_ago_prefix: '', | 
 |  |  |     time_minutes_ago_suffix: ' min temu', | 
 |  |  |      | 
 |  |  |     type_vehicle: 'Pojazd', | 
 |  |  |     type_bus: 'Autobus', | 
 |  |  |     type_tram: 'Tramwaj', | 
 |  |  |     type_stop: 'Przystanek', | 
 |  |  |     type_stop_bus: 'Przystanek autobusowy', | 
 |  |  |     type_stop_tram: 'Przystanek tramwajowy', | 
 |  |  |     type_stoppoint: 'Peron', | 
 |  |  |     type_stoppoint_bus: 'Peron autobusowy', | 
 |  |  |     type_stoppoint_tram: 'Peron tramwajowy', | 
 |  |  |     type_location: 'Twoja lokalizacja', | 
 |  |  |     types: { | 
 |  |  |         'v': 'Pojazd', | 
 |  |  |         'b': 'Autobus', | 
 |  |  |         't': 'Tramwaj', | 
 |  |  |         's': 'Przystanek', | 
 |  |  |         'sb': 'Przystanek autobusowy', | 
 |  |  |         'st': 'Przystanek tramwajowy', | 
 |  |  |         'p': 'Peron', | 
 |  |  |         'pb': 'Peron autobusowy', | 
 |  |  |         'pt': 'Peron tramwajowy', | 
 |  |  |         'l': 'Twoja lokalizacja', | 
 |  |  |     }, | 
 |  |  |      | 
 |  |  |     select_feature: 'W tym miejscu znajduje się więcej niż jeden element. Wybierz właściwy z listy:', | 
 |  |  |     departures_for_stop: 'Kliknij, by zobaczyć odjazdy dla całego przystanku (a nie tylko peronu).', | 
 
 |  |  | 
 |  |  | <div id="fail" class="ol-unselectable ol-control"><span></span> <span class="close">×</p></div> | 
 |  |  | </div> | 
 |  |  | <div id="panel"></div> | 
 |  |  | <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT" crossorigin="anonymous"></script> | 
 |  |  | <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList"></script> | 
 |  |  | <script src="https://polyfill.io/v3/polyfill.min.js?features=Array.prototype.forEach,Array.prototype.includes,Array.prototype.map,Element.prototype.classList,Promise,String.prototype.startsWith,XMLHttpRequest,requestAnimationFrame"></script> | 
 |  |  | <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v5.3.0/build/ol.js" integrity="sha384-iQkGyyH4ioz3m+maM3s9MX1Oq67mACa4B9Z3ovUv3Sv37LJ96fx3WnZfLoiC3Wfl" crossorigin="anonymous"></script> | 
 |  |  | <script tyle="text/javascript" src="lang_pl.js?v6" id="lang_script"></script> | 
 |  |  | <script tyle="text/javascript" src="common.js?v7"></script> | 
 |  |  | <script tyle="text/javascript" src="map.js?v18"></script> | 
 |  |  | <script tyle="text/javascript" src="lang_pl.js?v7" id="lang_script"></script> | 
 |  |  | <script tyle="text/javascript" src="common.js?v8"></script> | 
 |  |  | <script tyle="text/javascript" src="map.js?v20"></script> | 
 |  |  | </body> | 
 |  |  | </html> | 
 
 |  |  | 
 |  |  |  | 
 |  |  | function fail_ajax_generic(data, fnc) { | 
 |  |  |     // abort() is not a failure | 
 |  |  |     if(data.readyState == 0 && data.statusText == 'abort') return; | 
 |  |  |     if(data.readyState == 0) return; | 
 |  |  |      | 
 |  |  |     if(data.status == 0) { | 
 |  |  |         fnc(lang.error_request_failed_connectivity, data); | 
 |  |  | 
 |  |  | function unstyleSelectedFeatures() { | 
 |  |  |     stop_selected_source.clear(); | 
 |  |  |     route_source.clear(); | 
 |  |  |     if(feature_clicked && ttss_types.indexOf(feature_clicked.getId().substr(0, 1)) >= 0) { | 
 |  |  |     if(feature_clicked && ttss_types.includes(feature_clicked.getId().substr(0, 1))) { | 
 |  |  |         styleVehicle(feature_clicked); | 
 |  |  |     } | 
 |  |  | } | 
 |  |  | 
 |  |  |         var stop = stops[i]; | 
 |  |  |          | 
 |  |  |         if(stop.category == 'other') continue; | 
 |  |  |         if(stops_ignored.indexOf(stop.shortName) >= 0) continue; | 
 |  |  |         if(stops_ignored.includes(stop.shortName)) continue; | 
 |  |  |          | 
 |  |  |         stop.geometry = getGeometry(stop); | 
 |  |  |         var stop_feature = new ol.Feature(stop); | 
 |  |  | 
 |  |  |         })); | 
 |  |  |         route_layer.setVisible(true); | 
 |  |  |     }); | 
 |  |  |     return path_xhr; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | function vehicleTable(feature, table) { | 
 |  |  | 
 |  |  |          | 
 |  |  |         feature_timer = setTimeout(function() { vehicleTable(feature, table); }, ttss_refresh); | 
 |  |  |     }).fail(fail_ajax_popup); | 
 |  |  |     return feature_xhr; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | function stopTable(stopType, stopId, table, ttss_type) { | 
 |  |  | 
 |  |  |          | 
 |  |  |         feature_timer = setTimeout(function() { stopTable(stopType, stopId, table, ttss_type); }, ttss_refresh); | 
 |  |  |     }).fail(fail_ajax_popup); | 
 |  |  |     return feature_xhr; | 
 |  |  | } | 
 |  |  |  | 
 |  |  | function featureClicked(feature) { | 
 |  |  | 
 |  |  |     var tabular_data = true; | 
 |  |  |      | 
 |  |  |     var type = feature.getId().substr(0, 1); | 
 |  |  |     var full_type = feature.getId().match(/^[a-z]+/)[0]; | 
 |  |  |     var typeName = lang.types[full_type]; | 
 |  |  |     if(typeof typeName === 'undefined') { | 
 |  |  |         typeName = ''; | 
 |  |  |     } | 
 |  |  | 	 | 
 |  |  |     // Location | 
 |  |  |     if(type == 'l') { | 
 |  |  |         tabular_data = false; | 
 |  |  |         name = typeName; | 
 |  |  |         typeName = ''; | 
 |  |  |         name = lang.type_location; | 
 |  |  |     } | 
 |  |  |     // Vehicle | 
 |  |  |     else if(ttss_types.indexOf(type) >= 0) { | 
 |  |  |         typeName = lang.type_bus; | 
 |  |  |         if(type == 't') { | 
 |  |  |             typeName = lang.type_tram; | 
 |  |  |         } | 
 |  |  | 		 | 
 |  |  |     else if(ttss_types.includes(type)) { | 
 |  |  |         var span = displayVehicle(feature.get('vehicle_type')); | 
 |  |  |          | 
 |  |  |         additional = document.createElement('p'); | 
 |  |  | 
 |  |  |         styleVehicle(feature, true); | 
 |  |  |     } | 
 |  |  |     // Stop or stop point | 
 |  |  |     else if(['s', 'p'].indexOf(type) >= 0) { | 
 |  |  |     else if(['s', 'p'].includes(type)) { | 
 |  |  |         var ttss_type = feature.getId().substr(1, 1); | 
 |  |  |         if(type == 's') { | 
 |  |  |             typeName = lang.type_stop_tram; | 
 |  |  |             var second_type = lang.departures_for_buses; | 
 |  |  |             var mapping = stops_mapping['sb']; | 
 |  |  |              | 
 |  |  |             if(ttss_type == 'b') { | 
 |  |  |                 typeName = lang.type_stop_bus; | 
 |  |  |                 second_type = lang.departures_for_trams; | 
 |  |  |                 mapping = stops_mapping['st']; | 
 |  |  |             } | 
 |  |  | 
 |  |  |                 ); | 
 |  |  |             } | 
 |  |  |         } else { | 
 |  |  |             typeName = lang.type_stoppoint_tram; | 
 |  |  | 			 | 
 |  |  |             if(ttss_type == 'b') { | 
 |  |  |                 typeName = lang.type_stoppoint_bus; | 
 |  |  |             } | 
 |  |  | 			 | 
 |  |  |             stopTable('stopPoint', feature.get('stopPoint'), tbody, ttss_type); | 
 |  |  |              | 
 |  |  |             additional = document.createElement('p'); | 
 |  |  | 
 |  |  |                 featureClicked(feature); | 
 |  |  |             }}(feature)); | 
 |  |  |              | 
 |  |  |             var type = feature.getId().substr(0, 1); | 
 |  |  |             var typeName = ''; | 
 |  |  |             if(type == 'l') { | 
 |  |  |             var full_type = feature.getId().match(/^[a-z]+/)[0]; | 
 |  |  |             var typeName = lang.types[full_type]; | 
 |  |  |             if(typeof typeName === 'undefined') { | 
 |  |  |                 typeName = ''; | 
 |  |  |                 name = lang.type_location; | 
 |  |  |             } else if(ttss_types.indexOf(type) >= 0) { | 
 |  |  |                 typeName = lang.type_bus; | 
 |  |  |                 if(type == 't') { | 
 |  |  |                     typeName = lang.type_tram; | 
 |  |  |                 } | 
 |  |  |                 if(feature.get('vehicle_type').num) { | 
 |  |  |                     typeName += ' ' + feature.get('vehicle_type').num; | 
 |  |  |                 } | 
 |  |  |             } else if(type == 's') { | 
 |  |  |                 typeName = lang.type_stop_tram; | 
 |  |  |                 if(feature.getId().startsWith('sb')) { | 
 |  |  |                     typeName = lang.type_stop_bus; | 
 |  |  |                 } | 
 |  |  |             } else if (type == 'p') { | 
 |  |  |                 typeName = lang.type_stoppoint_tram; | 
 |  |  |                 if(feature.getId().startsWith('pb')) { | 
 |  |  |                     typeName = lang.type_stoppoint_bus; | 
 |  |  |                 } | 
 |  |  |             } else { | 
 |  |  |                 continue; | 
 |  |  |             } | 
 |  |  |              | 
 |  |  |             addElementWithText(a, 'span', typeName).className = 'small'; | 
 |  |  | 
 |  |  | } | 
 |  |  |  | 
 |  |  | function init() { | 
 |  |  |     if(!window.jQuery) { | 
 |  |  |         fail(lang.jquery_not_loaded); | 
 |  |  |         return; | 
 |  |  |     } | 
 |  |  | 	 | 
 |  |  |     $.ajaxSetup({ | 
 |  |  |         dataType: 'json', | 
 |  |  |         timeout: 10000, | 
 |  |  |     }); | 
 |  |  | 	 | 
 |  |  |     panel = new Panel(document.getElementById('panel')); | 
 |  |  |      | 
 |  |  |     route_source = new ol.source.Vector({ | 
 |  |  | 
 |  |  |     stops_type.forEach(function(type) { | 
 |  |  |         future_requests.push(updateStops(type.substr(0,1), type.substr(1,1))); | 
 |  |  |     }); | 
 |  |  |     $.when(future_requests).done(hash); | 
 |  |  |     Deferred.all(future_requests).done(hash); | 
 |  |  |      | 
 |  |  |     window.addEventListener('hashchange', hash); | 
 |  |  |      |