Unobtrusive Javascript: Expandable textareas

Using unobtrusive Javascript (see introduction), we can add behavior to textareas to make them automatically expand or contract as text is entered into them. Here is a script that accomplishes that:

autosize.js

Event.onReady(function() {
  $$('textarea').each(function(inputElement) {
    var textarea = inputElement;
    var initialHeight = textarea.getHeight();
    var currentHeight = -1;
    var currentTimer = false;
    var div = $div({id: textarea.id + '_hidden'});

    textarea.insert({'after': div});
    div.setStyle({'display'       : 'none',
                  'width'         : textarea.getWidth() ?
                                      (textarea.getWidth() + "px") :
                                      textarea.getStyle('width'),
                  'whiteSpace'    : 'pre-wrap',
                  'fontFamily'    : textarea.getStyle('fontFamily'),
                  'fontSize'      : textarea.getStyle('fontSize'),
                  'lineHeight'    : textarea.getStyle('lineHeight'),
                  'paddingTop'    : textarea.getStyle('paddingTop'),
                  'paddingLeft'   : textarea.getStyle('paddingLeft'),
                  'paddingRight'  : textarea.getStyle('paddingRight'),
                  'paddingBottom' : textarea.getStyle('paddingBottom'),
                  'marginTop'     : textarea.getStyle('marginTop'),
                  'marginLeft'    : textarea.getStyle('marginLeft'),
                  'marginRight'   : textarea.getStyle('marginRight'),
                  'marginBottom'  : textarea.getStyle('marginBottom'),
                  'borderTop'     : textarea.getStyle('borderTop'),
                  'borderLeft'    : textarea.getStyle('borderLeft'),
                  'borderRight'   : textarea.getStyle('borderRight'),
                  'borderBottom'  : textarea.getStyle('borderBottom')
                 });

    var timerHandler = function() {
      currentTimer = false;
      if(initialHeight == 0) {
        initialHeight = textarea.getHeight();
      }
      div.innerHTML = $F(textarea).replace(/&/g, '&')
                                  .replace(/</g, '<')
                                  .replace(/n/g, '<br />') +
                      '<br />z';
      var newHeight = Math.max(initialHeight, div.getHeight());
      if(newHeight != currentHeight && newHeight != 0) {
        textarea.setStyle({ 'height': newHeight + 'px' });
        currentHeight = newHeight;
      }
    }
    var eventHandler = function(ev) {
      if(!currentTimer) {
        setTimeout(timerHandler, 250);
      }
    }
    textarea.observe('change', eventHandler);
    textarea.observe('keyup', eventHandler);
    timerHandler();
  });
});

Here’s how you would use it. You don’t need to include any explicit Javascript or even styling within your document; the script automatically locates all textareas and adds the stretch behavior to them. Note that you need to include the Prototype and Low Pro Javascript libraries:

example.html

<script src="/js/prototype.js" type="text/javascript"></script>
<script src="/js/lowpro.js" type="text/javascript"></script>
<script src="/js/autosize.js" type="text/javascript"></script>
. . .
<textarea name="comment">blah blah . . .</textarea>

How it works

The script first searches for all textareas in the document, and then executes a function for each textarea to add the stretch behavior to the element. This function creates a hidden div element associated with the textarea, and copies much of the style information from the textarea to the div. Then, it associates a function with the onkeyup and onchange events for the textarea. This event handler function copies the textarea text into the hidden div, measures the size of the div, and adjusts the size of the textarea to fit the size of the div. This means that the textarea grows or shrinks (never smaller than its original size) based on the size of the text contained within it.

Additional notes

The onchange and onkeyup handlers don’t directly copy the text into the div and resize the textarea. I found that doing that immediately on every key press slowed typing down considerably. Instead, the event handlers set a timer to expire 1/4s after the textarea is changed, and this timer handler itself does the resizing. I do not notice any lags in typing responsiveness with this approach.

