readium / readium-js

EPUB processing engine written in Javascript
BSD 3-Clause "New" or "Revised" License
367 stars 107 forks source link

Handle programmatic navigation in zipped epubs (and exploded EPUBs?) #106

Open johanpoirier opened 9 years ago

johanpoirier commented 9 years ago

Hi,

I encountered a serious issue with a zipped epub 3. There is one page with an and many empty <div> (like a handmade <map>). There is a little javascript that listens to clicks on the divs and then calls the following code (the page param is the id of the div):

function goto(page){    
    window.location.href = "../page/"+page+".xhtml";
}

And this doesn't work at all with a zipped epub because the url is not replaced by a blob url. And I can't see how to handle such dynamic requests, do you?

In the future, we would use the Service Worker API but we ain't there yet.

danielweck commented 9 years ago

Yes, this is one of several major caveats when reading zipped EPUB (Media Overlays, audio/video track elements, source elements instead of src attributes, nested iframes, etc.). I agree that the Service Worker functionality looks exiting, or even better: a W3C specification implemented by all major web browsers to stream resources URIs from inside packaged apps/ebooks. Until then, we have to live with the fact that the BlobURI prefetcher only works for "static" content. Thanks for your feedback @johanpoirier

danielweck commented 9 years ago

Does programmatic navigation actually work in exploded EPUBs anyway? I am pretty sure that in order to correctly open spine item documents, Readium needs to hook click event listeners to a hyperlinks: https://github.com/readium/readium-shared-js/blob/develop/js/views/internal_links_support.js#L183

this.processLinkElements = function($iframe, spineItem) {

        var epubContentDocument = $iframe[0].contentDocument;

        $('a', epubContentDocument).click(function (clickEvent) {
            // Check for both href and xlink:href attribute and get value
            var href;
            if (clickEvent.currentTarget.attributes["xlink:href"]) {

                href = clickEvent.currentTarget.attributes["xlink:href"].value;
            }
            else {
                href = clickEvent.currentTarget.attributes["href"].value;
            }
etc.
kimtuck commented 8 years ago

I have written a plugin (with a few small hooks into the fetching logic) that will allow you to replace the built-in resource fetchers with your own custom fetchers. I'm using this to read exploded epubs from a server, using full encryption over the wire (encrypt on the server, decrypt on the client). This might provide a solution for you -- you can directly invoke the resource fetcher, I think, from your code; and if you can't do that you can go to a CFI and invoke the load process that way.

I'll be putting this up as a pull request in a few days.