From 19985dbb8c0aa66dc4bf7905abc1148de909097d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20Luka=20=C5=A0ijanec?= Date: Tue, 11 Jan 2022 12:35:47 +0100 Subject: prvi-commit --- main/survey/js/Maps/Geocoding.js | 92 ++++++++ main/survey/js/Maps/KlikNaMapo.js | 43 ++++ main/survey/js/Maps/MapDeclaration.js | 323 +++++++++++++++++++++++++++ main/survey/js/Maps/Markers.js | 317 +++++++++++++++++++++++++++ main/survey/js/Maps/SearchBox.js | 78 +++++++ main/survey/js/Maps/ShapeDrawing.js | 397 ++++++++++++++++++++++++++++++++++ main/survey/js/Maps/UserLocation.js | 94 ++++++++ 7 files changed, 1344 insertions(+) create mode 100644 main/survey/js/Maps/Geocoding.js create mode 100644 main/survey/js/Maps/KlikNaMapo.js create mode 100644 main/survey/js/Maps/MapDeclaration.js create mode 100644 main/survey/js/Maps/Markers.js create mode 100644 main/survey/js/Maps/SearchBox.js create mode 100644 main/survey/js/Maps/ShapeDrawing.js create mode 100644 main/survey/js/Maps/UserLocation.js (limited to 'main/survey/js/Maps') diff --git a/main/survey/js/Maps/Geocoding.js b/main/survey/js/Maps/Geocoding.js new file mode 100644 index 0000000..836d215 --- /dev/null +++ b/main/survey/js/Maps/Geocoding.js @@ -0,0 +1,92 @@ +// Author: Uroš Podkrižnik (17.12.2015) +// Tip vprasanja = 26 + +// GEOCODING + +/** + * pretvorba iz latitude, longitude v berljiv naslov + * funkcija vrne String - results[0] - prvi (najdaljsi naslov) + * @param {type} pos - koordinate - objekt {lat: ???, lng: ???} + * @param {type} callback - function - ker je geocode asinhrona funkcija, se uporabi, da se vrne rezultat + * @returns {undefined} + */ +function GeocodingF(pos, callback) { + geocoder.geocode({'location': pos}, function (results, status) { + + // ce je status OK - pridobil informacije o naslovu + if (status === google.maps.GeocoderStatus.OK) { + //console.log(results);//[0]= polni naslov, [1]= Ljubljana, Slovenija,.... + if (results[0]) { + //console.log(results[0].formatted_address); + //vrne rezultat (Objekt s polnim naslovom) + callback(results[0]); + } else { + console.log('No results found'); + callback(null); + } + } + // ce je prislo do napake + else { + console.log('Geocoder failed due to: ' + status); + if(status == 'ZERO_RESULTS'){ + var obj = {formatted_address: ""} + callback(obj); + } + else + callback(null); + } + }); +} + +/** + * centriranje na zemljevidu (kaj se bo prikazalo na zemljevidu / zajelo v okvir) + * @param {type} centerInMap - String - naslov, ki ga naj zemljevid zajame v okvir + * @param {type} map - mapa/zemljevid + * @returns {undefined} + */ +function centrirajMap (centerInMap, map){ + geocoderFromAddress(centerInMap, function(place){ + if(place){ + map.setCenter(place.geometry.location); + map.fitBounds(place.geometry.viewport); + //povecaj zoom za 1, ker google naredi prevec oddaljeno + //pri vecji povrsini na mapi (npr Slovenija), ne dela ok + //map.setZoom(map.getZoom()+1); + } + }); +} + +/** + * Geocoding from address to places, in callback only first place is returned + * @param {type} address - address to geocode + * @param {type} callback - callback function to call when place is found + * @returns {undefined} + */ +function geocoderFromAddress(address, callback){ + var delay = 100; + var stej_poizvedbe = 0; + + geocoder.geocode({'address': address}, function (results, status) { + if (status === google.maps.GeocoderStatus.OK) { + callback(results[0]); + } + //zelo redko pride do tega, recimo ce uporabnik na polno stanca lokacije + else if(status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT){ + if(stej_poizvedbe < 10){ + setTimeout(geocoderFromAddress(address, callback), delay); + stej_poizvedbe++; + delay += 100; + } + else + console.log('Geocoder error: OVER_QUERY_LIMIT; repeated: '+stej_poizvedbe); + } + //ce ni najdenih rezultatov za vpisan naslov v nastavitvah (fokus) + else if(status === google.maps.GeocoderStatus.ZERO_RESULTS){ + alert(lang['srv_branching_no_results_geo_map']+': '+address); + } + else + console.log('Geocoder error: ' + status); + + return null; + }); +} \ No newline at end of file diff --git a/main/survey/js/Maps/KlikNaMapo.js b/main/survey/js/Maps/KlikNaMapo.js new file mode 100644 index 0000000..4effd1e --- /dev/null +++ b/main/survey/js/Maps/KlikNaMapo.js @@ -0,0 +1,43 @@ +// Author: Uroš Podkrižnik (17.12.2015) +// Tip vprasanja = 26 + +// KLIK NA MAPO + +/** + * izvrsi funkcionalnost za klik na zemljevid + * @param {type} spremenljivka - int - id spremenljivke + * @returns {undefined} + */ +function klikNaMapo(spremenljivka) { + //pridobi mapo spremenljivke + var map = document.getElementById("map_"+spremenljivka).gMap; + + // ko user klikne na mapo, funkcija vrne pozicijo (koordinate - position) ter kreira + google.maps.event.addListener(map, 'click', function (event) { + + //koordinate + var pos = { + lat: event.latLng.lat(), + lng: event.latLng.lng() + }; + + //za omejitev odgovorov + if(ml_sprem.indexOf(spremenljivka) > -1 || max_mark[spremenljivka] != st_markerjev[spremenljivka]){ + // naslov se pridobi, da se klice geocoding + GeocodingF(pos, function (data) { + //ce ne vrne null - je nasel naslov + if (data != null) { + + //kreira marker na lokaciji, kjer je uporabnik kliknil + createMarker(spremenljivka, data.formatted_address, pos, false); + + } else { + //odpre se okno, ce je prislo do napake - null - (mozen je tudi prekratek delay med geocoding requesti) + alert(lang['srv_resevanje_alert_location_not_found_map']); + } + }); + } + + return pos; + }); +} \ No newline at end of file diff --git a/main/survey/js/Maps/MapDeclaration.js b/main/survey/js/Maps/MapDeclaration.js new file mode 100644 index 0000000..7ca8a7f --- /dev/null +++ b/main/survey/js/Maps/MapDeclaration.js @@ -0,0 +1,323 @@ +// Author: Uroš Podkrižnik (1.7.2016) +// Tip vprasanja = 26 + +//DECLARATION + +//GLOBALNE SPREMENLJIVKE ZA VSE SPREMENLJIVKE TIP 26 NA ENI STRANI +//mej/okvira prikaza na zemljevidu objekt za vsako spremenljivko +var bounds = {}, + //objekt stevila vseh markerjev za vsako spremenljivk posebej + st_markerjev = {}, + //object of number of shapes and ID of last shape for every variable ({spr_id: {'count': 5, 'last_id': 9}, ...}) + //'last_id' is not fully reliable as it is used for shapes colours + // -> to make it reliable, method must be creaed to store all id's and removing last id at shame removal + st_shapes = {}, + //infowindow iz API-ja, za prikaz markerja in informacije o markerju + infowindow, + //array id-jev spremenljivk, ki so tipa moja lokacija (max 1 marker) + ml_sprem = [], + //array id-jev spremenljivk, ki imajo F user location + usrLoc_sprem = [], + geocoder, + //ce je true, se do skript dostopa iz podatkov, analiz + //v primeru, ko se gre za resevanje mora vedno biti false + viewMode = false, + //objekt id spremenljivka : boolean, kjer je true, ce spremenljivka + //uporablja F z podvprasanjem v infowindow markerja + podvprasanje = {}, + //objekt id spremenljivka : string, kjer je naslov podvprasanja, ce + //uporablja F z podvprasanjem v infowindow markerja + podvprasanje_naslov = {}, + //objekt id spremenljivka : int, kjer je int stevilo max + //dovoljenih markerjev na mapi + max_mark = {}, + //objekt vseh markerjev na strani (respondetn ali branching) {spr_id:[markers array]} + allMarkers = {}, + //objekt id spremenljivka : marker + //potrebujejo ga samo spremenljivke tipa moja lokacija (max 1 marker) + //uporablja se za brisanje prejsnjega markerja na mapi + mlmarker = {}, + //colors for shapes - polylines and polgons + mapShapeColors = ['c0504d', '4f81bd', '9bbb59', '8064a2', '4bacc6', 'f79646', '92a9cf', '8c0000', 'f00800', 'ff8a82', 'f2c4c8', '0b0387', '0400fc', '9794f2'], + deleteMenu; + +function mapsAPIseNi(MapDeclaration) { + //prveri, ce je element skripte APIja ze kreiran + var google_api = document.getElementById("google_api"); + //ce je ze kreiran, dodaj funkcijo v onload (da se mapa kreira, ko se api dokoncno naloada) + if (google_api) { + //element z apijem ze obstaja, se pravi da se se loada + //deklariraj funkcijo za onload + var addFunctionOnLoad = function (callback) { + if (google_api.addEventListener) { + google_api.addEventListener('load', callback, false); + } else { + google_api.attachEvent('onload', callback); + } + }; + //dodaj funkcijo v onload + addFunctionOnLoad(MapDeclaration); + } + //ce element skripte za API se ne obstaja, jo nalozi + else + loadGoogleMapsScript(function () { + MapDeclaration(); + initializeDeleteMenu(); + }); +} + +//includaj oz. nalozi skripno google APIja ter nastavi mapo +function loadGoogleMapsScript(callback) +{ + // Adding the script tag to the head as suggested before + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.id = 'google_api'; + script.src = "https://maps.googleapis.com/maps/api/js?key="+google_maps_API_key+"&libraries=places,drawing"; + + // Then bind the event to the callback function. + // There are several events for cross browser compatibility. + script.onreadystatechange = callback; + script.onload = callback; + + // Fire the loading + head.appendChild(script); +} + +/** + * Used for clearing a map of polyline or polygon + * @param {type} controlDiv - div to put in custom settings - buttons + * @returns {div element} element of a control + */ +function drawingControl(controlDiv) { + + controlDiv.style.padding = '10px'; + + // Set CSS for the control border. + var controlUI = document.createElement('div'); + controlUI.style.backgroundColor = '#fff'; + controlUI.style.border = '2px solid #fff'; + controlUI.style.borderRadius = '3px'; + controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)'; + controlUI.style.cursor = 'pointer'; + controlUI.style.marginBottom = '22px'; + controlUI.style.textAlign = 'center'; + controlUI.style.display = 'inline-block'; + controlUI.title = lang['srv_vprasanje_button_map_clear']; + controlDiv.appendChild(controlUI); + + // Set CSS for the control interior. + var controlText = document.createElement('div'); + controlText.style.color = 'rgb(25,25,25)'; + controlText.style.fontFamily = 'Roboto,Arial,sans-serif'; + controlText.style.fontSize = '16px'; + controlText.style.lineHeight = '28px'; + controlText.style.paddingLeft = '5px'; + controlText.style.paddingRight = '5px'; + controlText.innerHTML = lang['srv_vprasanje_button_map_clear']; + controlUI.appendChild(controlText); + + return controlUI; +} + +/** + * create bounds of all points of polygon/polyline + * @param {type} path gon.getPath() + * @param {int} spremenljivka - id spremenljivke + */ +function createBoundsFromPath(path, spremenljivka) { + var pathArray = path.getArray(); + for (var i = 0, n = pathArray.length; i < n; i++) { + var latLng = pathArray[i]; + bounds[spremenljivka].extend(latLng); + } +} + +//pretvori lat in lng v en string +//uporabi se kot kljuc markerja za ID iz objekta markers +function getMarkerUniqueId(lat, lng, spr) { + var zdot = spr + '_' + lat + '_' + lng; + return zdot.split('.').join("-"); +} + +/** + * Find out if marker already exist on this variable whit this address + * @param {type} add - address to find if exist at some marker + * @param {type} spr - variable id + * @returns {type} - marker if exist, null otherwise + */ +function findMarkerFromAddress(add, spr) { + for (var i = 0; i < allMarkers[spr].length; i++) { + if (allMarkers[spr][i].address === add) + return allMarkers[spr][i]; + } + return null; +} + +////////////BRISANJE TOCK +function initializeDeleteMenu() { + /** + * A menu that lets a user delete a selected vertex of a path. + * @constructor + */ + function DeleteMenu() { + this.div_ = document.createElement('div'); + this.div_.className = 'maps-delete-menu'; + this.div_.innerHTML = lang['srv_vprasanje_delete_point_map']; + + var menu = this; + google.maps.event.addDomListener(this.div_, 'click', function (e) { + //this prevents to trigger click event on map (klikNaMapo.js) + e.cancelBubble = true; + if (e.stopPropagation) e.stopPropagation(); + + //remove whole shape + if(menu.get('shape') && menu.get('vertex') == undefined && menu.get('marker') == undefined) + menu.removeShape(); + //remove vertex in shape or marker + else + menu.removeVertex(); + }); + } + DeleteMenu.prototype = new google.maps.OverlayView(); + + DeleteMenu.prototype.onAdd = function () { + var deleteMenu = this; + var map = this.getMap(); + this.getPanes().floatPane.appendChild(this.div_); + + // mousedown anywhere on the map except on the menu div will close the + // menu. + this.divListener_ = google.maps.event.addDomListener(map.getDiv(), 'mousedown', function (e) { + if (e.target != deleteMenu.div_) { + deleteMenu.close(); + } + }, true); + }; + + DeleteMenu.prototype.onRemove = function () { + google.maps.event.removeListener(this.divListener_); + this.div_.parentNode.removeChild(this.div_); + + // clean up + this.set('position'); + this.set('shape'); + this.set('vertex'); + this.set('spremenljivka'); + this.set('DrawingControl'); + this.set('drawingManager'); + this.set('marker'); + this.set('markerId'); + }; + + DeleteMenu.prototype.close = function () { + this.setMap(null); + }; + + DeleteMenu.prototype.draw = function () { + var position = this.get('position'); + var projection = this.getProjection(); + + if (!position || !projection) { + return; + } + + var point = projection.fromLatLngToDivPixel(position); + this.div_.style.top = point.y + 'px'; + this.div_.style.left = point.x + 'px'; + }; + + /** + * Opens the menu at a vertex of a given path. + */ + DeleteMenu.prototype.open = function (map, shape, vertex, spremenljivka, DrawingControl, drawingManager, marker, markerId) { + if(shape) + this.set('position', shape.getPath().getAt(vertex)); + else if(marker) + this.set('position', marker.getPosition()); + + this.set('shape', shape); + this.set('vertex', vertex); + this.set('spremenljivka', spremenljivka); + this.set('DrawingControl', DrawingControl); + this.set('drawingManager', drawingManager); + this.set('marker', marker); + this.set('markerId', markerId); + this.setMap(map); + this.draw(); + }; + + /** + * Opens the menu at a geofence. + */ + DeleteMenu.prototype.open_shape = function (map, shape, position, spremenljivka) { + this.set('position', position); + this.set('shape', shape); + this.set('spremenljivka', spremenljivka); + this.setMap(map); + this.draw(); + }; + + /** + * Deletes the vertex from the path. + */ + DeleteMenu.prototype.removeVertex = function () { + var spremenljivka = this.get('spremenljivka'); + //shape + var shape = this.get('shape'); + var vertex = this.get('vertex'); + var DrawingControl = this.get('DrawingControl'); + var drawingManager = this.get('drawingManager'); + //marker + var marker = this.get('marker'); + var markerId = this.get('markerId'); + + if ((!shape || vertex == undefined) && !marker) { + this.close(); + return; + } + + //removing marker + if(marker){ + //accessed from respondent + if(markerId) + removeMarker(spremenljivka, marker, markerId); + //accessed from admin + else + removeMarkerVM(spremenljivka, marker); + } + //removing shape + else if(shape){ + shape.getPath().removeAt(vertex); + + if (shape.getPath().length < 2) { + //accessed from respondent + if(DrawingControl != null && drawingManager != null) + //handle visibility of tools + clearAndMakeDrawableAgain(spremenljivka, shape, DrawingControl, drawingManager); + //accessed from admin + else + //remove shape from DB + deleteLineInDB(spremenljivka, shape); + } + } + this.close(); + }; + + /** + * Deletes the whole shape. + */ + DeleteMenu.prototype.removeShape = function () { + //shape + var shape = this.get('shape'); + + //removing shape from DB and map + if(shape){ + maza_delete_geofence(shape); + } + this.close(); + }; + + deleteMenu = new DeleteMenu(); +} \ No newline at end of file diff --git a/main/survey/js/Maps/Markers.js b/main/survey/js/Maps/Markers.js new file mode 100644 index 0000000..cb37863 --- /dev/null +++ b/main/survey/js/Maps/Markers.js @@ -0,0 +1,317 @@ +// Author: Uroš Podkrižnik (17.12.2015) +// Tip vprasanja = 26 + +//MARKERS + +/** + * Ce obstajajo podatki v bazi (rec. uporabnik klikne 'Prejsnja stran'). + * Kreirajo se markerji, shranjeni v bazi. + * @param spremenljivka int id spremenljivke + * @param map_data JSON Object + * @param podtip int - podtip/enota - 1-mojalokacija, 2-multilokacija, 3-chooselokacija + */ +function map_data_fill(spremenljivka, map_data, podtip) { + for (var row in map_data) { + var row_object = map_data[row]; + var pos = {lat: row_object.lat, lng: row_object.lng}; + //kreiraj marker + createMarker(spremenljivka, row_object.address, pos, false, row_object.text, podtip, row_object.naslov, row_object.vre_id); + } +} + +/** + * funkcija, ki kreira osnovni marker (rdec) + * @param {type} spremenljivka - int - id spremenljivke + * @param {type} add - String - label o informacijah markerja + * @param {type} pos - koordinate - objekt {lat: ???, lng: ???} + * @param {boolean} fromSearchBox - true if called from searchBox, false otherwise (used to avoid duplicates) + * @param {type} text - string - text za windowinfo textarea + * @param {type} podtip - int - podtip/enota - 1-mojalokacija, 2-multilokacija, 3-chooselokacija + * @param {type} naslov - string - title of marker + * @param {type} vre_id - int - id of vrednost + * @returns {undefined} + */ +function createMarker(spremenljivka, add, pos, fromSearchBox, text, podtip, naslov, vre_id) { + //in case, we are creating marker from searchbox, check if marker with this address already exist + //if yes, do not create marker and focus on marker with this address, if not, create marker + var marker = fromSearchBox ? findMarkerFromAddress(add, spremenljivka) : null; + + if (!marker) { + //pridobi mapo spremenljivke + var map; + if (document.getElementById("map_" + spremenljivka)) + map = document.getElementById("map_" + spremenljivka).gMap; + else + map = document.getElementById("map_canvas_all").gMap; + + //pridobi ID markerja + var markerId = ((podtip == 3) && vre_id) ? vre_id : getMarkerUniqueId(pos.lat, pos.lng, spremenljivka); + + //ce ze obstaja marker s tocno takim ID (iste koordinate), ignoriraj + //do te situacije pride (da je spodaj false) lahko samo tako, da v + //searchbox uporabnik dvakrat vpise isto lokacijo in jo markira -podvajanje podatkov + if ($('#' + markerId).length == 0) { + + var path_img_dir = srv_site_url + 'admin/survey/img_0/'; + + var icon = { + fillColor: '#FF5555', + url: path_img_dir + (podvprasanje[spremenljivka] ? 'marker_text_off.png' : + 'marker_default.svg'), + fillOpacity: 1, + strokeWeight: 1 + } + + var namapo = null; + //var soda = spremenljivka % 2 == 0; + + //v view mode naredimo clusters, pri resevanju pa jhi sproti filamo v mapo + if (!viewMode) + namapo = map; + else if(podtip == 3){ + namapo = map; + } + + //nastavitve markerja + var marker = new google.maps.Marker({ + position: new google.maps.LatLng(pos.lat, pos.lng), + id: 'marker_' + markerId, + map: namapo, + icon: icon, + address: add + }); + + + //store marker in markers array + allMarkers[spremenljivka].push(marker); + + //ce je tip moja lokacija + if (ml_sprem.indexOf(spremenljivka) > -1) { + //ce obstaja marker, ga izbrisi + if (mlmarker['' + spremenljivka]){ + removeMarker(spremenljivka, mlmarker['' + spremenljivka], markerId); + deleteAllMarkerInputs(spremenljivka); + } + //shrani marker v array, za kasnejsi iibris markerja iz mape pri mojilokaciji + mlmarker['' + spremenljivka] = marker; + } + + if (!viewMode) { + //ustvari input, ce ze ne obstaja ta id (tocno te koordinate) + createMarkerInput(spremenljivka, marker, markerId, text); + + if (podtip != 3) + //markers[markerId] = marker; // cache marker in markers object + bindMarkerEvents(spremenljivka, marker, markerId, map); // bind right click event to marker + } + + //Create a div element for container. + var container = document.createElement("div"); + + if (podtip == 3) { + if (naslov) { + //Create a label element for title. + var title = document.createElement("label"); + title.innerHTML = '' + naslov + '
'; + container.appendChild(title); + } + + //Create a label element for address. + var label = document.createElement("label"); + label.innerHTML = '' + add + '
' + (podvprasanje_naslov[spremenljivka] ? '
' : ''); + label.style.cssText = 'font-size:0.85em'; + container.appendChild(label); + } else { + //Create a label element for address. + var label = document.createElement("label"); + label.innerHTML = viewMode ? '' + add + '
' : add + '
'; + container.appendChild(label); + } + + //naredi textbox, ce je nastavljeno podvprasanje + if (podvprasanje[spremenljivka]) { + //Create a label element for subquestion title + if (podvprasanje_naslov[spremenljivka]) { + var podvprasanje_title = document.createElement("label"); + podvprasanje_title.innerHTML = viewMode ? podvprasanje_naslov[spremenljivka] + '
' : + '' + podvprasanje_naslov[spremenljivka] + '
'; + container.appendChild(podvprasanje_title); + } + + if (!viewMode) { + //Create a textarea for the input text + var textBox = document.createElement("textarea"); + textBox.setAttribute("id", markerId + "_textarea"); + textBox.style.width = "100%"; + textBox.id = markerId + "_textarea_id"; + textBox.className = "boxsizingBorder"; + textBox.style.height = "50px"; + } else { + //Create a label for respondent text response + var textBox = document.createElement("label"); + } + //ce obstaja text, ga vstavi v textarea + if (text && (text != '-2' && text != '-4' && text != '-1')) { + textBox.innerHTML = viewMode ? '' + text + '' : text; + marker.setIcon({url: path_img_dir + 'marker_text_on.png'}); + } + + container.appendChild(textBox); + + if (!viewMode) { + //ko se spremeni textarea v windowinfo, spremeni value inputa za text + google.maps.event.addDomListener(textBox, "input", function () { + document.getElementById(markerId + '_text').value = textBox.value; + if (textBox.value) + marker.setIcon({url: path_img_dir + 'marker_text_on.png'}); + else + marker.setIcon({url: path_img_dir + 'marker_text_off.png'}); + }); + } + } + + //if "choose location" in view mode, declare own infowindow for each marker and open in + //otherwise use global variable infowindow + var infowin = (podtip == 3 && viewMode) ? new google.maps.InfoWindow() : infowindow; + + //listener ob kliku na marker - focus input mora biti po nastavljanju bounds ali zoom + google.maps.event.addListener(marker, 'click', function () { + infowin.setContent(container); + infowin.open(map, marker); + //focus on input + $("#" + markerId + "_textarea_id").focus(); + }); + + //nastavi label + infowin.setContent(container); + //odpre marker - prikaze label (kot da bi ga kliknil) + infowin.open(map, marker); + + if (ml_sprem.indexOf(spremenljivka) == -1) + //v okvir se doda nov marker + bounds[spremenljivka].extend(marker.position); + + //ce je samo eden marker, ga malo odzoomaj + if (ml_sprem.indexOf(spremenljivka) > -1 || (st_markerjev[spremenljivka] == 0) && viewMode) { + map.setCenter(marker.position); + map.setZoom(17); + } else if (st_markerjev[spremenljivka] > 0) { + //zemljevid se prilagodi okviru + map.fitBounds(bounds[spremenljivka]); + + //ce ni v viewMode - je v resevanju ankete - se za vsak marker odzooma + /*if(!viewMode && podtip != 3){ + //zmanjsaj zoom za 1, ker google naredi prevec oddaljeno + google.maps.event.addListenerOnce(map, "bounds_changed", function() { + map.setZoom(map.getZoom()-1); + }); + }*/ + //ce je v viewMode - v podatkih ali analizah - se odzooma za 1 samo pri zadnjem markerju + if (viewMode && max_mark[spremenljivka] == st_markerjev[spremenljivka] + 1) { + //zmanjsaj zoom za 1, ker google naredi prevec oddaljeno + google.maps.event.addListenerOnce(map, "bounds_changed", function () { + map.setZoom(map.getZoom() - 1); + }); + } + } + + //stevilo markerjev se poveca + st_markerjev[spremenljivka]++; + + //odstej od dovoljenih za opozorilo + if (ml_sprem.indexOf(spremenljivka) == -1 && !viewMode && max_mark[spremenljivka] == st_markerjev[spremenljivka]) + $('#max_marker_' + spremenljivka).show(); + + //focus on input - must be after setting bounds or zooming + $("#" + markerId + "_textarea_id").focus(); + } + } else { + //trigger click on marker, to focus it and open infowindow + google.maps.event.trigger(marker, 'click'); + } +} + +/** + * handler za desni klik in dvojni klik na markerja + * @param {type} spremenljivka - int - id spremenljivke + * @param {type} marker + * @param {type} markerId + * @param {type} map - google map + */ +function bindMarkerEvents(spremenljivka, marker, markerId, map) { + google.maps.event.addListener(marker, "rightclick", function () { + //removeMarker(spremenljivka, marker, markerId); // remove marker from array + deleteMenu.open(map, null, null, spremenljivka, null, null, marker, markerId); + $('#max_marker_' + spremenljivka).hide(); + }); + google.maps.event.addListener(marker, "dblclick", function () { + //removeMarker(spremenljivka, marker, markerId); // remove marker from array + deleteMenu.open(map, null, null, spremenljivka, null, null, marker, markerId); + $('#max_marker_' + spremenljivka).hide(); + }); +} + +/** + * brise marker iz zemljevida + * @param {type} spremenljivka - int - id spremenljivke + * @param {type} marker + * @param {type} markerId + */ +function removeMarker(spremenljivka, marker, markerId) { + marker.setMap(null); // set markers setMap to null to remove it from map + //remove marker from marker array + var index = allMarkers[spremenljivka].indexOf(marker); + if (index > -1) + allMarkers[spremenljivka].splice(index, 1); + //stevilo markerjev se zmanjsa + st_markerjev[spremenljivka]--; + + deleteMarkerInput(markerId); //remove input of marker fro form +} + +/** + * kreira hidden inpute s podatki markerja + * @param {type} spremenljivka - int - id spremenljivke + * @param {type} marker + * @param {type} markerId - id markerja + * @param {type} text - text za textarea v windowinfo + * @returns {undefined} + */ +function createMarkerInput(spremenljivka, marker, markerId, text) { + //najdi element za drzanje variabel + var $variable_holder = $("#spremenljivka_" + spremenljivka + "_variabla"); + + //kreiraj input s statičnimi podatki markerja + var $markerInput = $("", {id: markerId, name: "vrednost_" + spremenljivka + "[]", + type: "hidden", class: "marker_input", + value: markerId + "|" + marker.getPosition().lat() + "|" + + marker.getPosition().lng() + "|" + marker.address}); + $variable_holder.append($markerInput); + + if (podvprasanje[spremenljivka]) { + //kreiraj input s textom - textarea v infowindow + var $textareaInput = $("", {id: markerId + '_text', name: markerId + '_text', + type: "hidden", value: text, class: "marker_input"}); + $variable_holder.append($textareaInput); + } +} + +/** + * brise inpute s podatki markerja + * @param {type} markerId - id markerja + */ +function deleteMarkerInput(markerId) { + //brisi input s staticnimi podatki markerja + $('#' + markerId).remove(); + //brisi input s textom markerja v windowinfo + $('#' + markerId + '_text').remove(); +} + +/** + * brise vse inpute mape (vse markerje) + * @param {type} spremenljivka - int - id spremenljivke + */ +function deleteAllMarkerInputs(spremenljivka) { + //brisi vse inpute s staticnimi podatki markerja + $('#spremenljivka_' + spremenljivka + '_variabla').find('input.marker_input').remove(); +} \ No newline at end of file diff --git a/main/survey/js/Maps/SearchBox.js b/main/survey/js/Maps/SearchBox.js new file mode 100644 index 0000000..e71b6ea --- /dev/null +++ b/main/survey/js/Maps/SearchBox.js @@ -0,0 +1,78 @@ +// Author: Uroš Podkrižnik (25.6.2016) +// Tip vprasanja = 26 + +// SEARCH BOX + +/** + * Skripta, ki ustvari in nastavi iskalno polje za zemljevid + * @param {type} spremenljivka - int - id spremenljivke + * @returns {undefined} + */ +function searchBox(spremenljivka, doOnPlacesChanged){ + //pridobi mapo spremenljivke + var map; + if(document.getElementById("map_"+spremenljivka)) + map = document.getElementById("map_"+spremenljivka).gMap; + else if(document.getElementById("br_map_"+spremenljivka)){ + map = document.getElementById("br_map_"+spremenljivka).gMap; + } + else{ + map = document.getElementById("maza_map_geofencing").gMap; + } + + // Create the search box and link it to the UI element. + var input = document.getElementById('pac-input_'+spremenljivka); + input.style.display='inline-block'; + var searchBox = new google.maps.places.SearchBox(input); + map.controls[google.maps.ControlPosition.TOP_LEFT].push(input); + + // Bias the SearchBox results towards current map's viewport. + map.addListener('bounds_changed', function() { + searchBox.setBounds(map.getBounds()); + }); + + // Listen for the event fired when the user selects a prediction and retrieve + // more details for that place. + searchBox.addListener('places_changed', function() { + var places = searchBox.getPlaces(); + + if (places.length == 0) + return; + + //first place has data of geometry + if(places[0].geometry){ + //pozicija v latitude in longitude, ki jo najde + var pos = { + lat: places[0].geometry.location.lat(), + lng: places[0].geometry.location.lng() + }; + + doOnPlacesChanged(pos, places[0].formatted_address); + } + //first place does not have data of geometry, do a geocoding from adress + else{ + findPlace(places[0].name, function(pos, formatted_address){ + doOnPlacesChanged(pos, formatted_address); + }); + } + }); +} + +/** + * Find place from addres + * @param {type} address - address to geocode + * @param {type} doAfterPlaceFound - callback function to call when place is found + * @returns {undefined} + */ +function findPlace (address, doAfterPlaceFound){ + geocoderFromAddress(address, function(place){ + if(place){ + var pos = { + lat: place.geometry.location.lat(), + lng: place.geometry.location.lng() + }; + + doAfterPlaceFound(pos, place.formatted_address); + } + }); +} diff --git a/main/survey/js/Maps/ShapeDrawing.js b/main/survey/js/Maps/ShapeDrawing.js new file mode 100644 index 0000000..8495671 --- /dev/null +++ b/main/survey/js/Maps/ShapeDrawing.js @@ -0,0 +1,397 @@ +// Author: Uroš Podkrižnik (24.1.2017) +// Tip vprasanja = 26 + +//DRAWING POLYLINE + +/** + * Function to set parameters for drawing a shape on map + * + * @param {type} spremenljivka - id spremenljivke + * @param {google's shape} shape - polyline or polygon if already exists + * @param shape_type - string - type of shape 'polyline' or 'polygon' + * @returns {undefined} + */ +function drawShape(spremenljivka, shape, shape_type) { + var map = document.getElementById("map_"+spremenljivka).gMap; + + var drawingMode = (shape_type === 'polyline') ? + google.maps.drawing.OverlayType.POLYLINE : google.maps.drawing.OverlayType.POLYGON; + var startDrawingMode = shape!==null ? null : drawingMode; + var shapeOptions = (shape_type === 'polyline') ? polylineOptions() : polygonOptions(); + + var drawingManager = new google.maps.drawing.DrawingManager({ + drawingMode: startDrawingMode, + drawingControl: shape===null, + drawingControlOptions: { + position: google.maps.ControlPosition.TOP_RIGHT, + drawingModes: [shape_type] + }, + polylineOptions: shapeOptions, + polygonOptions: shapeOptions + }); + + //settings for custom drawing controls + var drawingControlDiv = document.createElement('div'); + var DrawingControl = new drawingControl(drawingControlDiv, map, spremenljivka); + drawingControlDiv.index = 1; + map.controls[google.maps.ControlPosition.TOP_RIGHT].push(drawingControlDiv); + //at start, there is no shape, so no need to show delete button + DrawingControl.style.display = (shape!==null && !viewMode) ? 'inline-block' : 'none'; + + if(shape!==null){ + shape.type = shape_type; + createBoundsFromPath( shape.getPath() , spremenljivka ); + map.fitBounds(bounds[spremenljivka]); + afterShapeCompleteSettings(drawingManager, DrawingControl, shape, spremenljivka, map); + } + + //listener when user colpetes shape + google.maps.event.addListener(drawingManager, shape_type+'complete', function(shape) { + shape.type = shape_type; + afterShapeCompleteSettings(drawingManager, DrawingControl, shape, spremenljivka, map); + }); + + drawingManager.setMap(map); +} + +/** + * Sets all kind of settings after shape is complete + * + * @param {type} drawingManager - google's drawingManager + * @param {type} DrawingControl - button for removing a shape + * @param {google's shape} shape - polyline or polygon if already exists + * @param {type} spremenljivka - id spremenljivke + * @param {type} map - google map on which we are drawing shape + * @returns {undefined} + */ +function afterShapeCompleteSettings(drawingManager, DrawingControl, shape, spremenljivka, map){ + //hide controls + drawingManager.setOptions({ + drawingControl: false + }); + //stop drawing + drawingManager.setDrawingMode(null); + //show delete button + DrawingControl.style.display = 'inline-block'; + + // Setup the click event listener for delete button + DrawingControl.addEventListener('click', function() { + clearAndMakeDrawableAgain(spremenljivka, shape, DrawingControl, drawingManager); + }); + + shapeInputHandler(shape, spremenljivka); + + //hide warning info for ending a shape + var end_info_warning = document.getElementById("end_shape_info_"+spremenljivka); + end_info_warning.style.display = "none"; + + /** + * Liteners when editing a shape + */ + //when editing end or start point + google.maps.event.addListener(shape.getPath(), 'set_at', function(index, obj) { + shapeInputHandler(shape, spremenljivka); + }); + //when inserting new point (break old one) + google.maps.event.addListener(shape.getPath(), 'insert_at', function(index, obj) { + shapeInputHandler(shape, spremenljivka); + }); + //when deleting a point -> undo + google.maps.event.addListener(shape.getPath(), 'remove_at', function(index, obj) { + shapeInputHandler(shape, spremenljivka); + }); + + setDeleteMenu(shape, map, spremenljivka, DrawingControl, drawingManager) +} + +/** + * Sets rightclick and dblclick listeners to open delete menu + * @param {type} shape - shape to set listeners on + * @param {type} map - map on which to hover menu (shape's map) + * @param {type} spremenljivka - id of variable + * @param {type} drawingManager - google's drawingManager + * @param {type} DrawingControl - button for removing a shape + * @returns {undefined} + */ +function setDeleteMenu(shape, map, spremenljivka, DrawingControl, drawingManager) { + google.maps.event.addListener(shape, 'rightclick', function (e) { + // Check if click was on a vertex control point + if (e.vertex == undefined) { + return; + } + //removeVertexVM(spremenljivka, shape, e.vertex); + deleteMenu.open(map, shape, e.vertex, spremenljivka, DrawingControl, drawingManager); + }); + google.maps.event.addListener(shape, 'dblclick', function (e) { + // Check if click was on a vertex control point + if (e.vertex == undefined) { + return; + } + //removeVertexVM(spremenljivka, shape, e.vertex); + deleteMenu.open(map, shape, e.vertex, spremenljivka, DrawingControl, drawingManager); + }); +} + +/** + * Ce obstajajo podatki v bazi izrisi info shapes + * Kreirajo se markerji, shranjeni v bazi. + * @param spremenljivka int id spremenljivke + * @param map_data JSON Object + */ +function map_data_fill_info_shapes(spremenljivka, map_data) { + //because of viewing a filled survey at data section + var fillMode = (document.getElementById("map_"+spremenljivka) !== null); + + //pridobi mapo spremenljivke + var map; + if(fillMode) + map = document.getElementById("map_"+spremenljivka).gMap; + else + map = document.getElementById("map_canvas_all").gMap; + + + var shapeOption = polylineOptions(map); + + for (var i=0; i'; + container.appendChild(Title); + + shape.ifnowin = container; + shape.address = map_data[i].address; + var infow = new google.maps.InfoWindow(); + + google.maps.event.addListener(shape, 'mouseover', function(ev) { + this.setOptions({strokeWeight: 6, zIndex: 2}); + //open infowindow if title exists + if(this.address){ + infow.setContent(this.ifnowin); + infow.setPosition(ev.latLng); + infow.open(map); + } + }); + google.maps.event.addListener(shape, 'mouseout', function() { + this.setOptions({strokeWeight: 4, zIndex: 1}); + infow.close(); + }); + } +} + +/** + * Clears the map, deletes all inputs, hides "Clear" button and sets drawing mode on + * @param {type} spremenljivka - id spremenljivke + * @param {google's shape} shape - polyline or polygon + * @param {type} drawingManager - google's drawingManager + * @param {type} DrawingControl - button for removing a shape + * @returns {undefined} + */ +function clearAndMakeDrawableAgain(spremenljivka, shape, DrawingControl, drawingManager){ + //remove shape + shape.setMap(null); + //remove all hidden inputs of a shape + deleteAllShapeInputs(spremenljivka); + //hide delete button + DrawingControl.style.display = 'none'; + //show drawing controls + drawingManager.setOptions({ + drawingControl: true + }); + + //start drawing + drawingManager.setDrawingMode(shape.type); + + //show warning info for ending a shape + var end_info_warning = document.getElementById("end_shape_info_"+spremenljivka); + end_info_warning.style.display = "inline-block"; +} + +/** + * Removes a vertex/point of shape and if it after last it clears the map + * and sets drawing mode on again + * @param {type} spremenljivka - id spremenljivke + * @param {google's shape} shape - polyline or polygon if already exists + * @param {type} vertex - vertex or point which was selected + * @param {type} drawingManager - google's drawingManager + * @param {type} DrawingControl - button for removing a shape + * @returns {undefined} + */ +/*function removeVertex(spremenljivka, shape, vertex, DrawingControl, drawingManager) { + if (!shape || vertex == undefined) + return; + + shape.getPath().removeAt(vertex); + + if(shape.getPath().length < 2){ + clearAndMakeDrawableAgain(spremenljivka, shape, DrawingControl, drawingManager); + } +}*/ + +/** + * Handle hidden input - remove old, create new + * @param {google's shape} shape - polyline or polygon + * @param {int} spremenljivka - id spremenljivke + * @returns {undefined} + */ +function shapeInputHandler(shape, spremenljivka){ + deleteAllShapeInputs(spremenljivka); + createAllShapeInputs( shape.getPath(), spremenljivka ); +} + +/** + * create hidden inputs of all points of shape + * @param {type} path shape.getPath() + * @param {int} spremenljivka - id spremenljivke + */ +function createAllShapeInputs( path , spremenljivka ) { + var pathArray = path.getArray(); + for( var i = 0, n = pathArray.length; i < n; i++ ) { + var latLng = pathArray[i]; + createShapeInput(spremenljivka, { lat: latLng.lat(), lng: latLng.lng() }, i+1); + } +} + +/** + * create hidden input of shape data + * @param {type} spremenljivka - int - id spremenljivke + * @param {type} vertices - array of lat and lng + * @param {type} index - order of point + * @returns {undefined} + */ +function createShapeInput(spremenljivka, vertices, index) { + //najdi element za drzanje variabel + var $variable_holder = $("#spremenljivka_" + spremenljivka + "_variabla"); + + //kreiraj input s statičnimi podatki markerja + var $shapeInput = $("", {name: "vrednost_" + spremenljivka + "[]", + type: "hidden", class: "shape_input", + value: index + "|" + vertices.lat + "|" + vertices.lng}); + $variable_holder.append($shapeInput); +} + +/** + * delete all hidden inputs of shape + * @param {type} spremenljivka - id spremenljivke + */ +function deleteAllShapeInputs(spremenljivka) { + //brisi vse inpute s staticnimi podatki shape + $('#spremenljivka_' + spremenljivka + '_variabla').find('input.shape_input').remove(); +} + +/** + * Ce obstajajo podatki v bazi (rec. uporabnik klikne 'Prejsnja stran'). + * Kreira se shape, shranjena v bazi. + * @param spremenljivka int id spremenljivke + * @param map_data JSON Object + * @param shape_type - string - type of shape 'polyline' or 'polygon' + */ +function map_data_fill_shape(spremenljivka, map_data, shape_type){ + //because of viewing a filled survey at data section + var fillMode = (document.getElementById("map_"+spremenljivka) !== null); + + //pridobi mapo spremenljivke + var map; + if(fillMode) + map = document.getElementById("map_"+spremenljivka).gMap; + else + map = document.getElementById("map_canvas_all").gMap; + + var shapeOption = shape_type === 'polyline' ? polylineOptions(map) : polygonOptions(map); + + //for respondents, fill a map + if(fillMode){ + //set and show the shape + shapeOption.path = map_data; + var shape = shape_type === 'polyline' ? + new google.maps.Polyline(shapeOption) : new google.maps.Polygon(shapeOption); + + //alsways viewMode = false, except at insight into survey at data + //if not viewMode, create shape inputs and start drawing + if(!viewMode){ + //create hidden inputs of shape + createAllShapeInputs( shape.getPath() , spremenljivka ); + + //set all data for shape drawing + drawShape(spremenljivka, shape, shape_type); + } + //if viewMode, just create and fit bounds + else{ + //set bounds + createBoundsFromPath( shape.getPath() , spremenljivka ); + map.fitBounds(bounds[spremenljivka]); + } + } + //for admins, show shapes + else{ + var keys = Object.keys(map_data); + + for (var i=0; i -1 || max_mark[spremenljivka]-st_markerjev[spremenljivka] != 0){ + //pretvori iz koordinat v naslov in nastavi label v infowindow + GeocodingF(pos, function (data) { + //ce ne vrne null - je nasel naslov + if (data != null) { + //kreira marker na lokaciji + for (key in usrLoc_sprem) { + //Param fromSearchBox is true because of possible duplicate at multilocation with userloction ON, + //if user goes to previous page. + //In very rare occasions this may couse bad UX in case: + //user has clicked on location with address 'Undefined road', then userlocation returns + //address as 'Undefined road' - in this case, marker will not be created from userlocation. + createMarker(usrLoc_sprem[key], data.formatted_address, pos, true); + } + } else { + //odpre se okno, ce je prislo do napake - null - (mozen je tudi prekratek delay med geocoding requesti) + alert(lang['srv_resevanje_alert_location_not_found_map']); + } + }); + } +} \ No newline at end of file -- cgit v1.2.3