FB.api is there a way to limit individual fields - javascript

I'm using the Facebook Javascript SDK. Is there a way to limit the number of elements returned for a specific field when making a request for multiple fields.
Example: If I wanted to get the 'bio' and liked 'movies' from all my friends, but limit the number of movies returned to let's say 10 movies.
FB.api('/me/friends', { fields: 'bio, movies' }, function(response) {
// Do something with data
handleResponse(response);
});
If I add the limit parameter it only limits the number of friends returned, but I want ALL my friends returned and the number of movies limited.
FB.api('/me/friends', { fields: 'bio, movies', limit: 10 }, function(response) {
// Do something with data
handleResponse(response);
});
Is there any way to do this using the Javascript FB.api method? Any ideas/help is appreciated.
**Edit
OK, so using Tommy's example of 'field expansion' below, this is what my example FB.api call would look like if you wanted to limit the number of movies returned to 10:
FB.api('/me/friends', { fields: 'bio, movies.limit(10)' }, function(response) {
// Do something with data
handleResponse(response);
});

Yes, add another parameter called movies.limit.
Example call:
https://graph.facebook.com/me/friends?fields=movies&movies.limit=3&access_token=<access_token>

Related

Select2 not showing results in dropdown with AJAX

I'm working on creating an interface for some system I am working on and I am required to write the Javascript around pre-existing PHP AJAX functions that are used elsewhere in the system (purely as the person who does our DB stuff is too busy to adapt the code to my needs).
Using Select2 I need to make a select field where the user searches for their name in the database and selects the one matching it so it can then be posted to another AJAX function later. I have done this with the following code:
//<select id="sltMyName" style="width: 100%;"></select>
$("#sltMyName").select2({
ajax: {
type: "POST",
url: "includes/php/report_searchPlayers.php",
delay: 250,
data: function (params) {
return {
q: params.term // search term
};
},
processResults: function (data) {
console.log({ results: data.split(",") });
return { results: data.split(",") };
}
},
minimumInputLength: 1
});
This should turn a returned string in the format of name1,name2,name3,name... into the required format for Select2 to display, however, it does not currently work. The dropdown just appears blank.
I've seen some questions referring to a text and id attribute, however, they are all in the context of a JSON string being returned, so I am not sure if they are required here and how to utilise them in this context. Furthermore, I cannot find any of this in the documentation.
Any suggestions? Thanks in advance.
Data returned:
Tommy,Jak_Tommy_Lee_Jones,Tommy_Shelby,Tommy_Balboner,TommyCZ,GA_Tommy,VA_Tommy,Tommy_Skrattar,Tommy_Knocker,Tommy_of_Elektro,Tommy_the_Destroyer,Old_Tommy,tommy_of_house_shelby,TommyDermo,TommyC,TommyCash_CZ,Tommyb69k,SA_Tommy,tommyfaster,Tommy_See,Tommy_de_Destroyer,Tommy_of_Whiteroses,TommyShelby,Templar_Intiate_Tommy,Templar_Initiate_Tommy,tommysuckspp,Tommy_the_Overweight
I think I've figured it out. The main issue is that the data that Select2 wants to use needs to be an array of objects with at least a property named id and a property named text. In the processResults function, just create those objects & then the dropdown will populate with the data from your URL!
I've noticed that it tries to filter the data as i type, but since the url I passed in does not accept the parameters, it just returns the same data each time. Let me know if you need a more robust example.
See my fiddle at https://jsfiddle.net/yp0rp2kw/3/ for a working solution.

Facebook Javascript SDK /me multiple field calls with large photo type

