<commit_before>/* JavaScript Document */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// @author: jmacura 2016-2017
// @author: kellar 2017

// global variables
var no; //number of searches made during one session
var destination = null;
var cats = false;

//defining Event Handlers
$(document).ready(function(e) {
	no = 0; //reset the number when the page reloads
	document.getElementById('search-by-name').addEventListener('submit', searchPlaceGeoNames);
	document.getElementById('search-by-latlon').addEventListener('submit', searchLocationHeader);
	document.getElementById('search-by-position').addEventListener('submit', searchAround);
	//console.log("loaded");
});


function searchAround(e) {
	e.preventDefault();
	var r = this.r.value;
	if (r > 5 || r <= 0) {
		printError('Radius has to be positive number smaller than 5');
		return;
	}
	runProgressbar('resultsLoader');
	if(!navigator.geolocation) {
		console.log("not possible in your browser");
		killProgressbar('resultsLoader');
		return;
	}
	navigator.geolocation.getCurrentPosition(function(position) {
		//console.log(position)
		searchLocation([position.coords.latitude, position.coords.longitude, r]);
		}, function(error) {
		killProgressbar('resultsLoader');
		switch(error.code) {
			case error.PERMISSION_DENIED:
				printError("User denied the request for Geolocation."); break;
			case error.POSITION_UNAVAILABLE:
				printError("Location information is unavailable."); break;
			case error.TIMEOUT:
				printError("The request to get user location timed out."); break;
			case error.UNKNOWN_ERROR:
				printError("An unknown error occurred."); break;
		}
		}, {enableHighAccuracy: false, timeout: 1000, maximumAge: 0}
	); //10 000 ms timeout
}

function searchPlaceGeoNames(e) {
	e.preventDefault();
	var place = this.place.value;
	if(place.length <= 1) {
		printError("Please, provide at least 2 characters");
		return;
	}
	//console.log("shit", e.type);
	runProgressbar('digestLoader');
	//console.log(this.place.value);
	var url = 'http://api.geonames.org/searchJSON';
	var queryUrl = url+'?q='+encodeURIComponent(place)+'&fuzzy=0.8&isNameRequired=true&username=spoi&callback=?';
	$.ajax({
		dataType: 'json',
		url: queryUrl,
		error: function(jqXHR, status, err) {
			console.log(status + err);
		},
		success: function(data) {
			console.log(data);
			digest(place, data.geonames);
			killProgressbar('digestLoader');
		}
	});
}

function digest(input, points) {
	var d, r, a;
	var nfo = document.createElement('DIV');
	var p = document.createElement('P');
	p.appendChild(document.createTextNode("Choose from places found:"));
	nfo.appendChild(p);
	var t = document.createElement('TABLE');
	for(var i = 0; i < points.length; i++) {
		r = document.createElement('TR');
		d = document.createElement('TD');
		a = document.createElement('A');
		a.data = points[i];
		a.addEventListener('click', searchPlaceSPOI);
		a.setAttribute("href", '#');
		a.appendChild(document.createTextNode(points[i].name));
		d.appendChild(a);
		r.appendChild(d);
		d = document.createElement('TD');
		d.appendChild(document.createTextNode(points[i].fclName + " in " + points[i].countryName));
		r.appendChild(d);
		t.appendChild(r);
	}
	nfo.appendChild(t);
	//nfo.setAttribute("class", 'digest');
	var infoBlock = document.getElementById('digest-block');
	infoBlock.removeChild(infoBlock.firstChild);
	infoBlock.appendChild(nfo);
}

/**
 * currently unused
 * performs hard regexp matching against SPOI endpoint
 */
function searchPlaceSPOI(e) {
	console.log(e);
	place = e.target.data;
	runProgressbar('resultsLoader');
	searchLocation([place.lat, place.lng, 3]);
	//searchLocation(place.,4);
	/*var url = 'http://data.plan4all.eu/sparql';
	var query = 'SELECT DISTINCT ?linkThing ?name ?wkt \n' +
		'WHERE {\n' +
		' ?linkThing rdfs:label ?name.\n' +
		' FILTER regex(?name, "' + place + '", "i").\n' +
		' ?linkThing ogcgs:asWKT ?wkt\n' +
		'}';
		console.log(query);
	var queryUrl = url+'?query='+encodeURIComponent(query)+'&format=json&callback=?';
	$.ajax({
		dataType: 'json',
		url: queryUrl,
		success: function(data) {
			var POIs = data.results.bindings;
			console.log(data);
			showInfo([place], data.head.vars, POIs);
			killProgressbar("resultsLoader");
		}
	});
	this.reset();*/
}

