2019-07-06 | Jacek Kowalski | |
2019-07-05 | Jacek Kowalski | |
2019-07-05 | Jacek Kowalski | |
2019-07-05 | Jacek Kowalski |
icons/loc.svg | ●●●●● patch | view | raw | blame | history | |
icons/pin.svg | ●●●●● patch | view | raw | blame | history | |
icons/zoom.svg | ●●●●● patch | view | raw | blame | history | |
index.html | ●●●●● patch | view | raw | blame | history | |
lang_en.js | ●●●●● patch | view | raw | blame | history | |
lang_pl.js | ●●●●● patch | view | raw | blame | history | |
map.css | ●●●●● patch | view | raw | blame | history | |
map.html | ●●●●● patch | view | raw | blame | history | |
map.js | ●●●●● patch | view | raw | blame | history |
icons/loc.svg
New file @@ -0,0 +1 @@ <svg xmlns="http://www.w3.org/2000/svg" width="80" height="80"><style>*{stroke:black;stroke-width:5;fill:none}</style><circle cx="40" cy="40" r="25"></circle><circle cx="40" cy="40" r="10" style="fill:black;"></circle><line x1="40" y1="15" x2="40" y2="0"></line><line x1="65" y1="40" x2="80" y2="40"></line><line x1="40" y1="65" x2="40" y2="80"></line><line x1="15" y1="40" x2="0" y2="40"></line></svg> icons/pin.svg
New file @@ -0,0 +1 @@ <svg xmlns="http://www.w3.org/2000/svg" width="64" height="64"><path d="M32,64L14.1855,29.0909A20,20 0 1 1 49.8145,29.0909ZM42,20A10,10 0 0 0 22,20A10,10 0 0 0 42,20"/></svg> icons/zoom.svg
File was renamed from zoom.svg @@ -1 +1 @@ <svg xmlns="http://www.w3.org/2000/svg" width="490" height="490"><path fill="none" stroke="#000" stroke-width="36" stroke-linecap="round" d="m280,278a153,153 0 1,0-2,2l170,170m-91-117 110,110-26,26-110-110"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="490" height="490"><path fill="none" stroke="#000" stroke-width="36" stroke-linecap="round" d="m280,278a153,153 0 1,0-2,2l170,170m-91-117 110,110-26,26-110-110"/></svg> index.html
@@ -135,7 +135,7 @@ </div> </div> <script src="https://polyfill.io/v3/polyfill.min.js?features=Promise,XMLHttpRequest"></script> <script type="text/javascript" src="lang_pl.js?v9" id="lang_script"></script> <script type="text/javascript" src="lang_pl.js?v10" id="lang_script"></script> <script type="text/javascript" src="common.js?v10"></script> <script type="text/javascript" src="index.js?v8"></script> </body> lang_en.js
@@ -9,6 +9,7 @@ action_expand: 'Expand', action_collapse: 'Collapse', enter_query: 'Enter stop name or vehicle number:', enter_stop_name_to_begin: 'Enter the stop name to begin.', select_stop_click_go: 'Select the stop and click "Go".', select_stop_type: { @@ -61,7 +62,8 @@ }, show_on_map: 'Show on map', select_feature: 'There is more than one feature here. Select the proper one:', select_feature: 'More than one feature was found. Select the proper one:', no_results: 'Nothing was found.', departures_for_stop: 'Click for stop departures (and not only this stop point).', departures_for_trams: 'Switch to tram departures.', departures_for_buses: 'Switch to bus departures.', lang_pl.js
@@ -9,6 +9,7 @@ action_expand: 'Rozwiń', action_collapse: 'Zwiń', enter_query: 'Wpisz nazwę przystanku lub numer pojazdu:', enter_stop_name_to_begin: 'Zacznij wpisywać nazwę przystanku.', select_stop_click_go: 'Wyierz przystanek i kliknij "Dalej".', select_stop_type: { @@ -61,7 +62,8 @@ }, show_on_map: 'Pokaż na mapie', select_feature: 'W tym miejscu znajduje się więcej niż jeden element. Wybierz właściwy z listy:', select_feature: 'Znaleziono więcej niż jeden element. Wybierz właściwy z listy:', no_results: 'Nie udało się znaleźć pasujących elementów.', departures_for_stop: 'Kliknij, by zobaczyć odjazdy dla całego przystanku (a nie tylko peronu).', departures_for_trams: 'Przełącz na odjazdy tramwajów.', departures_for_buses: 'Przełącz na odjazdy autobusów.', map.css
@@ -5,7 +5,7 @@ } #map { position: absolute; position: fixed; top: 0; left: 0; right: 0; @@ -28,7 +28,7 @@ transition: right .4s, width .4s; position: absolute; position: fixed; width: 350px; right: -365px; top: 0; @@ -135,25 +135,44 @@ float: right; } .pad-left-icon { .addon-icon { margin-left: 0.2rem; } .icon-zoom { .normal-icon, .addon-icon { font-size: 1rem; } .icon, .icon-loc, .icon-pin, .icon-zoom { display: inline-block; height: 1rem; width: 1rem; height: 1em; width: 1em; text-indent: 1rem; overflow: hidden; background-image: url(zoom.svg); background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OTAiIGhlaWdodD0iNDkwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iMzYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgZD0ibTI4MCwyNzhhMTUzLDE1MyAwIDEsMC0yLDJsMTcwLDE3MG0tOTEtMTE3IDExMCwxMTAtMjYsMjYtMTEwLTExMCIvPjwvc3ZnPgo=); background-size: contain; background-repeat: no-repeat; } .reverse { filter: invert(100%); } .icon-loc { background-image: url(icons/loc.svg); background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MCIgaGVpZ2h0PSI4MCI+PHN0eWxlPip7c3Ryb2tlOmJsYWNrO3N0cm9rZS13aWR0aDo1O2ZpbGw6bm9uZX08L3N0eWxlPjxjaXJjbGUgY3g9IjQwIiBjeT0iNDAiIHI9IjI1Ij48L2NpcmNsZT48Y2lyY2xlIGN4PSI0MCIgY3k9IjQwIiByPSIxMCIgc3R5bGU9ImZpbGw6YmxhY2s7Ij48L2NpcmNsZT48bGluZSB4MT0iNDAiIHkxPSIxNSIgeDI9IjQwIiB5Mj0iMCI+PC9saW5lPjxsaW5lIHgxPSI2NSIgeTE9IjQwIiB4Mj0iODAiIHkyPSI0MCI+PC9saW5lPjxsaW5lIHgxPSI0MCIgeTE9IjY1IiB4Mj0iNDAiIHkyPSI4MCI+PC9saW5lPjxsaW5lIHgxPSIxNSIgeTE9IjQwIiB4Mj0iMCIgeTI9IjQwIj48L2xpbmU+PC9zdmc+); } .icon-pin { background-image: url(icons/pin.svg); background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCI+PHBhdGggZD0iTTMyLDY0TDE0LjE4NTUsMjkuMDkwOUEyMCwyMCAwIDEgMSA0OS44MTQ1LDI5LjA5MDlaTTQyLDIwQTEwLDEwIDAgMCAwIDIyLDIwQTEwLDEwIDAgMCAwIDQyLDIwIi8+PC9zdmc+); } .icon-zoom { background-image: url(icons/zoom.svg); background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OTAiIGhlaWdodD0iNDkwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iMzYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgZD0ibTI4MCwyNzhhMTUzLDE1MyAwIDEsMC0yLDJsMTcwLDE3MG0tOTEtMTE3IDExMCwxMTAtMjYsMjYtMTEwLTExMCIvPjwvc3ZnPgo=); } #title { top: .5em; left: .5em; padding: 2px .5em; padding: 0 .5em; font-size: 1.14em; line-height: 1.4em; height: 1.375em; font-weight: bold; background-color: rgba(255,255,255,.6); } @@ -169,24 +188,27 @@ right: 0.5em; } .ol-zoom { top: 2.2em; top: 2.3em; } #track { #menu { top: 6em; left: 0.5em; } .ol-touch #track { .ol-touch #menu { top: 7em; } #menu button { border-radius: 0; } #menu button:first-child { border-top-left-radius: 2px; border-top-right-radius: 2px; } #menu button:last-child { border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; } .ol-control button svg * { stroke: white; stroke-width: 5%; fill: none; } .ol-control button svg .fill { fill: white; } .ol-control button.clicked { background-color: black; } map.html
@@ -5,27 +5,23 @@ <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v5.3.0/css/ol.css" integrity="sha384-C7SzZySesoxngSK5V0BaD1DUap0LPZGWZpnXQGoIwvBXFc8G21y4s1QYvyr84FNa" crossorigin="anonymous"> <link rel="stylesheet" href="map.css?v4" type="text/css" /> <link rel="stylesheet" href="map.css?v6" type="text/css" /> <link rel="manifest" href="map.manifest" /> </head> <body> <div id="map"> <div id="title" class="ol-unselectable ol-control"><a href="/">TTSS Kraków</a></div> <div id="track" class="ol-unselectable ol-control"><button type="button" title="GPS"><svg width="100%" height="100%"> <circle cx="50%" cy="50%" r="25%"></circle> <circle cx="50%" cy="50%" r="10%" class="fill"></circle> <line x1="50%" y1="25%" x2="50%" y2="10%"></line> <line x1="75%" y1="50%" x2="90%" y2="50%"></line> <line x1="50%" y1="75%" x2="50%" y2="90%"></line> <line x1="25%" y1="50%" x2="10%" y2="50%"></line> </svg></button></div> <div id="fail" class="ol-unselectable ol-control"><span></span> <span class="close">×</p></div> <div id="menu" class="ol-unselectable ol-control"> <button id="find" type="button" title="Find"><span class="icon-zoom normal-icon reverse"></span></button> <button id="track" type="button" title="GPS"><span class="icon-loc reverse"></span></button> </div> </div> <div id="panel"></div> <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?v9" id="lang_script"></script> <script tyle="text/javascript" src="lang_pl.js?v10" id="lang_script"></script> <script tyle="text/javascript" src="common.js?v10"></script> <script tyle="text/javascript" src="map.js?v23"></script> <script tyle="text/javascript" src="map.js?v25"></script> </body> </html> map.js
@@ -70,6 +70,7 @@ var map = null; var panel = null; var find = null; var fail_element = document.getElementById('fail'); var fail_text = document.querySelector('#fail span'); @@ -143,6 +144,80 @@ this._element.classList.remove('enabled'); }, }; function Find() { this.div = document.createElement('div'); this.form = document.createElement('form'); this.div.appendChild(this.form); var para = addParaWithText(this.form, lang.enter_query); para.appendChild(document.createElement('br')); this.input = document.createElement('input'); this.input.type = 'text'; this.input.style.width = '80%'; para.appendChild(this.input); para.appendChild(document.createElement('hr')); this.results = document.createElement('div'); this.div.appendChild(this.results); this.input.addEventListener('keyup', this.findDelay.bind(this)); this.form.addEventListener('submit', this.findDelay.bind(this)); } Find.prototype = { query: '', timeout: null, div: null, form: null, input: null, results: null, find: function() { var query = this.input.value.toUpperCase(); if(query === this.query) return; this.query = query; var features = []; stops_type.forEach(function(stop_type) { if(stop_type.substr(0,1) === 'p') return; stops_source[stop_type].forEachFeature(function(feature) { if(feature.get('name').toUpperCase().indexOf(query) > -1) { features.push(feature); } }); }); ttss_types.forEach(function(ttss_type) { vehicles_source[ttss_type].forEachFeature(function(feature) { if(feature.get('vehicle_type') && feature.get('vehicle_type').num.indexOf(query) > -1) { features.push(feature); } }); }); deleteChildren(this.results); this.results.appendChild(listFeatures(features)); }, findDelay: function(e) { e.preventDefault(); if(this.timeout) clearTimeout(this.timeout); this.timeout = setTimeout(this.find.bind(this), 100); }, open: function(panel) { ignore_hashchange = true; window.location.hash = '#!f'; panel.show(this.div, this.close.bind(this)); this.input.focus(); }, close: function() { if(this.timeout) clearTimeout(this.timeout); }, }; function fail(msg) { setText(fail_text, msg); @@ -269,7 +344,7 @@ if(vehicle_feature) { vehicles_source[prefix].removeFeature(vehicle_feature); if(feature_clicked && feature_clicked.getId() === vehicle_feature.getId()) { featureClicked(); panel.close(); } } continue; @@ -594,7 +669,7 @@ })}, 10); }; showOnMapElement.addEventListener('click', showOnMapFunction); showOnMapElement.className = 'icon-zoom pad-left-icon'; showOnMapElement.className = 'icon-pin addon-icon'; showOnMapElement.title = lang.show_on_map; if(additional) { @@ -626,6 +701,41 @@ feature_clicked = feature; } function listFeatures(features) { var div = document.createElement('div'); addParaWithText(div, lang.select_feature); var feature, p, a, full_type, typeName; for(var i = 0; i < features.length; i++) { feature = features[i]; p = document.createElement('p'); a = document.createElement('a'); p.appendChild(a); a.addEventListener('click', function(feature) { return function() { featureClicked(feature); }}(feature)); full_type = feature.getId().match(/^[a-z]+/)[0]; typeName = lang.types[full_type]; if(typeof typeName === 'undefined') { typeName = ''; } if(feature.get('vehicle_type')) { typeName += ' ' + feature.get('vehicle_type').num; } addElementWithText(a, 'span', typeName).className = 'small'; a.appendChild(document.createTextNode(' ')); addElementWithText(a, 'span', normalizeName(feature.get('name'))); div.appendChild(p); } return div; } function mapClicked(e) { var point = e.coordinate; var features = []; @@ -637,41 +747,7 @@ var feature = features[0]; if(features.length > 1) { featureClicked(); var div = document.createElement('div'); addParaWithText(div, lang.select_feature); var p, a, full_type, typeName; for(var i = 0; i < features.length; i++) { feature = features[i]; p = document.createElement('p'); a = document.createElement('a'); p.appendChild(a); a.addEventListener('click', function(feature) { return function() { featureClicked(feature); }}(feature)); full_type = feature.getId().match(/^[a-z]+/)[0]; typeName = lang.types[full_type]; if(typeof typeName === 'undefined') { typeName = ''; } if(feature.get('vehicle_type')) { typeName += ' ' + feature.get('vehicle_type').num; } addElementWithText(a, 'span', typeName).className = 'small'; a.appendChild(document.createTextNode(' ')); addElementWithText(a, 'span', normalizeName(feature.get('name'))); div.appendChild(p); } panel.show(div); panel.show(listFeatures(features)); return; } @@ -720,6 +796,7 @@ } } function hash() { if(ignore_hashchange) { ignore_hashchange = false; @@ -744,6 +821,9 @@ stopId = window.location.hash.substr(2,1) + 't' + window.location.hash.substr(3); } else if(window.location.hash.match(/^#![sp][tb]-?[0-9]+$/)) { stopId = window.location.hash.substr(2); } else if(window.location.hash.match(/^#!f$/)) { find.open(panel); return; } if(vehicleId) { @@ -777,6 +857,7 @@ function init() { panel = new Panel(document.getElementById('panel')); find = new Find(); route_source = new ol.source.Vector({ features: [], @@ -839,9 +920,9 @@ geolocation_layer = new ol.layer.Vector({ source: geolocation_source, }); geolocation_button = document.querySelector('#track button'); geolocation_button = document.querySelector('#track'); if(!navigator.geolocation) { geolocation_button.classList.add('hidden'); geolocation_button.remove(); } geolocation = new ol.Geolocation({projection: 'EPSG:3857'}); @@ -866,9 +947,11 @@ geolocation.on('error', function(error) { fail(lang.error_location + ' ' + error.message); trackingStop(); geolocation_button.classList.add('hidden'); geolocation_button.remove(); }); geolocation_button.addEventListener('click', trackingToggle); document.getElementById('find').addEventListener('click', find.open.bind(find, panel)); var layers = [ new ol.layer.Tile({ @@ -904,7 +987,7 @@ element: fail_element, }), new ol.control.Control({ element: document.getElementById('track'), element: document.getElementById('menu'), }), ]), loadTilesWhileAnimating: false,