Figure 12-7. The in-place editor’s edit mode Making It Pretty Astute readers will have already noticed that an h1 element looks much different from a text box with the same text content. We can fix that quite easily with CSS. Click the in-place editor to put it into edit mode once again—then use Firebug to inspect the text box that appears. (With the Firebug pane visible, click Inspect, and then click in the text box.) The HTML inspector shows us that the input element has a class name of editor_field, and that its form parent node has an ID of team_name-inplaceeditor (in other words, it adds -inplaceeditor to the ID of the original element. Armed with this information, we can write a CSS selector that targets both read mode and edit mode. Add this to the style element in your document’s head: h1#team_name, form#team_name-inplaceeditor .editor_field { font-size: 19px; font-weight: bold; } CHAPTER 12 ■ ADVANCED CONTROLS: AUTOCOMPLETERS, IN-PLACE EDITORS, AND SLIDERS 291 Now the element looks the same in either mode, as shown in Figure 12-8. Maintain- ing the text’s styling helps the user navigate a new and perhaps unfamiliar UI pattern. Figure 12-8. The read mode (on the left) and the edit mode (on the right) are now far less disjointed-looking, resulting in a friendlier user interface. Common Options and Features Ajax.InPlaceEditor is, like its script.aculo.us brethren, endlessly configurable. Here are some of the most useful options: • okButton and okText control the display of the button that submits the value to the server. Setting okButton to false hides the button altogether—the form can only be submitted via the Enter key. The okText parameter (which defaults to "ok") lets you change the label of the button (e.g., "Save", "Go", or "Make it Happen!"). • cancelLink and cancelText control the display of the link that cancels the edit oper - ation. Setting cancelLink to false hides the link. The cancelText parameter lets you change the label of the link from the default "cancel" to something far sillier, like "oops!" or "I've Made a Huge Mistake.". CHAPTER 12 ■ ADVANCED CONTROLS: AUTOCOMPLETERS, IN-PLACE EDITORS, AND SLIDERS292 • savingText changes the message that is displayed after you submit the form, but before the server responds. As shown, it defaults to "Saving ". • rows defaults to 1. If a greater value is given, the in-place editor’s edit mode will show a multiline textarea (of the given number of rows) rather than the single- line input. • cols is undefined by default; if specified, it controls how large the text entry field is. (For textareas, this is dictated by the cols attribute; for inputs, it’s dictated by the size attribute.) Adding Sliders The script.aculo.us slider control is one implementation of a control that, for whatever reason, has no native implementation in web browsers. The ability to drag a “handle” to a specific spot on a horizontal or vertical “track” has a quasi-analog feel that makes it ideal for zooming in and out, setting the size of an item, distributing resources among several tracks, and countless other scenarios. Creating a Slider The syntax for creating a slider is the following: new Slider(handle, track, options); Here, handle and track refer to the DOM elements that will serve as the “handle” and “track” of the slider, respectively. Configuration can be done with the options argument. But for our first example, we won’t need to do any configuration. Create a file called slider.html and make it look like this: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Chapter 12</title> <script <script src="js/scriptaculous.js" type="text/javascript"></script> CHAPTER 12 ■ ADVANCED CONTROLS: AUTOCOMPLETERS, IN-PLACE EDITORS, AND SLIDERS 293 <style type="text/css" media="screen"> body { font: 67.5% "Lucida Grande", Tahoma, sans-serif; } #track { width: 300px; height: 25px; border: 2px solid #555; } #slider { width: 50px; height: 25px; background-color: #ccc; font-size: 20px; text-align: center; } </style> <script type="text/javascript"> document.observe('dom:loaded', function() { new Control.Slider('handle', 'track'); }); </script> </head> <body> <div id="track"> <div id="handle"></div> </div> </body> </html> The highlighted parts of this HTML file show that we’re creating two elements with IDs of track and handle and placing the latter inside the former. We’re also styling these elements so that they look roughly like a scrollbar thumb and a scrollbar track. CHAPTER 12 ■ ADVANCED CONTROLS: AUTOCOMPLETERS, IN-PLACE EDITORS, AND SLIDERS294 The highlighted line of JavaScript is enough to attach the event listeners to make the handle draggable within the confines of the track. Open up slider.html in a web browser and you should see the slider shown in Figure 12-9. Figure 12-9. The slider with draggable handle In other words, the handle knows the dimensions of both itself and its parent (the track); it knows to stop whenever its left edge hits the left edge of the track or its right edge hits the right edge of the track. We can add more polish to this slider with some of Control.Slider’s options. Common Options A slider is used to set a v alue within a given range—to map a pseudo-analog control to a digital value. If your slider is 300 pixels long and a valid value is any integer from 0 to 11, then each pixel in the slider will map to a value between 0 and 11. Many of the following options control the relationship between the visual represen- tation of the slider and the internal range of values to which it maps. CHAPTER 12 ■ ADVANCED CONTROLS: AUTOCOMPLETERS, IN-PLACE EDITORS, AND SLIDERS 295 Here are the options you’ll use most often to configure your slider: • axis controls the slider’s direction of movement. It can be set to horizontal (the default) or vertical. • range allows you to set the minimum and maximum values for your slider. It expects an ObjectRange—the construct discussed in Chapter 3. For example, $R(0, 11) describes all integers between 0 and 11 (inclusive). • Instead of using range to set an explicit minimum and maximum, you can use increment to describe how pixels map to values. For example, setting increment to 1 means that the value will change by 1 for every pixel moved. • Finally, you can use values to specify, in array form, the exact values that will be allowed (e.g., [1, 2, 5, 10, 20]). The slider handle will snap to those points on the track that represent these values. Callbacks Naturally, a slider is useless without callbacks to hook into. Control.Slider provides two callbacks: • The onSlide callback is called continuously as the handle is dragged along the track. • The onChange callback is called when the user finishes moving the handle and lifts the mouse button. Both callbacks take the slider’s current value as a first argument. Summary You learned about three specific sorts of controls in this chapter, but in the process you also saw several good examples of how JavaScript behaviors should be encapsulated. Notice how each of these examples involves declaring an instance of a class with a partic- ular element as the “base” of the control. In Chapter 13, we’ll try to spot more patterns like these and glean some development principles and best practices. CHAPTER 12 ■ ADVANCED CONTROLS: AUTOCOMPLETERS, IN-PLACE EDITORS, AND SLIDERS296 . left) and the edit mode (on the right) are now far less disjointed-looking, resulting in a friendlier user interface. Common Options and Features Ajax.InPlaceEditor is, like its script .aculo. us. creating a slider is the following: new Slider(handle, track, options); Here, handle and track refer to the DOM elements that will serve as the “handle” and “track” of the slider, respectively. Configuration. script .aculo. us slider control is one implementation of a control that, for whatever reason, has no native implementation in web browsers. The ability to drag a “handle” to a specific spot on