The timer handler remembers the last measured size of the div so that it doesn’t need to resize the textarea if the div hasn’t changed in size. There are also some places where we check to be sure that a measured height is not zero — I found that IE6 sometimes reports a height of zero even though the DOM has loaded at the point that these functions are called.

If you have any unobtrusive Javascript code that hides your textareas, you should make sure that the autosize.js code runs before your textareas are hidden, so that it can measure their size while they are still visible. We’ll consider something like this in a later post, where you can have some text on your page with an edit link that automatically reveals a textarea to edit the text’s content.

Limitations

For unknown reasons, IE6 doesn’t seem to correctly report the fontFamily for an unstyled textarea. In cases where the textarea is clearly a monospace font, IE6 will report the body’s fontFamily (e.g., ‘arial’) instead of ‘monospace’ when retrieving the textarea’s fontFamily style. The result of this is that the div’s styling doesn’t match the textarea’s styling, and so the textarea will not necessarily be sized properly if it holds a lot of text. The workaround for this problem is to explicitly style your textareas using ‘font-family: monospace’; IE6 correctly reports the fontFamily in this case.

As indicated above, in some cases IE6 incorrectly reports a height of 0 for the textarea or div. The result of this is that in IE6 the textarea’s initial size may not stretch to fit its contents, but as soon as a character is typed into it it will expand to the correct size. I’m not aware of any universal workarounds for this. However, if you have textareas that are not auto-hidden on page load then you may be able to modify the code above so that instead of calling timerHandler() directly at DOM load time, it is scheduled to be called by a timer shortly thereafter.

Editor Color Scheme

Recently Slashdot featured a discussion of the best color scheme for programming. From that discussion I’ve discovered the zenburn color scheme, and have switched to it. I like the fact that the background is not stark black; the reduced contrast feels easier on my eyes.

Here are some resources I found from that discussion for color schemes:

What color scheme do you prefer for programming? There are several others at the vim color scheme test, above, that I’m also interested in trying out.

See also: Programming Fonts

Unobtrusive Javascript: Introduction

Unobtrusive Javascript is a way of using Javascript that cleanly separates your Javascript from your HTML code.  Instead of coding Javascript actions within your document (e.g., using an onchange=”…” handler), your Javascript actions are contained within an external script that inserts actions into your document based on CSS class names or element ids that you have pre-determined.

For example, you might have a link that toggles the presence of another element:

<script src="/js/prototype.js" type="text/javascript"></script>
. . .
<a href="#" onclick="$('toggle').toggle(); return false;">Toggle</a>
<div id="toggle" style="display:none">Some content here</div>

There are some problems with this, however.  First, the code is cluttered with messy Javascript.  Second, our code doesn’t fail gracefully if Javascript is not enabled — the “display:none” style will cause our div not to be displayed, but it would be better if the default were for it to be displayed when Javascript is not active.  Of course, we could create a body onload action to workaround this problem, but that clutters our HTML with even more Javascript and also causes the toggle behavior to be spread across several elements.

Unobtrusive Javascript solves these problems by defining and collecting the dynamic behavior in a single separate Javascript file.  The HTML document now contains only HTML, plus a few additional CSS class selectors that our Unobtrusive Javascript uses to locate elements that it should take action on.  Using the above example, we might create an Unobtrusive Javascript solution that looks like this:

autotoggle.js

Event.onReady(function() {
    $$('.auto_toggle').each(function(elem) {
        var element = elem;
        var anchor = $(elem.id + "_anchor");
        element.hide()
        anchor.observe('click', function(ev) { element.toggle(); ev.stop(); });
      });
  });

example.html

<script src="/js/prototype.js" type="text/javascript"></script>
<script src="/js/lowpro.js" type="text/javascript"></script>
<script src="/js/autotoggle.js" type="text/javascript"></script>
. . .
<a href="#" id="toggle_anchor">Toggle</a>
<div id="toggle" class="auto_toggle">Some content here</div>

