Web DevCenter    
 Published on Web DevCenter (http://www.oreillynet.com/javascript/)
 See this if you're having trouble printing code examples


Using JavaScript to Create a Powerful GUI

by Meg Hourihan
12/21/2001

The majority of computer users are familiar with the Windows graphical user interface (GUI). Most people know how buttons, toolbars, and tabs work, based on their experience with Microsoft Word or their email client. But contrast the consistent interfaces of client applications with online applications, and you find nearly every site does it differently. A user needs to learn how to use each Web application from scratch. While many applications aren't particularly complicated, it can still be a frustrating experience for a user to always feel like a newbie, needing to relearn an app interface again and again.

By utilizing JavaScript and CSS to build standard client interface components in your online application or Web site, you can make it easier for your users to understand, at a single glance, what actions are available to them and how to accomplish their tasks. The result? A site or application with powerful functionality and users who feel more confident about their actions and are less likely to make mistakes.

Now perhaps you're saying, "I didn't know JavaScript could do that!" Or perhaps you've seen a toolbar, or something similar on another site, but you don't know how it was accomplished. In this article, I will discuss how to build a simple formatting toolbar (like you see in Microsoft Word) to add functionality to any Web site that allows for user feedback or comments via a <textarea>. The skills required to do so are working knowledge of HTML, CSS and JavaScript (nothing we'll get into this article will require advanced JS skills). And the benefits for users are great.

A Short Disclaimer

The code that follows uses the createRange() method of the selection object. Sadly, the selection object is only available for IE4+ users on Windows. Similar functionality should be available via the Document Object Model (DOM) (see DOM Level 2 Traversal and Range Specification) but the document.createRange() implementation is currently broken in Mozilla, specifically in its inability to manipulate text in an input element or textarea element. For further information, see Jeffrey Yates' excellent article, Using the W3C DOM Level 2 Range Object as Implemented by Mozilla. When this bug is fixed, it will be possible to write a version of the following toolbar code for Mozilla, Netscape 6+, and any other browsers running Gecko.

But don't let that stop you from implementing some of the ideas I'll discuss below. If many of your users are on IE4+/Windows, you can offer additional functionality today that can improve the look and experience of your Web site. (For assistance in determining what browser your visitors are using, see Danny Goodman's Object Detection article.)

Building a Simple Toolbar

Screen shot.

Let's start by creating a simple toolbar to hold three buttons: a bold, an italic, and a link button. This toolbar is a nice way to add functionality to an existing text area. It allows users to add simple formatting to their entry without needing to know HTML to do so. Any site that allows user participation or feedback, from Yahoo! Message Boards and community sites like Slashdot or MetaFilter to weblogs utilizing comment features, can be enhanced with this toolbar.

Our toolbar can be broken into four areas of functionality:

Let's start by examining the two functions that will handle the insertion of HTML into our <textarea>:

Using JavaScript to Manipulate Text Selections

function format_sel(v) {
  var str = document.selection.createRange().text;
  document.my_form.my_textarea.focus();
  var sel = document.selection.createRange();
  sel.text = "<" + v + ">" + str + "</" + v + ">";
  return;
}

HippoRelated Reading

The O'Reilly web design collection provides working professionals with the tools they need to build high performance, attractive sites. In addition to our new Dreamweaver manual, we cover JavaScript, CSS and XHTML. Take a look at these selections:

Designing with JavaScript, 2nd Edition

JavaScript: The Definitive Guide, 4th Edition

Dreamweaver 4: The Missing Manual

Web Design in a Nutshell, 2nd Edition

Web Design CD Bookshelf

Cascading Style Sheets: The Definitive Guide

HTML & XHTML: The Definitive Guide, 4th Edition

Learning Web Design

format_sel() takes one parameter, a string, representing the tag value you wish to wrap around the selected text. In the case of the toolbar, we will use this function to wrap text in <b> and in <i>. If you wished, you could use <strong> and <em> in place of <b> and <i>. Or you could use this function to underline a selection (by using the deprecated <u>) or wrap the selected text in any tag of your choosing (<sub>, <H1>, etc.)

We can use the createRange() method of the selection object to easily create a TextRange object of the current text selection. By accessing its property text, we retrieve the selected (highlighted) text in the <textarea>. This text is then assigned to a local variable. The next line, where we call focus() to our <textarea>, is very important, otherwise our changes could be written to another part of the page. Finally, we create another reference to our selected text and assign it a new value: that of our original selection, wrapped in the appropriate HTML.

function insert_link() {
  var str = document.selection.createRange().text;
  document.my_form.my_textarea.focus();
  var my_link = prompt("Enter URL:","http://");
  if (my_link != null) {
    var sel = document.selection.createRange();
	sel.text = "<a href=\"" + my_link + "\">" + str + "</a>";
  }
  return;
}

Our second function insert_link() is identical to format_sel() with the addition of the prompt() method to allow the user to input a value for the a href. Using the results of the prompt(), we can wrap the selected text with the code to create a link. Now that we have these functions, we can build all sorts of interfaces for our users. Let's take a look at a few examples.

Using System Colors Through CSS

The simplest way to use the above functions on your site is to call the functions in the onclick event handler for buttons labelled "bold", "italic", and "link." But that's not very exciting. Since we've already limited ourselves to IE/Win by the use of the selection object, we should take advantage of IE's ability to access user-defined system colors through CSS and to create dynamic buttons like we see in installed applications. Let's take a look at a style sheet that defines a toolbar, a button, and two states for the buttons: raised and pressed.

#toolbar 	{	
			margin: 0;
			padding: 0;
			width: 262px;
			background: buttonface;
			border-top: 1px solid buttonhighlight;
			border-left: 1px solid buttonhighlight;
			border-bottom: 1px solid buttonshadow;
			border-right: 1px solid buttonshadow;
			text-align:right;
		  	}
			
.button 	{
			background: buttonface; 
			border: 1px solid buttonface;
			margin: 1; 
			}
			
.raised		{ 
			border-top: 1px solid buttonhighlight;
			border-left: 1px solid buttonhighlight;
			border-bottom: 1px solid buttonshadow;
			border-right: 1px solid buttonshadow;
			background: buttonface;
			margin: 1;
			}
			
.pressed	{
			border-top: 1px solid buttonshadow;
			border-left: 1px solid buttonshadow;
			border-bottom: 1px solid buttonhighlight;
			border-right: 1px solid buttonhighlight;
			background: buttonface;
			margin: 1;
			}

You'll notice that three system color references are used in our style sheet: buttonface, buttonshadow, and buttonhighlight. By using buttonface as the background for both our toolbar and our buttons, we are able to achieve the same application interface look for a user as any other installed app. Creating borders with buttonshadow and buttonhighlight, we can give our buttons a 3D effect by writing some simple JavaScript functions. Of course, if you're more interested in matching the GUI to your site rather than to a user's browser, you could swap in the appropriate colors instead.

JavaScript to Change Button Styles

The following four functions are called by event handlers to change the className of our images on mouse events. It's possible to put the JavaScript inline (i.e. onmouseover="this.className='raised';"), but by breaking it out into a function, we leave the door open for additional functionality, such as image swapping.

function mouseover(el) {
  el.className = "raised";
}

function mouseout(el) {
  el.className = "button";
}

function mousedown(el) {
  el.className = "pressed";
}

function mouseup(el) {
  el.className = "raised";
}

Putting It All Together With HTML

Now all that remains is to put this all together with the HTML containing our toolbar, images, and text area:

<form name="my_form">
<div id="toolbar">
<img class="button" 
 onmouseover="mouseover(this);" 
 onmouseout="mouseout(this);" 
 onmousedown="mousedown(this);" 
 onmouseup="mouseup(this);" 
 onclick="format_sel('b');" 
 src="bold.gif" 
 width="16" height="16" 
 align="middle" 
 alt="click to make your selection bold">
<img class="button" 
 onmouseover="mouseover(this);" 
 onmouseout="mouseout(this);" 
 onmousedown="mousedown(this);" 
 onmouseup="mouseup(this);" 
 onclick="format_sel('i');" 
 src="italic.gif" 
 width="16" height="16" 
 align="middle" 
 alt="click to make your selection italic">
<img class="button" 
 onmouseover="mouseover(this);" 
 onmouseout="mouseout(this);" 
 onmousedown="mousedown(this);" 
 onmouseup="mouseup(this);" 
 onclick="insert_link();" 
 src="link.gif" 
 width="32" height="16" 
 align="middle" 
 alt="click to add a link"></div>
<textarea cols="30" rows="6" name="my_textarea"></textarea>
</form>

A div holds our three button images and to make things simple, and our function calls are located in the event handlers for the <img> tag. For our formatting functions, we pass a reference to the element to be restyled with the this keyword. To our format_sel() function, we pass the appropriate parameter, based on the formatting we want to apply (b for bold, i for italic).

Feel free to use the following images in your toolbar:

a bold button for the taking an italic button for the taking a link button for the taking

Conclusion

Of course, this is only one way to create a toolbar, and there are many other ways it can be done (you could avoid images altogether and format your "buttons" with CSS, for example). The functionality of your toolbar doesn't have to be limited to what we've done here. Using the W3C DOM, it's possible to change a document's styles on the fly (see Steve Champeon's article, Modifying Styles).

With DOM manipulation, you could build a Microsoft-Word-style toolbar to give a user the ability to customize nearly every aspect of the display: to change the font size or font of the document they're viewing, or to adjust the width of the columns they're reading without having to resize the browser window. Using CSS, JavaScript, and the DOM, it's possible to build robust application GUIs inside standards-compliant browsers. In my next article, we'll take a look at how to build more advanced GUI elements (such as drop-down and cascading menus and tabs), and how to use keystrokes to create shortcut keys for repetitive tasks.

Meg Hourihan is an independent Web consultant and freelance writer. She is a co-author of the book, We Blog: Publishing Online with Weblogs.


Return to the JavaScript and CSS DevCenter.

Copyright © 2009 O'Reilly Media, Inc.