15.3. Visual Effects for That "Wow Factor"Though people ultimately use software because of the things the software will do for them, how people perceive the software will have a big impact on how they feel about it. People learn better and work better when they're having fun. Visual effects don't add anything tangible to your product (you don't get to add an extra bullet point for them!), but they can make a huge difference in how your users feel about your product. The MochiKit.Visual module provides a number of easy-to-use visual effects routines. MochiKit.DragAndDrop gives you a simple way to add drag-and-drop controls to part of your application. MochiKit.Sortable lets you give your users a way to sort a list with drag and drop with only a couple lines of code. Together, these three modules let you ratchet up the overall feel of your application by a couple of notches. 15.3.1. Rounded CornersWe start with the most humble feature in the package: rounded corners. Generally, if you want a rounded-off look for your application, you need to resort to images that you slice up just right to achieve the effect. The Visual module lets you round the corners of an element (or collection of them) with a single call, no images required. You can see the rounded-corners effect for yourself using MochiKit's interactive interpreter: writeln(DIV({"class" : "rounded", "style" : "text-align:center; background:black; color: white"}, "Square edge or round, you decide!")); That command gives us a white-on-black <DIV> element, with the traditional squared-off corners. Now run this: roundClass("div", "rounded"); Our <DIV> now looks rounded. That call said to make any <DIV> elements with the class rounded be rounded off. You can pass in null for either the tag or the class to match all tags or classes. Some caveats apply to using the rounded elements feature: It only works properly on "block" nodes and can be thrown off by padding. In addition to roundClass, there is also a roundElement function that lets you round a specific DOM node. Both roundClass and roundElement have an optional additional parameter of an options object. The options available for rounding are found in Table 15.2.
This feature was ported from OpenRico to MochiKit, so you may be able to find additional information regarding rounded corners at the OpenRico site: http://openrico.org/. 15.3.2. Getting Started with EffectsVisual lets you provide a nicer-looking experience right away. Give this a whirl in your interpreter. (Reload the page if you already had one open: otherwise, you'll have scrolling issues.) writeln(DIV({"id" : "nowyouseeit"}, "Now you don't!")); That puts a simple <div> up for you to play with. Let's make it disappear and then reappear, using functions we talked about earlier in the chapter: hideElement("nowyouseeit"); showElement("nowyouseeit"); As expected, the element appears and then disappears, each transition happening in an instant. Compare that with this: toggle("nowyouseeit"); toggle("nowyouseeit"); toggle(element[, effect[, options]]) will do a nice, simple fade in/fade out by default. It's simple, but sometimes more pleasing than having an element abruptly disappear. effect can be one of slide, blind, appear, and size. try those out, and you'll see that you can get pretty flashy without much fuss. 15.3.3. Effect OptionsAll the visual effects take an "options" parameter, which is an object that provides, you guessed it, options for the effects. There are a number of standard options, and their default values can be found in MochiKit.Visual.DefaultOptions. The standard options and their default values are listed in Table 15.3.
You can see the options in action for yourself with the toggle function we've already looked at: toggle("nowyouseeit", "appear", MochiKit.Visual.Transitions.pulse); If you have multiple interrelated elements, you can run the same effect on all of them in parallel: >>> writeln(DIV({"id":"one"}, "The First Element")); The First Element >>> writeln(DIV({"id":"two"}, "The Second Element")); The Second Element >>> multiple(["one", "two"], fade); 15.3.4. The Core EffectsThese effects are the building blocks for more-complicated effects. They are "classes," so you need to use new to use them. The general form used for all the effects, which we've already seen, is effect(element[, options]). For the core effects, you use new Effect(element[, options]), the one deviation from this in the standard set is Scale which also requires a percent parameter to be useful. Highlight gives you the famous Yellow Fade technique. By default, a yellow background fades in and then disappears. Of course, you can change the color with the startcolor option. The Scale(element, percent[, options]) effect has several options and an extra parameter. The percent parameter specifies how much you would like the element to scale by. The other options offered for the Scale effect are listed in Table 15.4.
Another class that is offered is Parallel(effects[, options]), which launches the provided effects in parallel. The remaining core effects all have fewer options, as summarized here:
15.3.5. Combination EffectsThe "combination effects" build on the core effects to provide easy-to-use functions that have a polished and complete look. All of these functions have the signature effect(element[, options]). The combination effects are as follows:
15.3.6. Customizing Effect BehaviorThe effect options described earlier in the chapter provide a number of ways you can customize the appearance of an effect, but they don't change the fundamental behavior of the effect. You can also change the behavior of an effect via options by setting callbacks for events that occur during an effect's lifetime. The events are as follows:
A simple example will chain two effects: writeln(DIV({"id" : "shaker"}, "Pulsate and shake!")); pulsaste("shaker", {"afterFinish" : function() { shake("shaker"); } } } You can also create your own, new effects based on the MochiKit.Visual.Base class. You can override the setup, update, and finish methods to design an effect that does whatever you want. As an example of a completely custom effect, we'll make a "rolling sign" effect that roughly simulates those signs that keep changing letters around until they reach the final desired text. This is visually similar to that, but the intermediate letters that are chosen are completely random: You can try this code out easily in the interpreter after you've entered it: writeln(DIV({id:"hiya"}, "Hey there!")); new RollingSign("hiya", "That's all folks!"); You can also try tweaking standard options, such as duration, to see the effect they have.
15.3.7. An Effects DemoTwo more packages have also been ported from Scriptaculous: DragAndDrop and Sortable. Both of these let you provide a drag-and-drop (DND) user interface for your application with a minimum of fuss. DND is an important user interface feature because certain types of UI problems are not solved gracefully through any other means on the web. One example of this is an "ordered list of items." Consider an election system where you don't just pick a single candidate, but instead need to put the candidates in order of preference. The "old-fashioned" way to do this in a web browser was a setup involving a "select multiple" control and up and down buttons. You'd select someone from the list and repeatedly click the up or down button until that person was in the right place. Then you'd painstakingly repeat the process until you were done, or until you just gave up and let the other guy win. DND is much more natural for this. Just drag the person up to the spot where you want the person to be. Simple. Note that DND on the web is not likely to work with accessibility solutions for disabled users. You might still consider offering some kind of up and down buttons for that reason. Yahoo!'s My Yahoo service, for example, lets you drag and drop modules on your My Yahoo page, but also offers a separate, old-style page that is doubtless more accessible. Ordered lists are such a common requirement that Scriptaculous/MochiKit offer something called a Sortable. A Sortable provides prepackaged, ready-to-run DND for ordered lists. As an example of this, we'll use an effects viewer that lets you view MochiKit's visual effects individually or create an ordered chain of effects that are run one after the other. There are two things to note about this demo before we look at the code. As of this writing, MochiKit.Visual is not yet complete. The API is not likely to change much, but the packaging might change some. At present, the packed MochiKit.js distribution does not include New.js, DragAndDrop.js, or Sortable.js. This packaging issue will undoubtedly be resolved by the time MochiKit 1.4 ships. In addition, the Sortable name is not exported by the Sortable.js module. So, you'll note in the following code that we refer directly to MochiKit.Sortable.Sortable. That style of access will continue working later on, so feel free to use it. It's just a bit wordier. And now, on to the Effects/Sortable/DND sample. This demo program, pictured in Figure 15.2, enables you to watch a number of MochiKit's effects as they're applied to the header of the page. You can set the duration and then click a button to see the effect. You can also view the RollingSign effect implemented in the preceding section. Figure 15.2. Effects PictureSortable comes in with the "effects chain" feature of the page. You can grab on to the green handles and drag effects from the left side of the page into the effects chain box. You can also change the ordering of the effects. That box will run the effects one after another in the same order in which the buttons appear on the page. It's a nifty bit of functionality, and you'll see that it's done with very little code: 15.3.8. Sortables and DragAndDropOne call to Sortable.create packs a lot of power! Sortable.create(element[, options]) takes an element (generally a ul) and a variety of options. Many of the options come straight from the DragAndDrop package, on which Sortable builds. Let's talk about the lower-level DND package before getting to the details of Sortable. DND provides you with two kinds of objects: Draggables and Droppables. They have the familiar-looking signatures new Draggable(element[, options]) and new Droppable(element[, options]). To allow an element to be picked up and dragged around the page is as simple as new Draggable('elementid'). However, you might want to change a number of options that affect the draggable's behavior. These options are listed in Table 15.5.
Wow! That's a lot of options! And that's just the draggable. It is, indeed, a lot of options. The DND module provides lower-level services and is set up to handle just about any drag-and-drop needs your application might have. It's quite easy to make an element draggable (new Draggable('elementid') is all it takes), but you'll likely spend a fair bit of time tweaking the behavior until it's exactly what you want it to be. Let's take a look at the options available for a droppable, as listed in Table 15.6.
Using the draggable and droppable classes, you have a large amount of control over how the drag-and-drop experience looks (via CSS that is applied at various points) and acts (via the effects and callbacks). As you saw from the effects demo, the specific case of making a list of items that is sortable via DND has a high-level interface. Using Sortable, you don't need to worry about all the different event possibilities. The options for Sortables can be found in Table 15.7.
The features outlined in previous sections of this chapter enable you to craft powerful, interactive, web-based applications with far less effort than in years past. MochiKit's effects, combined with Sortable and DND functionality, can help put a serious shine on your application, giving it a modern look and feel that will delight your users. Have fun with it without overdoing it, and your users will love you for it. |