Friday, 24 January 2014

Extending jQuery: the UI Effects Framework

The jQuery UI effects framework is modularized, just like the widget framework, allowing you to choose which parts of the package you want to use and reduce the code requirements. You can create a custom download for yourself,which takes into account dependencies between the modules.
Before looking at how to create a new effect, you should be aware of the other functionality already offered by the jQuery UI effects framework, so that you can use it when developing your own effects.
Underlying the individual jQuery UI effects modules is a core of commonly used functionality. These abilities are implemented here so that you don’t need to re-invent them and can apply them immediately to your own effects. Along with color animation, you’ll find animation from the attributes of one class to another, and several low-level functions that may be useful in developing new effects.

Color animation

The Effects Core module adds custom animation support for style attributes that contain color values: foreground and background colors, and border and outline colors. jQuery itself only allows the animation of attributes that are simple numeric values, with an optional units designator such as px, em, or %. It doesn’t know how to interpret more complex values, like colors, or how to increment those values correctly to achieve the desired transition, such as from blue to red via an intermediate purple color.
Color values are made up of three components: the red, green, and blue contributions, each with a value between 0 and 255. They can be specified in HTML and CSS in a number of different ways, as listed here:
  • Hexadecimal digits—#DDFFE8
  • Minimal hexadecimal digits—#CFC
  • Decimal RGB values—rgb(221, 255, 232)
  • Decimal RGB percentages—rgb(87%, 100%, 91%)
  • Decimal RGB and transparency values—rgba(221, 255, 232, 127)
  • A named color—lime
The red, green, and blue components must be separated out and individually animated from their initial values to their final ones, before being combined into the new composite color for the intermediate steps. jQuery UI adds animation steps for each affected attribute to correctly decode the current and desired colors, and to change the value as the animation runs. In addition to the color formats described in the previous list, the animate call can also accept an array of three numeric values (each between 0 and 255) to specify the color. Once these functions are defined, you can animate colors the same way you would do for other numeric attributes:
$('#myDiv').animate({backgroundColor: '#DDFFE8'});
jQuery UI contains an expanded list of named colors that it understands, from the basic red and green to the more esoteric darkorchid and darksalmon. There is even a transparent color.

Class animation

Standard jQuery lets you add, remove, or toggle classes on selected elements. jQuery UI goes one better by allowing you to animate the transition between the before and after states. It does this by extracting all the attribute values that can be animated (numeric values and colors) from the starting and ending configurations, and then invoking a standard animate call with all of these as properties to change. This new animation is triggered by specifying a duration when calling the addClass, removeClass, or toggleClass functions:
$('#myDiv').addClass('highlight', 1000);
jQuery UI also adds a new function, switchClass, which removes a class and adds a class, with the optional transition between the two states (when providing a duration):
$('#myDiv').switchClass('oldClass', 'newClass', 1000);


Common effects functions

