I am having a bit of trouble with the Facebook JS SDK, specifically when using the FB.api() method. I have a list that gets populated from calling a php script using JQuery.get(), and with it, for each list item, comes the Facebook User ID. There are three types of "list items" that have different HTML for each, and I need to make a FB.api() call for each item, because each will come from a different user.
Here is the code I'm currently working with:
function( data ){
// Parse the json data
var parsed = jQuery.parseJSON( data );
// Create arrays for each message type
notifications = parsed.notifications;
gifts = parsed.gifts;
requests = parsed.requests;
// Counter and message to add
var i = 0;
var message = '';
var userData;
var displayPicUrl = '';
//
// NOTIFICATIONS
//
if( notifications && notifications.length > 0 ) {
// Loop through and create a new list item for each notification
for( i = 0; i < notifications.length; i++ ) {
// Get originator user data
FB.api( notifications[i].originator, function( response ) {
userData = response;
displayPicUrl = "http://graph.facebook.com/"+userData.id+"/picture";
message = '<li class="message">' +
'<img src="'+displayPicUrl+'" width="50" height="50" alt="Not one of the five birds I know." title="Not one of the five birds I know" />'+
'<p class="messageText">'+notifications[i].message+'.</p>' +
'<button class="acceptButton">Ok</button>' +
'</li>';
document.getElementById( 'notifications' ).innerHTML += message;
});
} //end loop
} //end if
//
// GIFTS
//
if( gifts && gifts.length > 0 ) {
// Loop through and create a list item for each gift
for( i = 0; i < gifts.length; i++ ) {
FB.api( gifts[i].originator, function( response ) {
if( !response || response.error ) {
alert( 'An error occured retrieving gifts')
} else {
userData = response;
displayPicUrl = "http://graph.facebook.com/"+userData.id+"/picture";
message = '<li class="message">' +
'<img src="'+displayPicUrl+'" width="50" height="50" alt="Not one of the five birds I know." title="Not one of the five birds I know" />'+
'<img class="giftImage" src="'+gifts[i].url+'" width="50" height="50" title="'+gifts[i].name+'" alt="'+gifts[i].name+'" />' +
'<p class="messageText">'+gifts[i].message+'</p>' +
'<button class="declineButton giftDecline">Decline</button>' +
'<button class="acceptButton giftAccept">Accept Gift</button>' +
'<span style="display:none;" id="giftId">'+gifts[i].giftId+'</span>' +
'</li>';
document.getElementById( 'gifts' ).innerHTML += message;
}
});
}
} // end if
//
// REQUESTS
//
if( requests && requests.length > 0 ) {
// Loop through and create a list item for each request
for( i = 0; i < requests.length; i++ ) {
FB.api( requests[i].originator, function( response ) {
if( !response || response.error ) {
alert( 'An error occured retrieving Requests' );
} else {
userData = response;
displayPicUrl = "http://graph.facebook.com/"+userData.id+"/picture";
message = '<li class="message">' +
'<img src="'+displayPicUrl+'" width="50" height="50" alt="Not one of the five birds I know." title="Not one of the five birds I know" />'+
'<img class="giftImage" src="'+requests[i].url+'" width="50" height="50" />' +
'<p class="messageText">'+requests[i].message+'</p>' +
'<button class="declineButton requestDecline">Decline</button>' +
'<button class="acceptButton requestAccept">'+requests[i].okButtonLabel+'</button>' +
'</li>';
document.getElementById( 'requests' ).innerHTML += message;
}
});
}
} // end if
The problem that I seem to be having is that once it hits the parts for Gifts and Requests, both the Gifts and Requests arrays become "undefined," which is odd because the code works perfectly fine when it's not wrapped in the callback of FB.api()... And, oddly enough, this problem does not seem to occur for the Notifications section. The gifts, requests, and notifications are just arrays of objects returned from the database as I said using JQuery.get() and there are no problems until I wrap the stuff in the api() method.
Any help would be greatly appreciated.
Cheers
If they are undefined only when wrapped in a FB.api() then your getting a facebook error. There are many reasons that this can happen, so its hard to pinpoint the exact cause, but I'll throw out a few ways that I deal with these:
Add an access token to your graph call, some facebook calls require it.
You need to make sure that you're application has the proper facebook code in it. For HTML include:
You also need to include this code in some document.ready sort of call:
//Facebook iFrame include
window.fbAsyncInit = function () {
FB.init({ appId: AppID, status: true, cookie: true, xfbml: true });
FB.Canvas.setAutoResize();
};
(function () {
var e = document.createElement('script');
e.async = true;
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
} ());
There may be a problem with how you set this up in facebook. Make sure that all URLs match. If they do not then your application will throw errors. This must be exact (www.ex.com and ex.com are different, and only one will work)
Make sure that under "On Facebook" Canvas URL and Tab URL match as well
Your graph call is wrong. Try adding an alert(displayPicUrl); call to your code, it may show you what errors you are getting. If that doesn't work, then try to reproduce the graph url call and enter that in yourself to see what that returns.
Hopefully one of those work
Related
Battlefield Page
In the image above, there is a page that has a battlefield with 20 users on it. I have written JavaScript to capture the data and store it in a MySQL db. The problem comes into the picture when I need to hit next to go to the next page and gather that data.
It fetches the next 20 users with an Ajax call. Obviously when this happens, the script can't log the new information because the page never loads on an Ajax call which means the script doesn't execute. Is there a way to force a page load when the Ajax link is clicked?
Here's the code:
grabData();
var nav = document.getElementsByClassName('nav')[0].getElementsByTagName('td')[2].getElementsByTagName('a')[0];
nav.addEventListener("click", function(){
grabData();
});
function grabData(){
var rows = document.getElementsByClassName('table_lines battlefield')[0].rows;
var sendData = '';
for(i=1; i < rows.length -1 ; i++){
var getSid = document.getElementsByClassName('table_lines battlefield')[0].getElementsByTagName('tr')[i].getElementsByTagName('td')[2].getElementsByTagName('a')[0].href;
var statsID = getSid.substr(getSid.indexOf("=") + 1); //Grabs ID out of stats link
var name = document.getElementsByClassName('table_lines battlefield')[0].getElementsByTagName('tr')[i].getElementsByTagName('td')[2].textContent.replace(/\,/g,"");
var tff = document.getElementsByClassName('table_lines battlefield')[0].getElementsByTagName('tr')[i].getElementsByTagName('td')[3].textContent.replace(/\,/g,"");
var rank = document.getElementsByClassName('table_lines battlefield')[0].getElementsByTagName('tr')[i].getElementsByTagName('td')[6].textContent.replace(/\,/g,"");
var alliance = document.getElementsByClassName('table_lines battlefield')[0].getElementsByTagName('tr')[i].getElementsByTagName('td')[1].textContent.trim();
var gold = document.getElementsByClassName('table_lines battlefield')[0].getElementsByTagName('tr')[i].getElementsByTagName('td')[5].textContent.replace(/\,/g,"");
if(alliance == ''){
alliance = 'None';
}
if(gold == '??? Gold'){
gold = 0;
}else{
gold = gold.replace(/[^\/\d]/g,'');
}
sendData += statsID + "=" + name + "=" + tff + "=" + rank + "=" + alliance + "=" + gold + "#";
}
$.ajax({
// you can use post and get:
type: "POST",
// your url
url: "url",
// your arguments
data: {sendData : sendData},
// callback for a server message:
success: function( msg ){
//alert(msg);
},
// callback for a server error message or a ajax error
error: function( msg )
{
alert( "Data was not saved: " + msg );
}
});
}
So as stated, this grabs the info and sends to the php file on the backend. So when I hit next on the battlefield page, I need to be able to execute this script again.
UPDATE : Problem Solved. I was able to do this by drilling down in the DOM tree until I hit the "next" anchor tag. I simply added an event listener for whenever it was clicked and had it re execute the JavaScript.
Yes, you can force a page load thus:
window.location.reload(true);
However, what the point of AJAX is to not reload the page, so often you must write javascript code that duplicates the server-side code that builds your page initially.
However, if the page-load-code-under-discussion runs in javascript on page load, then you can turn it into a function and re-call that function in the AJAX success function.
Reference:
How can I refresh a page with jQuery?
In the image I have the code to display only the first element ( song, image , artist, etc ... ) .
I would like to know how to make it show me :
When a user clicks on that button, show a new modal with all the
results of the tracks search you performed previously.
When a user clicks on one of the track names, update the player with
that track's information, including its audio.
The button is already created.
$('#song_btn').on('click', function Search_Song (event) {
event.preventDefault();
var song = $('#song_input').val();
var request = $.get('https://api.spotify.com/v1/search?q=' + song +'&type=track');
function Data_Songs (song) {
var track = song.tracks.items[0];
$('.song_title').text(track.name);
$('.artist_name').text(track.artists[0].name);
var cover = '<img src="' + track.album.images[0].url + '">';
$('.cover_image').html(cover);
var audio = '<audio class="js-player" src="' + track.preview_url + '">';
$('.audio').html(audio);
var more_results = '<br/><button type="submit" class="btn btn-primary" id="more_btn">Ver más Resultados</button>';
$('.more_result').html(more_results);
};
function handle_Error () {
console.error('¡¡ Ha Fallado !!');
}
request.done(Data_Songs);
request.fail(handle_Error);
});
So it seems like you have button to trigger the event...Here are your next steps:
Take an input (through a text field for example) and search for it through the API.
Next, obtain the parsed JSON from the API.
Then you'll be able to do what you are doing in your Data_Songs function...
Here's my implementation:
$('#song_btn').on('click', function(){
var BASE_URL = 'https://api.spotify.com/v1/'
var QUERY = $('#search_field').val(); // This is the value of your text field
var spotify_json = $.get(BASE_URL + 'search?type=track&query=' + QUERY, function(data){
console.log(data.tracks); // Do whatever you want with them after here!
// Ex. alert(data.tracks[0].href);
})
})
Note that I used a success handler on the $.get() method, which is a little different from your code.
To use your Data_Songs function in the $.get() function,
var spotify_json = $.get(BASE_URL + 'search?type=track&query=' + QUERY, Data_Songs(data));
So I'm working on a project from a book where TaffyDB is used to create a collection of people. The project is a simple chatroom, where the list of users is generated as an html list of online users in the window. Currently I'm using fake data to test, and I have one for each loop (in jquery) that works correctly, printing five "avatars" to the screen.Yet, my each loop to print the online users runs twice: why is this? These two loops use the exact same setup, yet the second runs twice.
The for each that works:
people_db().each(function(person,idx){
var class_list;
if( person.get_is_anon() ){ return true; }
class_list = ['spa-avtr-box'];
if( person.id === chatee.id ){
class_list.push('spa-x-is-user');
}
$box = $('<div/>')
.addClass(class_list.join(' '))
.css( person.css_map )
.attr('data-id', String(person.id) )
.prop( 'title', spa.util_b.encodeHtml(person.name) )
.text( person.name )
.appendTo( $nav );
});
The loop that runs twice:
people_db().each(function(person,idx){
var select_class = '';
console.log(person);
if( person.get_is_anon() || person.get_is_user() ) {
return true;
}
if( chatee && chatee.id === person.id ){
select_class = 'spa-x-select';
}
list_html
+= '<div class="spa-chat-list-name'
+ select_class + '" data-id="' + person.id + '">'
+ spa.util_b.encodeHtml(person.name) + '</div>';
});
if( !list_html ){
list_html = String()
+ '<div class="spa-chat-list-note">'
+ 'To chat alone is the fate of all great souls...<br><br>'
+ 'No one is online'
+ '</div>';
clearChat();
}
jqueryMap.$list_box.html(list_html);
}
Any ideas what I'm doing wrong? I've gone through the rest of my code extensively and I'm not calling it twice, I'm almost certain is has to be something with the loop.
I'd start by making sure you're not calling it twice.
If you look at the console, does
console.log(person);
print twice?
If so unbind whatever is calling
people_db().each(function(person,idx){
before you bind it.
I am retrieving data from Parse in my Wordpress page fine. I can append the names of my objects into a page in Wordpress, but as soon as a try to append a HTML tag like <h1> or <p>, I get an error within my Chrome console:
Uncaught SyntaxError: Unexpected token ILLEGAL
Below is the code within my wordpress page that works without errors:
<div id="list1"><h1>Beer List</h1></div>
<div id="list2"><h1>Tap List</h1></div>
<script type="text/javascript">
if (typeof jQuery != 'undefined') {
Parse.initialize("", "");
var Objs = Parse.Object.extend("Obj");
var query = new Parse.Query(Objs);
query.ascending("name");
query.find({
success: function(results) {
var obj1String = '';
var obj2String = '';
for(var i=0;i<results.length;i++)
{
var object = results[i];
obj1String= obj1String +' '+object.get('name')+'</br>';
if(object.get('isObj2') == true){
obj2String = obj2String +' '+object.get('name')+'</br>';
}
}
jQuery( "#list1" ).append( obj1String );
jQuery( "#list2" ).append( obj2String );
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
}
</script>
But when I add, for example a tag to one of my objStrings, I get the error. i.e.:
obj1String= obj1String +'<h1>'+object.get('name')+'</h1></br>';
Here is how the page is rendering, any why the error is happening. It seems to be adding a line break when it sees those tags:
for(var i=0;i<results.length;i++)
{
var object = results[i];
obj1String= obj1String +' //line break added here
<h1>'+object.get('name')+'</h1>
<p></br>';
if(object.get('isObj2') == true){
objString = obj2String +' '+object.get('name')+'</br>';
}
I have see other threads for this error (i.e. here). But I could not get any suggestions there to work.
Any help would be greatly appreciated, thanks!
I've had a similar problem to this before and I fixed it by making sure all the HTML tags in the JavaScript are on the same line.
As for wordpress template files you can read more about it here http://codex.wordpress.org/Page_Templates. Simply it will allow you to use a PHP file as a template to display that page.
I am working on a PhoneGap iOS Facebook app and I am working on showing the user's newsfeed. Here is my code so far:
<script>
function showPosts() {
FB.api('/me/home', function(response) {
console.log(response);
if (!response.error) {
var markup = '';
var messages = response.data;
for (var i = 0; i < messages.length && i < 5; i++) {
var message = messages[i];
markup += '<p><img src="' + message.picture + '">' + message.message + '<img src="https://graph.facebook.com/' + message.from['id'] + '/picture">' + message.from['name'] + '</p><br>';
}
document.getElementById('newsfeedposts').innerHTML = markup;
}
});
}
</script>
Right now, if there is no message in a post, "undefined" is displayed. Also, when there is no message picture, there is an empty image icon, because the <img> tag is still being loaded. Would it be possible to create an if statement saying if message.picture is empty than don't display <img src="message.picture">?
The same goes for the post message. If message.message is empty, could I create an if statement saying don't display anything if there is no message, eliminating "undefined"?
If an if statement will work, where should I place it? I tried placing an if statement in "markup" but I couldn't get it to work.
Pretty simple:
if (typeof message.picture != 'undefined') {
// message.picture is not empty, so do the stuff inside of here.
}
Since message will always exist, and picture is inside message, even if picture is undefined it would not throw an error. Therefore you can do this:
if (message.picture) {
//Do things here.
}