readium / readium-shared-js

Repository for the shared JavaScript libraries that are used in the SDK-Launchers and other applications developed on top of the SDK
BSD 3-Clause "New" or "Revised" License
78 stars 102 forks source link

Provide functionality to be able to highlight the current location in a TOC #97

Open rkwright opened 10 years ago

rkwright commented 10 years ago

From John Nowak:

I'd like to highlight the user's current location in a book when displaying its TOC. As far as I can tell, this means getting the current idref and CFI by calling 'ReadiumSDK.reader.bookmarkCurrentPage', and then -- somehow -- turning this into data I can use to identify the navigation element accessible via the TOC that's immediately prior to the user's current location. Given that I can't find any obvious way to do this, and given that the Readium Chrome app doesn't indicate the user's position in the TOC, I think it may just not be possible with Readium at present. If anyone does know how to do this though, or has an idea about how such functionality could be added, I'd very much appreciate it! Thanks!

danielweck commented 10 years ago

CFI expressions are by nature comparable / sortable (because they are canonical, unlike XPath for example). So, assuming each heading link in the TOC has a corresponding CFI, then any bookmark location can be positioned reliably and precisely within the TOC hierarchy (we'll, relative to its nearest heading). Unfortunately, the EPUB3 Navigation Document typically contains links with traditional fragment identifiers (XHTML element IDs). So, Readium would need to resolve all the links in the TOC, in order to map with CFI expressions. This data should be cached to ensure decent performance.

danielweck commented 10 years ago

Related (readium-js-viewer UI): https://github.com/readium/readium-js-viewer/issues/213

becka11y commented 9 years ago

So here is a naive thought: Don't we know the URI of the currently displayed "pages"? I see that the iframe src data is cached in a blob but we do know the original URI and could cache it. Then it seems easier to match that value to the fragment identifiers contained in the TOC document. Although I suspect that large items or references to other spine items within the currently displayed "pages" could present a problem. And I'm sure I don't understand all of the nuances of TOC documents!

danielweck commented 9 years ago

Hi @becka11y you can use spineItem.href and resolve against the package's base URI, for example:

https://github.com/readium/readium-shared-js/blob/develop/js/views/internal_links_support.js#L55

    function getAbsoluteUriRelativeToSpineItem(hrefUri, spineItem) {

        var fullPath = reader.package().resolveRelativeUrl(spineItem.href);

        var absUrl = hrefUri.absoluteTo(fullPath);

        return absUrl;
    }
becka11y commented 8 years ago

So, I can highlight the top level TOC item but once the user starts paging through I can't find a way to identify the section that is currently displayed. Is there a way to get the dom of the currently visible "view"? If so, I can search for elements with the id's associated with the hrefs in the TOC associated with that spine item. Although this would probably be slow on continuous scroll documents.

I did find the api to get the domRange between two CFI's but I don't think the domRange gives me enough info to find the actual elements with a specific set of id's.
I'm thinking there is no way else to identify the current TOC items than to use CFI's as you originally suggested, but creating the cache of them will be tedious.

At least I am learning better how Readium goes together but I still have a long way to go!

becka11y commented 8 years ago

Documenting here so I don't forget! I tried using .getVisibleElements("[id]") to find the visible elements that are identified in the toc. I can then compare those id's with the ones in the toc to find the one to highlight. The problem is when the item represented in the toc is not actually displayed on the page. I can't find a way to match the currently displayed data with an id represented in the toc. It looks like there is no hack around using CFI's.