Links will not open in iframe target in an iOS standalone web app - ios

I am running into a pickle. When I view my web app within mobile safari via iOS 6, I am able to successfully open up my basic target links <a href="link.html" target="mainframe"into my retrospective iframe <iframe src="http://www.linkexample.org/" name="mainframe"></iframe>
Though when the app is opened via standalone all the links exit out of the app and into Mobile Safari. You can see a working example at http://lacitilop.com/m2
Anyone have any suggestions on how to fix this?

You'll need to write some javascript to change the src of the iframe.
For a start, get your app working so that links will not open Safari by using something like the following (it's using jquery by the way):
if (window.navigator.standalone) {
$(document).on(
"click",
"a",
function (event) {
event.preventDefault();
var aurl = $(event.target).attr("href");
if (aurl) {
location.href = $(event.target).attr("href");
}
else {
location.href = this;
}
}
);
}
then you'll need to modify it to work with iframes too.
For more iphone app stuff you'll want to look at this:
http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html

Related

Facebook share counter not working on iOS

I have facebook share counter on my website and it works correct,but on iOS Safari it doesn't show show number of shares. If I'm using incognito mode (private), it works correctly... Any suggestions?
$.getJSON( 'http://graph.facebook.com/?id=http://example.com', function( fbdata ) {
$('#fb-count').text(fbdata.share.share_count)
});
Even if I'll use simple alert() inside function it won't appear...
Ok, found a solution using PHP.
$fb = json_decode( file_get_contents('https://graph.facebook.com/http://example.com') );
$shares = $fb->share->share_count;

Open a link from a webview in a chrome app within the same webview

I am trying to create a chrome kiosk app that will open a webpage that contains links in a webview and then load the links within the same webview. However, the links on the webpage that I am working with are target="_blank" and I am getting the error <webview>: A new window was blocked wehn they are clicked. I found a solution to this here and tried to implement its suggestion like this:
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create(
'window.html',
{ 'width': 1000, 'height': 1000 },
function(win) {
win.contentWindow.onload = function() {
var webview = win.contentWindow.document.querySelector('#webview');
webview.addEventListener('newwindow', function(e) {
chrome.app.window.create(e.targetUrl,window.open()
});
};
}
);
});
However, I would like to have the link open not in the browser, but in the same webview that the link was launched from.
Is there some way to capture the target URL, strip it of its target="_blank" attribute, and then load the URL in the original webview?
An event listener in the content script will capture the URL when the newwindow event is fired. Once the URL is captured, it's a simple thing to set the URL as the webview's source.
var webview = document.querySelector('#webview');
webview.addEventListener('newwindow', function (e) {
//prevent the link from attempting to open a new window
e.preventDefault();
webview.src = e.targetUrl;
});
Because this script doesn't open any new windows, it doesn't have to be run specifically in the app's background script.

How to detect if a link works?

I need to know if a link will open.
See Maximilian Hoffmann's answer for a more robust solution.
An approach like this is common - hijack the timeout to redirect to a different URL. Would this approach work for you?
<a id="applink" href="comgooglemaps://?q=Red+Lobster+Billings">Show map</a>
<script type="text/javascript">
var backup = "http://maps.google.com/?q=Red+Lobster+Billings";
function applink(fail){
return function() {
var clickedAt = +new Date;
setTimeout(function(){
if (+new Date - clickedAt < 2000){
window.location = fail;
}
}, 500);
};
}
document.getElementById("applink").onclick = applink(backup);
</script>
The solution is adding an iframe with the URL scheme to your page. It silently fails if the app is not installed, so you need to check via a timer if opening the app worked or not.
// detect iOS
if (['iPhone', 'iPad'].indexOf(navigator.platform) > -1) {
// create iframe with an Apple URL scheme
var iframe = document.createElement('iframe');
iframe.src = 'twitter://';
// hide iframe visually
iframe.width = 0;
iframe.height = 0;
iframe.frameBorder = 0;
// get timestamp before trying to open the app
var beforeSwitch = Date.now();
// schedule check if app was opened
setTimeout(function() {
// if this is called after less than 30ms
if (Date.now() - beforeSwitch < 30) {
// do something as a fallback
}
});
// add iframe to trigger opening the app
document.body.appendChild(iframe);
// directly remove it again
iframe.parentNode.removeChild(iframe);
}
I wrote a post with a more detailed example that uses this approach to open the twitter app on iOS if installed.
There isn't a way for you to know if a link will work but there is for Safari with something called Smart App Banners
<!DOCTYPE html>
<html>
<head>
<meta name="Google Maps" content="app-id=585027354"/>
</head>
<body>
The content of the document......
</body>
</html>
What it basically does is checking if an app is installed. If it's not installed the user will be directed to the app store. If it's installed the user will be able to open the app from the website with the relevant data you'd be normally passing using the url scheme.
You could use if for Google Maps.
The down side of this is that it will only work on Safari but it's still better than nothing.

Jquery mobile full site link loads full site, but links there go to mobile site

