Calculate driving distance between user location and many destinations via javascript loop - javascript

I have a json feed with many locations:
http://hcafeeds.medcity.net/rss/er/ntx_rss_feed.xml
I plan on obtaining the user's location via html5 geolocation. At this point, I'd like to loop through the json feed and output the items from the feed along with their distance from the user's location.
I've tried every which way I can with the google maps api but I always seem to hit a hurdle an hour into the method.
Has anyone done something similar?
UPDATE: here's my existing code
Will output the hospitals just fine... just can't figure out how to get distance:
var hcafeed = 'http://hcafeeds.medcity.net/rss/er/ntx_rss_feed.xml';
var yql = 'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent('select * from rss where url="' + hcafeed + '"') + '&format=json&diagnostics=true&callback=?';
$.getJSON(yql,function(data){
if(data.query.count > 0) {
// Run through hospitals and set html
var hospitals = [];
$.each( data.query.results.item, function( key, val ) {
var hospitalAddress = val.address;
var wait = $.trim(val.description.replace("Mins",""));
var units = (wait == 1) ? " Min" : " Mins";
hospitals.push({
'name' : "<div class='name'>"+val.comments.replace(" ER Wait Time","")+"</div>",
'addy' : "<div class='addy'>"+val.address+"</div>",
'phone' : "<div class='phone'>"+val.phone+"</div>",
'waitOutput' : "<div class='wait'>"+wait+units+"</div>",
'wait' : wait,
'distanceOutput' : "<div class='distance'></div>",
});
});
// Sort array by wait time (default)
hospitals.sort(function(a, b){
return a.wait-b.wait;
});
// Prepare array for output (wrapper)
var output = [];
$.each( hospitals, function( key, val ) {
output.push("<div data-key='"+key+"' data-wait='"+val.wait+"' class='hospital'>"+val.name+val.addy+val.phone+val.waitOutput+val.distanceOutput+"</div>");
});
}
// Print array
$("#hospitals").html( output );
}).fail(function (j, t, e) {
console.error(e);
});
I've created a fiddle:
https://jsfiddle.net/potd25yy/3/

Rather than a distance matrix, you should use the Directions Service in Google Maps JavaScript API to calculate a path between your user's location and your hospital.
The function:
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
return a response, with multiple routes. And the distance of the first route would be:
response.routes[0].legs[0].distance.text
so you can display it to the corresponding entry.
I create a quick demo to calculate the distance from Google, Inc. to each hospital. Hope this help. And let me know if you have further questions.
https://jsfiddle.net/jqw3g914/1/

Related

Trouble getting a specific field from OpenWeatherMap API's output, via JS / XMLHttpRequest

