PDA

View Full Version : Dynamic AJAX Content - cant load PDFs



ralph
09-03-2010, 06:59 PM
1) Script Title: Dynamic Ajax Content

2) Script URL (on DD): http://www.dynamicdrive.com/dynamicindex17/ajaxcontent.htm

3) Describe problem:

I'm using this AJAX script to load external content into a DIV tag.
The problem is when i want to load PDF files to display in the DIV, all i get is illegible binary code.

So how i can i have the the actual PDF files display instead?

[I was originally using an IFRAME to load all the content, but switched to AJAX to avoid the two sets of scrollbars - one for the actual HTML page and one for the IFRAME.]



<div id="leftcolumn">
<a href="javascript:ajaxpage('myPage.htm', 'rightcolumn');">HTML content - loads fine</a>
<a href="javascript:ajaxpage('PDFs/ReadMe.pdf', 'rightcolumn');">A PDF file - gobbledigook!</a>
</div>

<div id="rightcolumn">
<h3>PDF files wont render properly here.</h3>
</div>

jscheuer1
09-04-2010, 03:04 PM
AJAX can only be used to import HTML code. There is a tag for displaying PDF. The object tag used for Flash and other multimedia content is used.

In IE 8, Firefox, Safari, Opera, and Chrome (all these the latest versions available for Windows 7 that I'm aware of), this works:


<object data="1234.pdf" type="application/pdf" width="600" height="600">
alt : <a href="1234.pdf">1234.pdf</a>
</object>

Acrobat reader opened in the object and scaled the document to the dimensions specified. The only scrollbar was for vertically scrolling the document in Acrobat, no scrollbars for the object tag. If the object tag is tall enough in relation to its width, there could be no scrollbar at all. If possible, this would be controlled by how the PDF was saved. With mine I got an empty vertical scrollbar, in Acrobat, not on the object tag.

Browsers that cannot show the PDF file with the object tag should show the nested text and link.

I also imported the above via AJAX. As with all pages so imported, it's best to only include the HTML code that you need to make a valid xml document that also will get you the content you desire. In this case, the above code is all that is required. This also worked in all of the browsers mentioned.

ralph
09-04-2010, 07:12 PM
That worked great. Thanks.

But how can i dynamically (?) set the height in the object/PDF so that it fills the entire height of the document body?

i tried setting its height to 100%, but that didnt work.


<object data="1234.pdf" type="application/pdf" id=myObject width="600" height="100%">

i also tried this script, but no joy here either:


document.getElementById('myObject').style.minHeight = (document.body.scrollHeight);

any ideas?

jscheuer1
09-04-2010, 09:15 PM
Which document? If you followed my instructions exactly, it already fills 100% of the document it's on, the imported document, as it's what sets that document's height.

But I think you mean the document that it's being imported to. For that it would have to be a child of the body element or a child of another element or elements all direct descendants of the body and all set to 100% height. If not using quirks mode (no DOCTYPE, where the html and body elements are assumed to be 100% height) one must also set the html and body to 100% height. It's also important (regardless of mode) to set the margin and padding of the html and body to 0. Some browsers will probably require overflow hidden on the html and body. Finally, there must not be anything else above or below the object, otherwise things will get weird.

Using jQuery for the import and HTML 5 standards, here's an example 'top' page:


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<style type="text/css">
html, body {
margin: 0;
padding: 0;
overflow: hidden;
height: 100%;
}
object {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
#target {
width: 600px;
height: 100%;
}
input {
float: right;
}
</style>
<script type="text/javascript">
jQuery(function($){
$('input').click(function(){
$('#target').load('1234.htm');
});
});
</script>
</head>
<body>
<input type="button" value="Go">
<div id="target">

</div>
</body>
</html>

Here's the external file (1234.htm, in this case):


<object data="1234.pdf" type="application/pdf">
alt : <a href="1234.pdf">1234.pdf</a>
</object>

ralph
09-05-2010, 03:08 AM
The problem occurs when the height of the parent window is greater than the height of the pdf in the child document.
I get two scrollbars - just as when i was using an iframe. And if i set the parent window to
overflow: hidden, then i cant scroll down the content within the parent document.

I used the AJAX script to achieve a single scrollbar for all the content - parent and child. But, as the AJAX didnt render the PDF, i tried embedding and then the double scrollbar issue comes up all over again.

You can see my first attemp at a solution here, using the original DD AJAX script...

http://fulcrum.ws/pdf_menu/index.htm

and here, using your solution:

http://fulcrum.ws/pdf_menu/index1.htm

Heres the code i used with your solution ("index1.htm" as in the link immiedately above).
[i didnt know how to write text hyperlinks with jQuery, so the only working link is the "Go" input button.]



<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<script type="text/javascript" src="jquery.min.js"></script>

<style type="text/css">
html, body {
margin: 0;
padding: 0;
height: 100%;
}
object {
margin: 0;
padding: 0;
height: 100%;
width: 600px;
}

#target {
float: left;
width: 600px;
height: 100%;
background: pink;
}

