Imposterrific

Coding can be fun!

Monday, February 08, 2010

New Blog Template

With the growing popularity of mobile phones and lower resolution netbooks, a fixed width blog format is looking less and less appealing. I decided to work on a new look for this blog. The main feature I was looking for was a set of CSS rules that would allow the main content to scale with the viewer's browser window width. If the window is too narrow, the less important content on the sidebar should flow down below the main content.

I began with an existing theme for Blogger, Tekka, that pushes the right sidebar down beneath the main content when the window is narrow. I then made some CSS changes to tweak the look to fit my tastes.

First things first, the default fonts must go! I drew much of my inspiration from Nick Johnson's blog, specifically the way that serif fonts are used in some places for accent while sans-serif is used for most of the content. This is a technique that I experimented with a bit in a graphic design class in college.

For titles I added:
h1, h2 {
...
font-family: Georgia, 'Times New Roman', Times, serif;
}

h3 {
...
font-family: Trebuchet MS, Verdana, Sans-serif;
}
To change the font used for the main text in the page, I set a template variable as follows:
<Variable name="bodyFont" description="Text Font"
type="font"
default="normal normal 100% 'Lucida Grande',
Verdana, Helvetica, sans-serif"
value="normal normal 100% 'Lucida Grande',
Verdana, Helvetica, sans-serif">
Next I set about changing the style of the title link. You see, when someone is viewing a single post, the blog title becomes a link to the main blog page. So, the blog's title is styled like a link and I found the default link styles a bit jarring. This might seem like a minor change but so often it's the little things that matter. I set this style using
h1 a:visited {
...
color: #505050;
}
Now that the text styling is done, the layout could use a bit of adjustment. I changed the margins on the main content to the following:
#content-wrapper { 
margin-top: 20px;
margin-$endSide: 30px;
margin-bottom: 30;
margin-$startSide: 35px;
}
I removed the padding from the h1 title style and the date header. I also removed the style rule entirely for the description.

We're nearing the end! The sidebar wasn't quite to my liking so I changed the border style. Lastly, in order to get the sidebar to flow down beneath the main content I set a minimum width. Here is the final style for the sidebar:
#sidebar {
text-transform:none;
background-color: $sidebarBgColor;
color: $sidebarTextColor;
padding-$startSide: 20px;
width: 30%;
min-width: 215px;
float: $endSide;
font: $bodyFont;
border-$startSide:1px solid $mainTextColor;
word-wrap: break-word;
overflow: hidden;
}
I debated about posting the whole template here, but I'm not sure that it would be very readable. If you would like the whole thing, leave a comment and I can email it to you.

Wednesday, January 13, 2010

DOM Manipulation in JavaScript, a Utility

In my latest addition to the q12 JavaScript library, I have added a simple function to construct a nested document structure. I grew tired of writing repetitive and difficult to follow code like this
var div = document.createElement('div');
div['id'] = 'outer-div';
var link = document.createElement('a');
link.href = 'http://blog.jeffscudder.com';
link.appendChild(document.createTextNode('my blog'));
div.appendChild(link);
Using the new tree function this would become:
var div = tree([
'div', {
id: 'outer-div'}, [
'a', {
href: 'http://blog.jeffscudder.com'}, [
'my blog']]]);
In the process of writing this utility function, I came across another small oddity in editing HTML using JavaScript related to the style attribute. Most HTML attributes are simple text properties, however when editing the CSS style of a node, you cannot set the full content of the style attribute.
// You cannot do this:
div.style = "color:red; font-weight:bold";
Instead, you set each sub item in the style attribute:
// This works:
div.style.color = 'red';
div.style['font-weight'] = 'bold';
The tree function that I've written handles this nested style structure as well. Here's an example:
['div', {
'id': 'foo',
'style': {'color': 'red', 'font-weight': 'bold'}},
'This works too!']
Now that you have an idea of how to use this utility, here's the code. Minus the comments it's only about twenty-one lines.
/**
* Creates a DOM tree from a simple list.
* The structure of the tree passed in is as follows:
* ['elementTag',
* {attribute1: value,
* attribute2: value,
* style: {property1: value,
* property2: value}},
* 'child text node',
* ['elementTag',
* {property: value},
* 'grandchild text node'],
* 'third node']
* The above will result in a DOM node which has three child nodes, the
* first and third will be text nodes because the values were strings.
* The second child node will be a DOM node as well.
*
* @param {Array} t The tree's structure as a collection of strings, lists,
* and simple objects. The structure is as follows
* ['elementTag', {attributes}, child, child, child, ...]
* @return {Element} Returns a new DOM element.
*/
function tree(t) {
// Create the node using the tag which is first in the list.
var domNode = document.createElement(t[0]);
// Add all HTML attributes to the node.
for (var key in t[1]) {
// The style attributes get special treatment.
if (key == 'style') {
for (var styleAttribute in t[1].style) {
domNode.style[styleAttribute] = t[1].style[styleAttribute];
}
} else {
domNode[key] = t[1][key];
}
}
// Iterate over all child nodes, converting them to either text or HTML
// nodes.
for (var index = 2, child; child = t[index]; index++) {
if (typeof(child) == 'string') {
domNode.appendChild(document.createTextNode(child));
} else {
// Buid recursively.
domNode.appendChild(tree(child));
}
}
return domNode;
}
What do you think, is there anything you would add?

