Here API clustering error: "addLayer is not defined" - javascript

I am try to use clastering in my aplication but I am get a error addLayer is not defined".
I have no Idea how to resolve this issue.
I just copy and paste this sample function from Here API samples api clusters
And I'm passing lat and lng, to the function but addLayer is undefined.
I have the map object, but the addLayer is undefined.
function startClustering(map, data) {
// First we need to create an array of DataPoint objects,
// for the ClusterProvider
var dataPoints = data.map(function(item) {
return new H.clustering.DataPoint(item.latitude, item.longitude);
});
// Create a clustering provider with custom options for clusterizing the input
var clusteredDataProvider = new H.clustering.Provider(dataPoints, {
clusteringOptions: {
// Maximum radius of the neighbourhood
eps: 32,
// minimum weight of points required to form a cluster
minWeight: 2
}
});
// Create a layer tha will consume objects from our clustering provider
var clusteringLayer = new H.map.layer.ObjectLayer(clusteredDataProvider);
// To make objects from clustering provder visible,
// we need to add our layer to the map
map.addLayer(clusteringLayer);
}
And I'm passing lat and lng, to the function but addLayer is undefined.
I have the map object, bust does not exist addLayer.
I'm embed the script
<script type="text/javascript" src="https://js.api.here.com/v3/3.0/mapsjs-clustering.js"></script>
on my index.
I don't know how to resolve this issue.
If someone knows how to resolve I'm glad to listen
EDIT: Additional code per comment request:
function addMarkerToCameraGroup(map, coordinate, html) { // add and remove markers
document.querySelector(".camera-box").addEventListener("click", function() {
if (document.getElementsByClassName("camera-marker-position")[0] === undefined) {
map.addObject(cameraMarker);
self.startClustering(map, coordinate);
} else {
map.removeAll();
}
});
}

You asked this question a second time as: "Try to create a cluster unsing a sample but addLayer got undefinied" which doesn't include some of the details in this question. Given the additional edit / context you made on this question however, it would seem you are adding an event listener in which map is probably out of scope or not yet defined for visibility inside the anonymous function.
document.querySelector(".camera-box").addEventListener("click", function() {
if (document.getElementsByClassName("camera-marker-position")[0] === undefined) {
map.addObject(cameraMarker);
self.startClustering(map, coordinate);
} else {
map.removeAll();
}
});
You could do a typing check to see if map has been defined when the click event occurs and/or confirm whether it is an H.map. Without seeing the full listing, it may also be the case that you have not made map a global variable but instead declared it somewhere else in the page initialization so is out of scope when the click event is fired.
You can check JavaScript callback scope for details on closures where you could provide the map to the event when declaring the function. For more general information: JavaScript HTML DOM EventListener

Related

How to read in data and assign marker to a layer based on variable in data

I am attempting to create a map with layers based on time periods. I would like to be able to link markers to a google spreadsheet so people can add markers if needed. However, I have been unsuccessful at getting the markers to populate in the layer they are assigned.
I have included a fiddle below but I think my issue is somewhere here:
var code = 'https://docs.google.com/spreadsheets/d/1L4L6ezp4Z38cfundpYUv1wEEkM-kDFClldq7kuZbEVw/edit?usp=sharing';
function addPoints(data, tabletop) {
for(var row in data){
var marker = L.marker([
data[row].lat,
data[row].lng
])
.addTo(data[row].groupfor);
}
}
function init() {
Tabletop.init({
key: code,
callback: addPoints,
simpleSheet: true
})
}
init()
the markers are added to the map correctly when I use addTo(map); however, I would like to assign them to layers based on the variable groupfor in my data.
JSFiddle
Currently, none of the markers populate in the map but I want them to be assigned to the correct layer in the map based on the variable I assign them in the data.
I finally got it to work by changing .addTo(data[row].groupfor) to .addTo(window[data[row].groupfor]);
Don't know if this is the best way to do that but it worked for me.

Recenter Mapbox map using user coords

