Blogs

Creating eBooks in ePub format

 

File 81One of the websites Tarakan created and continues to manage is Architecture & Governance Magazine, a community site with several hundred articles on the arcane art of Enterprise Architecture. A&G started as an actual print magazine, but it was discontinued with the success of the website. They continue to publish a PDF file for each issue, which is downloadble on the website.

Recently someone commented that they'd also like an eBook version of the current issue. Seemed like a reasonable request, and I was curious about the process of creating an eBook, so I decided to delve into it. And that world is still quite a mess.

An evolving standard used in iBooks and other places is the ePub format - "EPUB became an official standard of the International Digital Publishing Forum (IDPF) in September 2007, superseding the older Open eBook standard."  A single ePub book file is just an archive of other files, including XHTML and CSS for content and formating, an OPF file for metadata and ordering, and media files. 

I searched around the intertubes for info on creating ePub format eBooks and ... well, good information and tools are scarce.  So I just dug in, trying all the tools I could find to create a eBook from various sources files in A&G Issue 6-6. I had all the source text documents in RTF format, the original Adobe InDesign source file to create the PDF, the finished PDF, and all the image files. 

File 79First I tried Calibre, a "a free and open source e-book library management application" which seems geared more toward eBook reading and library management. It has numerous conversion options though, so I plugged in the PDF file and hit "convert". I received an unreadable 100 page mess of graphics and text.  Converting from a fixed-layout print-centric PDF to a flowable multi-sized text-centric epub format wasn't going to be as simple as clicking a button.  I played with it a bit more, putting in the source documents and it worked better, but I could not get a new article to display on a fresh page- it just flowed through.

I had discovered a few intereting websites on ePubs, including the oddly named and likely search engine confusing Pigs, Gourds and Wikis. The author wrote a book that focuses exclusively on ePub, which I wound up buying (although in dead tree format via Amazon, because it was cheaper than the ePub format .. go figure).  It focuses on using Word or InDesign to create ePub books, along with some chapters that go into the process more deeply than anything else I had found. I found another post that goes way deep into the format, but focused too much on roll-your-own for me- I was looking for a simpler, more automated approach (since we might be doing this more frequently).

I happened to have InDesign CS5 and the Issue 6-6 InDesign source file, so I tried to follow her method in the book above. But again, trying to take a print-centric file and convert it was going to take too much manual effort to make a nice looking eBook. That and I had very little experience with InDesign.  So what else..?  A little more searching helped me find Sigil, "a multi-platform WYSIWYG ebook editor. It is designed to edit books in ePub format."  Sounded perfect.

File 80And it pretty much is- it works very well.  I had learned from the Pigs.. website that the only way to get chapter breaks to work in iBooks was to create a separate XHTML file for each chapter, so I created three XHTML files, one for each article in Issue 6-6. I cut & pasted the text from the RTF files into Sigil, which stripped all formatting. That was ok- it is better to start clean and build up, so I used the WYSIWYG features of Sigil to add heading tags, bold and italics and bullet points. I could even add images, although getting text to flow around them requires some CSS work (a similar method is shown in the ePub book). Perhaps a future version of Sigil will include a WYSIWYG method to make images inline.

