How to open Safari from a WebApp in iOS 7 - javascript

In previous versions of iOS, <a> tags would open Mobile Safari, and you had to intercept those to instead stay inside the webapp (an HTML page that has been saved to the home screen by the user).
Starting in iOS 7, all links are staying inside the WebApp. I cannot figure out how to get it to open Safari, when I really want it to.
I've tried using window.open and a target="_blank" but neither works.
Here is a sample. https://s3.amazonaws.com/kaontest/testopen/index.html
If you save that to your home screen in iOS 6, the link opens Safari. But in iOS 7, it doesn't.
Note that this is the OPPOSITE question that everyone is usually asking ("how to NOT open Safari"). That behavior seems to be the new default, and I can't figure out how to get the old behavior back!

Update 10/23/13: Fixed in iOS 7.0.3. Add a target="xxx" attribute to your links to do this. Also works with mailto: and friends.
This is a bug in iOS 7.0, 7.0.1 and 7.0.2 and there's no known way to do this.
It's a regression from earlier versions of iOS, where links that open in Safari work just fine. It appears to be a part of a cluster of problems revolving around opening URLs, with no external URL schemes working (for example "mailto:" doesn't work either).
The usual suspects of working around a problem like this unfortunately don't work (for example using a form and submitting it with a target of "_new").
There's other grave issues, like alert and confirm modal dialogs not working at all.
It may help to submit these as bugs to Apple, http://bugreport.apple.com

Having an anchor tag with target _blankwill work in iOS 7.0.3 but using window.open will not work and will remain to open within the webview in 7.0.3:
window.open('http://www.google.com/', '_blank');

This is a known issue for the last couple months of betas. There are no work arounds, and from what I can tell Apple has been silent on any ETAs on fixes, or even recognizing it's a bug. Bug reports have been submitted, but not updated/responded to.
More: http://www.mobilexweb.com/blog/safari-ios7-html5-problems-apis-review

UPDATE
Just wanted to let any one following this know that iOS 7.0.3 seems to fix the issue. I've keep standalone webapps saved for testing and the update released today restored external link/app functionality. So I've updated my code to let customers know to update their phones instead of deleting and re saving the web app.
I was going to just add a comment but apparently this is too long.
Apple set the stage for a WebApp world when they allowed chromeless webapps to be saved to the homescreen of the device. This "bug" feels like a major step backwards. It doesn't seem very apple to leave such a gapping bug in a final release. At least not one that, once they become aware of it, they don't publicly state they are working on a fix for it like they did with the lockscreen bypasses. I can't help that this feels intentional though there doesn't seem to be a clear reason why.
For developers dealing with this issue the only solution I could find was to
1st) Set the meta tag apple-mobile-web-app-capable to "no" - this prevents future users from dealing with the problem
2nd) Updated the code in our webapp to look for "standalone" and iOS version 7+. When conditions are meet I offered a popup that stated the issue and added a link to that page and asked the users for their forgivness and requested they copy the link and paste in in safari.
I wrapped the link in edge to edge tag with line breaks above and bellow to help make the copy and pasting process of the url a bit easier.

iOS v7.0.3 released 10/22/13 fixes the problem.

