Leaflet-search on multiplelayers won't work - javascript

Hey guys i got some problems with searching multiplelayers in leaflet-search by Stefano Cudini. First i will explain my problem and add the complete code at the end.
I already tried this:
var barLayer= new L.geoJson(bar).addTo(map);
var attraktionenLayer= new L.geoJson(attraktionen).addTo(map);
L.control.search({
layer: L.layerGroup([barlayer, attraktionenlayer]),
initialize: false,
propertyName: 'name',
buildTip: function(text, val) {
var type = val.layer.feature.properties.amenity;
return ''+text+'<b>'+type+'</b>';
}
}).addTo(map);
I also tried to combine my layers before using L.control.search like this:
var poiLayers = L.layerGroup().addTo(map);
poiLayers.addLayer(barLayer);
poiLayers.addLayer(attraktionenLayer);
//also tried this in a single command like
var poiLayers = L.layerGroup([barLayer,attraktionenLayer]).addTo(map);
But everytime i try to search something i get the following error in console:
Uncaught TypeError: m.getLatLng is not a function
at leaflet-search.js:571
at eachLayer (leaflet.js:7)
at e.<anonymous> (leaflet-search.js:570)
at eachLayer (leaflet.js:7)
at e._recordsFromLayer (leaflet-search.js:522)
at e._fillRecordsCache (leaflet-search.js:715)
at leaflet-search.js:677
For single layers the search is working and also if i get the arrays from my FeatureCollections and concat them like this:
var barsarray = bar.features;
var restaurantsarray = attraktionen.features;
var poiarray = barsarray.concat(restaurantsarray);
var poiLayer = new L.geoJson(poiarray);
But with this workaround i get all my markers on the map twice and if i want to hide the single layers with L.control.layers the poilayer will always be shown.
Any suggestions?
Complete Codeexample:
<head>
<link rel="stylesheet" href="../src/leaflet.css" />
<link rel="stylesheet" href="../src/leaflet-search.css" />
<script src="../src/leaflet.js"></script>
<script src="../src/leaflet-search.js"></script>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<div id="map" style="width: 1600px; height: 400px;"></div>
<script src="../data/Bars.js"></script>
<script src="../data/Attraktionen.js"></script>
<script>
var map = L.map('map', {
zoom: 14,
center: new L.latLng(50.957703,6.967322),
layers: L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png')
});
var barLayer= new L.geoJson(bar).addTo(map);
var attraktionenLayer= new L.geoJson(attraktionen).addTo(map);
var barsarray = bar.features;
var restaurantsarray = attraktionen.features;
var poiarray = barsarray.concat(restaurantsarray);
var poiLayer = new L.geoJson(poiarray);
var poiLayers = L.layerGroup().addTo(map);
poiLayers.addLayer(barLayer);
poiLayers.addLayer(attraktionenLayer);
L.control.search({
layer: poiLayers,
initialize: false,
propertyName: 'name',
buildTip: function(text, val) {
var type = val.layer.feature.properties.amenity;
return ''+text+'<b>'+type+'</b>';
}
}).addTo(map);
var baseLayers = {
//"Bars": barsLayer,
//"Restaurants": restaurantsLayer
};
var overlays = {
"Bars": barLayer,
"Attraktionen": attraktionenLayer
};
L.control.layers(baseLayers, overlays).addTo(map);
</script>
</body>

Related

Global variable not accessible to ViewModel in KnockoutJS