Been trying for 1.5 hours. Can someone please help me out? "your post appears to contain code that is not properly formatted as code" issue.
Please can someone help me format this code?
It works now in this post, but not when making a new one...
Now I cannot make a new post for a day... What the...
FIXED: It appears that the browser output had to be in code layout.
This was my original question:
TITLE: Working with geolocation API - scope question
Hi all
I am working with Mapbox and am trying to update the vars lngreal and latreal (from default Greenwhich coordinates). The function initializeMap() is called during setup, and the idea is that it updates it with user's longlat coordinates if possible. When I run the code below...
function initializeMap() {
mapboxgl.accessToken = 'HIDDEN FOR THIS POST';
var lngreal = 0.0098;
var latreal = 51.4934;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(displayLocationInfo);
}
function displayLocationInfo(position) {
//Why does this not work to update the map zoom?
lngreal = position.coords.longitude;
latreal = position.coords.latitude;
console.log(lngreal);
console.log(latreal);
}
console.log(lngreal);
console.log(latreal);
// This adds the map to your page
var map = new mapboxgl.Map({
// container id specified in the HTML
container: 'map',
// style URL
style: 'mapbox://styles/mapbox/light-v10',
// initial position in [lon, lat] format
center: [lngreal, latreal],
// initial zoom
zoom: 14
});
// More code after this but not related
}
It shows the following in html inspector console:
play-mapboxscripts.js:21 0.0098
play-mapboxscripts.js:22 51.4934
play-mapboxscripts.js:17 4.9212796
play-mapboxscripts.js:18 52.333704999999995
Why does it first show the last console.log lines, instead of the console.log lines in the displayLocationInfo function? Isn't that function called in the navigator.geolocation function, which comes before that?
I cannot get the lngreal and latreal variables updated correctly to match the user's location. They will default back to 0.0098 and 51.4934, and the loaded map (var map) will show the default Greenwhich location. Does this have to do with variable scope of the displayLocationInfo function?
It shows the last two console logs first because displayLocationInfo is the callback to the async method getCurrentPosition and so has to wait until that process has resolved before it can log the new coords.
To recenter the map with the new coords you need to do something like this:
function displayLocationInfo(position) {
const { coords: { latitude, longitude } } = position;
// Get a new lat/lng object
// https://docs.mapbox.com/mapbox-gl-js/api/#lnglatlike
const center = new mapboxgl.LngLat(longitude, latitude);
// Center the map
// https://docs.mapbox.com/mapbox-gl-js/api/#map#setcenter
map.setCenter(center);
}
Thanks Andy and #Chris G. I wasn't aware of asynchronous functions and am happy to have read about them now. Very helpful.
I have a question about callbacks, which relates to this topic. How does a function know that something is a callback; something that needs to be executed once certain I/O has completed. How does it know that it shouldn't execute right away? Is it defined in a function in a (standardized) way?
As far as I know the 'callback' keyword that is often used in an argument is just common practise, but does not automatically let the function interpret the argument as something that should start once certain I/O has completed.
Taking the below example, I have three questions (taken from https://medium.com/codebuddies/getting-to-know-asynchronous-javascript-callbacks-promises-and-async-await-17e0673281ee):
const request = require(‘request’);
function handleResponse(error, response, body){
if(error){
// Handle error.
}
else {
// Successful, do something with the result.
}
}
request('https://www.somepage.com', handleResponse);
What does the structure of the 'require' function look like so that it knows that argument 2 (handleResponse in this case) should be executed once the request has completed? I guess this gets down to the same question that I asked above.
Can functions be asynchronous even without the async keyword in the function? If yes, how does the browser know it's an asynchronous function?
In my code, is it possible to have the browser/script wait with execution of remaining code until the navigator.geolocation.getCurrentPosition has finished executing and therefore updated the lngreal latreal coords?

Undo/Redo for leafet routing machine

I am trying to implement simple undo/redo function for my tool which uses leaflet and leaflet routing machine.
Here is my function:
var activityBuffer = [];
var undoFlag = false;
Routing.on('routeselected', function(){
if (undoFlag) {
undoFlag = false;
}
else {
var newWaypoints = Routing.getWaypoints();
activityBuffer.push(newWaypoints);
console.log(activityBuffer);
}
});
function undoActivity(){
var lastStateIndex = activityBuffer.length - 2
if (lastStateIndex >= 0) {
var oldState = activityBuffer[lastStateIndex];
Routing.setWaypoints(oldState);
activityBuffer.splice( activityBuffer.length - 1, 1);
undoFlag = true;
console.log(activityBuffer);
}
}
It works fine if i just add more points and the routeselected event is fired, but problem is when i move my waypoints and the cordinates of same points are changed, the entry in the activityBuffer of that waypoint is also updated on its own, add another array of new waypoints is also pushed. why so?
For example:
I hope i explained my problem.
Looking for some help!
I think the problem is that Leaflet Routing Machine under some circumstances mutate (change) the existing waypoint instances in place, rather than always creating new waypoint instances. For example, when dragging a waypoint, the coordinate of the waypoint is overwritten in the same instance.
Since your activityBuffer saves the references to existing waypoints, those waypoints will also be updated when LRM updates them. Storing copies of the waypoints instead should fix your problem.
Also note that strictly, you should store the waypoints from the route that is passed to your event handler (routeselected) instead of grabbing the control's waypoints - this might be important when network latency is high, for example.

Altering external variable from Google Maps' StreetViewService.getPanorama({},callback) method

I am running into trouble with this piece of code since I'm not sure how to fix it. I already asked this in the chats but couldn't figure out myself after some answers.
I want to get Panorama from StreetViewService using the method from the Google Maps javascript API from a StreetViewService getPanorama() method.
The method receives a literal with the coordinates and a radius, and a callback function that receives 2 parameters: data and status.
in that callback you check wether the service returns some images for street view or not, in which case you do one thing or another.
It seems the callback is executed asynchronously or the getPanorama method, executing some kind of ajax behind the scenes.
I'm pasting the code below, but first I explain my intentions. I need to return from one method I made inside a literal that is inside a self made library wether the the request has valid images for that requested coordinates or not by setting a variable to true or false and then at the end returning that value. However, even if I set the variable to true inside that callback anonymous function, when the variable returns, it always has it's initial value without it not being changed.
Here the code. Not everything, just the essential code.
Then my intention is to used the boolean returned to know if I have to switch one button active for some kind of job or not or do some things or not depending of if it returned true or false, Change some style etc as well.
I'd appreciate if you could change my code in a way it could be done. I was told about a callback solution or wrapping it into a promise. However I don't know how to do it. I used promisses in jquery but not in vanilla javascript. I'd like to see how the callback solution could be made as well with this code.
//Library not show for shortenning the example.
streetView: { //This is inside a library
valid_request: false,
event_key: null,
panorama: null,
setStreetView: function(coords, element) {
libMapa.streetView.valid_request = false; // Initialize the value again.
let sv_service = new google.maps.StreetViewService();
var latlng = coords;
sv_service.getPanorama({ // This is a method from Google Map Javascript API.
location: latlng,
radius: 50
}, function(data, status) {
if (status === google.maps.StreetViewStatus.OK) {
if (!libMapa.streetView.panorama) {
libMapa.streetView.panorama = new google.maps.StreetViewPanorama(element);
libMapa.streetView.panorama.setEnableCloseButton(true);
}
libMapa.streetView.panorama.setPano(null);
libMapa.streetView.panorama.setPano(data.location.pano);
libMapa.streetView.panorama.setVisible(true);
libMapa.streetView.valid_request = true;
} else {
alert("No images for this place");
// Otherwise variable stays as FALSE.
}
});
return libMapa.streetView.valid_request;
}
}
/****************************************/
//OUTSIDE THE LIBRARY IN INDEX.HTML
var sv_valid = libMapa.streetView.setStreetView(coords, div_mapa);
//sv_valid still shows false even if it should return true.
if (sv_valid) {
// "pressed" is to control a button as if it was a switch by activatinc and deactivating it.
pressed = false; // It always ends up being false even when it should return true.
element.style.cursor = "default";
libMapa.mapa.unByKey(libMapa.streetView.event_key);
}
Use a callback to do some action or modify some variable after the AJAX call to getPanorama() (and by proxy, setStreetView()) is complete.
Modify setStreetView() to accept a callback parameter and pass it along to getPanorama().
streetView {
// streetView variables etc.
setStreetView: function(coords, element, callback) {
// get ready for the AJAX call etc.
sv_service.getPanorama({
// parameter object
}, function(data, status){
// The getPanorama() callback.
// Do stuff with the data/status here,
// then call the callback function that you passed in to setStreetView.
// You can send data along (e.g. the result of the AJAX call) to the callback.
callback(someResult);
});
}
}
// somewhere else, where you're calling streetView.setStreetView()
var someVar = "foo";
streetView.setStreetView(someCoords, someElement, function(eventualResult){
someVar = eventualResult;
});
Here's a small example: https://jsfiddle.net/_jered/pgftxgf3/
I also highly suggest you do some research on AJAX, asynchronous JavaScript, and callbacks.

Ajax Bing Maps version 7 - move and delete push pin - beginner's tutorial

I am currently learning about these maps. Now I would like to create a method which updates my push pin if I already have one.
a. I tried to use setLocation(newLocation) but unfortunately, when I did this, my client side code wasn't even reached (I'm thinking that the code syntax is incorrect, yet no error was given on chrome)
b. I then tried to learn how to delete it and create another one, yet I cannot find any resources from http://msdn.microsoft.com/en-us/library/gg427610.aspx - maybe I am not searching well enough.
Can anyone provide me with some guide on how to move a push pin and how to delete one? Thank you all very very much
var loc = new Microsoft.Maps.Location(lat, lon);
var pin = new Microsoft.Maps.Pushpin(loc);
Edit: partial answer
Removing a push pin:
if (pin != null)
{
map.entities.remove(pin)
}
To move a pushpin, setLocation() is indeed the function you need to use. Are you trying to call setLocation from an event handler on the map? If that's the case, it's possible that the event handler wasn't set up properly so it is never called. However, if you already have defined a pushpin(with a variable name myPushpin) and inserted it into the map, then executing the follow code will move it:
// Move pushpin to "38.0", "-97.0"
var loc = new Microsoft.Maps.Location(38.0, -97.0);
myPushpin.setLocation(loc);
To see this in action, head over to the Ajax Bing Maps v7 interactive SDK, modify the code in blue on the lower center of the screen by putting in different coordinates, hit the Run button and see the pushpin move.
To delete a pushpin that has been added to the map, you need to remove it from the EntityCollection from which it was added to. For example, if you simply inserted the Pushpin into yourmap.entities, this is how you remove it:
var index = yourmap.entities.indexOf(myPushpin);
if (index != -1) {
yourmap.entities.removeAt(index);
}
Or you can just remove it directly without using an index:
yourmap.entities.remove(myPushpin);
UPDATE:
To delete a pushpin when the user clicks on it, you essentially have to first identify the pushpin that was clicked in the click event handler. The pushpin can be obtained from the target Property of the MouseEventArgs Object that is passed into your click handler:
Microsoft.Maps.Events.addHandler(pushpin, 'click', function (mouseEvent) {
var pushPinThatWasClicked = mouseEvent.target;
// Do whatever you want with pushPinThatWasClicked
});
The following function can remove all the pushpins from the map:
//remove all the pushpins
function deletePushpin()
{
for(var i=map.entities.getLength()-1;i>=0;i--)
{
var pushpin= map.entities.get(i);
if (pushpin instanceof Microsoft.Maps.Pushpin) {
map.entities.remove(pushpin);
}
}
}

Categories

Resources