Problems displaying PDF in iFrame on Mobile Safari - ios

Within our web application we are displaying a PDF document in an iframe using the following line of code:
<iframe id="iframeContainer" src="https://example.com/pdfdoc.pdf"
style="width:100%; height:500px;"></iframe>
This works fine in all the major desktop browsers with the width of the PDF scaling to fit inside the confines of the iFrame and a vertical scroll bar to view all the pages within the document.
At the moment however I can't get the PDF to display correctly in Mobile Safari. In this instance only the top left portion of the PDF is visible without any horizontal or vertical scrollbars to see the rest of the document.
Does anybody know of I workaround for this problem in Mobile Safari?
UPDATE - MARCH 2013
After hours of searching and experimentation I can conclude that this problem is a real mess!! There are a bunch of solutions but each far from perfect. Anybody else struggling with this one I advise to refer to 'Strategies for the iFrame on the iPad Problem'. For me I need to write this one off and look for another solution for our iPad users.
UPDATE - MAY 2015
Just a quick update on this question. Recently I have started using the Google Drive viewer, which has mostly solved the original problem. Just provide a full path to the PDF document and Google will return a HTML formatted interpretation of your PDF (don't forget to set embedded=true). e.g.
https://drive.google.com/viewerng/viewer?embedded=true&url=www.analysis.im%2Fuploads%2Fseminar%2Fpdf-sample.pdf
I'm using this as a fallback for smaller viewports and simply embedding the above link into my <iframe>.

I found a new solution. As of iOS 8, mobile Safari renders the PDF as an image within an HTML document inside the frame. You can then adjust the width after the PDF loads:
<iframe id="theFrame" src="some.pdf" style="height:1000px; width:100%;"></iframe>
<script>
document.getElementById("theFrame").contentWindow.onload = function() {
this.document.getElementsByTagName("img")[0].style.width="100%";
};
</script>

<iframe
id="ifamePdf"
type="application/pdf"
scrolling="auto"
src={"https://docs.google.com/viewerng/viewer?url="+"https://example.com/pdfdoc.pdf"+"&embedded=true"}
height="600"
></iframe>

My solution for this is to use google drive on mobile and a standard pdf embed in an iframe on larger screens.
.desktop-pdf {
display: none;
}
.mobile-pdf {
display: block;
}
#media only screen and (min-width : 1025px) {
.mobile-pdf {
display: none;
}
.desktop-pdf {
display: block;
}
}
<div class="outer-pdf" style="-webkit-overflow-scrolling: touch; overflow: auto;">
<div class="pdf">
<iframe class="desktop-pdf" scrolling="auto" src="URL HERE" width="100%" height="90%" type='application/pdf' title="Title">
<p style="font-size: 110%;"><em>There is content being displayed here that your browser doesn't support.</em> Please click here to attempt to view the information in a separate browser window. Thanks for your patience!</p>
</iframe>
<iframe class="mobile-pdf" scrolling="auto" src="https://drive.google.com/viewerng/viewer?embedded=true&url=URL HERE" width="100%" height="90%" type='application/pdf' title="Title">
<p style="font-size: 110%;"><em>There is content being displayed here that your browser doesn't support.</em> Please click here to attempt to view the information in a separate browser window. Thanks for your patience!</p>
</iframe>
</div>
</div>

For using the google preview in 2021, I had to do the following. Some small adjustments to how it was posted above.
"https://drive.google.com/viewerng/viewer?embedded=true&url=" + encodeURIComponent(pdfUrl)

try pdf.js should also work inside mobile safari: https://github.com/mozilla/pdf.js/