On a realted note, if you're interested in a more powerful templating system, you might want to try Closure Templates which were recently open sourced.

Thursday, October 22, 2009

The joys of onKeyDown

I recently found myself in need of a way to detect when a user presses enter when typing in a text input box and happened upon one of the quirkiest of browser features, key press detection in JavaScript. Searching the Internet provided a few ideas but nothing that quite fit what I was looking for, so I thought maybe I should get the word out about what I've learned.

Lets assume that we have a form with an input box and we want to perform some special action when the user presses the enter key while focus is on the text input box. We begin by adding an onKeyDown event to the input box (you might also consider onKeyUp, but onKeyPress seems like it might be somewhat quirkier).
<form>
<input type="text" id="my-input">
</form>
<div id="output"></div>
<script>
document.getElementById('my-input').onkeydown = function(e) {};
<script>
Now the first hurdle is that in IE, Safari, and Chrome you can access the ASCII character code for the key which was pressed in window.event.keyCode but in FireFox you'll need to get the event object and look at the which member.
<script>
document.getElementById('my-input').onkeydown = function(e) {
var keyCode = 0;
if (window && window.event && window.event.keyCode) {
keyCode = window.event.keyCode;
} else if (e && e.which) {
keyCode = e.which;
} else {
alert('fail');
}
document.getElementById('output').innerHTML = 'You pressed ' + keyCode;
};
<script>
Now there is one gotcha with what we've written so far. Each key that we press when focus is on the desired input causes our code to be run, but the browser also performs the default behavior for that key. If our input is a simple text box, the characters pressed will show up in the text box. If the input is part of a form with a submit button, pressing enter will cause the form to be submitted. If the form is submitted then the browser is sent to a different page which in this case is not what we want.

There are a few ways to prevent the key presses from also triggering the default behavior and do only our behavior. One of the simplest ways is to return false from the onKeyDown function. If we change our handler to the below, characters will not show up in a text input box because our handler consumes them.
 document.getElementById('my-input').onkeydown = function(e) {
var keyCode = 0;
if (window && window.event && window.event.keyCode) {
keyCode = window.event.keyCode;
} else if (e && e.which) {
keyCode = e.which;
} else {
alert('fail');
}
document.getElementById('output').innerHTML = 'You pressed ' + keyCode;
return false;
};
With the above, the last key press is displayed in the output, but in most cases we probably do want the user to see the chracters they've typed showing up in the input box. We just want to prevent the form submit when the user presses the enter key. To accomplish this behavior, we can return false when we don't want the key press to propoage and return true when the default behavior should also be performed.
 document.getElementById('my-input').onkeydown = function(e) {
var keyCode = 0;
if (window && window.event && window.event.keyCode) {
keyCode = window.event.keyCode;
} else if (e && e.which) {
keyCode = e.which;
} else {
alert('fail');
}
document.getElementById('output').innerHTML = 'You pressed ' + keyCode;
if (keyCode == 13) { // 13 is the key code for the enter key.
return false;
} else {
return true;
}
};
There you have it, a way to detect when the enter key is pressed in our input box while also preventing the form from being submitted.