Before we defined an onclick action on our anchor, but now we set a special CSS class on the div.  By convention, we give the anchor an id based on the id for the div.  Our external Javascript code then finds all divs with the class “auto_toggle”, and inserts an onclick action into the anchor whose id matches the div’s id, with the suffix “_anchor”.  If Javascript is not active, the div will be displayed.

Going into more detail, here is what our unobtrusive toggle handler does:

  1. For DOM help, it uses the Prototype and Low Pro libraries (although it is possible to write unobtrusive Javascript using other libraries like jQuery).
  2. The call to Low Pro’s Event.onReady() registers a function to be called when the page’s DOM is loaded.  We’ve provided an anonymous function to this call that performs our unobtrusive action.
  3. Our function calls Prototype’s $$() function to locate the list of all elements matching the CSS selector specification “.auto_toggle”; i.e., any element having a class named “auto_toggle”.  It then iterates over this list using the Prototype Array.each() method, providing an anonymous element handler function to be called for each element.
  4. Our element handler creates variables referencing the matching element, and also locating the anchor element that has the id matching the current element’s id with the added suffix “_anchor”.  It then calls the Prototype Element.hide() method to ensure that the toggle element starts out hidden.
  5. Our element handler then calls the Prototype Element.observe() method to register a handler for whenever the toggle anchor is clicked.  For our click handler we provide an anonymous function that calls the Prototype Element.toggle() method to toggle the visibility of the target element and then stop the event by calling Event.stop() (stopping the event is the same as returning false in an onclick event; this causes the anchor target URL not to be visited).  You may notice that our click handler function is a Javascript closure — it references variables in the calling function, and these variables will be available to it even when the calling function has ended.

This is a simple example, but we could take it further.  For example, we could define the anchor as a span element, and our unobtrusive code could replace it with an anchor element only if Javascript is enabled.  That way, users without Javascript won’t see anything clickable on the toggle action.  Or, if we knew that every toggle-able div had the text “Toggle” for its anchor, we could remove the toggle anchor altogether and have our unobtrusive code insert it.

Apart from keeping our HTML code clean and simple, one of the great advantages of Unobtrusive Javascript is that we can build up a library of powerful unobtrusive actions that we can reuse with minimal changes to our HTML.  Growing more complex than the example we’ve considered here, we could insert dynamic pop-up calendars for every form input element that has a “date_calendar” CSS class.  Or we could create code to find every textarea element in the document and cause these textareas to be dynamically resized as users type text into them.  We’ll start to build up our Unobtrusive Javascript library by considering examples like these in subsequent posts.

GCC binary conditional

I recently ran into a nifty GCC extension to the C/C++ language, the binary conditional:

z = x ?: y;

At first glance this looks like the C++ ternary operator:

z = x ? y : w;

But notice that this new operator above is binary — it has only two parameters.  Unlike the dash and greater-than symbols in the C arrow operator (pointer -> member), GCC does not require that the binary conditional’s question mark and colon be adjacent, but you should probably write them adjacently to better distinguish them from the ternary operator.

But what does the binary conditional do?  In short, it is analagous to the Perl || operator, the Python or operator, and the Ruby || operator.  It evaluates to the value on the left unless the value on the left evaluates to false, in which case it evaluates to the value on the right.

x y x ?: y
0 0 0
0 80 80
NULL 0x16E212B4 0x16E212B4
15 0 15
15 20 15
0x16E212BC 0x16E212E8 0x16E212BC

You may wonder why the C || operator can’t be used for this same purpose. The reason for this is that C’s || operator performs a pure logical or operation: it always collapses the result value to 0 or 1. For example, the expression 80 || 0 evaluates to 1, not to 80. However, the expression 80 ?: 0 evaluates to 80.

That’s pretty nifty, although ?: is certainly a bit unfortunate; it’s not obvious from looking at the operator what it should do. Worse, it appears that the binary conditional is unique to GCC. I’ve tried this with several other C/C++ compilers without success.

