I've built up a basic library of epub classes to handle the functionality of epub editing - classes to handle the container, the package with its metadata, manifest, and spine, and the NCX.
At the front end, the user can perform the following:
- Create a new epublication (a term I prefer to 'epub publication').
- Insert a basic set of metadata items for the new publication.
- Limited editing of metadata for an existing publication.
- Create and manipulate content documents.
- Add images to the manifest and insert them (sort of) in a content document.
- Edit the CSS files of the publication.
However, there are aspects of an online system that can no longer be ignored. For instance, the application needs to be multi-user. To date I've worked with a single server folder for the epub library whereas each user needs a folder to hold their own library and to act as a work area for writing. The need to handle many users immediately suggests some kind of database would be useful; so far I've held data in constants, in the web.config and, embarrassingly, as hard-code. It's time to organise this better.
This review will step through the existing functionality and will identify where and how the application should be enhanced.
Library (Books View)
The screenshot in figure 1. shows the opening page of the application. It presents a list of books and a button for creating a new epub.
Figure 1. Books View
The user clicks on the book they want to open or clicks on the 'New epub' button to start a new publication. Currently, the list of books is fetched by extracting a folder path from web.config. All files with the extension .epub are shown in the list.
The following enhancements are deemed to be either essential or desirable:
- The application should be multi-user. User registration and login should be handled by the Membership Service using the range of built-in Login controls. This should use a SQL-Express database in the App_Data folder.
- Additional user information should be held; in particular a folder on the web server should be assigned for each user's work. This root folder would be the place to hold the user's library and it is from this folder that the Books list would be populated.
- It would be friendlier to display the title of the book rather than the filename for each book, for instance 'The Curious Case of Benjamin Button' rather than 'fitzgerald-curious-case-of-benjamin-button.epub'.
In figure 2. the Book Information view is shown. This displays the <metadata> from the publication's package document.
Figure 2. Book Information View
The user can modify any items on the screen and click the Save button to store the changes in the epub.
A review of the Open Packaging Format Schema shows, however, that the handling of metadata needs to be more sophisticated. Figure 3. is an extract from the schema showing the definition of metadata-content.
The <oneOrMore> wrapped around the title, language, and id elements indicates that there must be at least one of these elements in the metadata, but there may be more. The <zeroOrMore> identifies elements that are optional. However, the OrMore part of the definition means there can be many of these elements too. We've already seen in earlier posts that there can be a range of dates, creators, contributors, and descriptions. In fact the schema says there can be any number of these items.
The following enhancements are essential for handling the metadata of an epublication.
- Handle multiple instances of any metadata element.
- It should be possible to add, modify, and delete metadata elements.
- All metadata elements can be deleted except for one each of title, language, and id.
Figure 4. shows the latest incarnation of the Book Content view.
Figure 4. Book Content View
The functionality of this screen has been changed since it was last presented. The most significant differences are:
- Drag and drop functionality to move content documents within the publication. This activity is enabled/disabled by the 'Organise' checkbox. The Move Up/Move Down options were removed from the Action dropdown as they are no longer needed.
- The tinyMCE editor, which is where the content documents are displayed, has been configured with a default font size that's easier to read and a drag handle has been provided to allow the user to change the height of the text area.
- The new document details - Contents Entry and Document Heading - were moved above the editing area to allow the resize facility just mentioned.
- The ability to put a heading at the top of a new content document was made optional.
- Not shown in the screenshot, a 'boiler-plate' copyright document is inserted after the title page when a new epublication is created. It uses text like the following, where names and dates are taken from the metadata and inserted into the text at fixed locations. An author or publisher could change the text to that of their choice.
Copyright © Colin Hazlehurst, 2010
There are still useful enhancements that could be made to this view:
- The ability to promote and demote content document and reflect the changes in the <navMap> of the NCX document.
- The code should start with the Save button disabled. It should detect when either the Table of Contents or the text of the currently displayed content document are changed. It should then enable the Save button. The Save button should be disabled after any changes have been saved.
- There is a particular challenge with respect to handling images which is the subject of a separate note below. The problem is that the href of an image in the manifest is relative to the document which references it. When displaying the image in a browser, the URL in the image's src attribute needs to specify a path on the server relative to the root of the application.
Figure 5. shows the view when the user clicks on the Media tab. The application reads the manifest and finds all files that have a media-type beginning with the text 'image/'. For each file it finds, an Image control is added to the view and the source is set to the href for the manifest item.
Figure 5. Media View
A FileUpload control works in conjunction with an Upload button to allow the user to upload a new image for inclusion in the publication.
The following enhancements would greatly improve the handling of media by the application.
- Media types other than images should be handled.
- Some ability to generate thumbnails should be included which would keep the correct aspect ratio for each image.
- Currently images cannot be selected for deletion.
Remembering that the value of XHTML is that it gives structure to the content of a document, but it also separates the content from its presentation. The widespread tool-of-choice for presenting content is CSS. epublications can incorporate any number of CSS stylesheets to help present the content.
Figure 6. shows the Styles tab in the epub editor project.
Figure 6. Styles View
When the user clicks on the Styles tab, the application reads the manifest and finds all files that have the media-type 'text/css'. It constructs a list of these files and allows the user to select one by clicking on it. In the example shown, main.css was selected and the stylesheet is displayed.
The 'Action' dropdown list gives the user the ability to add and remove CSS files. The Save button is used to save any changes the user makes to the currently displayed stylesheet.
Image Handling Issue
It was mentioned above that there is an issue with the handling of images that is particular to the online environment. The href of an image in the manifest of an epub is set relative to the content document that references it. On the web, the src attribute of the image control is a URL relative to the root of the web application.
In the Benjamin Button example, the ePubBooks logo is referenced on the epubbooksinfo page in the OPS folder. The href is set to 'images/epubbooks-logo.png', and the logo is held in folder OPS/images. A web page with a root folder called epub displaying the epubbooksinfo page in a tinyMCE editor would expect to find the logo in folder .../epub/images.
In a multi-user system it would not be possible to put the images for all users' publications in one folder. Each user must have their own work area, which means they must have a separate folder on the server. If F.Scott Fitzgerald were using this application (and who, given the weirdness of Benjamin Button, can say that he can't?), then he might be saving his content in a folder like:
epub/fsfitzgerald/benjaminbutton/OPSTherefore, to view the image in the browser, its src would need to be something like:
epub/fsfitzgerald/benjaminbutton/OPS/images/myimage.svgThe epub must reference the image simply as: images/myimage.svg.
This difference in addressing must be handled by the application. The obvious choice is to use a pair of XSL transforms, one of which builds a web-relative URL and replaces the src attributes of all images in a content document with this value. This transform runs when the user selects a document from the table of contents to display it in the editing area.
The other transform runs when the user clicks the Save button after making changes to a content document. It strips out the web path and replaces it with a document relative path. The content documents saved to the filesystem and thus in the .epub must always use the document relative path - that's the only way the epub can be shipped.
How do you get to Carnegie Hall?
So that's the job facing me on this project. It's interesting, but time consuming. To sum up the way I feel is like:
Tourist: How do you get to Carnegie Hall?
Yokel: Well, you wouldn't want to start from here.