Overcoming connection limitation with mobile safari - html

I recently discovered that mobile safari (on iOS 9.1 - though unsure about older safari versions) has an unfortunate problem with multiple connections and images. If you have six images when you load a page, it will delay XHR requests that loads after those six images by a huge lag time (order of 30s).
For example, I loaded the following using a standard NodeJS/Express server and saw giant delays before the alert showed up - despite the fact that all there images are just a couple of KB and I can visibly see that they are all loaded. The dev console also shows the images loaded but not the XHR request. The duration it took to download the file was very small but the latency was huge.
This is not a problem on any other browsers (mobile chrome, regular safari, etc).
Sample problem html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<img src="/static/images/home/payment.png">
<img src="/static/images/home/couple-present-mobile.jpg">
<img src="/static/images/general/welcome.jpg">
<img src="/static/images/general/arrow-down.png">
<img src="/static/images/general/arrow-right.png">
<img src="/static/images/general/check.png">
<script>
var url = '/static/test.html'
var xhr = new XMLHttpRequest();
xhr.open('GET', encodeURI(url));
xhr.onload = function() {
alert(url) //This takes forever
};
xhr.send();
</script>
</body>
</html>
An odd thing is if you ran the XHR request BEFORE there were 6 images, it would work perfectly. In fact, if you even did something like this one below, it was fine. I think this works because the background CSS image must retrieve the URL after the XHR is initiated.
Replace one of the img tags with a background css image and it works:
<!DOCTYPE html>
<html>
<head>
<style>
.test {
background-image: url("/static/images/home/check.png");
height: 400px;
}
</style>
</head>
<body>
<img src="/static/images/home/payment.png">
<img src="/static/images/home/couple-present-mobile.jpg">
<img src="/static/images/general/welcome.jpg">
<img src="/static/images/general/arrow-down.png">
<img src="/static/images/general/arrow-right.png">
<!--<img src="/static/images/general/check.png"> REMOVE THIS LINE and add the background image instead-->
<div class="test"></div>
<script>
var url = '/static/test.html;
var xhr = new XMLHttpRequest();
xhr.open('GET', encodeURI(url));
xhr.onload = function() {
console.log(url) //NO DELAYS!
};
xhr.send();
</script>
</body>
</html>
Also I found out that just running 7 simultaneous XHR requests also does not cause this problem (such as the below):
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script>
var urls = ['/static/images/home/payment.png',
'/static/images/home/couple-present-mobile.jpg',
'/static/images/general/arrow-right.png',
'/static/images/general/arrow-down.png',
'/static/images/general/welcome.jpg',
'/static/images/general/check.png',
'/static/test.html'];
for(var i = 0, ii = urls.length; i < ii; i++){
(function(){
var url = urls[i];
var xhr = new XMLHttpRequest();
xhr.open('GET', encodeURI(url));
xhr.onload = function() {
console.log(url)
};
xhr.send();
})()
}
</script>
</body>
</html>
Has anyone come across this problem and figured out a way to deal with it without reducing the number of images or putting them in a sprite or something?

The hack I ultimately used to get around this was to load the images from a different host. For simplicity, if the browser detected that the host was www.domain.com, I would load images it from domain.com and vice versa. You can also just have all your images come from a certain host like images.domain.com and keep your api's and other stuff on another host.
Not the most ideal or elegant solution, but its super simple to implement and solves the problem.

Related

Rendering TIF files in HTML

