js call function stored in 2D array - javascript

I have an array:
var markerArray = [];//global var
var markerCnt = 0;//global var
for(var x=0;x<10;x++){
markerArray[markerCnt] = new Array(agency, address, marker, onMarkerClick);
//agency and agency = string
//marker = google maps marker
//onMarkerClick = function
markerCnt++;
}
How do I call a specified onMarkerClick function?
Would I just do:
markerArray[0][3]();

As an alternative solution, you can also do this:
var markerArray = [];
var markerCnt = 0;
for(var x=0;x<10;x++){
markerArray[markerCnt] = {
'agency' : agency,
'address' : address,
'marker' : marker,
'click' : onMarkerClick
};
markerCnt++;
}
//To call the click
markerArray[0].click();

The answer to your question is yes.
You can execute any function stored in an array, no matter how many dimensions.
// perfectly valid
markerArray[0][3]()
// as is this
someArray[0][1][7][2]()
To go a little bit beyond than just answering your question, I would suggest using an array of objects so you don't have to execute an array member. This will increase readability of your code and saves you a few hours if you look at it in 6 months trying to figure out what you did.
var markerArray = [];//global var
var markerCnt = 0;//global var
for(var x=0;x<10;x++){
markerArray[markerCnt] = {
agency: agency
address: address
marker: marker
onMarkerClick: onMarkerClick
};
//agency and agency = string
//marker = google maps marker
//onMarkerClick = function
markerCnt++;
}
// then reference your function
markerArray[0].onMarkerClick();

Related

How to add a marker to Mapbox on click event?

