Related
I'm testing my web app login flow on the iOS8. I notice that on iOS8, the login dialogue pops up, but after logging in, it just stays there, showing a blank page.
The login works, because the page behind it shows the user information, but the popup just stays there, while it should close automatically. On iOS7 and iOS6 it does close. On desktop browsers it closes too.
I've tested some other random sites (for example brainfall.com) using FB.login(): same thing.
Does anyone have a fix for this?
Any help is much appreciated!
Check this:
fb_window_redirect
Override de window.open method. This allows you to know what windows are opened.
Then you can redirect the window opened by the FB SDK.
...
window._open = window.open; // saving original function
//Override the function
window.open = function(url,name,params) {
var new_window = window._open(url,name,params);
if (typeof onWindowOpen === "function") {
onWindowOpen(url, name, params, new_window);
}
return new_window;
};
...
var openedWindows = [];
var fbWindows = [];
function onWindowOpen(url, name, params, new_window) {
...
// Filter the facebook oauth request
if (url.contains('facebook.com')
&& url.contains('oauth')) {
fbWindows.push(new_window);
}
openedWindows.push(new_window);
}
...
//On fb login button pressed callback:
FB.login(function(response) {
//Try login
if(response.authResponse) {
//Login succesful
// Fb window redirect.
// see onWindowOpen
var fbwin = fbWindows[0];
var redirect_url = ''
fbwin.location = redirect_url;
}
},
{scope: 'email,publish_stream,user_birthday'});
...
i am just trying to implement facebook and twitter in my Webworks App and cannot get them work together.
I am using the FaceBook-OAuth-2 and the Twitter-OAuth-1 sample and i just put both stuff together and my problem is that only the first startOAuth() opens a window in the app to login the second doesn't so if i first clicked facebook it works after when i try twitter nothing happens.
https://github.com/blackberry/BB10-WebWorks-Samples
thanks
function setClickHandlers() {
console.log('set click handlers');
var fb = document.getElementById('facebookOn');
fb.addEventListener('click', function(e) {
// if the childWindow is already open, don't allow user to click the button
if(childWindow !== null) {
return false;
}
e.preventDefault();
toast('Contacting Facebook...');
setTimeout(function() {
startOAuth();
}, 500);
});
console.log('set twitter click handlers');
var tw = document.getElementById('twitterOn');
tw.addEventListener('click', function(e) {
// if the childWindow is already open, don't allow user to click the button
if(childWindow !== null) {
return false;
}
e.preventDefault();
toast('Fetching access token...');
setTimeout(function() {
twittergetAccessToken();
}, 500);
});
}
I would start by adding some debug code in your click handler to see if that's getting called when you click the button in the first place.
If it is, then I recommended you use Web Inspector (console) to see if there are any errors. If there are, they'll show up there.
Good reference for Web Inspector here - http://developer.blackberry.com/html5/documentation/web_inspector_overview_1553586_11.html
If the click handler is not being fired then perhaps you have the wrong element ID, or the setClickHandlers function is not being executed.
I'm using Facebook JS SDK to develop a Facebook Page Tab application. There is a button in landing page. When clicked, user will be asked to install the App if they haven't done so.
The codes are as follow:
<script type="text/javascript">
function installApp() {
FB.login(function(response) {
if (response.authResponse) {
var accessToken = response.authResponse.accessToken;
}
if (response.status === 'connected') {
window.location = 'share.php';
} else {
alert('Please install app first');
}
}, {scope:'friends_likes,email'});
}
</script>
By default FB.Login will result in a popup box asking for permission. Is there any alternative way to AVOID the popup box? I have seen other Facebook apps successfully achieve this, but I have no idea how they did it.
You can use the Javascript Api with a Graph Api call for this,
function fbLogin() {
var oauth_url = 'https://www.facebook.com/dialog/oauth/';
oauth_url += '?client_id=APP_ID_HERE';
oauth_url += '&redirect_uri=' + encodeURIComponent('https://apps.facebook.com/APP_NAMESPACE/');
oauth_url += '&scope=email'
window.top.location = oauth_url;
}
then you can call it in a custom button with the onclick event:
Custom Login
Have you went through the Authentication documentation?
It pretty much cover all of the options that are available to you. i.e.:
Client-Side Authentication
Server-Side Authentication
Authentication within a Page Tab
You can probably use any of those approaches, but the 3rd probably will fit best.
The created the following web application:
http://www.web-allbum.com/
I also added it to the Chrome Web Store:
https://chrome.google.com/webstore/detail/idalgghcnjhmnbgbeebpdolhgdpbcplf
The problem is that when go to the Chrome Web Store and install this app the Facebook login windows hangs at a "XD Proxy" window. While the connect itself works, this blank window can confuse the users.
I did my research, and this seems to be a Chrome issue:
https://code.google.com/p/chromium/issues/detail?id=59285#c26
If you uninstall the app from Chrome, the problem disappears.
Is there any workaround for this problem?
Similar stackoverflow questions:
Facebook connect login window locking in Chrome
FB.login dialog does not close on Google Chrome
facebook connect blank pop up on chrome
https://stackoverflow.com/questions/4423718/blank-page-with-fb-connect-js-sdk-on-after-permission-request
This is my Facebook connect in case it helps:
FB.init({
appId : window.__FACEBOOK_APP_ID__,
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true, // parse XFBML
channelUrl : window.__MEDIA_URL__ + 'channel.html', // channel.html file
oauth : true // enable OAuth 2.0
});
FB.XD.Flash.init();
FB.XD._transport = "flash";
if (A.networks.facebook.connected) {
FB.getLoginStatus(function (response) {
// Stores the current user ID for later use
that.network_id = response.authResponse.userID;
if (!response.authResponse) {
// no user session available, someone you dont know
A.networks.facebook.connected = false;
}
callback();
});
}
else {
callback();
}
};
The Solution
Thanks to the reekogi reply I was able to workaround this issue. Here is the full implementation:
In order to avoid the XD Proxy problem, you have to connecte to Facebook without using the FB.login, this can be achieved by manually redirecting the user to Facebook page.
I had this login function in my code:
_facebook.connect_to_network = function (callback) {
FB.login(function (response) {
if (response.authResponse) {
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function (response) {
// Stores the current user Id for later use
that.network_id = response.id;
console.log('Good to see you, ' + response.name + '.');
callback();
});
}
else {
console.log('User cancelled login or did not fully authorize.');
that.connected = false;
callback();
}
}, {scope: window.__FACEBOOK_PERMS__});
};
Which I replaced by this code:
_facebook.connect_to_network = function (callback) {
var url = 'https://www.facebook.com/connect/uiserver.php?app_id=' + window.__FACEBOOK_APP_ID__ + '&method=permissions.request&display=page&next=' + encodeURIComponent(window.__BASE_URL__ + 'authorize-window?my_app=facebook&my_method=login') + '&response_type=token&fbconnect=1&perms=' + window.__FACEBOOK_PERMS__;
window.open(url);
};
The new code opens a popup which connects to Facebook and returns to the url specified in the 'next' parameter. I added some extra parameters in this callback url so that the javascript code could check for it and close the popup.
This code is executed when the Facebook redirects to the callback url:
_facebook.parse_url_params = function () {
// This is the popup window
if (URL_PARAMS.my_method === 'login') {
window.opener.A.networks.facebook.connected = true;
self.close();
}
};
URL_PARAMS is just a helper object that contains all the url parameters.
I still believe that this is a Chrome issue, but since this workaround has worked and solved my problem I am marking this question as solved.
Could you call a javascript redirect to get permissions then redirect back to the http://www.web-allbum.com/connected uri?
I described this method in detail here ->
Permissions on fan page
EDIT:
The method I demonstrated before will be deprecated when OAuth 2.0 comes into the requirements.
Here is the code, adapted for OAauth 2.0 (response.session is replaced with response.authResponse)
<div id="fb-root"></div>
<script>
theAppId = "YOURAPPID";
redirectUri = "YOURREDIRECTURI"; //This is the page that you redirect to after the user accepts the permissions dialogue
//Connect to JS SDK
FB.init({
appId : theAppId,
cookie: true,
xfbml: true,
status: true,
channelURL : 'http://yourdomain.co.uk/channel.html', // channel.html file
oauth : true // enable OAuth 2.0
});
//Append to JS SDK to div.fb-root
(function() {
var e = document.createElement('script');
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);
}());
//Check login status and permissions
FB.getLoginStatus(function(response) {
if (response.authResponse) {
// logged in and connected user, someone you know
} else {
//Redirect to permissions dialogue
top.location="https://www.facebook.com/connect/uiserver.php?app_id=" + theAppId + "&method=permissions.request&display=page&next=" + redirectUri + "&response_type=token&fbconnect=1&perms=email,read_stream,publish_stream,offline_access";
}
});
</script>
Just tried and tested, worked fine in chrome.
I didn't try the solution proposed by Cesar, because I prefer to stick with Facebook's official javascript SDK.
Nevertheless I would like to add a few observations:
Indeed, the blocking problem only happened on Chrome after installing from Chrome Web Store. Uninstalling the web app solves the problem. (tested with legacy authentication method, without oauth 2.0). After closing the XD Proxy popup manually, my application was working properly.
After switching to asynchronous FB.init() and enabling oauth 2.0 option, my application would not even get a valid facebook connect status at login time ({authResponse: null, status: "unknown"})... Again, uninstalling it from the Chrome Web Store, it's working... ({authResponse: Object, status: "connected"})
No problem encountered with Safari, in any of these cases.
In IE8 - this can be caused by your flash version. I tried everything and nothing worked until I disabled flash. More details from this blog:http://hustoknow.blogspot.com/2011/06/how-facebooks-xdproxyphp-seemed-to-have.html#comment-form
Open a new browser tab in Chrome and see if you have the Facebook 'App' installed. If so, drag it to the bottom right corner to uninstall. Once uninstalled the XD Proxy will work.
Reference: facebook connect blank pop up on chrome
I was experiencing same problem for all browsers. When user clicked "login" button, a popup opened and hanged; and unless user killed browser process, it caused a high load on CPU. If user managed to see "allow" button and click it however, then it appeared a "xd proxy" blank window and nothing happened. That was the problem.
After long investigations, I noticed my new JS code which proxies setInterval/clearInterval/setTimeout/clearTimeout methods, caused this problem. Code is as follows:
window.timeoutList = new Array();
window.intervalList = new Array();
window.oldSetTimeout = window.setTimeout;
window.oldSetInterval = window.setInterval;
window.oldClearTimeout = window.clearTimeout;
window.oldClearInterval = window.clearInterval;
window.setTimeout = function(code, delay) {
window.timeoutList.push(window.oldSetTimeout(code, delay));
};
window.clearTimeout = function(id) {
var ind = window.timeoutList.indexOf(id);
if(ind >= 0) {
window.timeoutList.splice(ind, 1);
}
window.oldClearTimeout(id);
};
window.setInterval = function(code, delay) {
window.intervalList.push(window.oldSetInterval(code, delay));
};
window.clearInterval = function(id) {
var ind = window.intervalList.indexOf(id);
if(ind >= 0) {
window.intervalList.splice(ind, 1);
}
window.oldClearInterval(id);
};
window.clearAllTimeouts = function() {
for(var i in window.timeoutList) {
window.oldClearTimeout(window.timeoutList[i]);
}
window.timeoutList = new Array();
};
window.clearAllIntervals = function() {
for(var i in window.intervalList) {
window.oldClearInterval(window.intervalList[i]);
}
window.intervalList = new Array();
};
Removing these lines solved my problem. Maybe it helps to who experiences the same.
It appears this has been fixed in Chrome. No longer happens for us in Mac Chrome 15.0.874.106
Another workaround is to use this code after you call FB.init():
if (/chrome/.test(navigator.userAgent.toLowerCase())) {
FB.XD._origin = window.location.protocol + '//' + document.domain + '/' + FB.guid();
FB.XD.Flash.init();
FB.XD._transport = 'flash';
}
The pop-up window remains open and blank, but I found that in my Chrome Web Store app, the authentication goes through when this code is used.
This bug is also filed on Facebook Developers here: http://developers.facebook.com/bugs/278247488872084
I've been experiencing the same issue in IE9, and it seemed to stem from upgrading to Flash Player 10. The answers suggested already did not work for me and I'd lost hope in trying to fix it since finding an open bug at Facebook covering it. But Henson has posted an answer on a similar question that fixed it for me. In the JavaScript in my site master I removed the lines
FB.UIServer.setLoadedNode = function (a, b) {
//HACK: http://bugs.developers.facebook.net/show_bug.cgi?id=20168
FB.UIServer._loadedNodes[a.id] = b;
};
and now it works. (N.B. I have not checked to see if the IE8 issue those lines were intended to overcome returns.)
I have problem with web after adding icon to Home Screen. If the web is launched from Home Screen, all links will open in new window in Safari (and lose full screen functionality). How can I prevent it? I couldn't find any help, only the same unanswered question.
I found JavaScript solution in iWebKit framework:
var a=document.getElementsByTagName("a");
for(var i=0;i<a.length;i++)
{
a[i].onclick=function()
{
window.location=this.getAttribute("href");
return false
}
}
The other solutions here either don't account for external links (that you probably want to open externally in Safari) or don't account for relative links (without the domain in them).
The html5 mobile-boilerplate project links to this gist which has a good discussion on the topic: https://gist.github.com/1042026
Here's the final code they came up with:
<script>(function(a,b,c){if(c in b&&b[c]){var d,e=a.location,f=/^(a|html)$/i;a.addEventListener("click",function(a){d=a.target;while(!f.test(d.nodeName))d=d.parentNode;"href"in d&&(d.href.indexOf("http")||~d.href.indexOf(e.host))&&(a.preventDefault(),e.href=d.href)},!1)}})(document,window.navigator,"standalone")</script>
If you are using jQuery, you can do:
$("a").click(function (event) {
event.preventDefault();
window.location = $(this).attr("href");
});
This is working for me on iOS 6.1 and with Bootstrap JS links (i.e dropdown menus etc)
$(document).ready(function(){
if (("standalone" in window.navigator) && window.navigator.standalone) {
// For iOS Apps
$('a').on('click', function(e){
e.preventDefault();
var new_location = $(this).attr('href');
if (new_location != undefined && new_location.substr(0, 1) != '#' && $(this).attr('data-method') == undefined){
window.location = new_location;
}
});
}
});
This is an old question and many of the solutions here are using javascript. Since then, iOS 11.3 has been released and you can now use the scope member. The scope member is a URL like "/" where all paths under that scope will not open a new page.
The scope member is a string that represents the navigation scope of
this web application's application context.
Here is my example:
{
"name": "Test",
"short_name": "Test",
"lang": "en-US",
"start_url": "/",
"scope": "/",
...
}
You can also read more about it here. I also recommend using the generator which will provide this functionality.
If you specify the scope, everything works as expected similar to
Android, destinations out of the scope will open in Safari — with a
back button (the small one in the status bar) to your PWA.
Based on Davids answer and Richards comment, you should perform a domain check. Otherwise links to other websites will also opened in your web app.
$('a').live('click', function (event)
{
var href = $(this).attr("href");
if (href.indexOf(location.hostname) > -1)
{
event.preventDefault();
window.location = href;
}
});
If using jQuery Mobile you will experience the new window when using the data-ajax='false' attribute. In fact, this will happen whenever ajaxEnabled is turned off, being by and external link, by a $.mobile.ajaxEnabled setting or by having a target='' attribute.
You may fix it using this:
$("a[data-ajax='false']").live("click", function(event){
if (this.href) {
event.preventDefault();
location.href=this.href;
return false;
}
});
(Thanks to Richard Poole for the live() method - wasn't working with bind())
If you've turned ajaxEnabled off globally, you will need to drop the [data-ajax='false'].
This took me rather long to figure out as I was expecting it to be a jQuery Mobile specific problem where in fact it was the Ajax linking that actually prohibited the new window.
This code works for iOS 5 (it worked for me):
In the head tag:
<script type="text/javascript">
function OpenLink(theLink){
window.location.href = theLink.href;
}
</script>
In the link that you want to be opened in the same window:
Link
I got this code from this comment: iphone web app meta tags
Maybe you should allow to open links in new window when target is explicitly set to "_blank" as well :
$('a').live('click', function (event)
{
var href = $(this).attr("href");
// prevent internal links (href.indexOf...) to open in safari if target
// is not explicitly set_blank, doesn't break href="#" links
if (href.indexOf(location.hostname) > -1 && href != "#" && $(this).attr("target") != "_blank")
{
event.preventDefault();
window.location = href;
}
});
I've found one that is very complete and efficient because it checks to be running only under standalone WebApp, works without jQuery and is also straightforward, just tested under iOS 8.2 :
Stay Standalone: Prevent links in standalone web apps opening Mobile Safari
You can also do linking almost normally:
TEXT OF THE LINK
And you can remove the hash tag and href, everything it does it affects appearance..
This is what worked for me on iOS 6 (very slight adaptation of rmarscher's answer):
<script>
(function(document,navigator,standalone) {
if (standalone in navigator && navigator[standalone]) {
var curnode,location=document.location,stop=/^(a|html)$/i;
document.addEventListener("click", function(e) {
curnode=e.target;
while (!stop.test(curnode.nodeName)) {
curnode=curnode.parentNode;
}
if ("href" in curnode && (curnode.href.indexOf("http") || ~curnode.href.indexOf(location.host)) && curnode.target == false) {
e.preventDefault();
location.href=curnode.href
}
},false);
}
})(document,window.navigator,"standalone")
</script>
This is slightly adapted version of Sean's which was preventing back button
// this function makes anchor tags work properly on an iphone
$(document).ready(function(){
if (("standalone" in window.navigator) && window.navigator.standalone) {
// For iOS Apps
$("a").on("click", function(e){
var new_location = $(this).attr("href");
if (new_location != undefined && new_location.substr(0, 1) != "#" && new_location!='' && $(this).attr("data-method") == undefined){
e.preventDefault();
window.location = new_location;
}
});
}
});
For those with Twitter Bootstrap and Rails 3
$('a').live('click', function (event) {
if(!($(this).attr('data-method')=='delete')){
var href = $(this).attr("href");
event.preventDefault();
window.location = href;
}
});
Delete links are still working this way.
I prefer to open all links inside the standalone web app mode except ones that have target="_blank". Using jQuery, of course.
$(document).on('click', 'a', function(e) {
if ($(this).attr('target') !== '_blank') {
e.preventDefault();
window.location = $(this).attr('href');
}
});
One workaround i used for an iOS web app was that I made all links (which were buttons by CSS) form submit buttons. So I opened a form which posted to the destination link, then input type="submit"
Not the best way, but it's what I figured out before I found this page.
I created a bower installable package out of #rmarscher's answer which can be found here:
http://github.com/stylr/iosweblinks
You can easily install the snippet with bower using bower install --save iosweblinks
For those using JQuery Mobile, the above solutions break popup dialog. This will keep links within webapp and allow for popups.
$(document).on('click','a', function (event) {
if($(this).attr('href').indexOf('#') == 0) {
return true;
}
event.preventDefault();
window.location = $(this).attr('href');
});
Could also do it by:
$(document).on('click','a', function (event){
if($(this).attr('data-rel') == 'popup'){
return true;
}
event.preventDefault();
window.location = $(this).attr('href');
});
Here is what I'd use for all links on a page...
document.body.addEventListener(function(event) {
if (event.target.href && event.target.target != "_blank") {
event.preventDefault();
window.location = this.href;
}
});
If you're using jQuery or Zepto...
$("body").on("click", "a", function(event) {
event.target.target != "_blank" && (window.location = event.target.href);
});
You can simply remove this meta tag.
<meta name="apple-mobile-web-app-capable" content="yes">