So I'm building this web forecast app using OpenWeatherMap API, and so far I'm being able to fetch the data from the first iteration of the list's output, however I need to obtain the data of other specific fields aswell. Here's a bit of my code:
ajaxGet("https://api.openweathermap.org/data/2.5/onecall?lat=4.6097&lon=-74.0817&exclude=current,minutely,hourly,alerts&appid=APPID&units=metric", function (response) {
var data = JSON.parse(response);
console.log(data);
var temperature = document.createElement("h6");
temperature.textContent = data.daily[0].temp.max + "°" + " / " + data.daily[0].temp.min + "°";
document.getElementById("temperaturaBogVier").appendChild(temperature);
});
And here's an example of what the API's output looks like (I'm only showing the first iteration in here, but there are at least 6 in total, https://api.openweathermap.org/data/2.5/onecall?lat=4.6097&lon=-74.0817&exclude=current,minutely,hourly,alerts&appid=APPID&units=metric):
{"lat":4.61,"lon":-74.08,"timezone":"America/Bogota","timezone_offset":-18000,"daily":
[
{"dt":1600876800,
"sunrise":1600857917,
"sunset":1600901504,
"temp":{"day":18.14,"min":8.99,"max":18.14,"night":12.08,"eve":15.45,"morn":8.99},
"feels_like":{"day":17,"night":11.02,"eve":14.6,"morn":7.58},
"pressure":1017,"humidity":54,
"dew_point":8.69,
"wind_speed":1.2,
"wind_deg":164,
"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],
"clouds":82,
"pop":0.94,
"rain":5.85,
"uvi":15.14}
]
}
So as you can see, I'm being able to print into my HTML the data contained into "data.daily[0].temp.", but it only works for the first set of fields and I got no clue how to select a specific iteration. I'm sure I'm missing something into the concat, but nothing I've tried has worked so far.
Any help would be greatly appreciated, and rewarded with an imaginary waffle. THX :D
The temperatures for each day data.daily are defined as an JavaScript array of objects. You can simply access them by their index, which indicates their position in the array.
data.daily[0] // First element
data.daily[1] // Second element
data.daily[2] // Third element
Once you have selected an object within the array, you can then access certain values like data.daily[2].temp.max.
The cool thing about arrays is that you can iterate them with a loop. This will save you a lot of writing, if you want to print out each temperatures for every day:
ajaxGet("https://api.openweathermap.org/data/2.5/onecall?lat=4.6097&lon=-74.0817&exclude=current,minutely,hourly,alerts&appid=YOUR_API_KEY_HERE&units=metric", function (response) {
var data = JSON.parse(response);
console.log(data);
data.daily.forEach(function (date) {
var temperature = document.createElement("h6");
temperature.textContent = date.temp.max + "°" + " / " + date.temp.min + "°";
document.getElementById("temperaturaBogVier").appendChild(temperature);
})
});
Please note: I've removed the appid=XXXXX part of the request URL, because it contains your personal API key for OpenWeather, which you should not share publicly.
If I understand the question correctly, you want to take all daily max/min-values and put them into elements that you want to append to another element.
Here is a way to do that
ajaxGet("https://api.openweathermap.org/data/2.5/onecall?lat=4.6097&lon=-74.0817&exclude=current,minutely,hourly,alerts&units=metric", function (response) {
var data = JSON.parse(response);
console.log(data);
data.daily
.map(datapoint => datapoint.temp) //get the temp value/object from each datapoint
.map(temp => { //create an element and add each max/min value to that element's textContent
const temperature = document.createElement("h6");
temperature.textContent = temp.max + "° / " + temp.min + "°";
return temperature;
})
.forEach(element => { //add each of the elements created in the previous map to the desired element
document.getElementById("temperaturaBogVier").appendChild(element);
});
});
As pointed out in the other answer, I've also removed the app-id query parameter

Create 2D Array out of another Array which is casted against an API

I'm working on a project using the opengeodata and some company-internal APIs. Therefore the code I'm using here is slightly changed.
First I'm using the Opencagedata Javascript API to get the lat/lng-Coordinates out of an address.
<script>
function geocode(query) {
$.ajax({
url: 'https://api.opencagedata.com/geocode/v1/json',
method: 'GET',
data: {
'key': 'MyKey',
'q': query,
'no_annotations': 1
},
dataType: 'json',
statusCode: {
200: function(response){ // success
var lat = response.results[0]['geometry']['lat'];
var lng = response.results[0]['geometry']['lng'];
$('#geo_result').text(lat + ' , ' + lng);
After that I'm using another internal API to get some information about places surrounding this location. Lets call them POI.
After getting those POIs I'm using splice to filter the three nearest POIs to the lat/lng Coordinates and filter on some specific keywords.
var radius = 1.5;
var POI = [];
var apiCall = $.get("CoorpAPI/" + radius + "/around/" + lat + "," + lng);
apiCall.done(function(result) {
var myLoc = result.filter(function(loc) {
return loc.id.substr(0, 3) != 'keyword';
});
$.each(myLoc, function(n, loc) {
POI.push(loc.id)
})
var top3 = POI.slice(0,3);
console.log(top3);
Now I want to run those three "top3" POIs ["AB1234", "BC2345", "CD3456"] against a second API which is returns location information.
Those information are supposed to be written into the same array into the second second dimension.
In the end I want to have something Like:
[
0: AB1234
Location Information: A
Location Information: B
1: CD2345
Location Information: C
Location Information: D
...
]
I guess the loop would have to look somewhat like this, but I'm not sure how to call the API and create a 2d-array out of the "top3" locations and the location information returned by the api:
for (var i = 0; i < top3.length; i++) {
var apiCall_2 = $.get("CoorpAPI_2"+top3[i]);
// ???
}
If I understand you correctly, you want to use a nested array inside POI to add more information after a second API call. One thing you can try is to push an array instead of just loc.id in the following manner:
POI.push([loc.id]);
Now you have a nested array in POI instead of a single string ID (I am guessing the ID is string; can be a number as well). For the second API call you can modify your code like this:
var apiCall_2 = $.get('CoorpAPI_2'+top3[i][0]);
In this way, you are using the ID which, is the first element in the nested array. Once you process all your data from API call 2, you can either push each data point separately into the nested array or, as another array like this:
// pushing each data points separately
top3[i].push(dataPoint1);
// ... up to say N data points
top3[i].push(dataPointN);
// adding as an array
top3[i].push([dataPoint1, dataPoint2, dataPointN]);
Your result will be like this:
[ ["AB1234", "dataPoint1", "dataPoint2"] ]
if you use the first approach and like this
[ [ "AB1234", ["dataPoint1", "dataPointN"] ], ]
if you use the second approach. Hope this helps.

Make changes of colors of icons visible in openlayers with a function

I try to accomplish that I will be able to change the color of marker icons to be visible in the map. They are in the map in different colors. Those colors are correspondenting to the json cat_id key's.
1: "http://dev.openlayers.org/img/marker.png",
2: "http://dev.openlayers.org/img/marker-blue.png",
3: "http://dev.openlayers.org/img/marker-gold.png",
4: "http://dev.openlayers.org/img/marker-green.png",
Each marker icon that is in the map is getting it's position, color and other valuable data from the json objects in the data id in the script tag. I didn't code the part of that work's close with the openlayer libary's. I wrote the following part of the total of the script:
var json = document.getElementById('data').innerHTML;
json = JSON.parse(json); // converts text into JSON
// search criteria (could be changed)
var $search_postal = "8912JB";
var $search_number = "10";
var $change_cat = 1;
function changeColor() {
for (var key in json) {
if (json.hasOwnProperty(key)) {
if (json[key].postal == $search_postal) {
if (json[key].number == $search_number) {
alert("Gonna change cat_id " + json[key].cat_id + " of the number search string " + $search_number + " of the postal search string " + $search_postal + " to cat_id " + $change_cat);
json[key].cat_id = "1";
alert('Changed!');
const posts = json; // the constant that is used to display the icons
var myJSON = json;
document.getElementById('demo').innerHTML = JSON.stringify(myJSON, undefined, 2); // changes of the json data to see on screen
}
}
}
}
}
const posts = json; //the constant that is used to display the icons
var myJSON = JSON.stringify(json);
document.getElementById('demo').innerHTML = myJSON;
This script will change the cat_id of the given search input. In the example it does a search for postal 8912JB with number 1. Once it has made the loop to find it's position it will change the cat_id value of 3 to 1. In other words the json data has been changed. Since it is stored in the const posts I replace this cons with the changed data. My problem is that I'm unable to refresh the marker icon(s) in the map with the new json data that is changed (cat_id: 1 of postal 8912JB number 10). This has to do with less knowledge about openlayers and Javascript. I'm struggling already 2 weeks with this. Can anybody help me to accomplish this? If it changes from color is the only thing that is required. I would only need to give the changes to the variables $search_postal, $search_number and $change_cat.
Here is the page for debug: https://jsfiddle.net/j4z1vpht/4/
Thanks for any help,
grid
You need to update the new category to the map feature, like this:
const updateFeatureCategory = (featureId, categoryId) => {
const feature = marker_layer.getSource().getFeatureById(featureId);
const post = feature.get("post");
const updatedPost = {
...post,
cat_id: categoryId
}
feature.set("post", updatedPost);
}
function changeColor() {
...
json[key].cat_id = "1";
updateFeatureCategory(key, "1");
...
}
Here's a working fiddle: https://jsfiddle.net/wsm2h3qz/1/

Beginner fusion table query...two column location and st_distance

I'm altering a google example template to try to construct a query that finds the nearest location in the table to the user-entered city. And in this example, I just want to output the lat and lon and probably the "id" of the nearest table location to the user-inputted city. First, I'm using my LATITUDE column as location because it's been geocoded in the table as a two-column location. Strangely, when I alerted that variable, it only displays the latitude instead of the lat/lng coordinates. I thought since LATITUDE was acting as a two column location, it would return a lat/lng.
So when I run this simple query after pushing the "go" button after entering a city:
var queryList = [];
queryList.push("SELECT LATITUDE,LONGITUDE FROM ");
queryList.push(tableid);
and then alert the values, in the popup window, it works fine: http://greenandtheblue.com/whentoplant/test_query_geocode.html, alerting a lat and lon from the table...what I hoped it would.
But when I try to use the st_distance, I don't get any suggestion that it's working.
queryList.push("ORDER BY ST_DISTANCE(LATITUDE, LATLNG("+coordinate.lat()+","+coordinate.lng()+")) LIMIT 1");
http://greenandtheblue.com/whentoplant/test_query_geocode_notworking.html
I prefer this method of querying...seems simpler:
query: {
select: 'LATITUDE',
from: tableid
},
but I gathered from the example that I needed to put the second query (acted on when I push go) in an array of sorts, which makes it a bit more complicated.
I hope this is a clear enough question. Thanks for any help.
Shad
If I make the query like this:
queryList.push("SELECT STATION,STATION_NAME,ELEVATION,LATITUDE FROM ");
queryList.push(tableid);
//query seems to work when I comment out the line below.
queryList.push("ORDER BY ST_DISTANCE(LATITUDE, LATLNG("+coordinate.lat()+","+coordinate.lng()+")) LIMIT 1");
var query = encodeURIComponent(queryList.join(' '));
var gvizQuery = new google.visualization.Query(
'http://www.google.com/fusiontables/gvizdata?tq=' + query);
gvizQuery.send(function(response) {
var datatable = response.getDataTable();
var header = 'No results';
var content = 'Sorry, no store delivers here.';
if (datatable && (datatable.getNumberOfRows() > 0)) {
header = datatable.getValue(0, 0);
content = datatable.getValue(0, 1)+"<br>Station:"+datatable.getValue(0,0)+"<br>Elevation:"+datatable.getValue(0,2);
}
infoWindow.setContent('<h3>' + header + '</h3>' +
'<p>' + content + '</p>');
infoWindow.setPosition(coordinate);
infoWindow.open(map);
});
It works for me.
changed:
var query = encodeURIComponent(queryList.join('')); // empty string
to:
var query = encodeURIComponent(queryList.join(' ')); // single space

Iterating through YQL JSON results in geo.places via javascript

I'm trying to iterate through some JSON results from the YQL geo.places table using the YQL jQuery plugin (http://plugins.jquery.com/project/jquery-yql) troubleshooting with the following code;
$.yql("select * from geo.places where text=#{placename}", {
placename: '90210'
},
function(data) {
var Results = data.query.results;
$.each(Results.place, function(name, value) {
alert(name + ":" + value);
});
});
});
Except, whenever there is more than one "place" in the results, the alert will spit back "0:[object][object]", "1:[object][object]", etc (for each place). Whenever there is only one place result, the alert will spit back all the names and values of just the one place (woeid, name, country, admin1, etc.)
Essentially I'd like to...
input a zip code to YQL
verify the city/state/country from results against user submitted data
update latitude and longitude fields from the results
Thanks!
If Yahoo returns a single place, it does so as a property of results, not as an array of places. If it's not an array, you can't iterate. So test whether it's an array; if it's not, make it one:
$.yql("select * from geo.places where text=#{placename}", {
placename: '90210'
},
function(data) {
var Places = data.query.results.place;
if (!Places.length) Places = [Places];
$.each(Places, function(index, place) {
alert(index + ":" + place.name);
});
});
});

Categories

Resources