I found two solutions for the time being to this problem, both of which obviously using preventDefault on the external links.
If you're linking to another website or something to download, the only option I see is to ironically alert the user to hold their finger on the link to get the touch callout prompt. Then again, depending if it's a website or a PDF, instruct them to either copy the link or in the case of a PDF, add it to their reading list. Since the alert and confirm modals are also broken you'll need to implement your own modal notifications. If you already have that it shouldn't be that much trouble.
Update [2013-10-25] Apparently it's been fixed in iOS 7.0.3 and links open in Safari...
Edit [2013-10-05] Here's pretty much what I use with a jQuery UI modal
// iOS 7 external link polyfill
$('a[rel=external], a[rel=blank], a[target=_blank], a[href$=".pdf"]').on('click', function(e) {
if (navigator.standalone && /iP(hone|od|ad) OS 7/.test(navigator.userAgent)) {
e.preventDefault(); e.stopPropagation();
var href = $(this).attr('href');
var $dialog = $('<div id="ios-copy"></div>')
.html('<p>iOS 7 prevents us from opening external links in Safari, you can continue to the address and risk losing all navigation or you can copy the address to your clipboard by <strong>holding your finger on the link</strong> for a few seconds.</p><p><a style="background-color: rgba(0,0,0,.75); color: #fff; font-size: 1.25em; padding: 1em;" href="' + href + '">' + href + '</a></p>')
.appendTo('body')
.dialog({
title: 'External link',
modal: true,
buttons: {
Ok: function() {
$( this ).dialog( "close" );
}
}
});
}
});
The other workaround is using ajax or an iframe to load the external content, but unless you have a good sub-browser or something in your app it will look sketchy. Here's something along those lines.
// iOS 7 external link polyfill
if (/iP(hone|od|ad) OS 7/.test(navigator.userAgent) && window.navigator.standalone) {
$('a[rel=external], a[href$=".pdf"]').on('click', function(e) {
e.preventDefault(); e.stopPropagation();
var link = this;
var href = $(link).attr('href');
var frameContainer = $('<div></div>').css({
position: 'absolute',
left: 10,
top: $(link).position().top,
opacity: 0,
overflow: 'scroll',
'-webkit-overflow-scrolling': 'touch',
height: 520,
transition: 'opacity .25s',
width: 300
});
var iosFrame = $('<iframe class="iosFrame" seamless="seamless" width="1024" height="5000"></iframe>')
.attr('src', href)
.css({
height: 5000,
'max-width': 1024,
width: 1024,
overflow: 'scroll !important',
'-webkit-overflow-scrolling': 'touch !important'
});
var iosFrameClose = $('<i class="icon-cancel icon-remove icon-3x"></i>').css({
position: 'absolute',
left: -10,
top: $(link).position().top - 20,
'text-shadow': '1px 1px 1px #000',
transition: 'opacity .25s',
opacity: 0,
'-webkit-transform': 'translate3d(0, 0, 0)',
width: '3em',
height: '3em'
}).on('click', function(e) {
e.preventDefault();
setTimeout( function() {
$(frameContainer).remove();
$(iosFrameClose).remove();
}, 250);
});
iosFrame.appendTo(frameContainer);
frameContainer.appendTo('body');
iosFrameClose.appendTo('body');
iosFrame.contents().css({
'-webkit-transform': 'translate3d(0, 0, 0)'
});
// Show this thing
setTimeout( function() {
$(frameContainer).css({ opacity: 1 });
$(iosFrameClose).css({ opacity: 1 });
}, 1);
});
}

window.open('http://www.google.com/'); // stays in web app view
<a href='http://www.google.com/' target='_blank'>Click Here</a> // opens in safari
If you want to open Safari, but using an anchor tag like this isn't possible for whatever reason, the JavaScript solution to this question will open in Safari as well.

It looks suspiciously like an intentional bug to limit the ability of web apps to deliver advertisements. Maybe you can try open the new page in an iframe.

EDIT: Sorry, I misread your original problem. This solution was for opening an external website at all. Basic A href tags used to work in opening links and stopped working in iOS7. This was the only way I could get it to open an external link at all.
Here's how I got it to sort of work with a webapp saved to desktop in iOS7.
function openpage()
{
window.open('http://www.yourlinkhere.com', '_blank');
}
...
<a ontouchstart="openpage();" onclick="openpage();">LINKED TEXT</a>
The issue though is that it seems to ignore the target option and it opens it in the same full screen desktop webapp and there is no way to navigate back that I can see.

window.open('http://www.google.com/', '_system');
this will open native Safari Application even on latest version of iOS...
Happy coding!!

Maybe you should remove the meta setting of "apple-mobile-web-app-capable" in the head of page2.html
https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html#//apple_ref/doc/uid/TP40002051-CH3-SW1

Related

Expand/Collapse on mobile page

I have a weird thing happening.
I have a page that with several items on it, and each one has an iconfont. When the icon is clicked it changes the icon, and a new element shows below it. And of course, the opposite happens, clicking again changes back the icon and hides it. This works great.
However, when I try to make it work on a mobile version, which is called "modal" (and it kind of is a modal), the expand/collapse does not work. The main modal appears when clicked by a button, so that is not a problem. I am using the Chrome emulator for an iPhone 5. The same function is called, and I have verified it finds the function, but it won't expand (so I can't test collapsing either).
This is the basic HTML:
<p><span id="CraveTV" class="featureToggle plus-fa"></span> CraveTV </p>
<p id="CraveTV_list" class="goApps">Stream Showtime hits, HBO classics, the best sitcoms in TV history, and CraveTV originals. Available on iOS or Android.</p>
The css:
.plus-fa {
&:before {
#include icon($icon-plus-fa);
color: #0056A7;
}
}
.minus-fa {
&:before {
#include icon($icon-minus-fa);
color: #0056A7;
}
}
.goApps {
display:none;
padding-bottom: 10px;
}
And the jquery function:
$(document).ready(function(){
$(".featureToggle").click(function(){
var togglelist = "#" + $( this ).attr('id') + '_list';
$(togglelist).toggle();
$( this ).toggleClass('plus-fa');
$( this ).toggleClass('minus-fa');
});
});
The code used is exactly the same on the desktop version and the mobile version, although they are in difference scss files, specified for the desktop version and the mobile version.
Can anyone help me figure out why it won't work? I am wondering if it is a "modal" limitation, or something simple I am missing.
Put # inside href
<p><span id="CraveTV" class="featureToggle plus-fa"></span> CraveTV </p>
<p id="CraveTV_list" class="goApps">Stream Showtime hits, HBO classics, the best sitcoms in TV history, and CraveTV originals. Available on iOS or Android.</p>