To better support the various effects of jQuery UI, the Effects Core module provides several functions that are of use to these effects, and perhaps to your own. To illustrate how several of these functions are used, the following listing shows the relevant parts of the slide effect.
$.effects.effect.slide = function( o, done ) {
// Create element
var el = $( this ),
        props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
        mode = $.effects.setMode( el, o.mode || "show" ), ...; // Determine mode of operation

// Adjust
$.effects.save( el, props ); // Save current settings
el.show();
distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
$.effects.createWrapper( el ).css({overflow: "hidden"}); // Create wrapper for animation
...

// Animation
animation[ ref ] = ...;

// Animate
el.animate( animation, {
                       queue: false,
                       duration: o.duration,
                       easing: o.easing,
                       complete: function() {
                               if ( mode === "hide" ) {
                                       el.hide();
                               }
                               $.effects.restore( el, props ); // Restore original settings
                               $.effects.removeWrapper( el ); // Remove animation wrapper
                               done();
                       }
            });
};
You can use the setMode function to convert a mode of toggle into the appropriate show or hide value based on the current visibility of the element. If the provided mode is show or hide, it retains that value, and in this case, defaults to show if not given at all.
Before starting the animation for the effect, you might want to use the save function to remember the original values of several attributes (from the names in props) on the element, so that they can be restored when finished. The values are stored against the element using the jQuery data function.
To facilitate the movement of an element for an effect, you can wrap a container around that element with the createWrapper function to use as the reference point for the motion. Positional information is copied from the specified element onto the wrapper so that it appears directly atop the original element. The element is then positioned within the new container at its top left so that the overall effect is unnoticeable by the user. The function returns a reference to the wrapper.
Any changes to the left /right /top /bottom settings for the original element will now be relative to its original position, without affecting the surrounding elements. Having saved certain attribute values earlier, you’d use the restore function at the completion of the animation to return them to their original settings. At the same time, you should remove any wrapper that you created previously with the remove-Wrapper function. This function returns a reference to the wrapper if it was removed, or to the element itself if there was no wrapper.
There are some other functions provided by the jQuery UI Effects Core module that may be of use:
getBaseline(origin, original) This function normalizes an origin specification (a two-element array of vertical and horizontal positions) into fractional values (0.0 to 1.0) given an original size (an object with height and width attributes). It converts named positions (top, left, center, and so on) to the values 0.0, 0.5, or 1.0, and converts numeric values into the proportion of the relevant dimension. The returned object has attributes x and y to hold the fractional values in the corresponding directions. For example,
var baseline = $.effects.getBaseline(['middle', 20], {height: 100, width: 200}); // baseline = {x: 0.1, y: 0.5}
setTransition(element, list, factor, value) To apply a scaling factor to multiple attribute values at once, use this function. For each attribute name in list, retrieve its current value for element, and update that by multiplying it by factor. Set the result into the value object under the name of the attribute, and return that object from the function. For example, to reduce certain values by half, you might do this:
el.from = $.effects.setTransition(el, ['borderTopWidth', 'borderBottomWidth', ...], 0.5, el.from);
cssUnit(key) To separate a named CSS attribute (key) into its amount and units (em, pt, px, or %), returned as an array of two values, use this function. If the units aren’t one of these known types, an empty array is returned. For example,
var value = el.cssUnit('width'); // e.g. value = [200, 'px']
The functions presented in this section are used by many of the effects provided by jQuery UI. These effects are reviewed in the next section.

Existing effects

Numerous effects are provided by jQuery UI. Most of these are designed to enhance how an element appears or disappears (such as blind and drop), whereas others serve to bring your attention to an element (such as highlight and shake):
  • blind: Element expands or contracts vertically (default) or horizontally from its top or left
  • bounce: Element drops into or out of view and bounces a few times
  • clip: Element expands or contracts vertically (default) or horizontally from its center line
  • drop: Element slides into or out of view from the left (default) or top, and fades to or from full opacity
  • explode: Element breaks up into sections and flies apart, or reassembles itself from flying parts
  • fade: Element fades to or from full opacity
  • fold: Element expands or contracts first in one direction then in the other (horizontally then vertically by default)
  • highlight: Element changes background color briefly
  • puff: Element decreases or increases in size, and fades to or from full opacity
  • pulsate: Element fades out and in several times
  • scale: Element expands or contracts from or to its center point by a percentage amount
  • shake: Element moves from side to side several times
  • size: Element decreases or increases in size to given dimensions
  • slide: Element slides horizontally (default) or vertically from its own edge
  • transfer: Element is moved and resized to match a target element
These effects may be used in conjunction with the enhanced jQuery UI show, hide, and toggle functions by providing the name of the desired effect as the first parameter. You can also supply additional options that change the behavior of the effect, the duration of the animation, and a callback function that’s triggered on completion.
$('#aDiv').hide('clip');
$('#aDiv').toggle('slide', {direction: 'down'}, 1000);


No comments:

Post a Comment