I'm building a utility which will pull TIF files from blob storage and render them in html. Since it's just a utility, I will view them in Edge, which shows TIF files.
I can see the eighth example on this page renders fine. Meaning, this code works:
<img width=200 height=200
src="tiffdocument.tif" alt="">
However, my HTML, below, does not render anything:
<img src="https://atpblob.blob.core.windows.net/imagedata/94ae9802-4e42-4ba1-8955-11ac7c7e3509.tif" alt="" width="500" height="500">
If I go directly to the link in the source, it will download the image, so why won't it render?
Got it.
img does not work the way I was trying to use it. You have to explicitly use a GET request to pull the file.
For rendering the file cross-browser, I ended up using tiff.js.
The final html/js/css string I pushed to the browser ended up looking like this:
<!doctype html>
<html>
<head>
<title>TIF View</title>
</head>
<body>
<script type="text/javascript" src="https://cdn.rawgit.com/seikichi/tiff.js/f03d7965/tiff.min.js"></script>
<script>
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open('GET', 'https://atpblob.blob.core.windows.net/imagedata/${blob}.tif');
xhr.onload = function (e) {
var tiff = new Tiff({buffer: xhr.response});
var canvas = tiff.toCanvas();
document.body.appendChild(canvas);
};
xhr.send(null);
</script>
<style>
canvas {
min-height: 60px;
}
</style>
</body>

Google Docs Viewer occasionally failing to load content in iframe

I'm having an issue with the Google Docs viewer that is causing a nightmare to solve because it only happens intermittently. I'm looking for guidance on how to make the content in the iframe load everytime without issue as it should.
Steps to reproduce
1) This page is a basic HTML page with a h1 tag and an iframe containing a link to a PDF on the same server
http://bit.ly/1mqbuf7
2) When you load the page, the pdf document will load in the iframe 60% of the time.
3) If you hit refresh 10 or so times, at least once it will fail to appear. Google returns a 307 first (Which it also does when it works) and then returns a 204 - no content. When it works, it returns a 200, with the content you see in the viewer.
I'm struggling to understand why it only does this some of the time with no visible errors. This has been tested and failed on Google Chrome v 48.0.2564.103 (PC) and Internet Explorer Edge v25.10586 (PC) with the same results and frequency of failure.
Any guidance would be greatly appreciated.
This is not fixing your problem per se, but since I had the same problem and I eventually managed to find an acceptable solution, I thought I'd share it.
var $docViewer = $(`<iframe src="${newValue}" height="100%" width="100%"></iframe>`);
//If using modern browser, use and embed object
if (window.chrome || typeof (window.mozInnerScreenX) != "undefined")
$docViewer = $(`<object width="100%" height="100%" data="${newValue}" type="application/pdf">
<embed src="${newValue}" type="application/pdf">
<p>This browser does not support PDFs.Please download the PDF to view it: Download PDF.</p>
</embed>
</object>`);
//Add the new viewer
$docViewer.appendTo($("#invoicePreview"));
Basically, use an embed if modern browser, and the gviewer if not. The embed object behaves identically to the google doc viewer, it works in 100% of cases (no failed loads), but since it's not supported for IE and/or low-end mobile devices, use the google doc viewer for that... Progressive Enhancements I guess.
Here's a "hack" that will ensure a proper loading every time (albeit with some delay, due to potential failed attempts - it's Google's fault, don't shoot the messenger!). The 2s interval duration can be modified to best fit the time expected for a successful effort to start loading the iFrame.
HTML:
<div id="test-id-1" style="text-align: center; width: 100%; height: 1150px" class="embed-pdf" data-url="{insert_pdf_link_here}"><span class="loader">Please wait...</span></div>
JS:
$(document).ready(function() {
let embed_pdfs = {};
$('.embed-pdf').each(function() {
var $pdfViewer = $('<iframe src="https://docs.google.com/viewer?url=' + $(this).data('url') + '&embedded=true" style="width: 100%; height: 100%" frameborder="0" scrolling="no"></iframe>');
$pdfViewer.appendTo($(this));
console.log($(this).attr('id') + " created");
embed_pdfs[$(this).attr('id')] = 'created';
});
$(document).find('.embed-pdf iframe').load(function(){
embed_pdfs[$(this).parents('.embed-pdf').attr('id')] = 'loaded';
$(this).siblings('.loader').remove();
console.log($(this).parents('.embed-pdf').attr('id') + " loaded");
});
let embed_pdf_check = setInterval(function() {
let remaining_embeds = 0;
$.each(embed_pdfs, function(key, value) {
try {
if ($($('#' + key)).find('iframe').contents().find("body").contents().length == 0) {
remaining_embeds++;
console.log(key + " resetting");
$($('#' + key)).find('iframe').attr('src', src='https://docs.google.com/viewer?url=' + $('#' + key).data('url') + '&embedded=true');
}
}
catch(err) {
console.log(key + " reloading");
}
});
if (!remaining_embeds) {
clearInterval(embed_pdf_check);
}
}, 2000);
});
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<div id="iframeContainer"></div>
</body>
<script>
var URL = "https://docs.google.com/viewer?url=http://www.africau.edu/images/default/sample.pdf&embedded=true";
var count = 0;
var iframe = ` <iframe id = "myIframe" src = "${URL}" style = "width:100%; height:500px;" frameborder = "0"></iframe>`;
$(`#iframeContainer`).html(iframe);
$('#myIframe').on('load', function(){
count++;
if(count>0){
clearInterval(ref)
}
});
var ref = setInterval(()=>{
$(`#iframeContainer`).html(iframe);
$('#myIframe').on('load', function() {
count++;
if (count > 0) {
clearInterval(ref)
}
});
}, 4000)
</script>
</html>
Change var URL = your_googel_docs_pdf_url
The code will keep loading the url into iframe until the doc loads successfully.
It's not the best solution. But I waited a few seconds after the page loaded and checked if the iframe was loaded (see how below). If it wasn't, then I set the iframe's src attribute to null and then back to the correct source, affectively reloading it. Then waited a few seconds to check again and repeated. Once it has loaded you can stop checking.
conditionalPdfIFrameReloadTimeout() {
setTimeout(() => {
let iFrame = document.GetElementById("pdfIframe")
if (iFrame.contentDocument/*pdf iframe failed to load*/) {
iFrame.src = null
iFrame.src = "the url to your pdf"
conditionalPdfIFrameReloadTimeout()
}
}, 6000)
}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en" style="width:100%; height:100%;">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body id="iframeContainer" style="height: 100%; width: 100%; overflow: hidden; margin:0px;">
<script>
var URL = "https://docs.google.com/gview?url=enteryoururl&embedded=true";
var count = 0;
var iframe = `<iframe id = "myIframe" src = "${URL}" style="width:100%; height:100%;" frameborder="0" allowfullscreen=""></iframe>`;
$(`#iframeContainer`).html(iframe);
$('#myIframe').on('load', function(){
count++;
if(count>0){
clearInterval(ref)
}
});
var ref = setInterval(()=>{
$(`#iframeContainer`).html(iframe);
$('#myIframe').on('load', function() {
count++;
if (count > 0) {
clearInterval(ref)
}
});
}, 2000)
</script>
</body>
</html>
The above code worked for me.

