YUI 3.x Home -

Site Search (YDN & YUIBlog):

# YUI Library Examples: Drag & Drop: Animated Drop Targets

## Drag & Drop: 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>

    <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>

<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.yui-dd-drop-over {    background-color: #EDFF9F;}.anim.done {    background-color: white;}#drag1.yui-dd-drag-over {    opacity: .5;    filter: alpha(opacity=50);}

    .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.yui-dd-drop-over {
        background-color: #EDFF9F;
    }
    .anim.done {
        background-color: white;
    }
    #drag1.yui-dd-drag-over {
        opacity: .5;
        filter: alpha(opacity=50);
    }

.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.yui-dd-drop-over { background-color: #EDFF9F; } .anim.done { background-color: white; } #drag1.yui-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');

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

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.Node.get('#drag');    d.plug(Y.Plugin.Drag, { dragMode: 'intersect' });});

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

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

### Animating the Nodes

Now we will setup 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)        });    });

        //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)
            });
        });

//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 plugina.plug(Y.Plugin.NodeFX);//Add the Drop plugina.plug(Y.Plugin.Drop);

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

//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);

    //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);

//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-drop', 'anim', 'dd-plugin', 'dd-drop-plugin', function(Y) {    //Get the node #drag    var d = Y.Node.get('#drag');    d.plug(Y.plugin.Drag, { dragMode: 'intersect' });     //Get all the div's 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;         //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.Node.get('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();    });});

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

        //Get all the div's 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;
            //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.Node.get('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();
        });
    });

YUI().use('dd-drop', 'anim', 'dd-plugin', 'dd-drop-plugin', function(Y) { //Get the node #drag var d = Y.Node.get('#drag'); d.plug(Y.plugin.Drag, { dragMode: 'intersect' }); //Get all the div's 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; //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.Node.get('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(); }); });

Copyright © 2009 Yahoo! Inc. All rights reserved.

Privacy Policy - Terms of Service - Copyright Policy - Job Openings