function searchLocationHeader(e) {
	e.preventDefault();
	if (this.r.value > 5 || this.r.value <= 0) {
		printError("Radius has to be positive number smaller than 5");
		return;
	}
	runProgressbar('resultsLoader');
	searchLocation([this.lat.value, this.lon.value, this.r.value]);
	this.reset();
}

function searchLocation(input) {
	//e.preventDefault();
	//runProgressbar("resultsLoader");
	//console.log(input);
	//var input = [this.lat.value, this.lon.value, this.r.value]; //[latitude, longitude, radius]
	var url = 'http://data.plan4all.eu/sparql';
	var query = "PREFIX poi: <http://www.openvoc.eu/poi#>\n" +
		"SELECT ?linkThing ?name ?sg AS ?wkt ?category WHERE {\n" +
		"?linkThing ogcgs:asWKT ?sg;\n" +
		" rdfs:label ?name.\n" +
		" FILTER(bif:st_intersects (?sg, bif:st_point (" + input[1] + ", " + input[0] + "), " + input[2] + ")).\n" +
		" OPTIONAL {?linkThing poi:class ?category .}\n" +
		"}";
	console.log(query);
	var queryUrl = url+'?query='+encodeURIComponent(query)+'&format=json&callback=?';
	$.ajax({
		dataType: 'json',
		url: queryUrl,
		error: function(jqXHR, status, err) {
			console.log(status + err);
		},
		success: function(data) {
			//console.log(data);
			var POIs = preprocess(data.results.bindings);
            mymap.setView([input[0], input[1]], 13);
			showInfo(input, data.head.vars, POIs);
			killProgressbar("resultsLoader");
		}
	});
	//this.reset();
}

// **** Get  the list of Categories (Classes) from SPOI ****
function getCats() {
	if(cats) {return;};
	cats = true;
	document.getElementById("catFilter").style.display = 'block';
	runProgressbar('catProgress');
	var url = 'http://data.plan4all.eu/sparql';
	var query = "PREFIX poi: <http://www.openvoc.eu/poi#>\n" +
	"SELECT DISTINCT ?Concept WHERE {?obj poi:class ?Concept}";
	console.log(query);
	var queryUrl = url+'?query='+encodeURIComponent(query)+'&format=json&callback=?';
	$.ajax({
		dataType: 'json',
		url: queryUrl,
		error: function(jqXHR, status, err) {
			console.log(status + err);
		},
		success: function(data) {
			var catz = data.results.bindings;
			killProgressbar('catProgress');
			var catFilter = document.getElementById("catFilter");
			var ls = document.createElement("UL");
			for(var i = 0; i < catz.length; i++) {
				var cat = catz[i].Concept.value.slice(32);
				//console.log(cat);
				var li = document.createElement("INPUT");
				li.setAttribute("type", 'checkbox');
				li.setAttribute("value", cat);
				li.setAttributeNode(document.createAttribute("checked"));
				li.addEventListener('change', filter);
				ls.appendChild(li);
				ls.appendChild(document.createTextNode(cat));
				ls.appendChild(document.createElement("BR"));
			}
			catFilter.appendChild(ls);
			//showInfo(input, data.head.vars, POIs);
			//killProgressbar("resultsLoader");
		}
	});
}