There is, however, a more portable way to accomplish the same thing. Instead of writing x ?: y, you can write the equivalent x ? x : y. This is a little less concise, but it has the advantage that any skilled C programmer can immediately understand what it does. And it is more portable.

A performance comparison of AF_UNIX with loopback on Linux

[PostgreSQL]On various Linux hosts I use either MySQL or PostgreSQL for my back-end database.  Typically the database is running on the local host, and this raises the question of how to connect to the database.  For both MySQL and PostgreSQL it is possible to connect using a local AF_UNIX connection, or using an AF_INET connection over the loopback socket (address 127.0.0.1).

I had thought that it might actually be more efficient to connect over loopback; for my day job I work on the TCP/IP stack for the z/OS operating system, and I know firsthand that our TCP/IP implementation is heavily optimized, including specific optimizations for local traffic.

I decided to test this hypothesis by comparing both the throughput and latency of AF_UNIX and AF_INET connections.  I was running on a Celeron Dual-core system running Debian 4.0 with kernel version 2.6.18-4-686.  The results disproved my hypothesis, at least for Linux:

  • AF_UNIX:
    • 100GB transferred in 80.575200 s
    • 100 million 8-byte messages:
      • Average latency 14.463910 μs
      • Standard deviation 0.003376 μs
  • AF_INET, loopback address
    • 100GB transferred in 226.717520 s
    • 100 million 8-byte messages:
      • Average latency 1133.444424 μs
      • Standard deviation 0.067419 μs

So, for both throughput and latency, on the Linux platform AF_UNIX is a superior choice to AF_INET.  For local MySQL and PostgreSQL connections you should use a local socket rather than the loopback socket.

Computer monster

Speaking of Sesame Street (see my last post), below is a funny video of a proto-Cookie Monster eating a computer. This monster is a little bigger than Cookie Monster and has fangs. Unlike Cookie Monster, he has a hole in his mouth and actually consumes some of what he destroys. Apparently he was the origin of Cookie Monster. My favorite part is the Jabberwocky reference. What’s yours?

HT: Jeffrey Meyers

Richard Scarry and hexadecimal

When you read a hexadecimal number out loud, how do you pronounce the letters?

At my workplace, I’ve grown used to our custom of pronouncing the letters using the Joint Army/Navy Phonetic Alphabet standardized in 1941. The letter digits are pronounced Able, Baker, Charlie, Dog, Easy and Fox. Under this scheme, the hexadecimal number 0x7F8D3BC0 would be pronounced “Seven Fox Eight Dog Three Baker Charlie Zero.” This was disorienting to me at first, but after eight years this is now so natural that this is how I pronounce the digits in my mind even if I’m not speaking them.

We’ve started collecting Richard Scarry’s children’s books. Richard Scarry writes with a degree of detail and whimsy that holds an adult’s interest — much like old-school Sesame Street. (How far it has fallen — modern-day Sesame Street is much too postmodern, pluralistic, saccharine and juvenile for my taste. I console myself by searching for old Sesame Street clips on Youtube.) Recently I was amused and pleased to discover that one of Richard Scarry’s characters is named Able Baker Charlie! What a strange juxtaposition of worlds for me — programming and children’s books.

Able Baker Charlie is a mouse. He is a baker, and assists Baker Humperdink, a pig. Despite his small size, Able Baker Charlie is capable assisting with any step of the baking process, from stoking the oven, to mixing the dough, to putting loaves in the oven, and even delivering bread around Busytown. Below you may see a picture of Able Baker Charlie ably distributing French baguettes to Louie’s Restaurant.

Richard Scarry served in the U. S. Army during World War II. No doubt this is the source of the Able Baker Charlie aptonym. It still gives me a chuckle every time we read it.

Programming Fonts

I’ve long been dissatisfied with Courier New as a programming font; I’ve found the characters to be bulky and the serifs distracting.  For the past year or so I’ve settled on the beautiful Lucida Console as my favorite font to code in.  Lucida Console is bundled with Windows XP and Windows Vista, and unfortunately it doesn’t seem to be available for free redistribution.  However, you can find some other aesthetically pleasing fixed-width programming fonts, some of which are available for free download, at Hamstu’s Typography of Code.