touch events in attachments iphone not working

JS touch events in an .html file that I mail as an attachment to an iPhone5 (OS9.2), are never executed because a touch on the screen is intercepted by the Mail and interpreted as DONE. I'm new to this. Am I missing something obvious? The following code works in XCodeSimulator but not in a real phone. Is there a workaround? Are .html files unsupported in an attachment, for some reason?
Below is a typical test code I'm using. I prefer to work in vanilla JS, rather than JQuery, but I'd be grateful for any suggestions or advice, whatever.
<!DOCTYPE html>
<html>
<head>
<style>
#mycanvas{
position: absolute;
top:100px;
left:100px;
border:4px solid;
}
</style>
<script>
function init() {
var touchzone = document.getElementById("mycanvas");
touchzone.addEventListener("touchstart",draw,false);
}
function draw() {
var canvas = document.getElementById('mycanvas');
if(canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.fillRect(event.touches[0].pageX-100, event.touches[0].pageY-100,10,10);
}
}
</script>
</head>
<body onload="init()">
<canvas id="mycanvas" width="500" height="500">
Canvas element not supported.
</canvas>
<h2> Tap inside rectangle to leave a spot. Outside leaves nothing.</h2>
</body></html>
We realized that an .html e-mail attachment cannot work in iOS. Placing the file in Public folder on Dropbox gives it a web address that the phone can link. This works for us so far.

HTML code to scroll through pdf files