#menu {float: left;
width: 400px;
height: 100%;
}

input {
float: right;
padding: 50px;
}

A {
float: right;
display: block;
padding: 100px;
}

</style>

<script type="text/javascript">
jQuery(function($){
$('input').click(function(){
$('#target').load('1234.htm');
});
});
</script>
</head>
<body>

<h1>HEADER</h1>

<div id="target">
<object data="abcd.pdf" type="application/pdf">
alt : <a href="abcd.pdf">abcd</a>
</object>
</div>


<div id="menu">
<input type="button" value="Go">

<A>LINK 1 of 6 :: 1234.htm</A>
<A>LINK 2 of 6 :: abcd.htm</A>
<A>LINK 3 of 6 :: 1234.htm again</A>
<A>LINK 4 of 6 :: abcd.htm again</A>
<A>LINK 5 of 6 :: 1234.htm again</A>
<A>LINK 6 of 6 :: abcd.htm again</A>
</div>

</body>
</html>

jscheuer1
09-05-2010, 04:23 AM
Well, one can always make something up that "doesn't work". All I was saying is that if you want the object to take up 100% of the height of the body, there are things you can do.

In both of your examples it doesn't appear as though you want 100% of the height of the body, which is what you asked. In your first example, the target is only 400px high, at least it must be 100% high for the object it will contain to also be 100% high. In your second example there's a header above the PDF. If the PDF is 100% high, there will either be no room for the header, or no room for part of the PDF.

I'm thinking that perhaps what you are after is to get one page of the PDF to take up 100% of the height of the object. To do that all you need to do is determine the ratio of width to height required. It's roughly 8.5 x 11 (the ratio of an actual piece of paper, but that doesn't account for Acrobat's "chrome"). Then use a fixed width and a fixed height that will accommodate that. 600 x 800 (you may want to tweak these) pixels seems about right:


<object data="1234.pdf" type="application/pdf" width="600" height="800">
alt : <a href="1234.pdf">1234.pdf</a>
</object>

Then just make sure that the target container you are importing to has at least those dimensions, and the only scrollbars you will have will be in Acrobat and for the page itself. The scrollbars for the page will not be present unless needed, or if viewing in IE 6 or less where there is always a vertical bar for the browser whether required by the page or not.

ralph
09-05-2010, 05:33 AM
Of course, you are right. I apologise for not explaining myself properly the 1st (and 2nd!) time round :p.

what i actually want is: the height of the target in which the linked content appears to (dynamically) equal the scroll height of the parent/window itself. Or, more precisely, i want the scroll height of the parent/window to at least equal the full height of the linked content in the target, and thus, rendering the scrollbar of the target DIV redundant. phew! got there in the end. LOL.

the original DD script allows for this to happen with HTML. i've edited the code in "index.htm" (see: http://fulcrum.ws/pdf_menu/index.htm) to set all the heights to 100% and have added a header above both boxes.

as you can see, the new first link "pureHTML" links to a html page (pureHTML.htm) several thousand pixels in height. yet the ony scrollbar is that of the overall parent window. the target height has been stretched to accomodate all the content - removing the need for another scrollbar.

the problem remains with the other links (1234.htm, abcd.htm) to the embedded PDF files. i just cant get them/the target DIV/the object to strech out to the scrollHeight of the parent window.

incidentally, i first found this workaround for loading HTML content in an iframe:


<BODY onload="resizeFrame(document.getElementById('target'))">


<script type="text/javascript">
function resizeFrame(f) {
f.style.height = f.contentWindow.document.body.scrollHeight + "px";
}
</script>

it forces the target frame to take the height of the parent. but i couldnt get PDFs to fill the height in the same way. hence the recourse to AJAX.

so, bascially, can you pls show me how to render/stretch the height of the target - as achieved with external HTML content via the DD AJAX script or the script above - for embedded PDF content? [in order for there to be no need to scroll through the target content independantly of the overall window content itself.]

your knowledge and patience is much appreciated.

jscheuer1
09-05-2010, 03:40 PM
I still don't understand, and think you may be over complicating things. Forget about getting 100% of anything. If the object has the correct width to height ratio, it will have no scrollbars. If the target division's width is equal to or greater than the object and has no height set (either explicitly or implicitly), it will have no scrollbars. In fact, if the target division is not constrained at all - no width or height limits, it will never have a scrollbar.