Monday, September 28, 2009

Journaling

This evening I found my long lost journal. In dusting it off and cracking it open I learned that my last entry had been over a year ago. With the exception of this last year long hiatus, I've regularly kept a journal since sometime in 1999 or 2000. I've found writing my thoughts helps me crystallize them and I tend to deal with thoughts and emotions internally, mulling them for hours or days. This is one of the reasons I think I've stuck with blogging.

Keeping a private journal is a completely different feeling than keeping a blog. When I write here I'm intensely (sometimes even paralyzingly) conscious of my audience. Not that it's a large one. Here I tend to focus on software related discoveries and creations. It is one creative outlet, but one decidedly different from when I journal.

It was refreshing to scratch blank pages with pen, writing for an audience which understands me better than most.

Okay now how many of you, when you saw the title, thought that I was going to talk about a file system or database? :-) How about you, do you keep a private journal?

Wednesday, August 26, 2009

A Matrix Sim in JavaScript

Do you ever find yourself working on a large project with a long lead-in time before you have visible results to show? I had been frustrated by this feeling recently. I had been focusing on a personal project which will likely be a long time in the making, so I decided to pick up a short, simple, and quick project to keep things lively and fresh. So our story begins.

During high school, I was wowed by the movie The Matrix. The special effects were mind blowing (for their day) and the story line was something I could really get behind (not so with the sequels, but I digress). I imagine this is how my elders felt when Star Wars was first released.

One of the most memorable visuals in the movie is the code of the matrix zipping by vertically on the screen in a retro green on black. Cypher, makes a statement, which seems to be a favorite among programmers, that he no longer sees the code itself, but what it represents. He has become fluent to the point of transcendence - a geek nirvana experience.

At this point in my life I had written a few moderately complex programs, mostly using Turbo C, and I thought: "Why, I could make my computer look like the matrix." It was one of the more involved programs I had written at the time and I was quite pleased with the result. I brought it in to the computer lab at school, loaded it onto all of the machines, and had the whole lab running it at once. I'm pretty sure that Ben, Yed, and Roman G. remember it. Sadly I doubt the code would run on the DOS emulator that ships with Windows XP and higher. I recall vaguely that Roman ported it to Win32 or something in our high school computer science class. Now that I think about it, I guess you could say that this was my first open source experience.

In thinking of something quick and easy to create with some immediate visual payoff, I decided to recreate my little DOS matrix sim, but this time in the browser. Behold: The matrix in JavaScript.

It turns out that the CSS rules needed to keep columns at a fixed width and height was actually quite complex and took longer than expected to get right. The vertical line height was still elusive in Chrome and Safari, but worked in Firefox and Opera. I don't think that this works yet in Internet Explorer. Though if past traffic is any indication, none of you would have noticed had I not said something :-)

Many thanks to Scudmissile for his mighty CSS kung fu. Oh, and that whirring sound that you hear may be your CPU fan trying to take flight. Apparently rendering a vertical text flow like this using DOM manipulation, CSS, and Math.random may be a bit more processor intensive than my obsolete C code.

Saturday, August 01, 2009

A Test Client for App Engine

I created a simple utility library in Python to help anyone debug their App Engine application. Many of the App Engine apps that I've seen use HTTP, HTML form posts, and the Users API and the easiest way to test these features is to fire up the web browser and click through the web pages generated by the app. However this can be a bit slow and repetative and it is difficult to determine exactly what is being sent over the wire (though this is greatly helped by using wireshark, fiddler, tcpdump, or antoher network packet sniffing tool).

Enter my little App Engine HTTP module. It provides a simple interface for making arbitrary HTTP requests and will print the full request and response to the terminal (though you can turn the noisy printing off if you want). Download, copy the http.py file to you working directory and try it out in your Python interpreter.

