From 5be662f756540fff10a35cb5b1caa933a257e62e Mon Sep 17 00:00:00 2001
From: Jacek Kowalski <Jacek@jacekk.info>
Date: Sat, 06 Jul 2019 00:01:22 +0000
Subject: [PATCH] Add search feature to the map

---
 map.js     |  152 +++++++++++++++++++++++++++++++++++++++-----------
 lang_en.js |    4 +
 index.html |    2 
 map.html   |    5 +
 lang_pl.js |    4 +
 5 files changed, 128 insertions(+), 39 deletions(-)

diff --git a/index.html b/index.html
index 9c3db11..4b7b298 100644
--- a/index.html
+++ b/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>
diff --git a/lang_en.js b/lang_en.js
index a9428b4..db691a6 100644
--- a/lang_en.js
+++ b/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.',
diff --git a/lang_pl.js b/lang_pl.js
index d6e280d..9682cd6 100644
--- a/lang_pl.js
+++ b/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.',
diff --git a/map.html b/map.html
index be0d733..351e1c4 100644
--- a/map.html
+++ b/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>
diff --git a/map.js b/map.js
index 07f2361..bd9765b 100644
--- a/map.js
+++ b/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(),

--
Gitblit v1.9.1