I am working on a simple Google Maps app using the KnockoutJS library - or at least it seemed simple enough in concept.
After reading up on KnockoutJS and working out some examples, I put together the initial parts. The html so far is just the map, I aim to populate the list as soon as I get over the first hurdle. The hurdle is in the Javascript. Here is the code for reference:
"use strict";
var map;
var center;
var defaultBounds;
var placesServices;
//LocationObject created to hold data for locations generated from google.places.nearbySearch
var LocationObject = function(data){
this.position = data.geometry.location;
this.lat = data.geometry.location.lat;
this.lng = data.geometry.location.lng;
this.name = data.name;
this.placeID = data.place_id;
this.rating = data.rating;
this.types = data.types;
this.linkToPhoto = data.html_attributions;
};
function initMap(){
map = new google.maps.Map(document.getElementById('map'), {
center: center,
zoom: 17,
mapTypeId: 'satellite',
draggable: true,
zoomControl: false,
scrollwheel: true,
disableDoubleClickZoom: true
});
defaultBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(47.614217, -122.317981),new google.maps.LatLng(47.612975, -122.316291));
map.fitBounds(defaultBounds);
placesServices = new google.maps.places.PlacesService(map);
}
//ViewModel created to observe changes on the map
var MapViewModel = function(){
var self = this;
self.testarr = ko.observableArray([
{ firstName: 'Bert', lastName: 'Bertington' },
{ firstName: 'Charles', lastName: 'Charlesforth' },
{ firstName: 'Denise', lastName: 'Dentiste' }
]);
self.locations = ko.observableArray([]);
self.markers = [];
this.getNearbyLocations = function(){
if(placesServices === undefined){
placesServices = new google.maps.places.PlacesService(map);
}
var request = {
location: center,
radius: getBoundsRadius(defaultBounds),
type: ['establishment']
};
placesServices.nearbySearch(request, function(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i <= 18; i++) {
var marker = new google.maps.Marker({
map: map,
position: results[i].geometry.location,
animation: google.maps.Animation.DROP
});
self.locations.push(new LocationObject(results[i]));
self.markers.push(marker);
}
} else{
alert("We were not able to find any nearby locations in this Neighbourhood.");
}
});
};
this.init = function(){
self.getNearbyLocations();
};
};
var myMapViewModel = new MapViewModel();
myMapViewModel.init();
ko.applyBindings(myMapViewModel);
/* Utility Functions */
function getBoundsRadius(bounds){....}
The error is:
Uncaught ReferenceError: google is not defined
at MapViewModel.getNearbyLocations
and I don't get why it's not being recognized here, when the map itself loads first without issue but here it get's hung up.
Here is the html for reference, but there shouldn't be an issue there:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Per Google guideline scheduled for the M65 release, css has been moved to an importer -->
<link rel="import" href="importer.htm"></link>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-xs-12 col-md-4">
<!-- List goes in this column. -->
</div>
</div>
<div class="col-xs-12 col-md-8">
<!-- Map goes into this column. -->
<div id="map" style="width:100%;height:100vh;"></div>
</div>
</div>
</div>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
<!-- Optional JavaScript -->
<script src="js/knockout.js" ></script>
<script src="js/app.js"></script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyC-1EdIyUOb74oGG_mEoPvJTAGCSJvSQms&callback=initMap&libraries=places"></script>
</body>
I also thought that the error was because your app.js is being called before the maps script. But I tried changing it, same error, and I also tried removing the async parameter (as suggested by user3297291's comment), still the same error. Theoretically it should have worked.
But this worked - wrap the last 3 lines of your app.js code inside a ready() function:
$(document).ready(function(){
var myMapViewModel = new MapViewModel();
myMapViewModel.init();
ko.applyBindings(myMapViewModel);
});

How to get VieBag Data in Google Map Using javascript and ASP.NET MVC

With My Code I deserialized Json object for a city includes Tourist places. Each Tourist Places there are Name, Shor-Text, GeoCo-ordinates and Image. IN my controller class I deserialize all of this object and put all of this data in ViewBag.Now this portion is ok So far. My code to get The name and json deserilization in Controller class is as follows-
public ActionResult Index(City objCityModel)
{
string name = objCityModel.Name;
return View();
}
public ActionResult GoogleMap(City objCityModel)
{
string name = objCityModel.Name;
ViewBag.Title = name;
var ReadJson = System.IO.File.ReadAllText(Server.MapPath(#"~/App_Data/POI_Json/" + name + ".json"));
RootObject json = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<RootObject>(ReadJson);
List<Poi> mycities = new List<Poi>();
foreach (var item in json.poi)
{
Poi obj = new Poi()
{
Name = item.Name,
Shorttext = item.Shorttext,
GeoCoordinates = item.GeoCoordinates,
Images = item.Images,
};
mycities.Add(obj);
}
ViewBag.Cities = mycities;
return View();
}
I create a search box to get the name to go to the google map view. I am giving this code just for understanding-
#using (Html.BeginForm("GoogleMap", "Home"))
{
<div class="wrapper wrapper-content">
#Html.TextBoxFor(m => m.Name)
<label for="somevalue">City Name</label>
<div class="input-group-btn">
<button id="mapViewBtn" class="btn btn-primary" type="submit">Map View</button>
}
</div>
</div>
}
Now My problem is in the GoogleMap view. I am getting how to use all of my View bag data in this google map. I use the below link to write my code. Well I am trying in my way but could no succeed. I only want to use Javascript not the Ajax. But This is not working at all. My code is as follows-
Modified Code
<meta name="viewport" content="width=device-width" />
<title>GoogleMap</title>
<script src="http://maps.google.com/maps/api/js?sensor=true" type="text/javascript"></script>
<style>
#map_canvas img{max-width:none}
</style>
<style>
.infoDiv {
height: 200px;
width: 300px;
-webkit-user-select: none;
background-color: white;
}
</style>
<div id="map_canvas" style="height: 600px;"></div>
#section scripts {
<section class="scripts">
<script type="text/javascript">
$(document).ready(function () {
Initialize();
});
function Initialize() {
google.maps.visualRefresh = true;
var #ViewBag.Title = new google.maps.LatLng(53.408841, -2.981397);
var mapOptions = {
zoom: 14,
center: Liverpool,
mapTypeId: google.maps.MapTypeId.G_NORMAL_MAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var myLatlng = new google.maps.LatLng(53.40091, -2.994464);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Tate Gallery'
});
marker.setIcon('http://maps.google.com/mapfiles/ms/icons/green-dot.png')
var cities = JSON.parse('#Html.Raw(Json.Encode(ViewBag.Cities))');
$.each(cities , function(index, obj){
var marker = new google.maps.Marker({
'position': new google.maps.LatLng(item.GeoLong, item.GeoLat),
'map': map,
'title':obj.Name
});
var infowindow = new google.maps.InfoWindow({
content: "<div class='infoDiv'><h2>" +
item.Name + "</h2>" + "<div><h4>Opening hours: " +
item.ShortText + "</h4></div></div>"
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.open(map, marker);
});
})
}
</script>
</section>
}
Convert ViewBag which contains list of poi into json array using #Html.Raw and Json.Encode and then loop thru the array using.
<script>
var cities = JSON.parse('#Html.Raw(Json.Encode(ViewBag.Cities))');
$.each(cities , function(index, obj){
//here obj contains the POI information
console.log(obj.GeoCoordinates);
});
</script>
First convert your c# object to Json like below.
Write this in your cshtml page on top
#{
var jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.Cities);
}
Then inside your script block you can do this.
<script>
var citiesList= JSON.parse(#Html.Raw(Json.Encode(jsonData)));
alert(citiesList);
</script>
let me know if you have any issues

SAPUI5 and dynamic URL for OData service

I am doing sample example using sapui5. I want to pass URL service dynamically and load ODATA service, but I really new with sapui5 and I don’t know how to do it.
This code below is what i tried to do but it is not working. Thanks a lot for your help.
createContent : function(oController) {
var oLayout = new sap.ui.commons.layout.AbsoluteLayout({width:"340px",height:"150px"});
oLayout.addStyleClass("CustomStyle"); //Add some additional styling for the border
var oLabel = new sap.ui.commons.Label({text:"Service Url"});
var oUrlInput = new sap.ui.commons.TextField({width:"190px"});
oLabel.setLabelFor(oUrlInput);
oLayout.addContent(oLabel, {right:"248px",top:"20px"});
oLayout.addContent(oUrlInput, {left:"110px",top:"20px"});
var oLabel = new sap.ui.commons.Label({text:"Service"});
var oSvcInput = new sap.ui.commons.TextField({width:"190px"});
oLabel.setLabelFor(oSvcInput);
oLayout.addContent(oLabel, {right:"248px",top:"62px"});
oLayout.addContent(oSvcInput, {left:"110px",top:"62px"});
var loadData =new sap.ui.commons.Button({
text : "load",
width:"133px",
press: function() {
oController.load();
}});
oLayout.addContent(loadData, {left:"110px",top:"104px"});
return oLayout;
}
// Controller
load: function(oEvent){
var url = sap.ui.getControl("oUrlInput").getValue();
var svc = sap.ui.getControl("oSvcInput").getValue();
var oModel = new sap.ui.model.odata.OdataModel(url + "/" + svc ,false);
var mylist = new sap.ui.model.ListBinding(oModel);
return mylist;
}
// index.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>
<script src="resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-libs="sap.ui.commons,sap.ui.table,sap.ui.ux3"
data-sap-ui-theme="sap_bluecrystal">
</script>
<!-- add sap.ui.table,sap.ui.ux3 and/or other libraries to 'data-sap-ui-libs' if required -->
<script>
sap.ui.localResources("simpleform");
var view = sap.ui.view({id:"idsimpleForm1", viewName:"simpleform.simpleForm", type:sap.ui.core.mvc.ViewType.JS});
view.placeAt("content");
</script>
</head>
<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>
You have to give your controls an id to access them in the controller. Like this:
// create controls with id
var oLabel = new sap.ui.commons.Label("oLabelId", {text:"Service Url"});
var oUrlInput = new sap.ui.commons.TextField("oUrlInputId", {width:"190px"});
// then to get reference to the control later
var oLabel = sap.ui.getCore().byId("oLabelId");
var oUrlInput = sap.ui.getCore().byId("oUrlInputId");
Make sure, that you use the right Url:
var oModel = new sap.ui.model.odata.OdataModel("/sap/opu/odata/sap/" + svc ,false);
Make sure following.
Change the case of odataModel to ODataModel
Ensure the Service URL also correct
Obtain the reference of the control As described by kjokinen
Regards

spit string and set them to map as a marker

i am try to create marker on map.
i am use bing Map
i have two string with comma separate.
in two different variable.
var Region = "Pune,Kolkata";
var Activity = "Cricket,One Day";
i am try this java-Script ajax:-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/MapControl/mapcontrol.ashx?v=6.3c">
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
var Region = 'Pune,Kolkata';
var cntry_code= 'IN';
var Activity = "Cricket,One Day"
var map = null;
function GetMap() {
map = new VEMap('myMap');
map.LoadMap();
$(document).ready(function(){
var array_region = Region.split(',');
var array_activtiy= Activity.split(',');
for(var item_region in array_region)
for (var item_activity in array_activtiy)
{
$.ajax({
url: "http://services.gisgraphy.com//geocoding/geocode?address="+array_region[item_region]+"&country="+cntry_code+"&format=json",
async: false,
dataType:'jsonp',
success: function(data){
lat = data.result[0].lat;
lng = data.result[0].lng;
alert(lat);
alert(lng);
map.LoadMap(new VELatLong(lat,lng));
var pinpoint = map.GetCenter();
shape = new VEShape(VEShapeType.Pushpin, pinpoint);
shape.SetTitle("Activity Name:- ");
shape.SetDescription(array_activtiy[item_activity]+","+array_region[item_region]);
map.AddShape(shape);
}
});
alert(array_region[item_region]);
}
});
}
</script>
</head>
<body onload="GetMap();">
<div style="width:630px; background-color: #E0E0E0; height: 500px; border: 1px solid black">
<div id='myMap' style="position:relative; width:600px; height:400px; margin-left:15px"></div>
</div>
</body>
</html>
with this try to split string with comma.
and pass this to ajax url.
and got the lat and lng.
use this lat and lng.
set those place there Activity.
its work fine.
just little problem its add last place and last activity as a marker.
i think problem in my for loop.
please some one check it out my this query.
thanks.
You should not use the for(var item_region in array_region) construct with Arrays. Replace that line with something like:
for (var item_region, i = 0; i < array_region.length; i++)
item_region = array_region[i];
You will need to do a similar change on the following line - left as an exercise

Javascript: how to find the content of h3 header with id "map"?

I have a web page with a Google Map which works well. Instead of having the city name hardcoded to "Bochum" there, I'd like to find the header
<h3 id="city"><i>Bochum</i></h3>
and use that value in my init() function.
I'm probably missing something minor in the code below. Please help me and please refer me to the API reference for such a "child", my Javascript skills are very rusty.
Also I wonder, how could I pass one more value through my h3 header, like the color for my marker?
Thank you!
Alex
<html>
<head>
<style type="text/css">
h1,h2,h3,p { text-align: center; }
#map { width: 400; height: 200; margin-left: auto; margin-right: auto; }
</style>
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=false">
</script>
<script type="text/javascript">
function init() {
for (var child in document.body.childNodes) {
child = document.body.childNodes[child];
if (child.nodeName == "H3")
alert(child);
}
// use the #city value here instead
city = 'Bochum';
if (city.length > 1)
findCity(city);
}
function createMap(center) {
var opts = {
zoom: 9,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP,
};
return new google.maps.Map(document.getElementById("map"), opts);
}
function findCity(city) {
var gc = new google.maps.Geocoder();
gc.geocode( { "address": city}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var pos = results[0].geometry.location;
var map = createMap(pos);
var marker = new google.maps.Marker({
map: map,
title: city,
position: pos,
});
}
});
}
</script>
<head>
<body onload="init();">
<h3 id="city"><i>Bochum</i></h3>
<div id="map"></div>
</body>
</html>
To include more data, you could use attributes:
<h3 id="city" data-citycolor="red"><i>Bochum</i></h3>
And get them out like this:
var city = document.getElementById("city");
var name = city.textContent || city.innerText;
var color = city.getAttribute("data-citycolor");
I think that you would be better off using jQuery, even if it is a 26kb library file, since then you can simplify it to this:
var city = $("#city");
var name = city.text();
var color = city.data("citycolor");
Note that you used "#city" in you comment, and with jQuery, you can use that exact string in your code. That's a good win. It also makes it trivial to use $(".city") in the future, if you want to have more of these on one page.
Assuming that the ID 'city' is unique(what an ID has to be):
document.getElementById('city').getElementsByTagName('i')[0].firstChild.data
The id attribute should be unique for the page - in other words you shouldn't have any other elements with id="city". Assuming that's the case, here's an example of what you could do:
<html>
<script type="text/javascript">
function init()
{
var node = document.getElementById("city");
var cityName = node.childNodes[0].innerHTML;
alert("Found city name: " + cityName);
}
</script>
<body onload="init();">
<h3 id="city"><i>Bochum</i></h3>
</body>
</html>
As a suggestion, I would lose the <i> and </i> tags, and instead add a style rule for your h3 node. In that case, the cityName would be just node.innerHTML.
Well, the h3 has an ID, no?
var city = document.getElementById('city').innerText;
Or, using jQuery:
var city = $('#city').text();

Categories

Resources