// **** Background support for displaying info ****
function showInfo(input, headers, points) { //points is the array of data
	var heads = thingsAndLinks(headers);
	var infoBlock = document.getElementById("info-block");
	var nfo, ls, r, d, l, t, p;

	//print heading
	nfo = document.createElement("H2");
	var info = 'Results for ';
	for(var i = 0; i < input.length; i++) {
		if(i > 0) {info += " "};
		info += input[i];
	}
	t = document.createTextNode(info + ':');
	nfo.appendChild(t);

	
	var charts = document.createElement("DIV");
	charts.setAttribute("id", 'charts');

	//create map
    /*
	var mappa = document.createElement("DIV");
	mappa.setAttribute("id", 'map');
	charts.appendChild(mappa);
	if (input[1]) {
		var map = L.map(mappa).setView([input[0], input[1]], 11);
	}
	else {
		var map = L.map(mappa).setView([0, 0], 1);
	}
	L.tileLayer('http://{s}.tiles.mapbox.com/v3/yjm.j5j87g72/{z}/{x}/{y}.png', {
		attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery &copy; <a href="http://mapbox.com">Mapbox</a>',
		maxZoom: 18
	}).addTo(map);
*/

	//create block for weather forecast
	var forecast = document.createElement("DIV");
	forecast.setAttribute("id", 'forecast');
	charts.appendChild(forecast);
	phpUrl = './getWeather.php?lat=' + input[0] + '&lon=' + input[1];
	//phpUrl = 'predpoved2.xml'; //ONLY FOR LOCAL TESTINGS
	$.ajax({
		dataType: 'xml',
		url: phpUrl,
		error: function(jqXHR, status, err) { //if weather API does not work
			var p = document.createElement("P");
			p.appendChild(document.createTextNode('Error obtaining weather forecast: ' + status));
			forecast.appendChild(p);
		},
		success: function(data) {
			var obj = xmlToJson(data.firstChild);
			//console.log(obj);
			var weather = parseWeather(obj); //<- implement var [[day, time, symb, minT, maxT]] = parseWeather() ??
			//console.log(weather);
			var h = document.createElement("H3");
            h.setAttribute("style", 'text-align: center;');
			h.appendChild(document.createTextNode('Weather forecast in the location for the upcoming 48 hours'));
           	forecast.appendChild(h);
			r = document.createElement("TR");
			for(var i = 0; i < weather.length; i++) {
				d = document.createElement("TD");
				p = document.createElement("P");
				p.appendChild(document.createTextNode(weather[i][0].slice(3,5) == new Date().getDate() ? 'today' : weather[i][0])) //den
				d.appendChild(p);
				p = document.createElement("P");
				var printtime = weather[i][1] + '–' + (weather[i][1]+6); //forecasted time interval
				p.appendChild(document.createTextNode(printtime));
				d.appendChild(p);
				var img = document.createElement("IMG"); //image of weather condition
				var night = ((weather[i][1] == 18 || weather[i][1] == 0) ? true : false);
				var imgSrc = 'http://api.met.no/weatherapi/weathericon/1.1/?symbol=' + weather[i][2] + ';' + (night ? 'is_night=1;' : '') + 'content_type=image/svg%2Bxml';
				img.setAttribute("src", imgSrc);
				d.append(img);
				var maxT = 'max: ' + weather[i][4] + ' °C';
				p = document.createElement("P");
				p.setAttribute("class",'tmax');
				p.appendChild(document.createTextNode(maxT)); //max temperature in interval
				d.appendChild(p);
				var minT = 'min: ' + weather[i][3] + ' °C';
				p = document.createElement("P");
				p.setAttribute("class",'tmin');
				p.appendChild(document.createTextNode(minT)); //min temperature in interval
				d.appendChild(p);
				r.appendChild(d);
			}
			var tab = document.createElement("TABLE");
			tab.appendChild(r);
			forecast.appendChild(tab);
			p = document.createElement("P");
			p.setAttribute("class", 'weather-info');
            p.setAttribute("style", 'text-align: center;');
			p.appendChild(document.createTextNode('Weather forecast from Yr, delivered by the Norwegian Meteorological Institute and NRK'));
			forecast.appendChild(p);
            

		}
	});

//Category filtering
	var catFilter = document.createElement("DIV");
	catFilter.setAttribute("id", 'catFilter');
	var catProg = document.createElement("DIV");
	catProg.setAttribute("class", 'progressbar');
	catProg.setAttribute("id", 'catProgress');
	catFilter.appendChild(catProg);
	//catFilter.addEventListener('mouseover', getCats);

	ls = document.createElement("TABLE");
    ls.setAttribute("class", 'table-results');
	//set headers
	r = document.createElement("TR");
	for(var i = 0; i < heads[1].length; i++) {
		d = document.createElement("TH");
        d.setAttribute("class", 'results-heading');
		t = document.createTextNode(heads[1][i]);
		d.appendChild(t);
		if(heads[1][i] == "category") {
			var aCat = document.createElement("A");
			aCat.setAttribute("href", '#');
           // aCat.setAttribute("target", '_blank');
			aCat.appendChild(document.createTextNode(' (Filter)'));
			aCat.addEventListener('click', getCats);
			d.appendChild(aCat);
		}
		r.appendChild(d);
	}
	ls.appendChild(r);
    


	//print POIs
	var color = 'rgb('+ Math.floor((Math.random() * 250) + 1)+', 163, 61)';
    var mypoints = new L.LayerGroup();
	for(var i in points) {
		if (!points.hasOwnProperty(i)) {
			//The current property is not a direct property of p
			continue;
		}
		var objName = points[i]['linkThing'].value.split('#')[1];
		r = document.createElement("TR");
		var latlng = points[i]['wkt'].value.split(" ");  //get lat and long from WKT
		//console.log(latlng);
		var m = L.circleMarker([latlng[1].slice(0,-1), latlng[0].slice(6)], {radius: 7, color: color});
		m.name = objName;
        m.on('click', navigateTo);
        
        
        m.addTo(mypoints);
                
	
		//console.log(lat, lng);
		for(var j = 0; j < heads[1].length; j++) {
			d = document.createElement("TD");
			var a = document.createElement("A");
			a.setAttribute("name", objName);
			d.appendChild(a);
			//console.log(j, heads[1][j]);
			var txt = '';
			//console.log(points[i][heads[1][j]]);
			if(points[i][heads[1][j]].list) {
			//If there is more then 1 category, then they are in the list attribute
				for(var k = 0; k < points[i][heads[1][j]].list.length; k++) {
					if(txt.length > 1) {
						txt += ', ';
					}
					appendAttribute(r, "class", points[i][heads[1][j]].list[k].slice(32));
					txt += points[i][heads[1][j]].list[k].slice(32).replace(/_/g, ' ');
				}
			} else if (points[i][heads[1][j]].value.includes('#')) { //If the line contains # sign => it is a single category
				appendAttribute(r, "class", points[i][heads[1][j]].value.slice(32)); // if there is a category for given point => save it to the class attribute of corresponding row
				txt = points[i][heads[1][j]].value.slice(32).replace(/_/g, ' '); //Prettyprint categories
			}
			else {
				txt = points[i][heads[1][j]].value; // If the object has no name => print ---
			}
			t = document.createTextNode( (points[i][heads[1][j]]) ? txt : '---');
			if(heads[0][j]) {
				l = document.createElement("A");
				l.setAttribute("href", points[i][heads[0][j]].value);
				l.setAttribute("target", '_blank');
				l.appendChild(t); d.appendChild(l);
			}
			else {
				d.appendChild(t);
			}
			r.appendChild(d);
		}
		//d = document.createElement("TD");
		//t = document.createTextNode(points[0].s.value);
		//d.appendChild(t);
		//r.appendChild(d);
		ls.appendChild(r);
	}
    mymap.addLayer(mypoints);
    layerControl.addOverlay(mypoints, "My Points "+no);
    
    var f = document.createElement("div");
    f.setAttribute("class", 'to-top');
    var e = document.createElement("a");
    e.setAttribute("href", '#');
    e.setAttribute("onclick", 'moveToMap()');
    f.appendChild(e);
    var k = document.createElement("span");
    k.setAttribute("class",'glyphicon glyphicon-chevron-up');
    e.appendChild(k);


	var exporter = document.createElement("BUTTON");
	exporter.appendChild(document.createTextNode("EXPORT & SAVE POINTS"));
	exporter.addEventListener('click', exportHandler);

	//remove existing information
	/*while(infoBlock.hasChildNodes()) {
		infoBlock.removeChild(infoBlock.firstChild);
	}*/
	//append new information

    infoBlock.insertBefore(f, infoBlock.firstChild);
	infoBlock.insertBefore(exporter, infoBlock.firstChild);
	infoBlock.insertBefore(ls, infoBlock.firstChild);
	infoBlock.insertBefore(catFilter, infoBlock.firstChild);
	infoBlock.insertBefore(charts, infoBlock.firstChild);
	infoBlock.insertBefore(nfo, infoBlock.firstChild);
}

