Why does Facebook give me an empty response on Android? - javascript

I've inherited a Facebook app, which doesn't work 100% as intended. I don't understand the logic of the previous developer, but I'm not strong enough in the Facebook API to rewrite it.
The app has a form, in which the user (when logged in) needs to answer a few questions. When he clicks submit, we want to check whether or not he likes the page. The form will only be submitted if he does.
window.fbAsyncInit = function() {
FB.init({
appId : '[myappid]',
channelUrl : '//www.myurl.com/channel.aspx',
status : true,
cookie : true,
xfbml : true
});
};
$("form input[type='submit']").on("click", function(e) {
e.preventDefault();
setTimeout(function() {
FB.api('/me/likes/MY-PAGE-ID',function(response) {
if(response.data) {
alert(response.data); // I get this (empty) alert
if(!isEmpty(response.data)) {
alert('all ok'); // I never get this :(
//$("form").submit();
} else {
alert("You must \"Like\" the page."); // Every time
}
}
});
}, 1000);
// Unrelated code edited out - end brackets may not match 100%
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
return false;
}
return true;
}
Now, on desktop this works as intended. However, on Android it doesn't. It does enter the first if(response.data) { but the following alert box which should return the data, returns empty. It therefore never enters the following if-statement.
The part I don't understand, is why it enters the first if (response.data exists) but not the second (because the response is somehow empty, even if the page is liked).
I don't have a different device to test on, sadly.
Am I overlooking some obvious glaring mistake? What can I do to salvage it?

I figured it out. It seems I was not asking for the necessary permissions, because I thought "likes" was part of the basic info. Silly of me, I realize.
FB.login(function(response) {
// Truly amazing code goes here
}, { scope : 'user_likes' }); // Scope is important, yo
What I don't understand, is why it worked on desktop, but not on mobile, but I'm happy now that it works.

Related

localStorage checker not working when it looks fine?

So I have a script on one part of my domain that sets the localStorage:did to true, and then send them to another part of my domain.
The page, which the viewer was sent to, checks to see if the did is true, and it is, but for some reason the function that starts if did is true does not work (but I have used that function a few days ago, so it works).
$(document).ready(function() {
var is = localStorage.getItem('did');
if (is == 'true') {
localStorage.setItem('did','false');
window.alert("ok")
$.get('give.php' , {} , function(response){
//window.alert(response);
});
} else {
window.alert("no")
}
});
This is the checker. I don't think there is something wrong with it, but if I am mistaken, please tell me.
localStorage.setItem('did','true');
This is from the original page which sets did to true. I'm pretty sure that's how you do it.
When logging did on the other page, it comes out as true, but why is the if function not firing?

Using location.reload on Chrome is not working as it should, using the same code in Firefox works fine

