Angular dart: Route links in Safari on iOS 7 stop working - ios

I have been tearing my hair out over this for over a week now...
TL;DR: hash based links stop working in Safari on iOS 7 after a certain number of clicks.
We had a strange issue in our Angular Dart application - people using iPhones reported that links were "freezing" after "a while". The typical non helpful error reports, so we had to work hard to figure out exactly how to replicate the issue.
It eventually became clear that after the same number of clicks each time, Safari on iOS 7 would just stop navigating to the hash based route links.
After much diagnosis (removing bits of the app piece by piece until the issue stopped happening), I've managed to narrow it down to routes which contain parameters. After these routes are followed a certain number of times, Safari on iOS 7 just stops following them - it's like they get "half" clicked - the link gets underlined, but it is never followed, and subsequently no amount of clicking on it will allow it to be followed.
Here is a very simple dart application that will replicate the issue:
In the root folder:
pubspec.yaml:
name: DartRouteChecker
description: A sample web application
dependencies:
angular: 0.14.0
browser: any
transformers:
- angular
Then in the web folder:
dartroutechecker.dart:
library dart_route_checker;
import 'package:angular/angular.dart';
import 'package:angular/application_factory.dart';
class MyAppModule extends Module {
MyAppModule() {
bind(NgRoutingUsePushState, toValue: new NgRoutingUsePushState.value(false));
bind(RouteInitializerFn, toImplementation: Routes);
}
}
void main() {
applicationFactory()
.addModule(new MyAppModule())
.run();
}
#Injectable()
class Routes
{
void call(Router router, RouteViewFactory views) {
views.configure({
'route1': ngRoute(path: '/route1', defaultRoute: true, view: 'route1.html'),
'route2': ngRoute(path: '/route2/:id', view: 'route2.html')
});
}
}
dartroutechecker.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>DartRouteChecker</title>
<script async type="application/dart" src="dartroutechecker.dart"></script>
<script async src="packages/browser/dart.js"></script>
<link rel="stylesheet" href="dartroutechecker.css">
</head>
<body>
<ng-view></ng-view>
</body>
</html>
dartroutechecker.css
body {
background-color: #F8F8F8;
font-family: 'Open Sans', sans-serif;
font-size: 14px;
font-weight: normal;
line-height: 1.2em;
margin: 15px;
}
h1, p {
color: #333;
}
#sample_container_id {
width: 100%;
height: 400px;
position: relative;
border: 1px solid #ccc;
background-color: #fff;
}
#sample_text_id {
font-size: 24pt;
text-align: center;
margin-top: 140px;
-webkit-user-select: none;
user-select: none;
}
route1.html:
<h1>ROUTE 1</h1>
<div>
Go to second route
</div>
route2.html:
<h1>ROUTE 2</h1>
<div>
Go to first route
</div>
Use pub build to build the app (generate javascript), then navigate to it using an iPhone with iOS 7 (I tested it on an iPhone 5 and an iPhone 4S both with iOS 7.1.2). Click on "Go to second route" then "Go to first route" over and over again until you get to around 30 clicks - the link will then stop responding... It's almost always exactly 30 clicks that will cause it (though I have once or twice seen it be around 43, though I can't be sure I didn't click something else during those times - I've done so much stinkin' clickin' in the last week that I feel I'm going slightly insane...)
I can't replicate this issue when the iPhone is plugged in to a mac to debug it. It also doesn't happen if neither of the routes contains a parameter. And it happens with FEWER clicks if there are more routes defined in the route initialisation class, or if the routes contain multiple parameters. Initially I thought that the problem might have been that one of our routes had an ampersand in it, but that didn't turn out to be the case. And it doesn't happen at all in any other browsers, including Chrome on iOS.
I suspect this might be a bug in Safari (possibly related to Safari not handling hashchanges correctly, and not handling browser history correctly when using appcache (which, BTW, I am not using here)), but this is a real showstopper for us here - many of our customers are using iPhones, so if our app keeps freezing on the standard browser on an iPhone, we're in a lot of strife.
Has anyone seen anything like this before? Anyone have any suggestions for a workaround? Or a new career?.....
EDIT:
We have tracked the issue down to the route method in route.dart:
https://github.com/angular/route.dart/blob/master/lib/client.dart#L480
In the method gotoUrl (https://github.com/angular/route.dart/blob/master/lib/client.dart#L782), if we change it from route(url).then((success) { to new Future.value(true).then((success) { then the issue no longer occurs - of course then we lose all the "preenter" etc etc functionality that routing provides. But it seems that somewhere in that route function, something is going awry...

According to this issue linked in the comments by Günter, this has been fixed in 0.5.0 by this commit.
I can't understand what part of that commit fixes it from reading the code; so hopefully 0.5 is a relatively compatible version to upgrade to!

Related

Parameters for opening pdf files not working in electron

I am trying to open pdf files in an iframe by also using parameters to control how the pdf is opened. They work great on the website, but they don't seem to work on electron: the pdf is opening inside the iframe, however, the zoom level specified by the 'view=fitH' does not seem to work in electron. Is there any way to make the parameters work in electron too? This is the code that I am using.
<iframe src='./res/test.pdf#page=1&toolbar=0&statusbar=0&messages=0&navpanes=0&scrollbar=0&view=fitH' frameborder="0" style="width:72.5%;height:95%;position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"></iframe>
Update:
I will try to offer more details of what I'm trying to do. I'm building the app from macOS Sierra and the end goal is to have a local app for windows which can be used instead of the online app when there is no internet connection. I am using the following command to build the app:
electron-packager ./ --platform=all --arch=all --overwrite --asar
However, the pdf is not fitting the width of the iframe as it should, but is instead zoomed out like in the following image:
The actual result - you can see that the pdf is zoomed out a lot
I will try to build the app from windows and see if that solves the issue.
I see this working just the same way as in browsers
main.js
const {app, BrowserWindow} = require('electron')
app.once('ready', () => {
let win = new BrowserWindow({
webPreferences: {
plugins: true
}
})
win.loadURL(`${__dirname}/pdfargs.html`)
})
pdfargs.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Page Title</title>
</head>
<body>
<iframe src='./res/test.pdf#page=1&toolbar=0&statusbar=0&messages=0&navpanes=0&scrollbar=0&view=fitH' frameborder="0" style="width:72.5%;height:95%;position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"></iframe>
</body>
</html>
I found out what the problem was. I was breaking the rule:
Individual parameters, together with their values (separated by & or #), can be no greater then 32
characters in length.
I am now using page=1&toolbar=0&view=fitH and it works like expected now.
I don't know why it worked in browsers even though I was using more than 32 characters, but I guess there is an exception to every rule.

ITMS-9000 "element "img" not allowed here; expected..."

Trying to get an ePub file to pass through Apple's ePub checker but get two errors multiple times.
(1) element "img" not allowed here; expected the element...
This is the coding on the page:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link href="../Styles/Style.css" type="text/css" rel="stylesheet"/>
<title></title>
</head>
<body>
<h2>Tokyo</h2>
<p>Japan is made up of five main islands: Hokkaido, Honshu, Shikoku, Kyushu, and Okinawa. Over three-quarters of the 127 million people in Japan live on Honshu, the largest and most developed island. Tokyo, the capital, lies on its eastern shore.</p>
<img alt="Tokyo Metropolis" src="../Images/Tokyo-Metropolis.jpg"/>
<p>Tokyo Metropolis, one of Japan’s 47 prefectures, is comprised of two areas: the <a class="hook" id="Special-Wards-23">23 special wards</a>, which together make up what most consider to be Tokyo, and the rest—the cities and towns that lie to the west. It is best thought of as a constellation of cities that have, over the course of time, merged into one vast urban sprawl which is home to over 13 million people.</p>
I have the alt tag inserted correctly and it displays correct in iBooks.
CSS for img is as follows:
img
{
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 15px;
margin-bottom: 15px;
padding: 1px;
border: 1px solid #021a40;
background-color: #FFFFFF;
}
I've looked around at numerous forums but am none the wiser as to why I'm getting this error.
(2) Same error but in relation to tags ("element "ul" not allowed here; expected end-tag or element "li"...")
Html here...
<ul>
<li><b>Introduction</b></li>
<ul>
<li>Tokyo</li>
<li>A Brief History</li>
<ul>
<li>The Emergence of Japan</li>
[Html cut short as it is a table of contents and long].
I think this is because I have nested lists, but this works perfectly in iBooks so I don't know why it is causing an error at validation.
I'd be very grateful for some help!
The second one is clear: lists can only contain list items. That's how it is.
You say "this works perfectly in iBooks" but that's not true. It doesn't work perfectly. It's just that the app's error handling routines happen to handle this in such a way that the result looks roughly like what you expected. This will not be the same on other machines, other versions of the app etc. Avoid such errors.
The first error message is more subtle.
What version of HTML does the file identify itself as?
If it's XHTML 1.x or HTML 4.x strict, then plain text and inline elements are officially not allowed at the body level. Don't ask me why, I don't know.
If the file version is HTML 4.01 Transitional or HTML5 (or the XHTML equivalents) then images as children of the body are fine.
If anybody can tell me why this difference exists, I'd be delighted!
As for a solution, if you can't change the HTML version to HTML5 or XHTML5, then simply putting everything in the body in one big div will do the trick. Just put <div> right after the <body> and </div> just before the </body>.

Detect Quicktime plugin withOUT using Javascript

Is it possible to detect the existence of the Browser's Quicktime plugin withOUT using Javascript?
I know how to test for Quicktime using Javascript, but not without.
My logic says that Javascript can be enabled/disabled by the user and the existence of the Quicktime plugin is determined by the programmers for each Browser. Therefore, each should an independent statistic ... even for Apple's iOS which has Quicktime built in.
Thanks,
I am really throwing away my question. However, I thought some of you might be curious why ...
I honestly do not know if it is possible to detect the existence of the Browser's Quicktime plugin withOUT using Javascript. I do know, for example, that Quicktime is built into Apple's current OS and probably many prior ones.
Nevertheless, I have come across the expression "Progressive Enhancement". As a direct result, I have discovered the works of others that result in my being okay with detection of Quicktime using Javascript.
The following illustrates what I mean:
The way-back-when driving force was to avoid document.write in the display of media players for .mp3, .m4a and the like.
The new approach places the media player, the no-js message, and the no-qt message in the html markup.
The default case is to show just the no-js message in the html markup. Using the "Progressive Enhancement" paradigm, if Javascript is enabled, then Javascript is used to first hide the no-js message. Depending on the presence of Quicktime, we then show the media player and hide the no-qt message, or vice versa. As a result, we progress from a "vanilla" text message about no Javascript to showing a media player if Quicktime is present.
For example, my html markup presents:
<section class="mediaWrapper">
<div class="mediaplayer">
<audio name="aMedia" class="aMedia" controls preload="auto"
src="audio/My Love Song Forever.mp3">
</div>
<div class="nojs">
Turn on Javascript to hear an awesome Love Song
</div>
<div class="noqt">
<a href="http://www.apple.com/quicktime/download/"
title="Get Quicktime"
onclick="window.open(this.href); return false">
Install Quicktime
</a>
to hear an awesome Love Song
</div>
</section> <!-- mediaWrapper -->
In my <head> is this <style>:
/* default settings for the html markup */
.mediaWrapper {
display: block;
position: relative;
text-align: center;
}
.mediaplayer {
display: none;
}
.nojs {
display: block;
font-size: 110%; /* for the no-js alert text */
color: #360;
font-weight: bold;
/*
text-align: center; // inherited from .mediaWrapper
*/
}
.noqt {
display: none;
font-size: 110%; /* for the no-qt alert text */
color: #360;
font-weight: bold;
/*
text-align: center; // inherited from .mediaWrapper
*/
}
Also in the <head> is this <script>:
$(document).ready (function() {
$('.nojs').hide(); // we're here, already!
if (QuicktimeIsPresent)
{
$('.mediaplayer').show();
$('.noqt').hide();
}
else
{
$('.mediaplayer').hide();
$('.noqt').show();
}
}); // $(document).ready
As already stated, the html markup (via the above <style>) shows just the vanilla no-js message. Via Progressive Enhancement, if Javascript is enabled, then the above <script> is seen. So, Javascript is used to first hide the no-js message. Depending on the presence of Quicktime, we then show the media player and hide the no-qt message, or vice versa.

Grails Twitter Bootstrap Plugin Issue with navbar-fixed-top

I am using Grails 2.1.0 and Twitter Bootstrap Plugin 2.1.1 and am encountering an issue with navbar-fixed-top.
In order to get the Navbar fixed to the top of the page to behave correctly during resize, the Twitter Bootstrap Docs states:
Add .navbar-fixed-top and remember to account for the hidden area underneath it by adding at least 40px padding to the . Be sure to add this after the core Bootstrap CSS and before the optional responsive CSS.
How can I do this when using the Grails Plugin for Twitter Bootstrap?
Here is what I have tried:
main.gsp
<head>
...
<r:require modules="bootstrap-css"/>
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
.sidebar-nav {
padding: 9px 0;
}
</style>
<r:require modules="bootstrap-responsive-css"/>
<r:layoutResources/>
</head>
The problem is that Grails Plugin for Twitter Bootstrap takes the content of bootstrap.css and bootstrap-responsive.css and combines them into the following merged file: static/bundle-bundle_bootstrap_head.css.
Thus, I am not able to put the body padding style "after core Bootstrap CSS and before Responsive CSS" as per Twitter Bootstrap docs.
Here is the View Source HTML that I get from the main.gsp above
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
.sidebar-nav {
padding: 9px 0;
}
</style>
<link href="/homes/static/bundle-bundle_bootstrap_head.css" type="text/css"
rel="stylesheet" media="screen, projection" />
If there is no way to do this, I could always just drop the Grails Twitter Bootstrap Plugin and manually download Twitter Bootstrap and put it my Grails Project's web-app/css, web-app/images, and web-app/js. However, I would like to be able to use the Grails Twitter Bootstrap Plugin.
Thank you very much in advance, I appreciate it!
Bootstrap recommends that place for the style because when the screen width goes below 980px navbar becomes static (not fixed). So calling bootstrap-responsive.css after the padding prevents from a blank space at the top in mobile devices (there's not fxed element to fill that padding).
You can reproduce this behaviour using a media query:
#media (min-width:980px) {
body {
padding-top: 40px;
}
}
Put this CSS anywhere in your stylesheets, and don't worry about your <links>

jquery modal windows - closing frustrations with greybox and jqmodal

I've been trying to get modal windows working on a new site for some time now. I first tried jqmodal and had no issues displaying the modals, but the close buttons never worked - or at least they worked on some pages but not on others. I put a great deal of effort into debugging and couldn't find the issue.
I recently tried out greybox to see if I had better luck, but ran into a very similar issue. The close button at the top-right works fine, but I can't make a button within the modal that acts as a close. I've tried:
onclick="parent.parent.GB_hide();"
and similar variants but they just load whatever href is set to within the modal. However, if I do:
onclick="top.window.location.href='www.google.com'; parent.parent.GB_hide();"
this will close the modal and open Google, as intended. What I can't figure out is why I can't make a button that will just plain close it.
I feel like I'm missing something pretty fundamental since I keep running into similar issues. Incidentally the site is written in ASP.NET MVC with jquery and I'm primarily testing on Firefox right now.
I also realize this question is a bit vague, so I appreciate any thoughts and can supply more info if requested. Thanks in advance!
Edit: I still have no idea how to proceed. Nick's ideas were well taken but I see no Javascript errors on the page with either Firebug or Venkman. As far as I can tell the window should be closing.
Why would the second 'onclick' event above work, but not the second?
If I read your issue right, you simply are having problems closing the modal dialog.
I just put together an example using jqModal:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="Scripts/jquery-1.3.2.js" type="text/javascript"></script>
<script src="Scripts/tmp/jqModal.js" type="text/javascript"></script>
<style type="text/css">
.jqmWindow
{
display: none;
position: fixed;
top: 17%;
left: 50%;
margin-left: -300px;
width: 600px;
background-color: #EEE;
color: #333;
border: 1px solid black;
padding: 12px;
}
.jqmOverlay
{
background-color: #000;
}
.jqmWindow
{
position: absolute;
}
</style>
<script type="text/javascript">
$().ready(function() {
$('#dialog').jqm();
$('#jqmOpen').click(function() {
$('#dialog').jqmShow();
return false;
});
});
</script>
</head>
<body>
Open
<div class="jqmWindow" id="dialog">
Close
<input type="button" class="jqmClose" value="Close" id="jqmCloseBtn" name="jqmCloseBtn" />
Some text in the modal dialog
</div>
</body>
</html>
I have put both a hyperlink and a button just for example. It appears that jqModal needs/looks for the class to attach the close trigger.
EDIT:
I just tried your exact code from above and I didn't get a JavaScript error but also nothing happened, which is to be expected as my code does not know what GB_hide() is. So this got me thinking.
Is the button your clicking on like:
<input type="button" value="Close" id="Button1" name="Button1" onclick="parent.parent.GB_hide();" />
If so what is parent.parent.GB_hide()? Could GB_hide() be a function your are not implementing on this page.
Firebug shows me that parent.parent is the Window, so after putting:
<script type="text/javascript">
function GB_hide() {
alert('Close');
}
</script>
on the page I now get an alert displayed.
rather then using google give page url where you want to redirect
OnClientClick="top.window.location.href='http://localhost/yourpagename.aspx'; parent.parent.GB_hide();"
is the code to close and redirect jquery grey box on button click.

Resources