//Handle duplicates
function preprocess(arr) {
	//console.log(arr);
	var obj = {};
	var geojs = {};
	for(var i = 0; i <arr.length; i++) {
		if(obj[arr[i].linkThing.value]) { //if the object already exist..
			obj[arr[i].linkThing.value].category.list = [obj[arr[i].linkThing.value].category.value, arr[i].category.value]; //..then only create array of categories
			geojs[arr[i].linkThing.value].properties.category.list = [geojs[arr[i].linkThing.value].properties.category.value, arr[i].category.value]; //the same for GeoJSON serialization
			//console.log(obj[arr[i].linkThing.value].category.list);
		}
		else {
			var props = {};
			for(var j in arr[i]) {
				if(!arr[i].hasOwnProperty(j) || (arr[i][j] && arr[i][j].datatype == 'http://www.openlinksw.com/schemas/virtrdf#Geometry')) { //skip subproperties & geometry type
					continue;
				}
				props[j] = arr[i][j];
				//console.log(props);
			}
			geojs[arr[i].linkThing.value] = {"type": "Feature", "geometry": {"type": "Point", "coordinates": [arr[i].wkt.value.split(" ")[1].slice(0,-1), arr[i].wkt.value.split(" ")[0].slice(6)]}, 'properties' : props};
			obj[arr[i].linkThing.value] = arr[i]; //the simple way for generic JSON object
		}
	}
	console.log(geojs);
	if (typeof(Storage) !== "undefined") { // If Browser supports the localStorage/sessionStorage
		sessionStorage.setItem('result'.concat(no++), JSON.stringify(geojs));
	} else { //No Web Storage support..
		printError('Your browser does not support Web Storage API. Export of data will not be available!');
	}
	return obj;
}

