Improved www.ttss.krakow.pl
Jacek Kowalski
2019-07-05 5be662f756540fff10a35cb5b1caa933a257e62e
Add search feature to the map
5 files modified
167 ■■■■ changed files
index.html 2 ●●● patch | view | raw | blame | history
lang_en.js 4 ●●● patch | view | raw | blame | history
lang_pl.js 4 ●●● patch | view | raw | blame | history
map.html 5 ●●●●● patch | view | raw | blame | history
map.js 152 ●●●● patch | view | raw | blame | history
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.html
@@ -13,14 +13,15 @@
<div id="title" class="ol-unselectable ol-control"><a href="/">TTSS Kraków</a></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?v24"></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);
@@ -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 = [];
@@ -638,40 +748,7 @@
    
    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 +797,7 @@
    }
}
function hash() {
    if(ignore_hashchange) {
        ignore_hashchange = false;
@@ -744,6 +822,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 +858,7 @@
function init() {
    panel = new Panel(document.getElementById('panel'));
    find = new Find();
    
    route_source = new ol.source.Vector({
        features: [],
@@ -870,6 +952,8 @@
    });
    geolocation_button.addEventListener('click', trackingToggle);
    
    document.getElementById('find').addEventListener('click', find.open.bind(find, panel));
    var layers = [
        new ol.layer.Tile({
            source: new ol.source.OSM(),