I am making a Snake game using Javascript and checking if the user has touched the borders, if he has than it's gameover and a game over function is called which shows a confirm box with it's content based on the language of the html file because i have 2 html files: one for French and one for English.
this.alert = alert;
this.gameOver = function() {
const langCheck = document.getElementById("html").lang;
if (langCheck === "fr") {
alert = confirm("\t\tPerdu!\n\n Votre longueur était: " + this.eaten);
} else {
alert = confirm(
"\t\tGame Over!\n\n Your snake length was: " + this.eaten
);
}
console.log(alert);
if (alert === true) {
document.location.reload(true);
} else {
document.location.reload(true);
}
};
In chrome when i click either Ok or Cancel the confirm box just reopens instantly and it doesn't reload (Edit: Forgot to mention but the page just hangs after clicking ok) even though console logging alert it returns true. So why isn't this working on Chrome when on Firefox it's working perfectly?
I tried many different location.reload i saw when i researched on it like window.location.reload() but it's the exact same.
I'm stuck here because as i said in Firefox it works flawlessly and that's where i initially tested when i programmed the game but when i finished i decided to take a look if on Chrome it worked, that's when i found out.
Instead of location.reload() you can try (code taken from another solution online)
setTimeout(function(){
window.location.reload();
},100);
Also considering you're running the same code if alert === true and if it's not true, I would just get rid of the if/else and run the code directly (if that's what you intend to do)
document.location.reload(true); will be ok for Google chrome you can check the fiddle example here.
You have other alternatives also
setTimeout(function(){ window.location.reload(); });
window.location.reload();
A short note :
if (alert === true) {
document.location.reload(true);
} else {
document.location.reload(true);
}
Irrespective of result you are doing the same operation here, So you can simplify the code like below. The if else is not at all needed there.
document.location.reload(true);
it should be
window.location.reload(false);

Unique jQuery popup issue

So I have to have a popup form display once per user session, the client wants it to popup after 10 seconds. If the user navigates to another page on the site, the form still needs to popup and not display after the user closes it on any other part of the site. Here is the jQuery I have written so far.
$(document).ready(function() {
sessionStorage.setItem('firstVisit', '1');
if (sessionStorage.getItem('firstVisit') === "1") {
setTimeout(function() {
$('.verif').fadeIn('fast');
}, 1000);
} else {
$('.verif').hide();
}
});
I have the form on each page and right now it just pops up all the time. Am I using the wrong method for the situation? All suggestions are welcome.
Note that the line 2 always sets firstVisit as '1' in session storage. This way, the expression for if will always be true and thus, user will always see the popup.
You need to get the item first, and check its value. Then if it doesn't exist, set it.
$(document).ready(function() {
var item = sessionStorage.getItem('firstVisit');
if (!item || item !== "1") {
setTimeout(function() {
$('.verif').fadeIn('fast');
}, 1000);
sessionStorage.setItem('firstVisit', '1');
} else {
$('.verif').hide();
}
});
Also, using sessionStorage is not a good idea as it is volatile across page refreshes. You, instead, may want to use localStorage for this as you mentioned that this needs to be done for any page.

How do I ask the user to confirm they want to leave the page?

I have a web site that contains several pages where the user can add and edit information. In order to provide a consistent UI, I have the following JavaScript function...
function setWindowBeforeUnload(changed) {
$(window).on("beforeunload", function() {
if (confirmLeave && changed && changed()) {
return "You haven't saved the information. If you leave this page, the information will be lost.";
}
});
}
confirmLeave is a global variable that specifies if we are to ask them for confirmation before navigating away (which we don't if we are navigating to another page after a successful save). changed is a function that checks if the entity has changed.
This is called from a details page (say the customer page) as follows...
$(document).ready(function() {
setWindowBeforeUnload(customerChanged);
});
function customerChanged() {
// Checks the data and returns true or false as appropriate
}
This all worked fine until recently, when a change in Chrome broke it.
I have searched for hours, and found loads of people suggesting code like this...
addEventListener('beforeunload', function(event) {
event.returnValue = 'You have unsaved changes.';
});
...which works fine as it is, except that it fires the warning whenever they leave the page, irrespective of whether or not the data has changed.
As soon as I try to add any logic (such as my checking code in the first sample), it doesn't work...
function setWindowBeforeUnload(changed) {
addEventListener('beforeunload', function(event) {
if (confirmLeave && changed && changed()) {
event.returnValue = 'You have unsaved changes.';
}
});
}
With this code, I can navigate away from the page without getting a warning.
Is there any way to reproduce my original behaviour now?
You can use logic in the handler, you just can't have a custom message any more.
See the code below. Use the "Run code snippet" to simulate navigation. Run the snippet, run it again no confirm. Toggle the button to "false" run the snippet and get a confirm.
var test = true;
function otherTest() {
return true;
}
addEventListener('beforeunload', function(event) {
if(!test || !otherTest()) {
event.returnValue = 'You have unsaved changes.';
}
});
document.getElementById('theButton').addEventListener('click', function(event) {
test = !test;
this.innerHTML = test.toString();
});
<p>Click the button to turn the confirm on and off</p>
<button id="theButton">true</button>

Google+ Sign-In with JavaScript callback issue

I am working on a function which allows users to sign in on my website with their Google account.
My code is based on the Google documentation (others signIn() options are in meta tags).
function login() {
gapi.auth.signIn({'callback':
function (authResult) {
if (authResult['status']['signed_in']) {
console.log('Okay');
}else {
console.log('Error');
}
}
});
}
When I call login(), a Google pop up appears, I approve the terms of my application and everything works fine.
But the callback is called twice :
1st case: If I never approved apps permissions then the callback will be call at the opening of the pop up AND when I will approve the permissions. So it will write "Error" and "Okay".
2nd case: If I already approved the permissions, it will write "Okay" two times.
I added the option 'approvalprompt': 'force' to the signIn() function. The callback function is no longer called twice but it forces the user to approve the app's permissions, even if previously approved. So it's not user friendly.
Is there a friendly user way to approve the app's permissions one time without having two callback ?
Thank you.
I'm facing this same issue here, but I'm calling gapi.auth.signIn() via a button click handler. The callback is still called twice. One thing I noticed between the two authResult objects was that authResult.status.method is 'AUTO' in the first call (before the popup window appears) and is 'PROMPT' in the second call after the window is auto-dismissed due to previous authorisation.
The solution I'm exploring now is to ignore the AUTO instance and only process the PROMPT instance of the callback. Not sure how this will work once I revoke the permissions within Google due to the lack of details in the docs on the 'status' object.
I am facing the same issue: signin callback called twice in case of user that already granted permission; the local variable approach (initializedGoogleCallback) isn't working for me because it call the callback one time only when the user already granted access, but didn't call it if the user is the new one.
After a bit of research (i especially dig in site using the g+ auth) i noticed that all of them use the 'approvalprompt': 'force' and they have the already granted user to reapprove a "Offline Access" policy everytime.
Even the google example i followed to setup my app (https://developers.google.com/+/web/signin/javascript-flow) even if it did not mention it, it uses the "force" parameter.
For the moment it seems the only solution if you want to use the javascript flow (that mean if you need a personal style signin button)
Try to register first call in some local variable and then process it
This quick solution helps me:
function login() {
var initializedGoogleCallback = false
gapi.auth.signIn({
'callback': function (authResult) {
if (!initializedGoogleCallback) {
// after first call other will be ignored
initializedGoogleCallback = true;
if (authResult['status']['signed_in']) {
console.log('Okay');
} else {
console.log('Error');
}
}
}
});
}
also you can add following code before call gapi.auth.signIn
window.removeEventListener('load')
Like the Drew Taylor's answer, to avoid the double callback with the pure javascript sign in solution, you can check the user's session state:
if (authResult["status"]["method"] == "PROMPT") {...}
I think that the callback with the AUTO method is fired by the bottom welcome bar that appears on first login.
That is the intentional plan for page level config! It being present in the page causes the callback to fire when the Javascript is finished loading. What you should do is prepare for that in your code.
Don't show the sign in button until you have received a callback - if authResult['status']['signed_in'] == true, then treat the user as signed in (setup a session etc, whatever you would normally do). If it is false, then display the button.
function signinCallback(authResult) {
if (authResult['status']['signed_in']) {
document.getElementById('signinButton').setAttribute('style', 'display: none');
// Do sign in stuff here!
} else {
document.getElementById('signinButton').setAttribute('style', 'display: block');
}
}
I would avoid using approval prompt force if you can!
finally i solved with a workaround; i don't know if this is the correct way to approach or i am just cheating but i do this way:
first of all some script in the page (i am using bootstrap + jquery)
function render() {
//I am not using it but kept anyway
}
var i;
// Function called from a onClick on a link or button (the 'sign in with g+' button)
function gp_login() {
i=0;
$('#alertbox').remove();
var additionalParams = {
'callback': signinCallback,
/*'approvalprompt': 'force' finally removed*/
};
$('#gp-login').button('loading');
gapi.auth.signIn(additionalParams);
}
function signinCallback(authResult) { //my callback function
var email='';
var given_name='';
if (authResult['status']['signed_in']) { //get some user info
gapi.client.load('oauth2', 'v2', function() {
gapi.client.oauth2.userinfo.get().execute(function(resp){
email = resp.email; //get user email
given_name = resp.given_name; //get user email
family_name=resp.family_name;
id=resp.id;
if (i<2) { //execute the doLogin just one time (my cheat)
doLogin(email,given_name,family_name,id); //dologin does my logic with an ajax call to signup/register user to my site
}
i=2;
});
});
} else {
// Update the app to reflect a signed out user
}
}
this approch have the doLogin part called just one time, but the callback is called twice (gapi.client.oauth2.userinfo.get() this function is called twice); with a bit more tweaking with the if / var check i think is possible to call everything once.
This way if the user already granted the auth, it will be automatically signed.
I notice that sometimes google have a popup layer on the bottom of layer showing a "welcome back message", but i didn't understand when it appears or if i have to call it manually

Categories