I'm getting a set of points along my route but in the paths where the car is on a highway, the segments are distant. I'd like to get a finer granulation of the routing. Is it possible?
$.ajax({
url: 'https://route.cit.api.here.com/routing/7.2/calculateroute.json',
type: 'GET', dataType: 'jsonp', jsonp: 'jsoncallback',
data: {
waypoint0: '59.159486,17.645687',
waypoint1: "59.397635,17.891626",
mode: 'fastest;car;traffic:enabled',
app_id: 'VXZP5fwHfh2WQIWnp0Zx',
app_code: 'NgKq-kVEUMKxxNpBKP_hBg',
departure: 'now'
},
success: function (data) {
moves = data.response.route[0].leg[0].maneuver;
timeAvailable = 45;
trackPoints = moves.map(function (d) { return {
lat: d.position.latitude,
lng: d.position.longitude,
time = d.travelTime }; });
for (var i = 0; i < trackPoints.length; i++) {
smackUpArea(map, trackPoints[i], timeAvailable);
timeAvailable -= trackPoints[i].time;
};
}
})
Optimally, I'd like t get a point every x kilometer or every y minutes driven. Is that possible at all?
To get more fine-grained routing information, you can request the links that the route is composed of. To do so, add the legattributes query parameter with value links or li. This will add a link array to the response for each leg object in each route. Furthermore, you can decide what information you want to see for each link, using the linkattributes query parameter. You could include things like length and shape of the link, as well as the remaining time or distance on the route at the moment a user reaches this link along the route. There's many other possibilities, which you can find here (look for RouteLinkAttributeType).
So in your code, this might look something like:
data: {
waypoint0: '59.159486,17.645687',
waypoint1: "59.397635,17.891626",
mode: 'fastest;car;traffic:enabled',
app_id: 'VXZP5fwHfh2WQIWnp0Zx',
app_code: 'NgKq-kVEUMKxxNpBKP_hBg',
departure: 'now',
legattributes: 'li',
linkattributes: 'le,rt'
},
And an actual link returned in the response would look something like:
{
"linkId":"-733185668",
"shape":["52.5158286,13.3774424","52.5158286,13.3774424"],
"length":0,
"remainTime":249,
"speedLimit":13.8888893,
"_type":"PrivateTransportLinkType"
}
I think there is one possible solution, but this would not be optimal.
I would add shape in the route attributes as a parameter of the request. And from the response, iterate through the every two pairs of lat/long to calculate the route of them. This would break down the segment into smaller pieces. It is still not optimal like what you asked in the question though. Using time-based or distance-based isoline with start as center then get the intersection seems painful to me. Hopefully someone has a better solution to this.
Related
I'm currently trying to get select2 to work, however, I'm struggling a little bit right now. What I want to achive, is fairly simple: I fetch a JSON from a webserver which consists out of key/value pairs (one ID to one string). After fetching those, I want to create options out of those and add them to select2 so they user can select one of them.
I kept as close to the code in the documentation as humanly possible:
$('#catSearchBox').select2({
width: '500px',
ajax: {
url: "url/to/data",
dataType: 'json',
delay: 250,
cache: false,
data: function (params) {
return {
searchKey: params.term
};
},
processResults: function (data, params) {
$.each(data, function(catName, catId) {
var newOption = new Option(catId, catName, false, false);
$('#catSearchBox').append(newOption).trigger('change');
});
}
},
placeholder: 'Suche nach Kategorie ...',
minimumInputLength: 3
});
Now, everything here works up until the append. When I search for anything, the options are generated correctly, however, the append seems to fail as no options are displayed at all. It looks like this:
However, it's not because of an empty or invalid response, because the options are definitely created:
I'm kinda at a loss here, I don't see why my code is not working, especially since I kept as close as possible to the code in the documentation (https://select2.org/data-sources/ajax and https://select2.org/programmatic-control/add-select-clear-items).
Does anyone have any idea on how to solve this problem? If you need any additional information I might have missed out, please let me know.
processResults Is not used to append options to the select2. It is used to transform the response from the API. It should return a valid array of objects to feed select2.
Something like:
var newData = [];
$.each(data, function(catName, catId) {
newData.push({ id: catId, text: catName });
});
return { results: newData };
I believe the main problem is in your processResults function and Select2's expectations of it.
From what I was able to partly read and partly deduce from the documentation at https://select2.org/data-sources/ajax#transforming-response-data is that processResults is supposed to return an object containing a key results and those results should be an array of objects. Further down there were some examples and one of them shows that those objects contain 2 keys - id and text.
Moreover, the info box at the top of the docs it says that select2 will create <option> only for element that was chosen (it's done for performance reasons). This implies that you are not supposed to create the <option> elements yourself, but just return the data in the expected format and select2 will take care of the rest.
This is a fiddle based on your code: https://jsfiddle.net/mkilmanas/jkx2mwv5/1/ and it doesn't work, it throws an error of trying to access results of undefined.
This is another fiddle with analogous behaviour but done according to those findings from the documentation: https://jsfiddle.net/mkilmanas/3s0kupaw/5/
I'm not sure if this is the solution but there are 2 things in your code that I don't like so much.
Try this:
processResults: function (data, params) {
// First, remove all previous elements
$('#catSearchBox').html('');
$.each(data, function(catName, catId) {
var newOption = new Option(catId, catName, false, false);
$('#catSearchBox').append(newOption);
});
// Second, fire change when all elements are appended
$('#catSearchBox').trigger('change');
}
I have a dashboard that is displayed on the main screen when the user logs on.
Initially I have two graphics, one of lines and one of bars. The problem is that the graphical queries are a bit heavy and take about 30 seconds to load.
I already did optimization of the queries and they improved a little, the problem is that when wanting to access other options of the system does not leave me, because I have to wait until the graphs are loaded.
It is difficult for the user to wait until the graphs load, I would like to know if there is a way that other system options can be accessed, regardless of the graphs being loaded.
The code I have is the following:
/*
* You get the urls that the user has access to in the dashboard. This is executed * when the user is on the main screen.
*/
$.getJSON(getBaseUri() + 'dashboard/index', function(data) {
var datas = data['return'];
if(datas == ""){
$productivities.removeClass('chartID');
$productions.removeClass('chartID');
$combox.addClass('hidden');
}
for (var i in datas) {
receiveData({
div : datas[i].div,
title : datas[i].privilege,
sign : datas[i].sign,
iconClass : datas[i].class,
id : datas[i].id,
label : datas[i].label,
xaxis : datas[i].xaxis,
yaxis : datas[i].yaxis,
background: datas[i].background,
url : datas[i].route,
type : datas[i].type
});
}
});
/*
* The function receiveData () receives the parameters of the dashboard that the user has access and brings the data of each url consulted, and according to the type of graph the function is executed.
*/
function receiveData(param) {
$.ajax({
url: param.url,
method: 'GET',
dataType: 'json',
success: function(data){
var datas = data['return'];
if(param.type === "LineChart"){
lineChart({
data : datas,
div : param.div,
title: param.title,
url : param.url
});
$loaderProduction.addClass("hidden");
}
if (param.type === "BarChart") {
barCharts({
data : datas,
div : param.div,
title : param.title,
url : param.url,
label : param.label,
xaxis : param.xaxis,
yaxis : param.yaxis,
background: param.background
});
$loaderProductivity.addClass('hidden');
}
if (param.type === "Indicator") {
indicatorsChart({
data : datas,
div : param.div,
title : param.title,
icon : param.sign,
class : param.iconClass,
idDash: param.id
});
}
if (param.type === "Sowing") {
sowingIndicator({
data : datas,
div : param.div,
title : param.title,
idDash: param.id
});
}
},
error: function(error){
console.log(error);
}
});
}
Basically these are the functions I'm using to display dashboard graphs.
I think that this case I need to use WebWorkers, but I donĀ“t know how to use it
Right now you're making an AJAX call for every iteration of your for...in loop. Depending on the number of iterations this could mean a huge overhead, although it is best to reduce the number of round trips to the server in all cases.
You could try to modify both the front- and backend logic to combine multiple datasets into one request instead of one dataset per request and multiple requests.
Other than this there are no obvious bottlenecks in your code, so if the slowness persists the problem is most likely with your backend code.
Of course you got some options:
go through a Single Page Application, i.e. make your app in the way that, when user navigate other application options, the execution remains always in the same page. It may be heavy, exspecially if your application is already structured. Angular (or AngularJs), as other frontend frameworks, do this for you in an automated way.
let execute your loading js in an iframe, old and dirty but it works. When finished send a notification message in the main page,
Anyway you should optimize your code too, reducing number of calls from n (one for each element in datas) to 1.
I want to add ordering to the search query for the Youtube JS API but I cannot get it to work.
This is a standard search using browser
https://www.youtube.com/results?search_query=test
This is part of the script that does the same search but using the player
player.cuePlaylist({listType:'search', list:'test'});
Tested it and it works perfectly. However when I want to add ordering to the search query. It doesn't work.
For example, the searching for test with extra filter "Today". IT doesn't work (play list is empty array).
The browser search is
https://www.youtube.com/results?sp=CAESAggC&q=test
This however
player.cuePlaylist({listType:'search', list:'sp=CAESAggC&q=test'});
Does not yield a result. The documentation states:
If the listType property value is search, then the list property specifies the search query.
I tried replacing & with & a m p ;(without spaces) but still no dice.
I also couldn't find anything related to filtering in the documentation.
Basically the question is how do I apply filtering to the cuePlaylist method.
Edit:
Tried this:
player.cuePlaylist({listType:'search', list:'test', sp:'CAESAggC'});
The sp didn't do anything
I'm not sure if cuePlaylist supports filtering but, the closest I can suggest is to use a search function
type: 'GET',
data: {
key: 'API_KEY',
q: query,
part: 'snippet'
}
})
then add a order by or any filters you can add, you can check Search document for additional info.
Here is a snippet for it :
// search video
$("#search").click(function() {
var query = $("#query").attr("value");
if ( !query ) {
return;
}
$.ajax({
url: 'https://www.googleapis.com/youtube/v3/search',
dataType: 'json',
type: 'GET',
data: {
key: 'AIzaSyBda8mhaE8x10RiF0uzvBMPUszbUIQsy0g',
q: query,
part: 'snippet'
}
}).done(function(data) {
player.stopVideo();
player.clearVideo();
$('#video').fadeIn();
var videos = [];
console.log(data);
$.each(data.items, function() {
console.log(this.id.videoId)
videos.push(this.id.videoId);
});
// sort by favorite
videos = videos.sort(function(a, b) {
return b.favoriteCount - a.favoriteCount;
});
player.cuePlaylist(videos);
});
});
});
Here is the source for the snippet, I made some adjustment using the tutorial because the github is using api v2.
Hope this helps!
I'm trying to create a leaflet routing machine route in my web app using waypoints stored in a database. I'm first creating the control:
var routeControl = L.Routing.control({waypoints: [null]}).addTo(map);
getTestRoute("1");
The function 'getTestRoute' pulls in my waypoints from a db as lat/long pairs and adds them to the control, here's the function:
function getTestRoute(route){
$.ajax({
url: './get_route.php',
type: 'POST',
dataType: 'JSON',
data: {
getRoute: route
},
success: function (res) {
$.each(res,function(key,value){
var newLatLng = new L.LatLng(res[key].latitude, res[key].longitude);
routeControl.spliceWaypoints(0, 0, newLatLng);
})
}
});
}
My issue is that instead of seeing a route on the map I'm seeing my waypoints (five in total) added to the map as markers with no routing between them.
Please please help!!!
Here is a fiddle of my issue: http://jsfiddle.net/c4yfy4ek/46/
As can be seen on the fiddle no routes are created between the points, and the points are added as markers (which I'm assuming is unexpected??).
The problem is the use of spliceWaypoints combined with an undocumented feature in Leaflet Routing Machine.
When the control is created, it will automatically add waypoints such that the route always has a start and an end waypoint, it such waypoints are not already supplied. That means: whatever you do, getWaypoints will always return an array with at least two entries; if not provided, these waypoints will however have their latLng properties set to undefined, indicating the location has not yet been provided.
In the code in question, the control is created and will get two waypoints added implicitly by Leaflet Routing Machine, with undefined locations. Later, you add a couple of new waypoints, but the implicit two waypoints remain, without locations. No route will be calculated, since two waypoints are missing locations.
The solution is to build the array of waypoints first, and then call setWaypoints, instead of spliceWaypoints.
See an updated version of the fiddle: http://jsfiddle.net/c4yfy4ek/53/
I'm using the graph api endpoint /PAGE_ID/posts to get all posts from a facebook page.
Now I want the full sized image from these posts. The picture property of the returned objects gives me only a cropped version of that image.
With the object id from these posts and the API endpoint /OBJECT_ID/picture I get the only the small, normal and album sized version of the picture. But with a little modification to the URL I managed to get the full sized image.
Example
This URL:
https://graph.facebook.com/10152843929471041/picture
redirects to this URL:
https://fbcdn-sphotos-b-a.akamaihd.net/hphotos-ak-xpa1/t31.0-8/s720x720/10838228_10152843929471041_5251228402651650719_n.jpg
I removed the 720x720 from that URL to get this URL:
https://fbcdn-sphotos-b-a.akamaihd.net/hphotos-ak-xpa1/t31.0-8/s/10838228_10152843929471041_5251228402651650719_n.jpg
which is finally the full sized image.
I think, that I can achieve this modification with a regex pattern. But now is my question, how I can get the URL after the redirect from the original URL (the first one).
Any ideas or simpler solutions?
This is how you can get larger pictures:
/OBJECT-ID/picture?width=500&height=500
Or:
/OBJECT-ID/picture?type=large
Also take a look at answer in this thread: Facebook Graph API : get larger pictures in one request
Edit: As this does not seem to work with Object IDs, you can just grab the image from this response:
https://graph.facebook.com/10152843929471041
Look out for the "images" array.
One can also request the images collection of a photo object, then search for the highest resolution entry.
See documentation. Code:
MyFacebookWrapper.getBestImage = function(photoId) {
var deferred = new $.Deferred();
var params = { fields: "images" };
FB.api("/" + photoId, "get", params,
function (response) {
console.log("MyFacebookWrapper.getBestImage, response:");
console.log(response);
var images = _.sortBy(response.images, 'width');
var best = _.last(images)
deferred.resolve(best);
}
);
return deferred.promise();
};
Usage:
MyFacebookWrapper.getBestImage("photo Id ...").then(function(image) {
console.log(image);
});