Safari offsetWidth on reload is wrong

The past few weeks I've been working on a website which is live now. It can be seen here: http://www.momkai.com/
This website works fine in all browsers I tested it in except one: Safari. When I open this website in Safari 10.1 and hover over the first paragraph, this is what I see:
This is correct. The first word of each line of text should be underlined. Hovering of the lines results in this styling:
So far everything is going well. Now I reload the page and I see this:
The underlines are way to wide! I've logged the offsetWidths and they are just completely wrong. This is the code which I use to retrieve the widths:
const parentParagraph = this.el.parentNode.parentNode;
let selfIndex;
let siblingUnderlineWidth;
this.underlineWidth = this.el.querySelector('.js-text-block-link-text-highlight').offsetWidth;
this.siblings = [].slice.call(parentParagraph.querySelectorAll('.js-text-block-link-text'));
this.siblingUnderlineWidths = [];
for (let sibling of this.siblings) {
if (sibling.isSameNode(this.underline)) {
selfIndex = this.siblings.indexOf(sibling);
} else {
siblingUnderlineWidth = sibling.querySelector('.js-text-block-link-text-highlight').offsetWidth;
console.log(siblingUnderlineWidth);
this.siblingUnderlineWidths.push(siblingUnderlineWidth);
}
}
this.siblings.splice(selfIndex, 1);
I've also added two screenshots of the console.log's to demonstrate how the values differ:
I'm experiencing this behaviour in Safari 10.1 on desktop and Safari for iOS. I've no idea what's going wrong so I hope someone can help me. Thanks in advance!
I'll be happy to provide more code if required.
I have found that when something CSS changes after I refresh, it is usually a loading order issue.
For example I was using
document.addEventListener('DOMContentLoaded', runsWhenReady);
But sometimes the offsetWidth would be wrong.
Figured out this we because the CSS file wasn't fully loaded, which changes how the offsetWidth is.
Chrome and Safari handle caching differently, which is why it would be different on refresh.
So I switched to:
window.addEventListener('load', runsWhenReady);
Which only fires after everything including CSS is loaded and it solved the issue.

Button not working on Mobile Devices but works on PC bootstrap

