Convertly is up!

Convertly lets you convert docx documents into standards compliant, accessible XHTML. If you want to skip the technical blah blah blahing, head on over to convertly.com and check out our tool. We think it’s quite nice and we hope you find a use for it.

When it comes down to it, we hate seeing Word documents on the web. Nothing interrupts our browsing mojo more than clicking on a link and having Word punch us right in the face. Hopefully you’ll agree that punches to the face, your face in this case, are bad — even if you deserve it. To help save ourselves and our Internet browsing brethren from this, we built Zombie, an open source library, written in Python, that can convert Word documents into XHTML. It’s pretty swell and we want all of our wonderful developer counterparts out there to take it and use it in their applications.

Unfortunately though, there is a problem with open source libraries written in Python. To the untrained eye, they’re ugly, and not particularly useful. That’s a bad place to be. To solve this problem, we gave our library what every lonely zombie needs — a really hot friend named Convertly.

Succinctly put, we built Convertly to help us evangelize Zombie. That’s the ‘why’. Download Zombie and integrate it. Your users will love you and we will too.

With that said, here’s the ‘how’ behind Convertly:

The Setup

The decision to build a form to interact with our handy new Python library initially made me groan. It didn’t sound like fun. It was just another form among the countless forms that were conquered before it. So, I decided to spice things up a little by throwing out our usual set of constraints. Internet Explorer 6? Pffph! More like, not my problem. Not knowing jQuery very well? I’ll use it just for kicks! Caution and experience be damned!

There’s a million reasons not to learn a new technology. In the environment that I work in, it’s really easy to become so ingrained in a set of methods for achieving broad platform compatibility and Section 508 compliance that we forget that we need to come out of our shell and experiment from time to time. Regardless of your specific excuse, take some time out and play with new things for no other reason than lack of familiarity. Then, drink a beer. You’ll love yourself for it and you might even stave off obsolescence.

My feelings won’t be hurt if you stop reading right now and go do that. Maybe you should start integrating Zombie into your application.

The Markup

I took an extremely minimalist approach to the markup by only using tags that semantically and accessibly represented the instructions and functionality of the tool.  This was a refreshing change of pace for a seasoned web developer, and it had the added bonus of making the CSS part a bit more interesting. Hurray!

For reference, the ‘no compromises’ markup looked like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
		"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 
<head>
	<title>Convertly: Convert your Word .docx documents to HTML</title>
	<meta http-equiv="content-type" content="text/html; charset=utf-8" />
	<link href="/assets/css/fix.css" rel="stylesheet" type="text/css" />
	<style type="text/css">@import "/assets/css/convertly.css";</style>
	<script type="text/javascript" src="/assets/js/jquery.js"></script>
	<script type="text/javascript" src="/assets/js/form.js"></script>
	<script type="text/javascript" src="/assets/js/convertly.js"></script>
</head>
<body id="home">
	<h1>Convertly</h1>
	<ol id="process">
		<li id="step1">
			<h2>Step 1:</h2>
			<p>Select a docx document to convert to html.</p> 
			<form id="upload_form" enctype="multipart/form-data" action="/upload" method="post">
				<fieldset>
					<p><label for="id_file">Document:</label> <input type="file" name="file" id="id_file" /></p>
				</fieldset>
			</form>
			<p>To convert multiple documents at once, zip them and upload the zip file.</p>
		</li>
		<li id="step2">
			<h2>Step 2:</h2>
			<p class="waiting">Complete Step 1 to begin conversion.</p>
			<p class="result">Magic! Let <a href="http://zombieproject.googlecode.com/">Zombie</a> do what it does best.</p>
			<p class="convert_button"><a id="convert">Convert</a></p>
		</li>
		<li id="step3">
			<h2>Step 3:</h2>
			<p class="waiting">Complete Step 2 to download.</p>
			<p class="result">Done! Click below to download your file.</p>
			<p class="download_button"><a id="download">Download</a></p>
			<p>We'll eventually throw out your files to conserve space, so grab them while they're fresh.</p>
		</li>
	</ol>
	<ul id="shout_outs">
		<li><a href="http://zombieproject.googlecode.com">Zombie</a></li>
		<li><a href="http://www.webappers.com/2008/02/12/webappers-released-free-web-application-icons-set/">WebAppers</a></li>
		<li><a href="http://www.ajaxload.info/">ajaxload.info</a></li>
		<li><a href="http://www.stripegenerator.com/">StripeGenerator</a></li>
		<li><a href="http://jquery.com/">jQuery</a></li>
		<li><a href="http://malsup.com/jquery/form/">jQuery Form Plugin</a></li>
		<li><a href="http://www.djangoproject.com/">Django</a></li>
		<li><a href="http://www.python.org/">Python</a></li>
		<li><a href="http://boxedviking.com">Boxed Viking</a></li>
	</ul>
