|
||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
This article is in the Product Showcase section for our sponsors at The Code Project. These reviews are intended to provide you with information on products and services that we consider useful and of value to developers.
Some Background
PDFs are probably the most popular digital document exchange format on the planet. Being recently ratified as an ISO standard can’t hurt Adobe’s cause either. Because of its popularity, there are many instances where you run into these documents on the web and viewing them in place is largely faked by our browsers. Clicking on one of these PDFs causes Adobe to open while the document downloads in the background, and eventually, you get to see it in all its glory. Well, I say there’s a better way. What’s the Point?It’s simple. PDFs can be large. What’s the point of taking the time to download the whole document and start Adobe Reader if you only want to see the 150th page of our 369 page documentation PDF? There isn’t. ThinDoc achieves the goal of being a zero-footprint PDF Viewer using the WebImageViewer from Atalasoft’s DotImage SDK, and with a little bit of magic, can be integrated into your daily life with no programming knowledge whatsoever. Being “zero-footprint” implies that ThinDoc requires no plugins (like Flash), Acrobat Reader, or Applets. It is pure JavaScript and HTML on the client. The Design GoalsIt needed to be fast, it needed to be full screen (read “full browser”), and it needed to be simple.
Full-screening the WebImageViewerTo make any block level element in an HTML page have 100% height, you must not only set that element's height to 100%, but also the height of its parent… and its parent’s parent… and its parent’s parent… and so on. When you get to the body, it might feel a bit weird and your IDE may bark at you, but do it anyways: The WebImageViewer is built from an iFrame. To interact with the image and pan around in it, the iFrame has scroll bars. The bottom scroll bar we can deal with -- that’s good to have -- but every browser interprets page height a little differently and therefore you can’t guarantee that the viewer will not stretch beyond the length of the browser window, causing the window's scroll bar to appear. What we need to do is use a few techniques to force each browser to hide scroll bars entirely. The Everything-but-IE FixTo remove scroll bars from every browser except for IE, you simply set the overflow CSS property of the body to body {
...
overflow:hidden;
}
For the Other 85% of the People Out There…To remove scroll bars from IE, you need to set the scroll attribute of the body to Making It Simple
Making this as minimalistic as possible was a goal. There are two sets of controls and neither of them appears unless you are moving your mouse; this lets you see the whole document without anything in your way. The zoom, close, and download controls are fairly straightforward, so I won’t go into them. ThumbnailsThe thumbnail viewer on the bottom uses a bit of JavaScript to be able to page through the frames. Here’s a look at what’s inside: var ScrollInterval;
var xPos = 0;
var _thumbWidth;
function scrollright() {
clearInterval(ScrollInterval);
ScrollInterval = setInterval("moveright()", 25);
}
function moveright() {
if(xPos > -_thumbWidth * (WebThumbnailViewer1.getCount()-4)) {
xPos = xPos - 50;
WebThumbnailViewer1.setScrollPosition(new atalaPoint(xPos,0));
}
}
function scrollleft() {
clearInterval(ScrollInterval);
ScrollInterval = setInterval("moveleft()", 25);
}
function moveleft() {
if(xPos < 0) {
xPos = xPos + 50;
WebThumbnailViewer1.setScrollPosition(new atalaPoint(xPos,0));
}
}
// This makes sure that we are seeing exactly 4 full
// thumbnails when the user stops scrolling
function snap() {
clearInterval(ScrollInterval);
var numThumbs = Math.round(xPos / _thumbWidth);
xPos = numThumbs * _thumbWidth;
WebThumbnailViewer1.setScrollPosition(new atalaPoint(xPos,0));
}
<!-- the Scroll Right Button -->
<a href="#" onmousedown="scrollright();" onmouseout="snap();" onmouseup="snap();">
<img alt="Move Left Button" src="images/moveRight.png" height="140px" width="30px" />
</a>
The right-arrow button in the thumbnail viewer that controls scrolling to the right has an Hiding and Showing the Controls
When the application starts, the controls are displayed to give the user a hint that they exist. By simply moving the mouse, they will reappear and remain visible until the mouse stops moving for two seconds. The WebImageViewer provides a var iframes =
document.getElementById("WebImageViewer1").getElementsByTagName("iframe");
iframe = iframes[0].contentWindow || iframes[0].contentDocument;
if(iframe.document)
iframe = iframe.document;
iframe.onmousemove = showAll;
First, we grab the document element with the ID of our WebImageViewer. In this case, it is var HideAllTimeout;
function showAll() {
clearTimeout(HideAllTimeout);
HideAllTimeout = setTimeout("hideAll();", "2000");
WebThumbnailViewer1.setVisibility("visible");
document.getElementById("thumbs").style.visibility = "visible";
document.getElementById("controls").style.visibility = "visible";
}
// if they keep their mouse still for 2 whole seconds, we hide the controls
function hideAll() {
clearTimeout(HideAllTimeout);
WebThumbnailViewer1.setVisibility("hidden");
document.getElementById("thumbs").style.visibility = "hidden";
document.getElementById("controls").style.visibility = "hidden";
}
The CachingTo make sure that any documents requested are loaded quickly, we need to cache it locally for future processing. First, the code-behind grabs the image at the requested URL and saves it to a folder on disk. url = Server.HtmlDecode(url);
filename = MapPath(FileMapper.GetHashedName(url));
if (!File.Exists(filename))
{
WebClient client = new WebClient();
client.DownloadFile(url, filename);
}
This lets us not only load the subsequent pages of the document more quickly, but also makes the next load of this document blazingly fast. Since I don’t want to eat up more than 50MB of my disk, I remove the n least recently used documents until the cache is smaller than 50MB. The BookmarkletTo make this app as usable as possible, I wrote a simple Bookmarklet. Drag this ThinDocify link into your browser’s Bookmarks Bar (for Firefox and Safari) or right click it and add it as a Favorite (for IE). To use it, navigate to your favorite page that contains links to PDF documents, click the ThinDocify Bookmarklet in your Bookmarks Bar, and click the links to the PDFs on that page. A Bookmarklet is simply a piece of JavaScript that is crammed into a link. When you add that link to your Bookmarks bar and run it, it is run in the context of the page that is currently in the browser. In the code below, we loop through every link on the page and check to see if the URL ends in PDF or TIF. I also do a quick don’t-break-Google check and make sure that none of the URLs contain question marks. Granted, this does limit its functionality on sites that serve PDFs from scripts that take in their names in the query string, but hey, at least it doesn’t break the internet. For each of those URLs, we replace it with a call to the JavaScript function <script type="text/javascript">
<!--
(function() {
var i;
for(i = 0; i < document.links.length; i++) {
var url = document.links[i].href;
if((url.substring(url.length-3, url.length) == 'pdf' ||
url.substring(url.length-3, url.length) == 'tif') &&
url.indexOf('?') == -1) {
document.links[i].href =
'javascript:window.open(\'http://thindoc.atalasoft.com/?url=' +
escape(url) +
'\',\'_thindoc\');';document.links[i].target = '_thindoc';
}
}
}
)();
-->
</script>
You can also add this script to the bottom of your own web pages and it will automatically convert all PDF links to open in ThinDoc. For more information about ThinDoc, please visit its About page. Sample DocumentsClick on the following documents to see ThinDoc in action:
Link to a specific page within a document: Download the SourceYou can get the source for ThinDoc here.
|
|||||||||||||||||||||||||||||||||||||||||||||||