I think I've looked over 50 different examples online, but can't find the same problem.
I've got a jquery mobile site and a full site (it's a WordPress site). I've put the following code in the header.php file of the full site:
<script type="text/javascript">
function urlParam(name){
var results = new RegExp('[\\?&]' + name + '=([^amp;#]*)').exec(window.location.href);
if(results)
return results[1] || 0;
else
return '';
}
if(urlParam('view') == 'full'){
}
if(urlParam('view') == ''){
// <![CDATA[
var mobile = (/iphone|ipad|ipod|android|blackberry|mini|windows\sce|palm/i.test(navigator.userAgent.toLowerCase()));
if (mobile) {
document.location = "http://mysite.com/mobile/index.html";
}
// ]]>
}
</script>
This works fine and when I load the full site on my iphone it redirects to the mobile version.
However, I have a link to the full site on my mobile site like so:
<li>Full Site</li>
When I click this link it DOES take me to the full site, but if I click on any links on the full site, I get redirected back to the mobile site.
FYI, I've tried (and failed) setting cookies. All the scripts I've used haven't worked (I'm sure it's my fault) and I end up stuck in a continuous redirect.
First off, you only need the statement: if(urlParam('view') != 'full'){ check if mobile and redirect.. }
I suggest you use document.write(urlParam('view')); to check what urlParam('view') actually returns. This should make it easier for you to debug. Though the best way to debug is to use chrome or firefox tools.

PhoneGap InAppBrowser: open iOS Safari Browser

In our PhoneGap iOS application, we are using the InAppBrowser plugin to display some content, and we need to open a page in Safari from within the InAppBrowser.
How can we have links from within the InAppBrowser open in Safari?
From the phonegap documentation:
Opens a URL in a new InAppBrowser instance, the current browser instance, or the system browser.
var ref = window.open(url, target, options);
ref: Reference to the InAppBrowser window. (InAppBrowser)
url: The URL to load (String). Call encodeURI() on this if the URL contains Unicode characters.
target: The target in which to load the URL, an optional parameter that defaults to _self. (String)
_self: Opens in the Cordova WebView if the URL is in the white list, otherwise it opens in the InAppBrowser.
_blank: Opens in the InAppBrowser.
_system: Opens in the system's web browser.
So to answer your question, use:
window.open(your_url, '_system', opts);
Note that the domain will need to be white-listed.
Update 4/25/2014:
I think I kind of misunderstood the question (thanks to commenter #peteorpeter) -- you want to have some way to click a link in the InAppBrowser and have that open in the system browser (e.g. Mobile Safari on iOS). This is possible, but it will require some forethought and cooperation between the app developer and the person responsible for the links on the page.
When you create an IAB instance, you get a reference to it back:
var ref = window.open('http://foo.com', '_blank', {...});
You can register a few event listeners on that reference:
ref.addEventListener('loadStart', function(event){ ... });
This particular event is fired every time the URL of the IAB changes (e.g. a link is clicked, the server returns a 302, etc...), and you can inspect the new URL.
To break out into the system browser, you need some sort of flag defined in the URL. You could do any number of things, but for this example let's assume there's a systemBrowser flag in the url:
.....html?foo=1&systemBrowser=true
You'll look for that flag in your event handler, and when found, kick out to the system browser:
ref.addEventListener('loadStart', function(event){
if (event.url.indexOf('systemBrowser') > 0){
window.open(event.url, '_system', null);
}
});
Note that this is not the best method for detecting the flag in the url (could lead to false positives, possibly) and I'm pretty sure that PhoneGap whitelist rules will still apply.
Unfortunately target=_system does not work from within the InAppBrowser. (This would work if the link originated in the parent app, though.)
You could add an event listener to the IAB and sniff for a particular url pattern, as you mention in your comments, if that fit your use case.
iab.addEventListener('loadstart', function(event) {
if (event.url.indexOf("openinSafari") != -1) {
window.open(event.url, '_system');
}
}
The 'event' here is not a real browser event - it is a construct of the IAB plugin - and doesn't support event.preventDefault(), so the IAB will also load the url (in addition to Safari). You might try to handle that event within the IAB, with something like:
iab.addEventListener('loadstop', function(event) {
iab.executeScript('functionThatPreventsOpenInSafariLinksFromGoingAnywhere');
}
...which I have not tested.
This message is for clarification:
If you open an another with window.open by catching a link on loadstart, it will kill yor eventhandlers that assigned to first IAB.
For example,
iab = window.open('http://example.com', '_blank', 'location=no,hardwareback=yes,toolbar=no');
iab.addEventListener('loadstop', function(event) {console.log('stop: ' + event.url);});
iab.addEventListener('loaderror', function(event) { console.log('loaderror: ' + event.message); });
iab.addEventListener('loadstart', function(event) {
if (event.url.indexOf("twitter") != -1){
var ref2 = window.open(event.url, '_system', null);
}
});
When the second window.open executed, it will kill all the event listeners that you binded before. Also loadstop event will not be fired after that window.open executed.
I'm finding another way to avoid but nothing found yet..
window.open() doesn't work for me from within an InAppBrowser, whether or not I add a script reference to cordova.js to get support for window.open(...'_system'), so I came up with the following solution which tunnels the "external" URL back to the IAB host through the hashtag so it can be opened there.
Inside the InAppBrowser instance (I'm using AngularJS, but you can replace angular.element with jQuery or $ if you're using jQuery):
angular.element(document).find('a').on('click', function(e) {
var targetUrl = angular.element(this).attr('href');
if(targetUrl.indexOf('http') === 0) {
e.preventDefault();
window.open('#' + targetUrl);
}
});
Note that that's the native window.open above, not cordova.js's window.open. Also, the handler code assumes that all URLs that start with http should be externally loaded. You can change the filter as you like to allow some URLs to be loaded in the IAB and others in Safari.
Then, in the code from the parent that created the InAppBrowser:
inAppBrowser.addEventListener('loadstart', function(e) {
if(e.url.indexOf('#') > 0) {
var tunneledUrl = e.url.substring(e.url.indexOf('#') + 1);
window.open(tunneledUrl, '_system', null);
}
});
With this solution the IAB remains on the original page and doesn't trigger a back-navigation arrow to appear, and the loadstart handler is able to open the requested URL in Safari.

Resources