I'm a french student in computering and I have to use Mapbox but since I create a class I'm stuck by this error.When I wasn't in a class it worked perfectly but now it's fully broken.And I saw on some topics it could come from safari but I already tested it on Mozilla and it still broken.
This is my class.
constructor() {
//Temporary array of currentMarkers
let currentMarkers=[];
let type ="";
//Create the map
mapboxgl.accessToken = 'private data';
this.mapbox = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/streets-v11',
center: [-74.5, 40], // starting position
zoom: 9 // starting zoom
});
//Add search bar from a plugin
let geocoder = new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
placeholder: 'Saissisez une adresse', // Placeholder text for the search bar
marker: {
color: 'orange'
},
mapboxgl: mapboxgl
});
this.mapbox.addControl(geocoder);
const mbox = this;
this.mapbox.on("click",function(){
this.getcoordonates();
});
//Allow us to create marker just with a research
geocoder.on('result', function(e) {
//Deleting all current markers
if (currentMarkers!==null) {
for (let i = currentMarkers.length - 1; i >= 0; i--) {
currentMarkers[i].remove();
}
}
//Add the markers who come with the research
this.addMarker(e.result.center[0],e.result.center[1]);
// Delete the last marker who got placed
//currentMarkers[currentMarkers.length - 1].remove();
});
this.addPoint(2.333333 ,48.866667 ,"supervisor");
}
//split the JSON.stringify(e.lngLat.wrap()) to get the coordinates
async mysplit(m){
let z = m.split(',');
let x = z[0].replace("{\"lng\":","");
let g = z[1].replace("\"lat\":","");
let y = g.replace("}","");
await addMarker(x,y);
}
//Add a marker on click after the excution of mysplit() function
async addMarker(x,y) {
// tmp marker
let oneMarker= new mapboxgl.Marker()
.setLngLat([x,y])
.addTo(this.mbox);
currentMarkers.push(oneMarker);
}
// Get the coordinates and send it to split function
getcoordonates(){
mbox.on('click',function(e){
let m = JSON.stringify(e.lngLat.wrap());
this.mbox.mysplit(m);
});
}
addPoint(y,x,type)
{
let color ="";
let t = type;
if(t == "supervisor")
{
color = "grey";
}else if (t =="fieldworker") {
color = "red";
}else if (t == "intervention") {
color = "blue";
}else alert("Nous ne pouvons pas ajouter votre marker\nLatitude : "+x+"\nLongitude :"+y+"\n car "+t+" n'est pas un type reconnu" );
let myMarker = new mapboxgl.Marker({"color": color})
.setLngLat([y,x])
.addTo(this.mbox);
}
}
Thanks for help and have a good day :) ! Sorry if my English isn't that good.
As the first step, the
this.mapbox.on("click", function(e){
this.getcoordonates();
});
was called outside of any method of the Map class. It would most probably belong to the constructor (as discussed above in the question's comments section).
Next, the callback changes the scope of this, so it is not anymore pointing to a Map instance. A common solution to this issue is to store/backup this before, something like:
constructor() {
...
const thisObject = this;
this.mapbox.on("click", function(e) {
thisObject.getcoordonates();
});
}
Update:
The logic of code in its current form tries to add a new click event listener every time the map is clicked. Which is not desired. This getcoordonates() function is not really needed. Instead this should work (never tested it, it is based on your code):
constructor() {
...
const mbox = this;
this.mapbox.on("click", function(e) {
let m = JSON.stringify(e.lngLat.wrap());
mbox.mysplit(m);
});
}
Remarks:
There is no real logic behind JSON-encoding the lngLat object before calling mysplit just to decode it there.
You won't need it here, but the reverse of the JSON.stringify() is JSON.parse(). There is no need to work with it on a string level, like the current mysplit() method does.
Instead, the mysplit() method should be called directly with the e.lngLat object as its argument.
Going further, since there is no "splitting" (decoding) really needed, the mysplit() method isn't really needed either.
In the end, something like this should work:
constructor() {
...
const mbox = this;
this.mapbox.on("click", function(e) {
await mbox.addMarker(e.lngLat.lng, e.lngLat.lat);
});
}

Getting Data into the JSON

I am trying to visulize Coordinates on the map . Data is Coming form json.
I am getting and error Push is undefined. I am passing the Array but getting error
Here is the Code
var testCtrl = this;
testCtrl.allOrgUnits = response.organisationUnits;
console.log(testCtrl.allOrgUnits)
for (i = 0; i < testCtrl.allOrgUnits.length; i++) {
if(testCtrl.allOrgUnits[i].coordinates != undefined && testCtrl.allOrgUnits[i].coordinates.length < 200) {
testCtrl.geoCoords.push(new Array(testCtrl.allOrgUnits[i].name, testCtrl.allOrgUnits[i].coordinates.substring(1,testCtrl.allOrgUnits[i].coordinates.length-1).split(",")));
}
}
// Add the coordinates to the map.
addMarkers(testCtrl.geoCoords);
});
JSON Data is like
organization units [{ "name":david , "coordinates""[ 10.24 ,23.80] { "name":phil , "coordinates""[ 35.80 ,23.80]
Here is the Function addMarkers
function addMarkers(coordinates) {
var marker;
markers = [];
for (i = 0; i < coordinates.length; i++) {
// Create and add a new marker per coordinate.
marker = new google.maps.Marker({
position: new google.maps.LatLng(coordinates[i][1][1], coordinates[i][1][0]),
map: map,
title: coordinates[i][0],
icon: blueMarker,
current: false,
});
markers.push(marker);
// Add a listener to each marker, so that they will display the name of the facility when clicked.
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent("<div class='info'><h4>" + coordinates[i][0] + "</h4>Facility</div>");
infowindow.open(map, marker);
}
})(marker, i));
}
You probably need to initialize geoCords to be an array before trying to push something.
testCtrl.geoCoords = [];
You are trying to call push method on undefined
You are doing this
testCtrl.geoCoords.push()
where testCtrl has no property geoCoords, so first initialize this property like
testCtrl.geoCoords = []
Now it is an empty array , you can use push method on this
You could transform your json into Object, it might be easier after that.
private ObjectMapper mapper = new ObjectMapper();
listPersonCoordinates = mapper.readValue(query_result, new TypeReference<ArrayList<PersonCoordinate>>(){})
for (PersonCoordinate pc : listPersonCoordinate) {
pc.getName();
pc.getCoordinate();
// Do your stuff here
}
and
public Class PersonCoordinate {
String name;
ArrayList<double> coordinate;
// getters + setters + constructor
}
Hope this help :)
Edit : Your JSON looks strangely formatted. misses some "

Add Relational Query Data to main JSON result

in my Angular app I'm trying to display a set of results that come from three Classes. Data is stored on Parse.com.
I can do just fine with the Pointer relation type for one-to-one (associated scores are being returned).
Problem starts when I try to include data from the Location class into my final returned JSON.
Hopefully this is just a basic notation thing I'm missing.
Thanks a lot!
Doctors
String: firstname
Pointer: score
Relation: location
Scores
Number: scoreOne
Number: scoreTwo
Locations
String: name
String: address
.controller('BrowseCtrl', function($scope) {
// Get "Doctors" and associated "Scores"
// via Pointer in Doctors Class named "score"
var query = new Parse.Query("Doctors");
query.include("score");
query.find()
.then(function(result){
var doctorsArray = new Array();
for(i in result){
var obj = result[i];
var doctorIds = obj.id;
var docFirstname = obj.get("firstname");
var mainScore = obj.get("score").get("mainScore");
doctorsArray.push({
Scores:{
DocMainScore: mainScore
},
firstname: docFirstname,
});
}
// Get Locations.
// -can be more than one per Doctor
// Class Doctors has a Relation column "location" pointing to Locations
var locationsArray = new Array();
var locationRelation = obj.relation('location');
var locationQuery = locationRelation.query();
locationQuery.find({
success: function(locations) {
for(j in locations){
var locObj = locations[j];
var locName = locObj.get("name");
console.log(locName);
}
}
})
// send data to the view
$scope.myData = doctorsArray;
console.log(doctorsArray);
});
})
What I am trying to do is get the data from Locations into the doctorsArray.
First of all, you are using obj outside the for where it's assigned. This way it'll only get location for the last doc, I'm pretty sure it's not what you wanted.
What you want must be something like this:
// inside your Doctors query result
Parse.Promise.when(
// get locations for all doctors
result.map(function(doc) {
return doc.relation('location').query().find();
})
).then(function() {
var docsLocations = arguments;
// then map each doctor
$scope.myData = result.map(function(doc, i) {
// and return an object with all properties you want
return {
Scores: {
DocMainScore: doc.get('score').get('mainScore')
},
firstname: doc.get('firstname'),
locations: docsLocations[i]
};
});
});