I created a bootstrap button that has a link inside. Which looks like this:
When you hover on it:
This is the code inside the button:
<div class="s-8"><button type="button" onClick="javascript:location.href = 'administration.php';">Administration</button></div>
The logout button:
<div class="s-4"><button type="button" onClick="javascript:location.href = 'logout.php';">Logout</button></div>
This button works fine on the PC(IE, SAFARI, FireFox, Chrome, Opera) browser(takes me to the administration page, but it doesn't work on the Mobile devices.
I did the same thing for the logout button, and it works fine on PC and Mobile Devices. I am now puzzled.
The issue may be that you're using the onClick event which won't register on a mobile device (as you don't click - you tap).
This answer explains how to use the "touchstart" event which will work on a mobile.
https://stackoverflow.com/a/22015946/2619909
I know this might be a weird answer. But in some cases mobile clickevents dont work unless you put the style: cursor:pointer; to your button.
Mobile clickEvents are handled very differently, the first "click" or "tap" might be interpreted as a HOVER instead of the click which you are looking for.
So try setting the CSS style of the button to : cursor:pointer;
unfortunately neither setting cursor:pointer; nor adding a touchstart event listener
$(document).ready(function() {
$('#button_id').on('click touchstart', function() {
window.location.href = "/url";
});
});
as #noa-dev and #GitPauls suggested worked for me. for reference I tested on my phone7 (ios11.4 and safari)
working solution: I set the z-index of the button to a large positive number and the button now works.
#button_id{
z-index: 99;
}
solution found thanks to Daniel Acree https://foundation.zurb.com/forum/posts/3258-buttons-not-clickable-on-iphone. I don't know if this generalizes to all iphone/mobile devices.

JsPlumb Touch Screen

I have an application that use JsPlumb Framework. It works fine on a desktop, however when using an touch device it fails to work correctly.
I have an object that can be dragged around the screen, this works fine on both a touch device and desktop. However I have also got an action that when a user click on the device it can set a connector to drag a line to another object to join them together. However on the touch devices it fails to set the connector.
The touch device will draw an icon but it will display appear straight away. Is this before the touch device can't tell the difference between the drag/touch option.
I have added some code to see if it has something to do with my code.
$("#container").append(state)
jsPlumb.draggable("state" + i);
jsPlumb.makeSource($('.item'), {
connector: 'StateMachine',
});
jsPlumb.makeTarget($('.item'), {
anchor: 'Continuous',
reattach:true,
isTarget:true,
beforeDrop:function(params) {
'Some code'
}
});
EDIT
JSFiddle
http://jsfiddle.net/8jMqG/6/
EDIT AGAIN
From the docs the following is showed
Tip: use the three-argument addEndpoint method for common data
One thing that happens quite often is that you have an Endpoint whose appearance and behaviour is largely the same between usages on different elements, with just a few differences.
var exampleGreyEndpointOptions = {
endpoint:"Rectangle",
paintStyle:{ width:25, height:21, fillStyle:'#666' },
isSource:true,
connectorStyle : { strokeStyle:"#666" },
isTarget:true
};
Which is what I'm doing on the jsfiddle.
Thanks,
James
I have been using jsPlumb for some time now. My app works both on desktop & mobile. Of course, there's a difference between click & touch.
I use jquery-ui-touchpunch for mobile device support; clicking, dragging objects/connections & creating connections works smooth on mobile too.
http://touchpunch.furf.com/
Update
After creating the endpoints or making certain elements source & target, the next step is to join them for the connection to appear. Of course, if the sole-aim is to just connect, then you can skip creating endpoints/sources/targets & directly join them using
jsPlumb.connect({
source:"element1",
target:"element2",
anchors:["Right", "Left" ],
endpoint:"Rectangle",
endpointStyle:{ fillStyle: "yellow" }
});
DOCS
Currently, you're trying to make the same element(s) .item both source & target.
Also, you're trying to make the same elements source & target with every click (event). Why repeating it ?
APIDOCS
I guess there's some confusion in what you need and what the code says.

Dropdown menu flickering over slider, only on Chrome for Android

I'm pretty new to all this, so apologies if this is a dumb question:
I've got a Magento site located here: http://www.thisisnotavegetable.com It uses responsive design, and when displayed on mobile-width browsers, the topmenu becomes a javascript-enabled dropdown.
This all works fine, except on the home page (where it is loading over a javascript-enabled slider), and only on Chrome for Android. On that browser, the dropdown flickers and link text won't display. I assume this is a jQuery issue, but I'm not advanced enough to figure it out.
Any help is much appreciated!
Alex
Below is the jQuery for the dropdown (I think). The slider is ioSlider. I hope someone can help me without needing to see that jQuery, because it's unformatted and the license says I'm not supposed to post it.
if (jQuery('#categories-accordion').length){
jQuery('#categories-accordion li.level-top.parent ul.level0').before('<div class="btn-cat"><div class="inner"></div></div>');
if(mobileDevice == true){
jQuery('#categories-accordion li.level-top.parent').each(function(){
jQuery(this).on({
click: function (){
if(!jQuery(this).hasClass('touched')){
jQuery(this).addClass('touched closed').children('ul').slideToggle(200);
clearTouch(jQuery(this));
return false;
}
}
});
});
}else{
jQuery('#categories-accordion li.level-top.parent .btn-cat').each(function(){
jQuery(this).toggle(function(){
jQuery(this).addClass('closed').next().slideToggle(200);
},function(){
jQuery(this).removeClass('closed').next().slideToggle(200);
})
});
}
}
Would be great, if you could post the jQuery Code :)
Flickering might be solved by using hardware acceleration. You can force the browser to use hardware acceleration by adding "-webkit-transform: translateZ(0);" into the css class of the mobile menu.
mobileMenu {
...
-webkit-transform: translateZ(0);
}

Categories