The Table of Contents was created automatically using the Heading tags (so be sure to use them correctly- h1, h2, ..). I used the Meta Editor to add information on the Title, Publisher, Author, etc of the eBook. I took a screenshot of the PDF and created a document for it and moved it to the first- this caused it to be used as the cover image (maybe there is a better, more explicit way to do this, but I haven't found it yet).  And voila- that's it.  Since Sigil edits the ePub format directly, there is no conversion process - just save and you have an ePub.  The resulting eBook looked great on my iPad.

Sigil is a nice app for creating a simple ePub format eBook quickly. You'll have to dig into the code if you want to do anything more sophisiticated, but it has a nice split-screen code editor for that.  So unless you know InDesign well, I'd start with Sigil and see what you can do with it.

Creating Mobile Websites with Drupal Part 3

In Part 1 of this series we looked at the Why of building mobile websites.  In Part 2 we discovered how to analyze your website for mobile traffic. Here in Part 3 we will look at a few ways to mobilify your website.

The Sledgehammer Approach

First there is the "Draconian" solution- change your Drupal theme to a "mobile friendly" theme.  One option is the appropriately named Mobile theme, which is "intended to return only clean HTML with no styling ... inks and sidebars are placed in such a place that mobile- or handheld-devices can display just the content."  Let's look at a live example to see what that does.  Below is the normal desktop and mobile versions of a page on a site we did a while back:

File 69   File 70

The desktop version looks nice, but the mobile version is hard to read without zooming. According to Google Analytics, more mobile users go straight to this page (to see where the band is playing that night) than go to the home page. So we need an optimized mobile page.

If we install and enable the Mobile theme, then we get this on a mobile device for that page:

File 71

Well, it looks ... different.  Less messy.  But not necessarily better. And since this is a sledgehammer approach, all pages, viewed on mobile or desktop, are affected.  Looks what it does to the front page on a desktop browser:

 File 72

We've basically ruined our site.  Those images should be part of a JQuery slideshow on the front page.  So the sledgehammer approach might not be the best.  But, what if we could just show a different theme to mobile devices, keeping our pretty theme for desktop users.  Sounds like a good step.

Mobile Tools Module

For that we look to the Mobile Tools Drupal module.  It provides many mobile-centric features to a Drupal site, but we will focus on just two:

  • automatic detection of the "user agent" - is the user accessing the site from a mobile device?
  • automatic theme switching based on mobile / not mobile

Working together, those two features will ensure that mobile users get the "Mobile" theme while non mobile users get the regular theme.  And it is super-simple to enable- just go to the Mobile Tools settings and set it to switch theme for a mobile device, then pick the theme:

 File 73

You could also create a mobile version of your website, and put it somewhere like "mobile.mysite.com".  You can use Mobile Tools to automatically redirect mobile users to your mobile version.  The Domain Access module might be of use in that scenario as well.

We are making progress ... but really the Mobile theme is too simplistic to produce good results for our site.  There are few other mobile themes available - Adaptivetheme Mobile, Nokia Mobile, A Cloudy Day Mobile, and even Mobile Garland!  There's even a mobile base theme, Fuse.

Mobile-specific Custom Theme

For optimal results, and if you have themeing resources, creating a custom theme just for mobile users is your best choice.  We created a mobile theme for our example site above, with the following rather nice result:

 File 74

Thirty-Party Solutions

If you don't have the know-how or resources to build your own mobile theme, there are some thirty party options that might be easier / cheaper than paying someone else to do it.  

When I first did this presentation at DrupalCamp Austin 2009, there was a company called OSMobi that had a nice drag-drop interface for mobilizing your site. Not that nice I guess, since they went under by the time I updated this presentation and did it at OpenCamp / DrupalCamp Dallas in 2010.  

Another company, Mobify, has a similar solution with a combination Drupal module / Web app.  First you use the web app to identify the pages of your site that you want Mobify to mobilize:

File 75

You can also add custom CSS if you'd like.  You then use their Drupal module to set the custom Mobify.com subdomain that mobile users will get when they come to your site (like "mysite.mobify.com").  The result is actually rather nice:

File 77

The downside?  You have less control of course.  And anything other than the basics costs money. And the price keeps going up- their highest-end package was $49 / month when I first looked at them, was $499 / mon last fall, and is now $999.  So get in now while you can still afford it!

This concludes my series on Building Mobile Websites with Drupal- hope it was useful.  And of course, Tarakan Design is ready and willing to help you create your own mobile sites.

Basic Theming: Move AddThis to the Top

Prerequisites: Drupal 6, PHP, Basic theming

By default, the AddThis contrib puts a pretty button at the bottom of nodes, enabling users to share your content with various social networks. But what if you want to show the button at the top of the node instead of the bottom? Here's a quick way to do that.

You can, of course, just skip the AddThis module and add your own code from AddThis wherever you want, but that's not the point of this post. We're going to make a few small adjustments at the theme layer in order to make it happen.

Step 1. Add a new template variable and modify the old one

This code goes in your theme's template.php file. If you don't already have a preprocess_node hook, create a function called mytheme_preprocess_node(&$variables) (substituting your own theme name, of course). The preprocess_node hook simply prepares variables for use in your node template. There are two elements of interest to us in the $variables parameter: the links string and the node object. The links string is merely the literal HTML that gets displayed (usually) at the bottom of nodes. It contains things like links to add a comment or read more, read counts, and in this case, the AddThis button. Within the node object is another links element, but this contains the items separated into an array instead of rendered together in a single string.

function mytheme_preprocess_node(&$variables) {
  if (!empty($variables['node']->links['addthis'])) {
    $variables['addthis'] = $variables['node']->links['addthis']['title'];
    unset($variables['node']->links['addthis']);
    $variables['links'] = theme_links($variables['node']->links, array('class' => 'links inline'));
  }
}

All we're doing is taking the AddThis HTML and putting it in it's own template variable, called addthis ($variables['addthis']), and then recreating the links template variable ($variables['links']) without it.

Step 2. Use the new addthis variable

This part goes in your theme's node template (e.g., node.tpl.php). Remember that addthis variable we just created? Just print it out where you want it.

<?php if ($addthis): ?>
  <div class="addthis">
  <?php print $addthis ?>
  </div>
<?php endif; ?>

For convenience, we created an addthis div and put it above the content but below the title.

Step 3. Style it with CSS

Lastly, style it with your CSS of choice. We wanted it hanging out on the right, on the same line as the Submitted by info.

.addthis {
  float: right;
}

One last thing: in order for this to take effect, you may have to rebuild your theme registry or flush your caches depending on the state of the site. You can do this with the devel or admin_menu contribs or, lacking those, go to admin/settings/performance and click Clear Cached Data.

That does it. A basic solution to a basic problem.

Creating Mobile Websites with Drupal Part 2

In Part 1 of this series we looked at the Why of building mobile websites.  In Part 2 we'll look at how to analyze your website for mobile traffic. We will use this information in Part 3 to correctly plan and implement the mobile version of our website.

Google Analytics

So how do you know if mobile visitors are even visiting your website, and if so- which pages do they frequent?  Google Analytics (GA) is a good tool for this, and is already installed on many sites.  If not- get the GA Drupal module and install it.  Then sign up for Google Analytics- it's free- add your site, and get the "UA-xxxxxxx" number for that site (it will come with a code snippet they send you- you just need that number).  There is a field for that number in the GA settings page on your site- put it in, save, and ... wait.  It takes at least one day before GA will have any data on your site, and perhaps many more days or weeks (depending on your traffic level) before you have enough data.

Below is a typical Dashboard for GA - this one shows a month of overall traffic for one site:

File 66

Good info, but we specifically are looking for info on our mobile visitors. One method of figuring that out is to look at screen resolutions.  You can do this by drilling down into "Visitors Overview >> view report" then "screen resolutions".  Below is a real example

 File 67

Notice that #5 is "320 x 480" and #6 is "320 x 396" - either mobile devices, or a 1970 greenscreen terminal.  So we are getting maybe 11% of our traffic from mobile devices, which is likely enough to cause us to develop a better mobile version.  If that number was 0.1% then it probably isn't worth the effort.

GA can further break down the mobile traffic by device, if you need to know that.

File 68

More importantly is - what pages do mobile visitors read?  Often it is different than desktop users.  GA can tell you that as well, so you can make sure those pages are very mobile friendly.

Ok, so we know we are getting mobile traffic, and on what pages.  In Part 3 we will discuss ways to "mobilizificate" your Drupal site.

Don't Split My Terms

Prerequisites: PHP, Theming, Drupal 6, Regular Expressions

Adventures With Nested Regular Expression Functions

Sometimes a situation calls for skills you know you should have but just don't use often enough to claim as a weapon in your arsenal of tools. For me, that skill is competence with regular expressions. It seems like every six months or so I'm back to reading Mastering Regular Expressions and scouring the interwebs for help deciphering or creating one of those cryptic phrases.

Many thanks to regular-expressions.info, a great resource for learning about regular expressions.

Here's the scenario: a client's site has nodes that are tagged with multiple taxonomy terms, sometimes enough to make the list of terms span multiple lines. Sometimes the terms are phrases, so they contain multiple words and as a result are sometimes split across lines. We want to ensure that taxonomy terms are always kept together.

The simplest answer is probably to use display: inline-block; in the appropriate CSS declaration, but even though that's what we ended up doing, I thought this alternate solution was an interesting exercise in the use of regular expressions.

The Code

function exampletheme_preprocess_node (&$variables) {
  // Replace all spaces within <a> tags with non-breaking spaces so they don't span lines
  $pattern = '/(<a\b[^>]*>)(.*?)(<\/a>)/';
  $variables['terms'] = preg_replace_callback($pattern, create_function('$matches', 'return $matches[1] . preg_replace("/ /", "&nbsp;", $matches[2]) . $matches[3];'), $variables['terms']);
}

The code will go in your theme's template.php file, in the mytheme_preprocess_node function.

Now let's have a look at what's going on. The parameter &$variables is a keyed array, in which each of the keys eventually becomes a variable that is made available to the node template (e.g., node.tpl.php). The variable we're interested in is 'terms', which is the fully rendered list of taxonomy terms for the node. For example,

<ul class="links inline">
<li class="taxonomy_term_79 first"><a href="/category/business-categories/accessories-jewelry" rel="tag" title="">Accessories / Jewelry</a></li>
<li class="taxonomy_term_92"><a href="//category/business-categories/energy-savings" rel="tag" title="">Energy Savings</a></li>
<li class="taxonomy_term_100"><a href="/category/business-categories/home-furnishing" rel="tag" title="">Home Furnishing</a></li>
<li class="taxonomy_term_101"><a href="/category/business-categories/household-cleaning-products" rel="tag" title="">Household Cleaning Products</a></li>
<li class="taxonomy_term_106"><a href="/category/business-categories/paper-products" rel="tag" title="">Paper Products</a></li>
<li class="taxonomy_term_110 last"><a href="/category/business-categories/retail-stores" rel="tag" title="">Retail Stores</a></li>
</ul>

Our goal is to take spaces that occur within <a> tag text and replace them with non-breaking spaces (&nbsp;). For example, change Paper Products into Paper&nbsp;Products. To do that, we use a nested call to the PHP function preg_replace.

Let's look at the innermost preg_replace:

preg_replace("/ /", "&nbsp;", $matches[2])

This simply says, "find each space in $matches[2] and replace it with &nbsp;." The first parameter is a regular expression consisting of the start delimiter (a slash), a space, and an end delimiter (another slash). We'll get to $matches[2] in a sec.

The parent function is actually a slightly different form of preg_replace that takes a function as its second parameter. preg_replace_callback calls that function once for each match it finds. In our case, we define the function inline using create_function, but it can just as easily be done with a normal function declaration.

preg_replace_callback passes an array in the form of:

  • $matches[0] = the full matching text
  • $matches[1] = backreference 1
  • $matches[2] = backreference 2
  • ...
  • $matches[n] = backreference n

so, going back to the inner function, we're operating on the string passed as backreference 2. So, what's backreference 2? For that, we need to look at the regular expression:

/(<a\b[^>]*>)(.*?)(<\/a>)/

We already know that the slashes on the ends are just delimiters, so let's look at the three parenthetical clauses. Using parentheses around these clauses causes the regex engine to create backreferences which can then be referred to by our callback function.

First we have

(<a\b[^>]*>)

which matches

  • The literal "<a" as long as it is on a word boundary (\b). That's to distinguish an <a> tag from say, an <acronym> tag.
  • Followed by any number of characters as long as they are not a closed angle bracket ("[^>]*")
  • Followed by the literal ">" 

So, that's the <a> tag and all of it's attributes.

Let's skip the second one for now and look at number three:

 (<\/a>)

  • matching a literal "<"
  • followed by a "/", which needs to be escaped with a "\" first
  • followed by a literal  "a>"

That's our closing tag.

Going back to number two:

 (.*?)

which matches any character (".") any number of times ("*"). The "?" makes the star "lazy" so it will stop before the first closing tag rather than the last one. This represents the stuff in between the tags.

Lastly, we don't just need the stuff in the middle, we also need the tags, so we prepend $matches[1] and append $matches[3] to the string before we return the final value from the callback.

So there it is. A rather long explanation for a rather short amount of code, but a good opportunity to brush up on some regular expression basics.

Syndicate content

Our Philosophy

 

  • Customer centered, Agile development
  • Clear and open communication
  • Solid software engineering principles

 

Drupal

Drupal

 

We use the Drupal Content Management Framework for secure and reliable websites.
Learn More