#

Jump to Table of Contents

# Example: Animated Drop Targets

This example will show you how to make an animated node a Drop target.

View Example in New Window

### Setting up the HTML

First we will create our HTML.

    <div id="dock"></div>

    <div id="drag">Drag #1</div>

    <div id="anim1" class="anim">Anim #1</div>
    <div id="anim2" class="anim">Anim #2</div>
    <div id="anim3" class="anim">Anim #3</div>
    <div id="anim4" class="anim">Anim #4</div>
    <div id="anim5" class="anim">Anim #5</div>

Now we give that HTML some CSS to make it visible.

    .anim {
        position: relative;
        height: 50px;
        width: 100px;
        border: 1px solid black;
        background-color: #00B8BF;
        top: 100px;
    }
    #drag {
        height: 50px;
        width: 50px;
        border: 1px solid black;
        background-color: #004C6D;
        color: white;
        cursor: move;
        z-index: 5;
    }
    #dock {
        height: 600px;
        width: 75px;
        background-color: #D00050;
        border: 1px solid black;
        position: absolute;
        top: 5px;
        right: 0px;
    }
    .anim.yui3-dd-drop-over {
        background-color: #EDFF9F;
    }
    .anim.done {
        background-color: white;
    }
    #drag1.yui3-dd-drag-over {
        opacity: .5;
        filter: alpha(opacity=50);
    }

### Setting up the YUI Instance

Now we need to create our YUI instance and tell it to load the `dd-drop`, `dd-plugin`, `dd-drop-plugin` and `anim` modules.

    YUI().use('dd-drop', 'anim', 'dd-plugin', 'dd-drop-plugin');

### Making the Node draggable

Now that we have a YUI instance with the modules loaded, we need to instantiate the `Drag` instance on this Node.

In this example we will be using Node plugins to accomplish our tasks.

    YUI().use('dd-drop', 'anim', 'dd-plugin', 'dd-drop-plugin', function(Y) {
        //Get the node #drag
        var d = Y.one('#drag');
        d.plug(Y.Plugin.Drag, { dragMode: 'intersect' });
    });

### Animating the Nodes

Now we will set up the Animation sequence that we want to run.

    //Get all the div's with the class anim
    var anims = Y.Node.all('div.anim');
    var counter = 0;
    anims.each(function(v, k, items) {
        //Get a reference to the Node instance
        var a = v;
        counter++;
        //Add the FX plugin
        a.plug(Y.Plugin.NodeFX);
        //Add the Drop plugin
        a.plug(Y.Plugin.Drop);

        //Set the attributes on the animation
        a.fx.setAttrs({
            from: {
                left: 0
            },
            to: {
                curve: function() {
                    var points = [],
                        n = 10;

                    for (var i = 0; i < n; ++i) {
                        points.push([
                            Math.floor(Math.random()*Y.DOM.winWidth() - 60 - a.get('offsetWidth')),
                            Math.floor(Math.random()*Y.DOM.winHeight() - a.get('offsetHeight'))
                        ]);
                    }
                    return points;
                }
            },
            //Do the animation 20 times
            iterations: 20,
            //Alternate it so it "bounces" across the screen
            direction: 'alternate',
            //Give all of them a different duration so we get different speeds.
            duration: ((counter * 1.75) + 1)
        });
    });

### Making the Node a Target

Using the `dd-drop-plugin`, we now need to make this animated Node a Drop Target.

To do that, we need to add the plugin after the fx plugin.

    //Add the FX plugin
    a.plug(Y.Plugin.NodeFX);
    //Add the Drop plugin
    a.plug(Y.Plugin.Drop);

### Syncing the Target with the Animation

The Drop Target needs to be in sync with the animation, since we are changing the height, width, top and left style.

We do this by adding a listener to the `tween` event on the animation instance.

    //on tween of the original anim, we need to sync the drop's shim.
    a.fx.on('tween', function() {
        //Do we have an active Drag?
        if (Y.DD.DDM.activeDrag) {
            //Size this shim
            this.drop.sizeShim();
            //Force an over target check since we might not be moving the mouse.
            Y.Lang.later(0, a, function() {
                this.drop._handleTargetOver();
            });
        }
    }, a);

### Full example source

    YUI().use('dd', 'dd-plugin', 'dd-drop-plugin', 'anim', function(Y) {
        //Get the node #drag
        var d = Y.one('#drag');
        d.plug(Y.Plugin.Drag, { dragMode: 'intersect' });

        //Get all the divs with the class anim
        var anims = Y.Node.all('div.anim');
        var counter = 0;
        anims.each(function(v, k) {
            //Get a reference to the Node instance
            var a = v;
            counter++;
            //Add the FX plugin
            a.plug(Y.Plugin.NodeFX);
            //Add the Drop plugin
            a.plug(Y.Plugin.Drop);

            //Set the attributes on the animation
            a.fx.setAttrs({
                from: {
                    left: 0
                },
                to: {
                    curve: function() {
                        var points = [],
                            n = 10;

                        for (var i = 0; i < n; ++i) {
                            points.push([
                                Math.floor(Math.random()*Y.DOM.winWidth() - 60 - a.get('offsetWidth')),
                                Math.floor(Math.random()*Y.DOM.winHeight() - a.get('offsetHeight'))
                            ]);
                        }
                        return points;
                    }
                },
                //Do the animation 20 times
                iterations: 20,
                //Alternate it so it "bounces" across the screen
                direction: 'alternate',
                //Give all of them a different duration so we get different speeds.
                duration: ((counter * 1.75) + 1)
            });

            //When this drop is entered, pause the fx
            a.drop.on('drop:enter', function() {
                this.fx.pause();
            }, a);
            //When the drop is exited, run the fx again
            a.drop.on('drop:exit', function() {
                this.fx.run();
            }, a);
            //When a drop is on the node, do something special
            a.drop.on('drop:hit', function(e) {
                //Stop the animation
                this.fx.stop();
                //remove the tween listener
                this.fx.unsubscribeAll('tween');
                //move it to the dock
                this.fx.setAttrs({
                    from: {
                        opacity: 1
                    },
                    to: {
                        height: 50,
                        width: 50,
                        left: function() {
                            var dW = Y.one('body').get('viewportRegion').right;
                            return ((dW - 60)); //Minus 60 for the dock
                        },
                        top: 15,
                        opacity: .5
                    },
                    direction: 'normal',
                    iterations: 1,
                    duration: .5,
                    //We are using reverse above for the "bouncing", reset it here.
                    reverse: false
                });

                //On end, add a class and destroy the target
                this.fx.on('end', function() {
                    this.drop.get('node').addClass('done');
                    this.drop.destroy();
                }, this);
                //Run this animation
                this.fx.run();

                //others that were dropped on.
                Y.each(e.others, function(v, k) {
                    var node = v.get('node');
                    node.fx.run();
                });

            }, a);

            //on tween of the original anim, we need to sync the drop's shim.
            a.fx.on('tween', function() {
                //Do we have an active Drag?
                if (Y.DD.DDM.activeDrag) {
                    //Size this shim
                    this.drop.sizeShim();
                    //Force an over target check since we might not be moving the mouse.
                    Y.Lang.later(0, a, function() {
                        this.drop._handleTargetOver();
                    });
                }
            }, a);

            a.fx.run();
        });
    });