I got the same issue. I found that by setting the focus on an input (doesn't work with div tags) the pdf is displayed.
I fix it by adding an hidden input and set the focus on it. this work around doesn't slowdown the application.
<html><head>
<script>
$(document).ready(function () {
$("#myiframe").load(function () { setTimeout(function () { $(".inputforfocus").focus(); }, 100); });
});
</script></head>
<body>
<div class="main">
<div class="level1">Learning</div>
<input type="hidden" class="inputforfocus">
<div>
<iframe src="PDF/mypdf.pdf" frameborder="0" id="myiframe" allow="fullscreen"></iframe>
</div>
</div>
</body>
</html>

Related

PDF on iOS Mobile Devices rending PDF as Image

I can't seem to figure out why I am having issues with an embedded PDF in a simple HTML page on ONLY iOS devices (iPad/iPhone). Android and PC are fine. On iOS devices it renders the PDF on the page as what appears to be a PNG file. It only renders the first page of the PDF. Scrolling doesn't work, neither does tap and hold. The browser doesn't see it as a PDF. I've tried:
<object data='edoc.pdf'
type='application/pdf'
width='100%'
height='700px'>
</object>
Even tried an iFrame/DIV and while I can get the frame to scroll, it's only when I shrink the frame smaller than the "pdf" is renderd and it simply scrolls the single image around.
<style type="text/css">
.scroll-wrapper {
display: inline-block;
-webkit-overflow-scrolling: touch;
overflow-y: scroll;
}
.scroll-wrapper, .scroll-wrapper {
width: 400px;
height: 400px;
}
</style>
<div class="scroll-wrapper">
<iframe src="edoc.pdf" id="test" ></iframe>
</div>
I'm at a loss. My application needs to use an embedded PDF but I need to figure out why the iOS devices are such a hassle. This behavior has been repeated on Safari, Chrome, Firefox. On iPhone and iPad. Version has been consistently iOS 10+. I've checked the web server mime type is setup properly for PDF. I've tried multiple PDF's from multiple locations.
Linking to the PDF
<a href='edoc.pdf'>PDF Name</a>
Works just fine. I'm lost. Help.
Any help is welcome.

jQuery mobile data-role="button" not formatting

I'm loading into another div with .load('settings.html') function in
The settings.html page being loaded contains:
<div style="text-align: center; border: 1px solid black">
Application Settings: <br>
Reset Application Key
</div>
The problem is that the button is not getting formatted as per jquery mobile button data-role. If I place this on my main page the button is displayed correctly whereas by load function its a simple link.
What am I getting wrong here?
After you load settings.html use enhanceWithin() to enhance the markup and css of the button. Give your div a class and enhance it after load
Read more here -- https://api.jquerymobile.com/enhanceWithin/
Demo Take out the enhance to see that it does not render properly even when you append it
https://jsfiddle.net/5es81kgd/
Code
$('.but').append('Reset Application Key').enhanceWithin();

Remove scrollbar in iframe within div but not scrollable

Hi I'm working in Cordova/Phonegap and JqueryMobile. I have a div and a iframe here's the code. there is no cross domain issue in Cordova but in browser i cant show any one my working code but still here's the jsfiddle code
<div id="viewsites" class="viewsites">
<iframe class="clsIframe" src="http://www.google.com/" id="viewsite_iframe" width="0"></iframe>
</div>
i dont want to show scrollbars so i have set parent div overflow: hidden,
now problem in in iphone i cant drag the iframe site
I want to hide scrollbars without stopping scrollable
Use CSS:
iframe {
overflow:hidden;
}
In your iframe html tag:
<iframe src="" scrolling="no"></iframe>

iOS6 Youtube iFrame breaks when hidden and displayed again

This works fine in any Browser, but not on iOS6 (did not try it with iOS5)
I got an iFrame with a YouTube Video in it, situated in an overlay. After playing the video and toggle the overlay, the video again is broken. The video will playback in the background (you will hear the sound), but its not visible anymore.
Here's a minimal example:
http://jsfiddle.net/s9M6J/2/
<script>
/* jQuery */
$(document).ready(function() {
$('a').click(function() {
$('.videowrapper').toggleClass('hidden');
});
});​
</script>
<style>
.hidden{
display: none;
}​
</style>
<body>
toggleVideo
<div style="background: green; width: 500px; height: 500px;">
<div class="videowrapper">
<div id="video1">
<iframe width="500" height="315" src="http://www.youtube.com/embed/HMrlFLZFdnQ" frameborder="0" allowfullscreen></iframe>
</div>
</div>
</div>
</body>
Does anyone know a workaround for that?
Got a similar issue when embedding a Brightcove video on a jQuery Mobile page which is shown/hidden via javascript. Works on all desktop browsers and android but not Safari on iOS 6.
According to http://forum.brightcove.com/t5/General-Development/Video-in-show-hide-div-does-not-play-on-iOS/m-p/17558#M2352 a workaround is to hide your videowraper by moving it out of the screen using some CSS like position:absolute;top:-9999px then back to normal positioning when you want to show it.
For jQuery Mobile users it means embedding video iframes on multiple <div data-role="page"> on a single page structure won't work, need to put them on separate html pages.

Image in jquery mobile fixed header overlaps content until resize event

I have an image in my jquery mobile fixed header. When the page loads in Google Chrome or Apple Safari the header content overlaps the content div below the header until I resize the page. Firefox and IE work just fine.
Thanks!
I think the problem is that when jQuery Mobile initializes the page, the header image is not loaded and the header is much smaller so jQuery Mobile puts a padding on the .ui-page element that is too small once the image loads. A simple fix for this is to manually set the size of the header image so that it takes-up it's required space even before its source loads.
You could also do this, although it seems pretty hacky to me, force a redraw by triggering the resize event on document.ready or maybe window.load:
$(window).on('load', function () {
$(this).trigger('resize');
});
I pasted this code into the console while on your page and it re-positioned the title element as expected.
Does applying the following CSS help?
.ui-page {
padding-top: 91px !important;
}
Note that you will have to refine the selector as this will apply to overlay popups either.
I had lots of trouble with this. This worked until I wanted to add a link:
<div data-role="header">
<img border="0" src="logo.png" style="float:left;display:inline"/> <h1></h1>
</div>
Note the empty h1 tag.
I ended up not using a data-role="header" at all, I just couldn't get it to work with a link. I used a ui-bar class instead. Like this:
<div class="ui-bar ui-bar-a">
<a href="/" data-role="none">
<img border="0" src="images/logo.png" style="float: left; display:inline">
</a>
</div>
A solution based on #Jasper answer that worked for me was:
$(document).on('pageshow', "div[data-role='page']", function () {
$(window).trigger('resize');
});
It has an improvement that apply to all the jquery mobile pages
I played with the rather good solutions from Jasper and Carlos487 and found this to be the most up-to-date and reliable way to do it (jQM 1.4.x):
if it's due to an image without specified dimensions that will need some time to load and thus may cause the header to enlarge, then specifying the known dimensions (ideally via CSS) should do it. Otherwise there should be a way to determine if it has finished loading and thus applying the idea of solution 3 below.
if it's is due to some (maybe) unknown header resize event (e.g. through some image loaded later or some other content shrinking the header and thus making it vertically bigger), then this should work with a reasonable big enough timeout value:
$( ':mobile-pagecontainer' ).on( 'pagecontainershow', function(e) {
// maybe value > 100 needed for your scenario / page load speed
setTimeout( function() { $(window).trigger('resize'); }, 100 /*ms*/ );
}
if you know what is causing this (as in my case, where I am right shifting the page content on large screens via some (otherwise hidden/overlayed) left aligned navigation panel), then the following may be even better, beeing independent of the actual time the page needs to load on some device or scenario (which may be longer than your predefined timeout above):
// if its due to some animation like in my case
// otherwise try to find a similar way to determine when the resizing event has
// completed!
$('#someAnimated').animate( 'complete', function() { $(window).trigger('resize'); });
(I am not sure if Jaspers solution using $(window).on( 'load', ... will be correct in all jQM page load scenarios (with AJAX page navigation). That's why I would prefer Carlos487's approach in my example.)
None of the solutions above worked for me. But I found out my problem lies in the events after the page navigation. If the content div is hidden during this time, it doesn't get positioned under the header div, rather stays in its original place:
$(document).on("pageshow", "div[data-role='page']", function()
{
$("#pageContentDiv").hide();
setTimeout(function()
{
$("#pageContentDiv").show();
}, 0);
});
EDIT:
Found a better solution; set header div height and page div top padding to the same value:
<div data-role="page" style="padding-top: 60px">
<div data-role="header" data-position="fixed" style="height: 60px">
Hope this helps.

Resources