function exportHandler(e) {
	console.log(sessionStorage.getItem('result'.concat(no-1)));
	saveData();
	//console.log(e.target)<commit_msg>Fixed GeoJSON structure prettyfied export button<commit_after>/* JavaScript Document */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// @author: jmacura 2016-2017
// @author: kellar 2017

// global variables
var no; //number of searches made during one session
var destination = null;
var cats = false;

//defining Event Handlers
$(document).ready(function(e) {
	no = 0; //reset the number when the page reloads
	document.getElementById('search-by-name').addEventListener('submit', searchPlaceGeoNames);
	document.getElementById('search-by-latlon').addEventListener('submit', searchLocationHeader);
	document.getElementById('search-by-position').addEventListener('submit', searchAround);
	//console.log("loaded");
});


function searchAround(e) {
	e.preventDefault();
	var r = this.r.value;
	if (r > 5 || r <= 0) {
		printError('Radius has to be positive number smaller than 5');
		return;
	}
	runProgressbar('resultsLoader');
	if(!navigator.geolocation) {
		console.log("not possible in your browser");
		killProgressbar('resultsLoader');
		return;
	}
	navigator.geolocation.getCurrentPosition(function(position) {
		//console.log(position)
		searchLocation([position.coords.latitude, position.coords.longitude, r]);
		}, function(error) {
		killProgressbar('resultsLoader');
		switch(error.code) {
			case error.PERMISSION_DENIED:
				printError("User denied the request for Geolocation."); break;
			case error.POSITION_UNAVAILABLE:
				printError("Location information is unavailable."); break;
			case error.TIMEOUT:
				printError("The request to get user location timed out."); break;
			case error.UNKNOWN_ERROR:
				printError("An unknown error occurred."); break;
		}
		}, {enableHighAccuracy: false, timeout: 1000, maximumAge: 0}
	); //10 000 ms timeout
}

function searchPlaceGeoNames(e) {
	e.preventDefault();
	var place = this.place.value;
	if(place.length <= 1) {
		printError("Please, provide at least 2 characters");
		return;
	}
	//console.log("shit", e.type);
	runProgressbar('digestLoader');
	//console.log(this.place.value);
	var url = 'http://api.geonames.org/searchJSON';
	var queryUrl = url+'?q='+encodeURIComponent(place)+'&fuzzy=0.8&isNameRequired=true&username=spoi&callback=?';
	$.ajax({
		dataType: 'json',
		url: queryUrl,
		error: function(jqXHR, status, err) {
			console.log(status + err);
		},
		success: function(data) {
			console.log(data);
			digest(place, data.geonames);
			killProgressbar('digestLoader');
		}
	});
}

function digest(input, points) {
	var d, r, a;
	var nfo = document.createElement('DIV');
	var p = document.createElement('P');
	p.appendChild(document.createTextNode("Choose from places found:"));
	nfo.appendChild(p);
	var t = document.createElement('TABLE');
	for(var i = 0; i < points.length; i++) {
		r = document.createElement('TR');
		d = document.createElement('TD');
		a = document.createElement('A');
		a.data = points[i];
		a.addEventListener('click', searchPlaceSPOI);
		a.setAttribute("href", '#');
		a.appendChild(document.createTextNode(points[i].name));
		d.appendChild(a);
		r.appendChild(d);
		d = document.createElement('TD');
		d.appendChild(document.createTextNode(points[i].fclName + " in " + points[i].countryName));
		r.appendChild(d);
		t.appendChild(r);
	}
	nfo.appendChild(t);
	//nfo.setAttribute("class", 'digest');
	var infoBlock = document.getElementById('digest-block');
	infoBlock.removeChild(infoBlock.firstChild);
	infoBlock.appendChild(nfo);
}

/**
 * currently unused
 * performs hard regexp matching against SPOI endpoint
 */
function searchPlaceSPOI(e) {
	console.log(e);
	place = e.target.data;
	runProgressbar('resultsLoader');
	searchLocation([place.lat, place.lng, 3]);
	//searchLocation(place.,4);
	/*var url = 'http://data.plan4all.eu/sparql';
	var query = 'SELECT DISTINCT ?linkThing ?name ?wkt \n' +
		'WHERE {\n' +
		' ?linkThing rdfs:label ?name.\n' +
		' FILTER regex(?name, "' + place + '", "i").\n' +
		' ?linkThing ogcgs:asWKT ?wkt\n' +
		'}';
		console.log(query);
	var queryUrl = url+'?query='+encodeURIComponent(query)+'&format=json&callback=?';
	$.ajax({
		dataType: 'json',
		url: queryUrl,
		success: function(data) {
			var POIs = data.results.bindings;
			console.log(data);
			showInfo([place], data.head.vars, POIs);
			killProgressbar("resultsLoader");
		}
	});
	this.reset();*/
}

function searchLocationHeader(e) {
	e.preventDefault();
	if (this.r.value > 5 || this.r.value <= 0) {
		printError("Radius has to be positive number smaller than 5");
		return;
	}
	runProgressbar('resultsLoader');
	searchLocation([this.lat.value, this.lon.value, this.r.value]);
	this.reset();
}

function searchLocation(input) {
	//e.preventDefault();
	//runProgressbar("resultsLoader");
	//console.log(input);
	//var input = [this.lat.value, this.lon.value, this.r.value]; //[latitude, longitude, radius]
	var url = 'http://data.plan4all.eu/sparql';
	var query = "PREFIX poi: <http://www.openvoc.eu/poi#>\n" +
		"SELECT ?linkThing ?name ?sg AS ?wkt ?category WHERE {\n" +
		"?linkThing ogcgs:asWKT ?sg;\n" +
		" rdfs:label ?name.\n" +
		" FILTER(bif:st_intersects (?sg, bif:st_point (" + input[1] + ", " + input[0] + "), " + input[2] + ")).\n" +
		" OPTIONAL {?linkThing poi:class ?category .}\n" +
		"}";
	console.log(query);
	var queryUrl = url+'?query='+encodeURIComponent(query)+'&format=json&callback=?';
	$.ajax({
		dataType: 'json',
		url: queryUrl,
		error: function(jqXHR, status, err) {
			console.log(status + err);
		},
		success: function(data) {
			//console.log(data);
			var POIs = preprocess(data.results.bindings);
            mymap.setView([input[0], input[1]], 13);
			showInfo(input, data.head.vars, POIs);
			killProgressbar("resultsLoader");
		}
	});
	//this.reset();
}

// **** Get  the list of Categories (Classes) from SPOI ****
function getCats() {
	if(cats) {return;};
	cats = true;
	document.getElementById("catFilter").style.display = 'block';
	runProgressbar('catProgress');
	var url = 'http://data.plan4all.eu/sparql';
	var query = "PREFIX poi: <http://www.openvoc.eu/poi#>\n" +
	"SELECT DISTINCT ?Concept WHERE {?obj poi:class ?Concept}";
	console.log(query);
	var queryUrl = url+'?query='+encodeURIComponent(query)+'&format=json&callback=?';
	$.ajax({
		dataType: 'json',
		url: queryUrl,
		error: function(jqXHR, status, err) {
			console.log(status + err);
		},
		success: function(data) {
			var catz = data.results.bindings;
			killProgressbar('catProgress');
			var catFilter = document.getElementById("catFilter");
			var ls = document.createElement("UL");
			for(var i = 0; i < catz.length; i++) {
				var cat = catz[i].Concept.value.slice(32);
				//console.log(cat);
				var li = document.createElement("INPUT");
				li.setAttribute("type", 'checkbox');
				li.setAttribute("value", cat);
				li.setAttributeNode(document.createAttribute("checked"));
				li.addEventListener('change', filter);
				ls.appendChild(li);
				ls.appendChild(document.createTextNode(cat));
				ls.appendChild(document.createElement("BR"));
			}
			catFilter.appendChild(ls);
			//showInfo(input, data.head.vars, POIs);
			//killProgressbar("resultsLoader");
		}
	});
}

// **** Background support for displaying info ****
function showInfo(input, headers, points) { //points is the array of data
	var heads = thingsAndLinks(headers);
	var infoBlock = document.getElementById("info-block");
	var nfo, ls, r, d, l, t, p;

	//print heading
	nfo = document.createElement("H2");
	var info = 'Results for ';
	for(var i = 0; i < input.length; i++) {
		if(i > 0) {info += " "};
		info += input[i];
	}
	t = document.createTextNode(info + ':');
	nfo.appendChild(t);

	
	var charts = document.createElement("DIV");
	charts.setAttribute("id", 'charts');

	//create map
    /*
	var mappa = document.createElement("DIV");
	mappa.setAttribute("id", 'map');
	charts.appendChild(mappa);
	if (input[1]) {
		var map = L.map(mappa).setView([input[0], input[1]], 11);
	}
	else {
		var map = L.map(mappa).setView([0, 0], 1);
	}
	L.tileLayer('http://{s}.tiles.mapbox.com/v3/yjm.j5j87g72/{z}/{x}/{y}.png', {
		attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery &copy; <a href="http://mapbox.com">Mapbox</a>',
		maxZoom: 18
	}).addTo(map);
*/

	//create block for weather forecast
	var forecast = document.createElement("DIV");
	forecast.setAttribute("id", 'forecast');
	charts.appendChild(forecast);
	phpUrl = './getWeather.php?lat=' + input[0] + '&lon=' + input[1];
	//phpUrl = 'predpoved2.xml'; //ONLY FOR LOCAL TESTINGS
	$.ajax({
		dataType: 'xml',
		url: phpUrl,
		error: function(jqXHR, status, err) { //if weather API does not work
			var p = document.createElement("P");
			p.appendChild(document.createTextNode('Error obtaining weather forecast: ' + status));
			forecast.appendChild(p);
		},
		success: function(data) {
			var obj = xmlToJson(data.firstChild);
			//console.log(obj);
			var weather = parseWeather(obj); //<- implement var [[day, time, symb, minT, maxT]] = parseWeather() ??
			//console.log(weather);
			var h = document.createElement("H3");
            h.setAttribute("style", 'text-align: center;');
			h.appendChild(document.createTextNode('Weather forecast in the location for the upcoming 48 hours'));
           	forecast.appendChild(h);
			r = document.createElement("TR");
			for(var i = 0; i < weather.length; i++) {
				d = document.createElement("TD");
				p = document.createElement("P");
				p.appendChild(document.createTextNode(weather[i][0].slice(3,5) == new Date().getDate() ? 'today' : weather[i][0])) //den
				d.appendChild(p);
				p = document.createElement("P");
				var printtime = weather[i][1] + '–' + (weather[i][1]+6); //forecasted time interval
				p.appendChild(document.createTextNode(printtime));
				d.appendChild(p);
				var img = document.createElement("IMG"); //image of weather condition
				var night = ((weather[i][1] == 18 || weather[i][1] == 0) ? true : false);
				var imgSrc = 'http://api.met.no/weatherapi/weathericon/1.1/?symbol=' + weather[i][2] + ';' + (night ? 'is_night=1;' : '') + 'content_type=image/svg%2Bxml';
				img.setAttribute("src", imgSrc);
				d.append(img);
				var maxT = 'max: ' + weather[i][4] + ' °C';
				p = document.createElement("P");
				p.setAttribute("class",'tmax');
				p.appendChild(document.createTextNode(maxT)); //max temperature in interval
				d.appendChild(p);
				var minT = 'min: ' + weather[i][3] + ' °C';
				p = document.createElement("P");
				p.setAttribute("class",'tmin');
				p.appendChild(document.createTextNode(minT)); //min temperature in interval
				d.appendChild(p);
				r.appendChild(d);
			}
			var tab = document.createElement("TABLE");
			tab.appendChild(r);
			forecast.appendChild(tab);
			p = document.createElement("P");
			p.setAttribute("class", 'weather-info');
            p.setAttribute("style", 'text-align: center;');
			p.appendChild(document.createTextNode('Weather forecast from Yr, delivered by the Norwegian Meteorological Institute and NRK'));
			forecast.appendChild(p);
            

		}
	});

//Category filtering
	var catFilter = document.createElement("DIV");
	catFilter.setAttribute("id", 'catFilter');
	var catProg = document.createElement("DIV");
	catProg.setAttribute("class", 'progressbar');
	catProg.setAttribute("id", 'catProgress');
	catFilter.appendChild(catProg);
	//catFilter.addEventListener('mouseover', getCats);

	ls = document.createElement("TABLE");
    ls.setAttribute("class", 'table-results');
	//set headers
	r = document.createElement("TR");
	for(var i = 0; i < heads[1].length; i++) {
		d = document.createElement("TH");
        d.setAttribute("class", 'results-heading');
		t = document.createTextNode(heads[1][i]);
		d.appendChild(t);
		if(heads[1][i] == "category") {
			var aCat = document.createElement("A");
			aCat.setAttribute("href", '#');
           // aCat.setAttribute("target", '_blank');
			aCat.appendChild(document.createTextNode(' (Filter)'));
			aCat.addEventListener('click', getCats);
			d.appendChild(aCat);
		}
		r.appendChild(d);
	}
	ls.appendChild(r);
    


	//print POIs
	var color = 'rgb('+ Math.floor((Math.random() * 250) + 1)+', 163, 61)';
    var mypoints = new L.LayerGroup();
	for(var i in points) {
		if (!points.hasOwnProperty(i)) {
			//The current property is not a direct property of p
			continue;
		}
		var objName = points[i]['linkThing'].value.split('#')[1];
		r = document.createElement("TR");
		var latlng = points[i]['wkt'].value.split(" ");  //get lat and long from WKT
		//console.log(latlng);
		var m = L.circleMarker([latlng[1].slice(0,-1), latlng[0].slice(6)], {radius: 7, color: color});
		m.name = objName;
        m.on('click', navigateTo);
        
        
        m.addTo(mypoints);
                
	
		//console.log(lat, lng);
		for(var j = 0; j < heads[1].length; j++) {
			d = document.createElement("TD");
			var a = document.createElement("A");
			a.setAttribute("name", objName);
			d.appendChild(a);
			//console.log(j, heads[1][j]);
			var txt = '';
			//console.log(points[i][heads[1][j]]);
			if(points[i][heads[1][j]].list) {
			//If there is more then 1 category, then they are in the list attribute
				for(var k = 0; k < points[i][heads[1][j]].list.length; k++) {
					if(txt.length > 1) {
						txt += ', ';
					}
					appendAttribute(r, "class", points[i][heads[1][j]].list[k].slice(32));
					txt += points[i][heads[1][j]].list[k].slice(32).replace(/_/g, ' ');
				}
			} else if (points[i][heads[1][j]].value.includes('#')) { //If the line contains # sign => it is a single category
				appendAttribute(r, "class", points[i][heads[1][j]].value.slice(32)); // if there is a category for given point => save it to the class attribute of corresponding row
				txt = points[i][heads[1][j]].value.slice(32).replace(/_/g, ' '); //Prettyprint categories
			}
			else {
				txt = points[i][heads[1][j]].value; // If the object has no name => print ---
			}
			t = document.createTextNode( (points[i][heads[1][j]]) ? txt : '---');
			if(heads[0][j]) {
				l = document.createElement("A");
				l.setAttribute("href", points[i][heads[0][j]].value);
				l.setAttribute("target", '_blank');
				l.appendChild(t); d.appendChild(l);
			}
			else {
				d.appendChild(t);
			}
			r.appendChild(d);
		}
		//d = document.createElement("TD");
		//t = document.createTextNode(points[0].s.value);
		//d.appendChild(t);
		//r.appendChild(d);
		ls.appendChild(r);
	}

	mymap.addLayer(mypoints);
	layerControl.addOverlay(mypoints, "My Points "+no);

	var foot = document.createElement("DIV");
	foot.setAttribute("class", 'to-top');
	var e = document.createElement("a");
	e.setAttribute("href", '#');
	e.setAttribute("onclick", 'moveToMap()');
	foot.appendChild(e);
	var k = document.createElement("span");
	k.setAttribute("class",'glyphicon glyphicon-chevron-up');
	e.appendChild(k);

	var exporter = document.createElement("BUTTON");
	exporter.setAttribute("class", 'btn btn-default');
	exporter.appendChild(document.createTextNode("EXPORT & SAVE POINTS"));
	exporter.addEventListener('click', exportHandler);
	foot.insertBefore(document.createElement("BR"), foot.firstChild);
	foot.insertBefore(exporter, foot.firstChild);

	//remove existing information
	/*while(infoBlock.hasChildNodes()) {
		infoBlock.removeChild(infoBlock.firstChild);
	}*/
	//append new information

	infoBlock.insertBefore(foot, infoBlock.firstChild);
	infoBlock.insertBefore(ls, infoBlock.firstChild);
	infoBlock.insertBefore(catFilter, infoBlock.firstChild);
	infoBlock.insertBefore(charts, infoBlock.firstChild);
	infoBlock.insertBefore(nfo, infoBlock.firstChild);
}

//Handle duplicates
function preprocess(arr) {
	var obj = {};
	var geojs = [];
	var k = 0;
	for(var i = 0; i <arr.length; i++) {
		if(obj[arr[i].linkThing.value]) { //if the object already exist..
			obj[arr[i].linkThing.value].category.list = [obj[arr[i].linkThing.value].category.value, arr[i].category.value]; //..then only create array of categories
			//console.log(obj[arr[i].linkThing.value].category.list);
		}
		else {
			obj[arr[i].linkThing.value] = arr[i]; //the simple way for generic JSON object
		}
	}
	var k = 0;
	for(var i in obj) {
	var props = {};
		for(var j in obj[i]) {
			if(!obj[i].hasOwnProperty(j) || (obj[i][j] && obj[i][j].datatype == 'http://www.openlinksw.com/schemas/virtrdf#Geometry')) { //skip subproperties & geometry type
				continue;
			}
			props[j] = obj[i][j];
			//console.log(props);
		}
		geojs[k++] = {"type": "Feature", "geometry": {"type": "Point", "coordinates": [Number(obj[i].wkt.value.split(" ")[0].slice(6)), Number(obj[i].wkt.value.split(" ")[1].slice(0,-1))]}, 'properties' : props};
	}
	//console.log(geojs);
	geojs = {"type": "FeatureCollection", "features": geojs};
	if (typeof(Storage) !== "undefined") { // If Browser supports the localStorage/sessionStorage
		sessionStorage.setItem('result'.concat(no++), JSON.stringify(geojs));
	} else { //No Web Storage support
		printError('Your browser does not support Web Storage API. Export of data will not be available!');
	}
	return obj;
}

function exportHandler(e) {
	console.log(sessionStorage.getItem('result'.concat(no-1)));
	saveData();
	//console.log(e.target)
{'fraction_non_alphanumeric': 0.18650770740719358, 'fraction_numerical': 0.008948675018763352, 'mean_word_length': 4.225188536953243, 'pattern_counts': {'":': 10, '<': 43, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 6, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7262298', 'n_tokens_mistral': 12852, 'n_tokens_neox': 11709, 'n_words': 2403}