I am trying to develop a program that will switch between url locations every 10 seconds and then loop back after going to the last url. Description below:
Display url1 for 10 sec
Display url2 for 10 sec
Display url3 for 10 sec
LOOP BACK TO URL (continuous loop)
I believe this can be done using settimeout and for loop. I do not have a complete understanding of settimeout and java for that matter so that is where I am currently stuck at. I have placed a code below but since I do not know how to use settimeout believe this is my first mistake.
If there is a better way to do this I am all ears. I have been trying java for 3 days because it needed to be do for a project at work so I am brand new to it and probably over my head.
<!DOCTYPE>
<html>
<body>
"urls"
<script>
var myurl;
function urls()
{
myurl=setTimeout(url1,0);
myurl=setTimeout(url2,10000);
myurl=setTimeout(url3,20000);
}
function url1()
{
<embed width="100%" height="100%" name=plugin src="http://files.asme.org/ICOMES/News/15876.pdf#pagemode=none&scrollbar=0&page=2" type="application/pdf".;
}
function url2()
{
<embed width="100%" height="100%" name=plugin src="http://www.tbp.org/pubs/Features/Su04McMasters.pdf#pagemode=none&scrollbar=0&page=2" type="application/pdf".;
}
function url3()
{
<embed width="100%" height="100%" name=plugin src="http://milproj.dc.umich.edu/publications/EngFlex_report/download/EngFlex%20Report.pdf#pagemode=none&scrollbar=0&page=2" type="application/pdf".;
}
</script>
</body>
</html>
edit:
<!DOCTYPE>
<html>
<body>
<script>
var urlList = ['http://www.google.com', 'http://www.msn.com', 'http://www.yahoo.com'];
var wnd;
var curIndex = 0; // a var to hold the current index of the current url
function openWindow(){
wnd = window.open(urlList[curIndex], '', '');
setTimeout(function () {
wnd.close(); //close current window
curIndex++; //increment the index
if(curIndex < urlList.length) openWindow(); //open the next window if the array isn't at the end
}, 2000);
}
openWindow();
</script>
</body>
</html>
It's not java. It's javascript ;)
You can do one iframe in an HTML and use javascript to change it's source every 10 seconds.
For example:
<html>
<body>
<iframe id="theIframe" src="">
</iframe>
</body>
<script>
function timeout() {
setTimeout(function () {
document.getElementById("theIframe").src= 'http://www.google.com';
timeout();
}, 10000);
}
timeout();
</script>
<html>
I am not sure this exact code will work because I just wrote it without test. But you can get the general idea. Like this every 10 seconds it will reload google. You can modify it so the websites are taken from an array or something.
Not all browsers will support opening the PDF directly in browser though. Some might want to download it - depending on plugins. If you want to render the PDF it might require external libraries.

Crash in Firefox or Chrome when using FileReader

We try to upload a zip file using the “FileReader” javascript object on the client. For small files, everything seems to be fine. If we use a zip input file of 132Mo, in Firefox v21.0 on Windows 7, the first upload from the local disk thru the javascript object works well. But, if we try to select another file and start the transfert, Firefox crashes…. In Chrome v27.0 on Windows 7, it crashes(see the ‘oups’ page) on the first try. We tried on a Mac OS with same browsers without problem. Mainly strange but when the Windows task manager window is open, no more crash in Firefox or Chrome while loading big files. Maybe the presence of this TOP window forces the garbage collector to do its work faster?
Has anyone already faced this issue? As reference, I joined a simple HTML page that may reproduce the behavior.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function ()
{
$("#btnFile").change(startUpload);
});
function startUpload(e)
{
this.fileHandle = e.target.files[0];
var reader = new FileReader();
reader.onprogress = function (data)
{
if (data.lengthComputable)
{
var progress = parseInt(((data.loaded / data.total) * 100), 10);
$("#progress").html("Reading file: " + progress + " %");
}
};
reader.onloadend = function ()
{
$("#progress").html("Reading completed!");
};
reader.onerror = function (errorEvent)
{
console.error("FileReader error", errorEvent);
};
reader.readAsDataURL(this.fileHandle);
};
</script>
</head>
<body>
<input type="file" id="btnFile" />
<div id="progress"></div>
</body>
</html>