Associative Javascript Array

I have an issue and this is not something that I have ever used before.
This is a snippet of the code.
//Defined at top of file
var ships_array = [];
//Function later on
function refreshJSON(){
$.getJSON("scripts/getJSON.php", function(json){
if(json){
$.each(shiplist,function(i,item){
$.each(item,function(j,subitem){
var mmsi = subitem['mmsi'];
ships_array[mmsi].lat = subitem['lat'];
ships_array[mmsi].lon = subitem['lon'];
});
});
}
});
}
The error I am getting is
ships_array[mmsi] is undefined [Break
On This Error] ships_array[mmsi].lat =
subitem['lat'];
Is this the right way to use an associative array? I have seen an example similar to this but I am going wrong somewhere! At the end of it I want an array of Google Maps markers!
you just need to initialize the value at the hash key first
var mmsi = subitem['mmsi'];
ships_array[mmsi] = ships_array[mmsi] || {};
ships_array[mmsi].lat = subitem['lat'];
ships_array[mmsi].lon = subitem['lon'];
You can change your code like this:
//Defined at top of file
var ships_array = [];
//Function later on
function refreshJSON(){
$.getJSON("scripts/getJSON.php", function(json){
if(json){
$.each(shiplist,function(i,item){
$.each(item,function(j,subitem){
var mmsi = subitem['mmsi'];
ships_array[mmsi] = {lat: subitem['lat'], lon:subitem['lon']};
});
});
}
});
}

How can I get distances from Google maps javascript api v3

I'm trying to sort through an array of distances generated by google maps. I need to order my list, closest to furthest. I can get all of the directions and distances displayed just fine with the directionsService api example, but I cannot figure out how to retrieve that info outside of the function so that I can sort it.
function calcDistances() {
for (var x = 0; x < wineries.length; x++) {
var winery = wineries[x];
var trdistances = [];
var request = {
origin: map.getCenter(),
destination: new google.maps.LatLng(winery[1], winery[2]),
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
var route = response.routes[0];
var summaryPanel = document.getElementById("tasting_rooms_panel");
// For each route, display summary information.
for (var i = 0; i < route.legs.length; i++) {
//this works fine and displays properly
summaryPanel.innerHTML += route.legs[i].distance.text;
//I want to store to this array so that I can sort
trdistances.push(route.legs[i].distance.text);
}
}
});
alert(trdistances[0]);//debug
}
}
As commented in the code, I can populate summaryPanel.innerHTML, but when I populate the array trdistances, the alert gives me "undefined". Is this some rookie javascript coding error? I read up on the scope of variables and this should work. Help me oh wise ones.
function calcDistances() {
for (var x = 0; x < wineries.length; x++) {
var winery = wineries[x];
var trdistances = [];
var request = {
origin: map.getCenter(),
destination: new google.maps.LatLng(winery[1], winery[2]),
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
//Using Closure to get the right X and store it in index
(function(index){
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
var route = response.routes[0];
var summaryPanel = document.getElementById("tasting_rooms_panel");
// For each route, display summary information.
for (var i = 0; i < route.legs.length; i++) {
//this works fine and displays properly
summaryPanel.innerHTML += route.legs[i].distance.text;
//I want to store to this array so that I can sort
trdistances.push(route.legs[i].distance.text);
}
if(index == wineries.length-1){ //check to see if this is the last x callback
console.log(trdistances); //this should print the result
//or in your case you can create global function that gets called here like sortMahDistance(trdistances); where the function does what you want.
printMyDistances(trdistances); //calls global function and prints out content of trdistances console.log();
}
}
});
})(x); //pass x into closure as index
}
}
//on global scope
function printMyDistances(myArray){
console.log(myArray);
}
The problem is scope to keep track of the for loop's X. Basically, you have to make sure all the callbacks are done before you can get the final result of trdistances. So, you'll have to use closure to achieve this. By storing first for loops' X into index within closure by passing X in as index, you can check to see if the callback is the last one, and if it is then your trdistances should be your final result. This mod of your code should work, but if not please leave comment.
Furthermore, I marked up my own version of google map using closure to resolve using async directionServices within for loop, and it worked. Here is my demo jsfiddle. Trace the output of console.log(); to see X vs index within the closure.

Categories

Resources