// update the score cell with the player's point total from the JSON row.down('td.score').update(positionStats.points); } } document.observe("dom:loaded", function() { var team1totaler = new Totaler('team_1', 'team_1_total', { selector: 'tbody .score' }); var team2totaler = new Totaler('team_2', 'team_2_total', { selector: 'tbody .score' }); document.observe("score:updated", function() { // the "memo" property holds the custom data we attached to the event var json = event.memo; // break the JSON in half one piece for each table. updateTeam('table_1', json.team_1); updateTeam('table_2', json.team_2); team1totaler.updateTotal(); team2totaler.updateTotal(); }); }); </script> In other words, recomputing the total needs to be the last thing we do when a score updates. Now we need to emphasize rows when they change. This is the perfect use case for Effect.Highlight—the effect that “pulses” an element’s background color to draw atten- tion to it. For this, we’ll need to add some logic to our updateTeam function: <script type="text/javascript" charset="utf-8"> function updateTeam(table, json) { table = $(table); // a team is divided into several positions var positionStats, row; for (var position in json) { positionStats = json[position]; CHAPTER 10 ■ INTRODUCTION TO SCRIPT.ACULO.US EFFECTS 253 // match up the JSON property name (WR1, RB2, TE, etc.) with the // table row that has the corresponding class name row = table.down('tr.' + position); var scoreCell = row.down('td.score'), oldValue = Number(scoreCell.innerHTML); // update the score cell with the player's point total from the JSON scoreCell.update(positionStats.points); // is the new value larger than the old value? if (position.points > oldValue) { new Effect.Highlight(row); } } } document.observe("dom:loaded", function() { var team1totaler = new Totaler('team_1', 'team_1_total', { selector: 'tbody .score' }); var team2totaler = new Totaler('team_2', 'team_2_total', { selector: 'tbody .score' }); document.observe("score:updated", function() { // the "memo" property holds the custom data we attached to the event var json = event.memo; // break the JSON in half one piece for each table. updateTeam('table_1', json.team_1); updateTeam('table_2', json.team_2); team1totaler.updateTotal(); team2totaler.updateTotal(); }); }); </script> Now, as we cycle through the table rows, we check whether the new point value for that row is greater than the current one. If so, we declare a new Effect.Highlight to draw attention to that row. We’re done! Reload the page and congratulate yourself for doing something awe- some. Figure 10-23 shows the fruits of your labor. CHAPTER 10 ■ INTRODUCTION TO SCRIPT.ACULO.US EFFECTS254 Figure 10-23. Rows are highlighted as their point values change. Summary We’ve spent quite a few pages on effects for good reason: they’re the meat and potatoes of script.aculo.us, and the only piece that’s a dependency for all the rest. The script.aculo.us UI widgets all rely on the subtle and purposeful animations we’ve surveyed. In fact, certain other parts of script.aculo.us allow for pluggable effects—for instance, if you don’t like how an element animates when it’s dragged and dropped, you may spec- ify a custom or built-in effect to replace it. These parts of script.aculo.us will be covered in the next two chapters. CHAPTER 10 ■ INTRODUCTION TO SCRIPT.ACULO.US EFFECTS 255 Enabling Draggables, Droppables, and Sortables Drag-and-drop is a UI pattern that seems to have been around since the mouse was invented, but until recently it wasn’t used very often in web applications. But why not? The technological capabilities are there. DOM scripting lets us listen for the mousedown, mousemove, and mouseup events that comprise a drag. It also lets us modify the CSS posi- tioning of an element so that it can “follow” the mouse pointer around the screen. In this chapter, we’ll look at the two low-level objects, Draggable and Droppables, provided by script.aculo.us for drag-and-drop. Then we’ll look at a high-level object, Sortable, that adapts drag-and-drop for a specific task. Exploring Draggables In script.aculo.us, a draggable is anything that can, not surprisingly, be dragged around the page. There are a number of things you can customize about the drag itself, but the simplest way to make something draggable is to declare a new instance of the Draggable class: new Draggable('some_element'); Let’s create a sandbox for playing around with draggables. Create draggable.html and add this markup: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Draggable demo</title> 257 CHAPTER 11 <style type="text/css" media="screen"> body { font-family: 'Trebuchet MS', sans-serif; } #container { width: 200px; list-style: none; margin-left: 0; padding-left: 0; } #container li { border: 1px solid #ccc; margin: 10px 0; padding: 3px 5px; } </style> <script <script src="js/scriptaculous.js" type="text/javascript"></script> </head> <body> <ul id="container"> <li id="item_1">Lorem</li> <li id="item_2">Ipsum</li> <li id="item_3">Dolor</li> <li id="item_4">Sit</li> <li id="item_5">Amet</li> </ul> </body> </html> The bold section of markup represents the items we’ll make draggable. Save this page, load it in Firefox, and then type the following into the Firebug console: CHAPTER 11 ■ ENABLING DRAGGABLES, DROPPABLES, AND SORTABLES258 $$('container li').each( function(li) { new Draggable(li); }); We’re grabbing all the li elements within the ul and declaring each to be a draggable. Run this code, and you’ll be able to drag the five list items anywhere on the page, as shown in Figure 11-1. Figure 11-1. Declaring an instance of Draggable adds dragging behavior to an element. These draggables don’t do anything yet, of course, but we’ll address that when we go over droppables. This example tells you a few things about the Draggable class, but the fact that they can now be dragged around on the screen illustrates how the Draggable class works. CHAPTER 11 ■ ENABLING DRAGGABLES, DROPPABLES, AND SORTABLES 259 . reason: they’re the meat and potatoes of script .aculo. us, and the only piece that’s a dependency for all the rest. The script .aculo. us UI widgets all rely on the subtle and purposeful animations. it. These parts of script .aculo. us will be covered in the next two chapters. CHAPTER 10 ■ INTRODUCTION TO SCRIPT .ACULO. US EFFECTS 255 Enabling Draggables, Droppables, and Sortables Drag -and- drop. fact, certain other parts of script .aculo. us allow for pluggable effects—for instance, if you don’t like how an element animates when it’s dragged and dropped, you may spec- ify a custom or built-in