Javascript in ebooks
But first the case against and for javascript in ebooks.
Against
The reasons not to support javascript are quite numerous. When you list them all I’m almost embarrassed about how much of an ebook javascript supporter I’ve been in the past. (I still am, in a way. But more on that later.)
Problems for ereader vendors:
- Support. Your ereader becomes an app platform with all of the responsibilities and problems that follow. The documentation and support requirements of a non-JS ereader are extensive enough, now they are expected to add javascript.
- Security. Being an app platform and because ebooks are persistent downloads, ebooks potentially face more serious security problems than a website would. Ebooks are more extensive than the persistent widgets we’ve used in the past and many ereader devices don’t have as neat an update story as you’d need to deliver security updates.
- Consistency. Nobody has delivered solid javascript support in a reflowable, paginated, ereader app yet. (iBooks is too buggy to count as solid.) We have no idea whether the various ereader vendors are even capable of delivering javascript support in a consistent manner. (Readium might solve this problem.)
- Context mismatch. The javascript DOM and APIs all assume that they are run in specific context. When you implement a browser-based ereader app you create a context mismatch where the book’s javascript is executed in the app’s context. This creates bugs both in the book’s JS and in the app and opens the app up to a host of security problems. (It’s a bit as if every web page were allowed to execute arbitrary Objective C code in Mac OS X’s Safari browser, rewriting the UI, preferences, rendering, etc. at will.)
Javascript in ebooks also has problems for authors/devs. Where many ereaders have no update story, ebooks are worse. One of the core concepts in web development is iterative development. Every website is a living thing that is regularly updated and tweaked to match the changing browser landscape. Javascript-heavy websites that aren’t updated often end up being unusable when the market takes an unusual turn. There are many pages, for example, that still don’t work on the iPad, despite it having a screen resolution and CPU speed that was considered desktop mainstream only a few years ago.
Ebooks that rely on javascript are, quite simply, going to stop working some day. Any ereader vendor who wants to support JS in ebooks has to support automatic, silent, background ebook updates so that ebook authors can push out fixes when (not if) the books break.
Apple’s current tactic with iBooks is worse than useless:
- Different APIs enabled depending on whether you are in an ePub or in the iBooks 2.0 format. No documentation to help you out with the differences.
- No auto-update story for the ebooks. When an update breaks a book (which happens almost with every iBooks release) it remains broken until the reader re-downloads it. That is, if the author has sent Apple an update and if Apple has approved it.
- If iBooks were a browser it would be the buggiest browser maintained. The latest releases of all browsers are by far more stable, more documented, more programmer-friendly than iBooks. Even the worst mainstream browser I can think of (which would be Android’s default browser) isn’t as bad as iBooks.
- All documentation is secret. You only have access to it if you are publishing through iTunes Connect. Anybody going through an aggregator, or freelance ebook developers who aren’t publishing themselves, aren’t supposed to have access to the documentation or the testing tools Apple provides.
- No console. No debugging tool. No DOM inspector. No breakpoints. No nothing. iBooks is a dark, secretive, hellhole that doesn’t tell you anything about anything. It’s next to impossible to know what’s going on if something isn’t working.
In short, iBooks is a nightmare to develop for. It is the platform from hell. It offers more design features than other platforms, and is the only one that supports javascript, but, frankly, those features aren’t worth the pain involved.
So, if iBooks is any indicator of what the authoring experience for ebook javascript will be like, then you can count me out.
Thanks, but no thanks. I put a higher value on my sanity than that.
There’s one additional hurdle. One that most people keep misunderstanding when I state it: Apple won’t let third party ereader apps ship with javascript support.
They think I’m saying that Apple won’t let ereader apps ship with more or better javascript support than iBooks, or that Apple will be heavy-handed in protecting iBooks from competitors.
They may well, but that’s not the reason. Apple wouldn’t let ereader apps ship with comprehensive javascript support even if they didn’t make iBooks and weren’t in the ebookstore business.
Why?
Because an ereader app that supports javascript in ebooks is, as I said above, an app platform and Apple doesn’t allow competing app platforms ship through the iOS app store. They just don’t. They even sometimes block apps that vaguely smell like app platforms, like customisable dashboards and the like.
Allowing an app platform to ship via the iOS app store would be a major policy change at Apple.
The only exception I can think of is if an ereader app adds javascript support that is horrible, buggy, and unusable, Apple might let that slide, but that won’t help authors, for obvious reasons.
Third party ereader apps just aren’t going to ship with javascript support on iOS and iOS is too big a chunk of the tablet market to be ignored. Nobody is going to author javascript-enabled ebooks when they’d only work in less than 10% of the market. It doesn’t matter what the ereader vendors keep saying, or what IDPF says, it just isn’t worth it for authors or publishers. A delusion repeated like a chant still remains a delusion.
For
With all those problems, why have I always been in favour of javascript in ebooks, even to the point of tweet-flooding the patient folks at IDPF about the issue?
Simple: We don’t know what an interactive ebook looks like, yet.
We have plenty of ideas. Quite a few antecedents from the days of pre-web hypertext. Then a few more from the era of CD-ROMs. These interactive works vary enormously and require different capabilities. Then we have the web.
All of these platforms have allowed some sort of programming and many of the common features require it.
We are only now, after two decades, reaching a point where we have a bit of an idea of what common features the web requires and have started to implement them declaratively (like some of HTML5’s form features). Even so, we still rely on javascript because it’s just simpler than going through the process of inventing and then standardising declarative methods of authoring the same features.
We aren’t even close to this for ebooks. We don’t know what we want. We don’t know what we need. We don’t know what will be popular or enjoyable. What we don’t know can’t be implemented as native widgets and can’t be integrated into the ereader’s UI and chrome.
The problem space
There are several contexts were javascript might be useful in an ebook.
Main body. Running a script in the primary text of the ebook gives you access to several things. You can:
- Modify the text depending on actions (like StretchText) and outside factors (like the weather).
- Monitor the readers using software similar to our current web analytics (if network access is allowed).
- Alter the book’s content and structure based on the reader’s progress and demonstrated intent.
- Dynamically add links to the text based on arbitrary factors.
Most of these options don’t seem particularly appealing. StretchText never grew beyond a niche and I’m not sure readers are comfortable with the idea of having their book reading tracked like their web reading. Some of these options might be useful but are next to impossible to do well. (Intelligently coming up with useful/interesting changes to main content is harder than it sounds.)
Dynamically adding links might be useful, but since most uses I can think of (and most precedents) are sleazy marketdroid tactics, that’s also of doubtful value.
Still, hard to know the value when nobody’s trying.
Embedded widgets. The web equivalent would be iframes executing javascript code.
The iBooks 2.0 textbook format implements this, at least for native widgets. (I don’t know if they do so for HTML/JS widgets).
The web has plenty of examples, most of them ads. Google, I think, uses this for their native HTML5 video embed codes.
Popups and appendices. This is how a large majority of non-app interactivity works on the web. You take an action (click on an image, link, graphic) and something interactive pops up in an overlay or separate window. Then you use the slideshow, flash infographic, or whatever in that separate window or context and when you’re done you close it to return. The state of the original reading context is preserved.
Spine. A javascript that runes in the context of the entire book – not just a chapter – with access to the entire book’s structure.
Not many antecedents because it hasn’t really been done before. But I can think of several hypertext structures and tactics that would probably require this. Many of the hypertexts that have been authored with Storyspace, for example, might need this. The most complex ones are usually distributed as applications.
The solution
One solution has already been implemented by, at least, a couple of apps:
- In-app browser windows.
Kindle and Kobo for iOS (I haven’t tested the Android versions) both do this when you click on a link in an ebook. An embedded webview window pops up fullscreen over the main content. You aren’t thrown out of the app into Safari. You aren’t asked what you want to do before throwing you out of the app into Safari (iBooks really is one on the most half-baked apps I’ve ever encountered). You just get a fully-fledged, fully-enabled, browser view in an overlay over the book.
The best part is that this is standard practice across the iOS platform – most apps pop up a web page in an overlay – so the readers will know exactly what to do and how it works.
It’s easy to see the use cases:
- You have a thumbnail image of a graph floated to the right in your book. The reader clicks/presses it and the web page pops up with a fully interactive graph they can play with.
- Every chapter in a textbook might offer links to exercises as either lists of links or sets of thumbnails that the student can press and complete online, allowing the textbook author to optionally maintain some sort of state using bog-standard web tech.
- A photo thumbnail links to a slideshow web page.
- A map image links to a Google maps page.
When an OS or browser engine update breaks the web pages, the author just updates them on the server like any other web page. No need to involve the ereader vendor.
Of course, websites don’t live as long as books might, many of them go offline after a few years, but I doubt that would be as big a problem as people expect.
This also is completely useless when the reader is offline, but that’s a small price to pay, IMO.
This solution, obviously, only addresses overlay widgets, but that’s a very big and rich territory for us to mine in authoring ebooks.
Officially supporting this as a way to extend ebooks also gets ereader vendors out of implementing and supporting javascript.
Improving the solution
Ereader vendors can improve on this in several ways.
They can offer integrated mirroring for webpages that are supposed to be linked to from their ebooks. That way they can make sure the pages are live (if the official page is down, load it from a mirror) and don’t go offline for the lifetime of their platform.
They can implement prerendering in their ereaders. The ebook author would include this:
<link rel="prerender" href="http://example.org/index.html">
in a tag in the head of the current ebook chapter and the ereader would prefetch and prerender that page, off-screen, so that it displays instantaneously when the reader presses the link or thumbnail.
They might even extend the ePub’s metadata with a scheme that lets authors list prerendering hints; a list of webpages they intend to link to from the book. The ereader could cache the files and when a chapter is loaded that links to one of these files it could prerender the page while the user is reading the main text. They could even use this metadata list to implement backup mirrors for the web pages.
If you can’t tell, I like this solution
I think this is a classic 80/20 compromise. It gets us 80% of what we want from both widgets and javascript with 20% of the effort.
With prerendering and official mirroring we get what we want, both as readers and authors. We get stability. We get rich interactivity. We get javascript.
All with much less hassle for the ereader vendor than full javascript or widget support would entail.
Best of all, we already have a basic implementation of this solution on two major platforms, Kindle iOS and Kobo iOS.