HT: Woot

Python generators – saving time and memory

Python version 2.2 introduced support for generator functions. A generator is a function that returns something kind of like a list. You can think of a generator as a function that gets to return more than once; each time it returns, it produces a new item in the list. Here is a simple example of a generator:

def mygen() :
  print "calling generator"
  for x in [1, 2, 3, 4] :
    print "yielding next value"
    yield x

for item in mygen() :
  print item

This example prints the following:

calling generator
yielding next value
1
yielding next value
2
yielding next value
3
yielding next value
4

Instead of return, we used the yield statement inside our generator. yield returns an item from the generator, but marks that point in the code so that we continue processing when we go back to the generator to fetch the next item in the pseudo-list. Notice how the generator is only called once, but the yield points are interleaved with the print statements in the calling code. Each time the generator needs to produce a new value, it picks up from the previous yield point. When the generator reaches the end of the function, no more values are produced. You cannot use return within a generator.

Let’s look at some code where the use of generators might help us. The following code instantiates a list of objects and then creates HTML to display them. We’ll assume the existence of a database API to execute queries and retrieve results:

def get_objects() :
  result = []
  query = db_execute("...")
  row = query.fetchrow()
  while not row is None :
    result.append(MyObject(row))  # Build object from DB, append to result
    row = query.fetchrow()
  return result
. . .
for object in get_objects() :
  print object.getHTML()

This code creates the entire list of objects before it can print any of them. There are two problems with this — first, there is a huge delay to create all of the objects before any progress is made in printing; this means that the user’s browser has no partial results to display. Second, all of the objects must be held in memory at the same time; if there are many objects, this can cause significant overhead.

Generators allow us to attack both of these problems. Since a generator produces items one at a time, on demand, it avoids both of these problems. We don’t have to wait to construct all of the objects in the list before we use the first one. And once we are done using an object, the Python garbage collector is now free to immediately clean it up. Here’s how we might rewrite the above code to use generators:

def get_objects() :
  query = db_execute("...")
  row = query.fetchrow()
  while not row is None :
    yield MyObject(row)    # Build object from DB, yield to caller
    row = query.fetchrow()
. . .
for object in get_objects() :
  print object.getHTML()

With a small change we have now significantly improved our code’s memory footprint — all of the objects do not need to be held in memory at the same time. And we are now producing the output for each object as we create it, without needing to wait for all the objects to be instantiated first. This is a significant improvement!

We can also build a chain of generators. Let’s assume that we need to modify the code above to optionally display only those objects that have an “active” flag set. Ordinarily, if we use Python’s filter function to accomplish this, it needs to create the entire list all at once. But if we use a generator to perform the filtering, then we can still keep our optimizations since we are only ever creating and filtering one object at a time. Here’s an example:

my_objs = get_objects()         # This returns a generator object

if display_active_only :
  def active_filter(objects) :  # A filtering generator
    for object in objects :
      if object.active :
        yield object

  my_objs = active_filter(my_objs)

for object in my_objs :
  print object.getHTML()

A generator function doesn’t produce a real list; instead, it produces a generator object that behaves like something called an iterator. You can’t write either of the following statements for a generator or iterator:

print len(get_objects())
print get_objects()[3]

The for statement is smart enough to traverse a generator, and it will probably be sufficient for your needs. Perhaps you can get the count of objects by other means, such as executing an SQL COUNT request. If you absolutely need to access a generator as a list, you can coerce it to a list as follows:

objlist = list(get_objects())

But be aware that this removes all of the advantages that we’ve discussed here, since this causes all of the objects returned by the generator to be created at once and stored in the list. If you find yourself needing to do this, you should consider rewriting your code so that you don’t need to do so. Or perhaps generators aren’t the right solution for your particular problem.