</body>
</html>

As you can see, headings are headings, and lists are lists. No compromises and no divs? That’s right. No divs. Neat, eh?

The Design

Stripes are nice.

Convertly.com's striped background.

Text shadow? Sure.

Text shadow example from convertly.com

Transparency? Wonderful.

An example of transparency from convertly.com

Fancy Web 2.0 buttons with icons. This is art.

A button from convertly.com

All together:

This is Convertly.com

The CSS

Finally. The fun part. You can look at the full set of styles right on Convertly.com. I typically put an entire definition on single line. It may seem counter intuitive at first, but if you’re using a widescreen monitor, it’s actually quite nice. I also list styles in an order that mirrors the sequence that you will encounter them in the XHTML. If an h1 is the first thing you see in the markup, then an h1 will probably be the first thing in the CSS document. For me, this leads to less mental context switching when I’m going back and forth between markup and CSS. If you have questions about anything specific, please post a comment.

For the main heading, I wrote this:

h1 {
     font-style: italic;
     font-size: 400%;
     font-family: 'Georgia', serif;
     margin: 5% auto -.15em auto;
     color: #f8f0ea;
     font-weight: normal;
     text-shadow: 1px 1px 1px #000;
     letter-spacing:5px;
}

This definition is pretty straight forward. As you might have guessed, I use the text-shadow property for the text shadow effect. Sadly, this isn’t currently supported by my beloved Firefox, Chrome, or Internet Explorer 6/7/8. Safari 3/4 and the Opera 10 beta get it right though. The heading is placed over the main content area by a -1.5 em bottom margin. The letter-spacing property is then used to make it look a smidgen more unique.

The transparency effect bordering the main content area is achieved using rgba color definitions. This is another one of those fancy things that isn’t very widely supported, but it works well when it is. In this case, #process has a semi-transparent black background, and the individual list items have gray backgrounds. The same effect could be achieved with broader compatibility using a transparent png, but it wouldn’t have been as fun.

Here’s a simple  example:

ol {
     background: rgba(0,0,0,.25);
     padding: 10px;
     width: 500px;
     list-style-type: none;
}
 
ol li {
     width: 100px;
     background: grey;
     float: left;
}

To force the ordered list to expand to contain the floated list items, I used something like below:

ol:after { 
     content: "";
     display: block;
     height: 0;
     width: 0;
     clear: both;
}

The footer is a bit trickier. Since the list items don’t cover the entire area of the unordered list, the same technique can’t be used. Also, since we didn’t wrap the list item in a div, we can’t just use that. Instead, I used the :before pseudo selector:

ul:before {
     content: "";
     background: rgba(0,0,0,0.25);
     display: block;
     border-top: 1px solid #000;
     border-bottom: 1px solid #000;
     height: 10px;
     width: 100%;
     margin: -12px 0 0 0;
}

Basically, this creates a semi-transparent block element the width of the page and then the negative margin positions the element above the footer so that it looks just like the transparent border around the main content area. It’s not pretty, but it works.

The Application Code

For the back-end, we used Django. Some people would say that using Django for such a small project is overkill. That’s great. It might even be true. But, that aside, Django is amazing. We really love it. If I could pour Django all over my cereal every morning, I would do it and I’d enjoy every minty bite of it. Try Django on your cereal today.

On the front-end, we used jQuery for some pretty effects and the jQuery Form Plugin for some sassy AJAXification.

The End

Checkout Convertly and let us know what you think. If you’re a developer and you’re building something that lets users access Word documents, then try integrating Zombie into your product and let us know how it goes.

One Response to “Convertly is up!”

  1. Justin Blake says:

    Nice work on Convertly!

    I also like what you said about learning new technologies. That “we forget that we need to come out of our shell and experiment from time to time”. I need to keep reminding myself of that in regards to my Ruby on Rails work. Just because I can’t use the latest bleeding edge features on the Big Important Project for my day job, doesn’t mean I can’t give it a go for everything else.

    Also, I LOVE that one liner CSS style.

Leave a Reply

Older EntriesNewer Entries

Recent Comments

  1. Justin Blake: Nice work on Convertly! I also like what you said about learning new technologies. That “we...