Note: After playing around with this, it seems that the dimensions of the object are best set in style on the 'top' page:


<style type="text/css">

object {
width: 600px;
height: 800px;
}

</style>

jscheuer1
09-05-2010, 06:47 PM
As I say, I'm still not real clear on what you are going for, here's something I'm playing with:


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
object {
display: none;
overflow: hidden;
}
#header {
overflow: hidden;
}
h1 {
float: left;
width: 8em;
}
input {
float: left;
margin-left: 1em;
position: relative;
top: 2em;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
jQuery(function($){
var win = $(window), b = $('body'), t = $('#target'), m = parseInt(b.css('marginTop')) + parseInt(b.css('marginBottom')), count = 0, h, w;
function sizeIt(){
$('#objectStyle_' + (count - 1)).remove();
h = win.height() - $('#header').outerHeight(true) - m;
w = Math.round(h * (6 / 8.25));
$('head').append('<style id="objectStyle_' + (++count) + '" type="text/css">object {display: block; height: ' + h + 'px; width: ' + w + 'px; }<\/style>');
}
sizeIt();
win.resize(sizeIt);

$('input.loader').click(function(){
t.load(this.value + '.htm', function(data){t.html(data);});
});
});
</script>
</head>
<body>
<div id="header">
<h1>Header</h1>
<input class="loader" type="button" value="1234">
</div>
<div id="target">

</div>
</body>
</html>

1234.htm:


<object data="1234.pdf" type="application/pdf">
alt : <a href="1234.pdf">1234.pdf</a>
</object>

Notes: This is a little non-standard for jQuery because of IE quirks. Ordinarily using the data of the load() function in the manner I have here is redundant. But it produces valid HTML 5 markup. Otherwise IE would frequently refuse to show the imported PDF.

Removing the next to most recently added style object during window resizing seemed only to be required in IE as well. Seems IE can only handle so many style sections in the head before it starts ignoring them. And it was unable to consistently keep the object tag visible without keeping at least one around during the process of inserting the next.

The markup and styles are fairly standard, but a bit constrained. Care should be taken in adding to this layout. An understanding of floats within an overflow: hidden container helps. For example, the header division should not be given dimensions. If so, some of its content may disappear.

Any external .htm file may be loaded by an input with the class 'loader'. It will be the value of the input + the .htm extension. So it can be used with selects or text inputs (caution here, the user can enter anything) as well as button inputs (as in this example) or with a radio button group. With a little tweaking to check for the checked state checkboxes could be used as well. Checkboxes and text inputs don't make a lot of sense to me though.

ralph
09-05-2010, 07:12 PM
Hopefully, this picture paints a thousand words.

Pls goto: http://fulcrum.ws/pdf_menu/abcd2.htm

The screenshot image in "abcd2.htm" illustrates the desired effect.

(In context: http://fulcrum.ws/pdf_menu/index.htm)

1. The PDF displays as a single unscrollable block. it width is fixed at @600px, regardless of the height - which will vary depending upon the number of pages the linked-to files contain (in this case 4).

2. The height of the PDF is is filled/stretched to near enough 100% of the target DIV in the parent/containing window.

4. In order to scroll through either the PDF or the HTML content, the HTML window - not the PDF object - is scrolled. Because the PDF displays as one single block of fixed width and dynamically fixed full height, no other scrollbar is reqired

5. The height cannot be in ratio to the width as any one document may contain 4 pages (as here) or 400 pages. Hence the attempt to force the height to 100% of the available height - although obviously this hasnt solved the problem.

jscheuer1
09-05-2010, 08:28 PM
That would require counting the pages in the PDF. There are, or at least were (I found instructions for Acrobat 7) methods for that in javascript, but that would probably only work for PDF's on the user's hard drive, and only if they have Acrobat 7 Pro installed). Assuming all that, do it remotely and security would be an issue. If it's not your computer, most browsers will not allow you to do that without an ssl, perhaps more certification. PHP can perhaps be used. I just Googled it and there appears to be a method for counting pages in PDF. In any case you would have to deal only with PDF's that have a standard page height.

Try out what I'm playing with in post #9. It's by no means a finished work. You need to use Acrobat's scrollbar to scroll through the pages. But at least you get to see all pages. The document has no scrollbar.

In most cases though, with PDF you just link them to the .PDF file. They can then view it online or off, and resize and scroll through it however they like.

Remember, you have no way of knowing what version of Acrobat or even if it is Acrobat that the user has to view PDF, or if they even have a viewer, or if they do, if it's even configured to work with their browser.

jscheuer1
09-05-2010, 09:29 PM
I'm testing the method using PHP to count the number of pages. It looks like it may be workable. Do you have PHP?

ralph
09-06-2010, 12:19 AM
Counting the pages - that makes perfect sense.
I'm ok with either PHP or ASP.
all the PDF pages will be standard A4 size (h: 29.7cm * w: 21 cm).

jscheuer1
09-06-2010, 02:13 AM
Well, it's working, more or less. There are a number of issues. I'm not sure I can recall them all here, these are the most important:


In Firefox when the page first loads with the first PDF on it, and each time a PDF is loaded via AJAX, the ability to use the home/end, up/down arrow, pgup/pgdn keys, and the scrollwheel are lost unless the tab/window loses focus and regains it. Using javascript (window.blur()/window.focus()) for this doesn't help. One may still scroll by dragging the window's/tab's scrollbar.


Even after that, one must click somewhere on the page other than on the PDF to activate use of these keys and the wheel. This part is true in other browsers. Click on the PDF and these functions are lost again until you click off of it. I haven't tested it, but covering the PDF with an almost transparent div or a transparent .gif might help a little here.


In IE there still are occasional instances where the PDF just doesn't show up. To fix this I've added the src param to the object tags and created a redundant loading of the imported tag (as mentioned before). Both of these strategies seem to help, but haven't eliminated the problem completely.


Here's a demo:

3523

Unzip it to a separate folder on your PHP host or PHP local server. The way the PHP code is written, the PDF files need to be in the same folder as the pages.php file. Easiest to just keep everything in the same folder. If you choose though, you can edit the PHP file and/or move things around. Just be careful not to break the PHP file's ability to find the PDF files. I've used parameters to make the PDF's appear without the Acrobat toolbar, bookmark menu, or scrollbar. Doing so helped in removing some browser's (notably Opera) artifacts in the rendering of the Acrobat chrome and left more real estate for the actual PDF. If you change that, tweaks to the dimensions and/or how the height is calculated may be required. The main page is:

1234_ajax_4.htm

On it you will see:


. . . margin-left: 1em;
position: relative;
top: 2em;
}
#target object {
width: 600px; /* set object width here */
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
jQuery(function($){
var pageHeight = 780, // set height for one page here
pagination = 65, // amount to add per page if more than one page
t = $('#target'), count = 0, h;
function sizeIt(pages){
pages = typeof . . .

These should be pretty self explanatory. I think however that my 1234_old.pdf file is a little non-standard. So if not using it, you can probably just do:


var pageHeight = 845, // set height for one page here
pagination = 0, // amount to add per page if more than one page

In any case, the height you use in the script needs to be worked out proportionally to the width you set in the style section. If more than one page, pageHeight is added to pagination and the sum is multiplied by the number of pages. If a single page, pageHeight is used alone.

jscheuer1
09-06-2010, 02:30 AM
Oh, and I just came across these:

http://flexpaper.devaldi.com/

and:

http://www.swftools.org/

Both look very good to me. Using Flash would eliminate many of the problems mentioned in my previous post.

Also:

http://www.axmag.com/

Not as sure about that last one.

ralph
09-06-2010, 04:43 PM
Thank you so much for your time and good effort. Your script is just what i was after. The links are also very useful.

If you can derive at least a fraction of the benefit from the token donation i've just paypal-ed you, then all the better.

:D

jscheuer1
09-06-2010, 05:33 PM
Thanks, I was playing with this idea a bit further though.

It seems that there's code (to prevent a system and/or browser crash) in Acrobat for only allowing X amount of memory for the display of PDF. I loaded a 410 page PDF which made moderate use of graphics into my viewer, it only would display fully up to page 42 regardless of the browser. You can toggle between scrolling being on the page or the PDF like I mentioned. But you couldn't see much below page 42 without scrolling the PDF. Without a scrollbar this can only be done with the mouse wheel and/or navigation keys.

At the same time, the page counter still worked. So there was a lot of blank and/or (depending upon the browser) garbage space below the last rendered page.

Even with a large PDF, if it's all text, this might not be a problem. There would still ultimately be a limit to how many pages could be displayed in this manner.

It probably depends upon how many bytes are in the PDF. The one I tried with was 6,140,343 bytes (5,997 k).

If there's even moderate use of images in a file with so many pages, one would be better off with some variation on my one page at a time version, or with one or a combination of two or more of the Flash approaches. An advantage with Flash is that the content can be buffered and streamed, allowing the user to begin viewing/reading before the entire document has downloaded.

Alternatively, we may be able to determine the cutoff for bytes (this could vary by computer though - available memory), measure the file size in PHP and then determine how to display the PDF from there. This assumes it's a byte cutoff. It may actually relate directly to the number of pages. If so, we could use that.