I'm trying to add parameters to my api call to facebook's javascript sdk. So far all of the calls are working, but I am having issues with adding a parameter to the picture, I want to return a large picture or be able to specify the height and width.
FB.api('/me', {
fields: [
'last_name',
'first_name',
'email',
'location',
'picture'
],
parameters: {
type: 'large'
}
)
I would like to keep the syntax of the call because it is very readable, I want to add the type large to the picture field
Did you try it like this?
FB.api('/me', {fields: 'last_name,first_name,email,location,picture.type(large)'}, (response) => () {
console.log(response);
});
I never saw the fields parameter as array in any docs, you should use a string instead.

Youtube JS API cuePlaylist Filtering

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!

Recursion and asynchronous methods with a flag variable

I have the following method:
function getRelevantArticles(amount,
userSuggestions,
suggestionPage,
relevantArticles,
continueFlag,
success,
error)
{
if(continueFlag)
{
getSuggestedArticles(suggestionPage, userSuggestions, function (articles)
{
if(articles.length == 0)
getRelevantArticles(amount, userSuggestions, suggestionPage, relevantArticles, false, success, error); // continueFlag= false
getUnvisitedArticles(articles, function (unvisited)
{
for(var i = 0; i < unvisited.length; i++)
relevantArticles.push(unvisited[i]);
relevantArticles= filterRelevant(amount, userSuggestions, relevantArticles);
if(relevantArticles.length < amount)
getRelevantArticles(amount, userSuggestions, suggestionPage + 1, relevantArticles, true, success, error); // continueFlag= true
else
getRelevantArticles(amount, userSuggestions, suggestionPage, relevantArticles, false, success, error); // continueFlag= false
}, error);
}, error);
}
else if(success)
{
fillWithContent(relevantArticles, success, error); //Should be last method to execute
}
}
The context
I know it may be hard to understand and can be optimized a lot, I'll try my best to explain what it's doing (or trying to):
The method is first called with a flag of continueFlag= true, so it starts by calling getSuggestedArticles, which is an async method that makes an AJAX request. I pass in a callback function with the result of the request.
getSuggestedArticles gets me the article Ids related to the user suggestions. (The user suggestions is a list of topics that may be of interest to the user).
I pass in a suggestionPage because the suggestions can be a lot, and I should be able to get the relevant articles with just a few (the first page).
If no articles are retrieved, then it means we are out of suggestions (every suggestion has at least one article), i. e., we reached the last page, so we set the continueFlag flag to false, to call the finalizer method.
If there is at least one article, I call getUnvisitedArticles, which is another asynchronous method that makes an AJAX request. This method gives me the articles that were not visited or read by the user, which are the ones I care about.
I have a relevantArticles variable which keeps track of the articles that I found out to be relevant and will be presented to the user. Once I get the relevant ones from my current page of unvisited articles, and have appended them to the previous page's relevant ones, I check if I have the minimum amount of articles to show.
If I don't yet satisfy the minimum amount, then I go on with the next page (suggestionPage + 1);
If I reached the minimum threshold, then I go on with the finalizer method (continueFlag= false)
fillWithContent is the method which will be called when I finished identifying the relevant articles. It is an asynchronous method that will make an AJAX request, and will fill my article objects with additional information.
getSuggestedArticles(Number: suggestionPage, Array: userSuggestions, Function: success, Function: error)
Receives an array of user suggestions, and takes the nth page of this array (page size 100).
Let's suppose we call the method like this:
getSuggestedArticles(0, [ 745, 4567, 1500 ], function (data) {
var articles = data;
}, error);
The method makes request to Database Web API, and pass an array of suggested articles to the success function. In the preceding example, the articles variable would have an array like this (Note that all the returned suggested articles have at least one user suggestion among their topics):
[
{
id: 12345,
topics: [ 998, 1500, 323 ] //has user suggestion 1500
},
{
id: 45778,
topics: [ 009, 1500, 745] //Has user suggestion 745 and 1500
},
...
]
getUnvisitedArticles(Array: articles, Function: success, Function: error)
Receives an array of articles and returns all the ones who weren't visited by the user.
Let's suppose we call this method like this:
//We are using the same "articles" variable from the previous example
getUnvisitedArticles(articles, function (data) {
var unvisited = data;
}, error);
The function makes request to the Database Web Api and pass an array with the unvisited articles to the success function. In the preceding example, the variable unvisited would have an array like this:
[
{
id: 45778,
topics: [ 009, 1500, 745]
}
]
Notice that article with id 12345 is gone. This is because it has been visited by the user.
fillWithContent(Array: relevantArticles, Function: success, Function: error)
Receives an array of articles and fill these objects with additional information.
Let's suppose we call this method like this:
//We are using the same "unvisited" variable from the previous example
fillWithContent(unvisited, function (data) {
filledArticles = data;
}, error);
The function makes request to the Database Web Api and pass an array with the filled articles to the success function. In the preceding example, the variable filledArticles would have an array like this:
[
{
id: 45778,
topics: [009, 1500, 745],
title: 'Article title',
publicationDate: 'Some date',
author: 'Some author',
...
}
]
This is the array my caller is expeting, by caller I mean the one calling my getRelevantArticles function.
The problem
The problem with this method is that fillWithContent is called infinitely, therefore causing a great deal of requests to be made, the browser to crash, and a recursion overflow to arise.
I'm not calling this method from another place, so it has to be a problem with this function.
I writed a console.log(suggestionPage), and it seems it keeps on incrementing the variable infinitely too. It should have stopped at page 3, because articles.length == 0. But it's not stopping.
What is going on here?
I think you should split your workload into independent parts that are easy reason about and easy to combine for more complex results.
As I understand it, the work consists three basic parts, all done through Ajax:
[topic IDs] to [article stubs for those topics] (getSuggestedArticles)
[article stubs] to [relevant (unread) article stubs] (getUnvisitedArticles)
[article stubs] to [full articles] (fillWithContent)
All of those Ajax requests should be made in a paged manner, e.g. 1000 items are handled by 10 requests with 100 items each.
For that we define a utility function that takes a list of items, pages them, makes an Ajax request for each page (through a worker function we pass as an argument) and returns the combined result of all requests.
// utility: runs an ajax request and handles errors on the low level
function ajax(options) {
return $.ajax(options).fail(function(jqXHR, textStatus, errorThrown) {
console.log(textStatus, errorThrown, jqXHR);
});
}
// utility: makes paged Ajax requests through a worker function
function pagedAjax(ajaxFunc, items, pageSize) {
var temp = [].slice.call(items), page,
requests = [];
// start as many parallel Ajax requests as we have pages
while (temp.length) {
page = temp.splice(0, pageSize);
requests.push( ajaxFunc(page) );
}
// wait until all requests have finished, return combined result
return $.when.apply($, requests).then(function (results) {
var combined = [];
$.each(results, function (i, result) {
// result is an array [data, textStatus, jqXhr]
// push all contained items onto combined
// (the following assumes that data is an array of objects)
[].push.apply(combined, result[0]);
});
return combined;
});
}
Now we can set up our three worker functions. They take arbitrary amounts of input, because all paging is done by the utility function above:
// worker: retrieves a list of article IDs from topic IDs
function getSuggestedArticles(topics) {
return ajax({method: 'post', url: '/articlesByTopic', data: topics});
// or whatever API request returns a list of articles IDs from topic IDs
}
// worker: takes a list of article IDs, returns a list of _unread_ article IDs
function getUnvisitedArticles(articles) {
return ajax({method: 'post', url: '/unvisitedArticles', data: articles});
// or whatever API request returns a list of unvisited articles from IDs
}
// worker: takes a list of article IDs, returns a list of articles
function fillWithContent(articles) {
return ajax({method: 'post', url: '/articles', data: articles});
// or whatever API request fills articles with content
}
After that, combining the functions is not difficult anymore:
// takes a list of topic IDs, requests article IDs, filters them, returns actual articles
function getUnvisitedArticlesByTopic(topicIds) {
var pageSize = 100;
return pagedAjax(getSuggestedArticles, topicIds, pageSize)
.then(function (allArticles) {
return pagedAjax(getUnvisitedArticles, allArticles, pageSize);
})
.then(function (unvisitedArticles) {
return pagedAjax(fillWithContent, unvisitedArticles, pageSize);
});
}
And we can use it all through a very simple call:
// renders unvisited articles
function renderUnvisitedArticles() {
var topicIds = [9, 1500, 745];
getUnvisitedArticlesByTopic(topicIds).done(function (articles) {
$.each(articles, function (i, article) {
// show article on page
});
});
}
Benefits of this promise-based approach:
No callback hell.
Short functions that do exactly one thing.
No self-calling functions.
Good re-usability and testability of the individual parts.
Recommended reading is of course jQuery's documentation on Deferred objects.
Disclaimer: The code is indeed untested. If you find mistakes, tell me.

Making a step-by-step ajax request

I'm thinking about how to change a content of a div dynamically. So, here is the ajax request:
$.ajax({
url:'/foos',
cache: false,
type: 'get',
}).done( function( foo_array ) {
for( foo in foo_array ) {
$('#foo-container').append('<div class="foo-var">'+foo+'</div>');
}
});
So bassically, this ajax append all foo-var divs from the server, but if the foo_array is too long or a big very big array there is a problem because i think that takes more and more time depending on the foo_array's length
How can I append one by one??, how can I query one by one and append in foo-container instead query all foos and make an iteration??
I want to do something like this
if(foos.hasNext()){ $.ajax..... append(foo)....}
foos is an array made by many documents from a mongodb database, so I cant get the length of the array because depends of the query's find() arguments..
I'm using nodejs, mongodb, expressjs and jquery for ajax
Sorry for my bad English, and thank you all!
EDIT 2
this is an example of the data in mongodb
{category:1, name:'robert',personal:true,option:'class'}
{category:1, name:'alfredo',personal:false,option:'class'}
{category:4, name:'ricardo',personal:true,option:'class'}
{category:1, name:'genaro',personal:true,option:'class'}
{category:2, name:'andres',personal:false,option:'class'}
{category:1, name:'jose',personal:true,option:'class'}
db.collection.find({personal:true}) // gives me 4 documents
db.collection.find({option:'class'}) // gives me 6 documents
db.collection.find({category:4}) // gives me 1 document
i dont know how many documents can get from the cursor, i need to charge one by one cause there are 5097841 documents in the databse so, ajax can take long time to return all the information, i need to query one by one if hasNext() in the cursor of mongodb
You can use skip and limit and can make multiple requests. It's like paging.The following syntax may help you
db.collection.find().skip(200).limit(100);

Categories

Resources