For our first demonstration, let's try to visit the Google search page.
import http
client = http.Client()
resp = client.request('GET', 'http://www.google.com')
You should see your request and the server's response (with the HTML for the Google Search page) in your terminal window. This should work with just about any website out there.

Other HTTP debugging tools can show you the request and response like this, but I find that this kind of simple Python client can be useful in writing end-to-end or integration tests which contact your App Engine app remotely.

Along those lines, one of the things which standard HTTP debugging tools do not provide, is a way to sign in to an App Engine app with a Google Account so that the App Engine Users API can identify the current user. I wrote an extremely simple app which illustrates the Users API, try it out here:

http://jscudtest.appspot.com/user

After signing in, the page should simply say, "Hello yourusername (yourusername@yourdomain.com)" You'll notice that during the sign in process, you signed in on www.google.com/accounts and were asked to approve access to the app. This kind of interaction works great in a browser, but can be tricky when you are using a command line, browserless, client.

It is possible however, to sign in to an App Engine app without using a browser. You can use the same technique used in appcfg, use ClientLogin and use the authorization token to obtain an app specific cookie which indicates the current user. This simple HTTP library can do this for you and all subsequent requests will use this cookie to tell the App Engine app who the current user is. Try it out by making the request to the simple user app that you visited earlier:
import http
client = http.Client()
client.appengine_login('jscudtest')
resp = client.request('GET',
'http://jscudtest.appspot.com/user')
print resp.body
You should see the following text displayed in the terminal:
Hello, yourusername (yourusername@yourdomain.com)
You can use the appengine_login method with your own app, just change the argument to the App ID of the app you want to access.

Along with simplifying access to apps which use Google Accounts, I wanted this library to simplify the process of using another feature used by many web apps: HTML form posts. Now I'm certain you've used HTML forms before, here's a simple example:

http://shoutout.appspot.com/

The above app uses both the Users API and a simple form. As an alternative to visiting this page in the web browser, you can post your shout-out using the following:
import http
client = http.Client()
client.appengine_login('shoutout')
client.request('POST', 'http://shoutout.appspot.com/',
form_data={'who': raw_input('From: '),
'message': raw_input('Message: ')})
If you've even wondered what gets sent across the wire to post on a form like this, look back in your terminal to see the request from your computer and the response from the server (this is of course just the HTTP layer, wireshark will show you traffic on the IP and Ethernet layer as well).

That's really all there is to it. I designed this as just a simple script to use on the command line and I wrote it in less time than it's taken me to write this blog post about it (I borrowed atom.http_core from the gdata-python-client as a foundation). With some tweaks to remove the interactive (getpass and raw_input) calls and replace them with parameters, I could see this module as a utility layer in a larger, more complex, App Engine client application. If you're creating on I'd love to hear about it ;-)

For more information on how the appengine_login method works behind the scenes, see this presentation I gave a few months ago:



Many thanks to Trevor Johns and Nick Johnson for helping me to understand how this ClientLogin-to-cookie exchange works.

I'm sure that App Engine's Java runtime users would appreciate a port of this simple library to Java, if you feel so inclined.

Tuesday, July 14, 2009

New version of my Dirt Simple CMS

I have just uploaded "version 2" of the dirt simple content management system which I developed almost a year ago. For those who don't recall, scud-cms is an extremely thin layer on top of App Engine with a plain text box based editor for creating web pages. The only new feature in this release is the ability to page through all of the content in your app by visiting the /content_lister page. I implemented the pagination system using "key only" queries and order-by-key which are fairly recent features in App Engine. For more potential designs to page through datastore entities, see this article on pagination.

I was inpired to work on this in part by a comment from Jason Worley (swirleydude on twitter) who has been using it and appears to like it quite a bit. At some point I plan to do a version 3 release which will include file uploads (great for images) just as Jason has done in his own modifications. Having someone use your software, enjoy it, tweak it, and build on it is rewarding in a way which is quite unique.