YUI 3.x Home -

Site Search (YDN & YUIBlog):

# YUI Library Examples: Drag & Drop: Photo Browser

## Drag & Drop: Photo Browser

Photo Browser built with YUI3 and YQL. This example was part of the YUI3 presentation by Dav Glass at Open Hack : London

View example in new window.

### YQL

This example uses the YQL YUI3 plugin: http://github.com/davglass/yui-yql

Here is the Flickr YQL query used in this example.

    SELECT * FROM flickr.photos.search(100) WHERE    (text="openhacklondon")    AND (safe_search = 1)    AND (media = "photos")    AND (extras = "o_dims")    AND (       (o_width = "1600" AND o_height = "1200")     OR (o_width = "1200" AND o_height = "1600")     OR (o_width = "800" AND o_height = "600")   )

    SELECT * FROM flickr.photos.search(100) WHERE
       (text="openhacklondon")
       AND (safe_search = 1)
       AND (media = "photos")
       AND (extras = "o_dims")
       AND (
           (o_width = "1600" AND o_height = "1200")
         OR (o_width = "1200" AND o_height = "1600")
         OR (o_width = "800" AND o_height = "600")
       )

SELECT * FROM flickr.photos.search(100) WHERE (text="openhacklondon") AND (safe_search = 1) AND (media = "photos") AND (extras = "o_dims") AND ( (o_width = "1600" AND o_height = "1200") OR (o_width = "1200" AND o_height = "1600") OR (o_width = "800" AND o_height = "600") )

### Slider and StyleSheet

In this example, we will use the Slider control to dynamically manipulate a CSS Style Rule.

First, we need to create the slider and render it.

    //Create and render the slidervar sl = new Y.Slider({    railSize: '200px', value: 40, max: 70, min: 5,    thumbImage: assetsDir + 'css/thumb-classic-x.png'}).render('.horiz_slider');

    //Create and render the slider
    var sl = new Y.Slider({
        railSize: '200px', value: 40, max: 70, min: 5,
        thumbImage: assetsDir + 'css/thumb-classic-x.png'
    }).render('.horiz_slider');

//Create and render the slider var sl = new Y.Slider({ railSize: '200px', value: 40, max: 70, min: 5, thumbImage: assetsDir + 'css/thumb-classic-x.png' }).render('.horiz_slider');

Now, we listen for the Slider's `valueChange` event. This event is fired when the value of the Slider has changed.

Next we use the StyleSheet utility to dynamically change a style rule to resize the images. The style rule that we want to change is `#yui-main .yui-g ul li`. When the Slider's value changes, we will take the value and divide it by 2, then use that as the percentage width of the li. This will give us the effect we want (resizing images) without touching all the images via the DOM.

    //Listen for the changesl.after('valueChange',function (e) {    //Insert a dynamic stylesheet rule:    var sheet = new Y.StyleSheet('image_slider');    sheet.set('#yui-main .yui-g ul li', {        width: (e.newVal / 2) + '%'    });});

    //Listen for the change
    sl.after('valueChange',function (e) {
        //Insert a dynamic stylesheet rule:
        var sheet = new Y.StyleSheet('image_slider');
        sheet.set('#yui-main .yui-g ul li', {
            width: (e.newVal / 2) + '%'
        });
    });

//Listen for the change sl.after('valueChange',function (e) { //Insert a dynamic stylesheet rule: var sheet = new Y.StyleSheet('image_slider'); sheet.set('#yui-main .yui-g ul li', { width: (e.newVal / 2) + '%' }); });

### Event Delegation

This listener listens for all `mouseup` events on the `document` and it will only fire when the target element matches the `*` selector (which should be all elements).

This way we can remove all the `selected` CSS classes from all the images in the browser when a `mouseup` occurs, only if the shift key was not pressed. We can then check to determine if the mouseup came from one of the images. If it has, add the selected class back to it.

    //Listen for all mouseups on the document (selecting/deselecting images)Y.on('delegate', function(e) {    if (!e.shiftKey) {        //No shift key - remove all selected images        wrapper.queryAll('img.selected').removeClass('selected');    }    //Check if the target is an image and select it.    if (e.target.test('#yui-main .yui-g ul li img')) {        e.target.addClass('selected');    }}, document, 'mouseup', '*');

    //Listen for all mouseups on the document (selecting/deselecting images)
    Y.on('delegate', function(e) {
        if (!e.shiftKey) {
            //No shift key - remove all selected images
            wrapper.queryAll('img.selected').removeClass('selected');
        }
        //Check if the target is an image and select it.
        if (e.target.test('#yui-main .yui-g ul li img')) {
            e.target.addClass('selected');
        }
    }, document, 'mouseup', '*');

//Listen for all mouseups on the document (selecting/deselecting images) Y.on('delegate', function(e) { if (!e.shiftKey) { //No shift key - remove all selected images wrapper.queryAll('img.selected').removeClass('selected'); } //Check if the target is an image and select it. if (e.target.test('#yui-main .yui-g ul li img')) { e.target.addClass('selected'); } }, document, 'mouseup', '*');

This listener, listens for all `click` events on the album list `#photoList li`. First, it stops the click, so the href is not followed. Next, it removes all the `selected` classes from the list. Then, it adds the `selected` class to the item that was clicked on.

After that UI setup, it uses Selectors to change the view of the images in the browser. First, it checks if we are viewing "all" or a "sub album". If all is selected, it removes the `hidden` class from all the images. If it was an album, it adds the `hidden` class to all the images, then selects all the images with the class of its `id`, then it removes the hidden class from them.

Basically, it hides all the images, then determines the ones it needs to show and removes the `hidden` class from them.

    //Listen for all clicks on the '#photoList li' selectorY.on('delegate', function(e) {    //Prevent the click    e.halt();    //Remove all the selected items    e.currentTarget.get('parentNode').queryAll('li.selected').removeClass('selected');    //Add the selected class to the one that one clicked    e.currentTarget.addClass('selected');    //The "All Photos" link was clicked    if (e.currentTarget.hasClass('all')) {        //Remove all the hidden classes        wrapper.queryAll('li').removeClass('hidden');    } else {        //Another "album" was clicked, get its id        var c = e.target.get('id');        //Hide all items by adding the hidden class        wrapper.queryAll('li').addClass('hidden');        //Now, find all the items with the class name the same as the album id        //and remove the hidden class        wrapper.queryAll('li.' + c).removeClass('hidden');    }}, document, 'click', '#photoList li');

    //Listen for all clicks on the '#photoList li' selector
    Y.on('delegate', function(e) {
        //Prevent the click
        e.halt();
        //Remove all the selected items
        e.currentTarget.get('parentNode').queryAll('li.selected').removeClass('selected');
        //Add the selected class to the one that one clicked
        e.currentTarget.addClass('selected');
        //The "All Photos" link was clicked
        if (e.currentTarget.hasClass('all')) {
            //Remove all the hidden classes
            wrapper.queryAll('li').removeClass('hidden');
        } else {
            //Another "album" was clicked, get its id
            var c = e.target.get('id');
            //Hide all items by adding the hidden class
            wrapper.queryAll('li').addClass('hidden');
            //Now, find all the items with the class name the same as the album id
            //and remove the hidden class
            wrapper.queryAll('li.' + c).removeClass('hidden');
        }
    }, document, 'click', '#photoList li');

//Listen for all clicks on the '#photoList li' selector Y.on('delegate', function(e) { //Prevent the click e.halt(); //Remove all the selected items e.currentTarget.get('parentNode').queryAll('li.selected').removeClass('selected'); //Add the selected class to the one that one clicked e.currentTarget.addClass('selected'); //The "All Photos" link was clicked if (e.currentTarget.hasClass('all')) { //Remove all the hidden classes wrapper.queryAll('li').removeClass('hidden'); } else { //Another "album" was clicked, get its id var c = e.target.get('id'); //Hide all items by adding the hidden class wrapper.queryAll('li').addClass('hidden'); //Now, find all the items with the class name the same as the album id //and remove the hidden class wrapper.queryAll('li.' + c).removeClass('hidden'); } }, document, 'click', '#photoList li');

### Full Source

Here is the full commented JavaScript source for this example.

    YUI().use('node', 'anim', 'dd', 'yql', 'slider', 'stylesheet', function(Y) {    //Get a reference to the wrapper to use later and add a loading class to it.    var wrapper = Y.get('#yui-main .yui-g ul').addClass('loading');    //Set its height to the height of the viewport so we can scroll it.    wrapper.setStyle('height', (wrapper.get('winHeight') - 50 )+ 'px');    Y.on('windowresize', function() { wrapper.setStyle('height', (wrapper.get('winHeight') - 50 )+ 'px'); });    //Make the YQL query.    new Y.yql('select * from flickr.photos.search(100) where text="openhacklondon" and safe_search = 1 and media = "photos" and extras = "o_dims" and ((o_width = "1600" and o_height = "1200") or (o_width = "1200" and o_height = "1600") or (o_width = "800" and o_height = "600") or (o_width = "600" and o_height = "800"))', function(e) {        if (e.query) {            var photos = e.query.results.photo;            //Walk the returned photos array            Y.each(photos, function(v, k) {                //Create our URL                var url = 'http:/'+'/static.flickr.com/' + v.server + '/' + v.id + '_' + v.secret + '_m.jpg',                    //Create the image and the LI                    li = Y.Node.create('<li class="loading"><img src="' + url + '" title="' + v.title + '"></li>'),                    //Get the image from the LI                    img = li.get('firstChild');                //Append the li to the wrapper                wrapper.appendChild(li);                //This little hack moves the tall images to the bottom of the list                //So they float better ;)                img.on('load', function() {                    //Is the height longer than the width?                    var c = ((this.get('height') > this.get('width')) ? 'tall' : 'wide');                    this.addClass(c);                    if (c === 'tall') {                        //Move it to the end of the list.                        this.get('parentNode.parentNode').removeChild(this.get('parentNode'));                        wrapper.appendChild(this.get('parentNode'));                    }                    this.get('parentNode').removeClass('loading');                });            });            //Get all the newly added li's            wrapper.queryAll('li').each(function(node) {                //Plugin the Drag plugin                this.plug(Y.Plugin.Drag, {                    offsetNode: false                });                //Plug the Proxy into the DD object                this.dd.plug(Y.Plugin.DDProxy, {                    resizeFrame: false,                    moveOnEnd: false,                    borderStyle: 'none'                });            });            //Create and render the slider            var sl = new Y.Slider({                railSize: '200px', value: 40, max: 70, min: 5,                thumbImage: assetsDir + 'css/thumb-classic-x.png'            }).render('.horiz_slider');            //Listen for the change            sl.after('valueChange',function (e) {                //Insert a dynamic stylesheet rule                var sheet = new Y.StyleSheet('image_slider');                sheet.set('#yui-main .yui-g ul li', {                    width: (e.newVal / 2) + '%'                });            });            //Remove the DDM as a bubble target..            sl._dd.removeTarget(Y.DD.DDM);            //Remove the wrappers loading class            wrapper.removeClass('loading');            Y.get('#ft').removeClass('loading');        }    });    //Listen for all mouseups on the document (selecting/deselecting images)    Y.on('delegate', function(e) {        if (!e.shiftKey) {            //No shift key - remove all selected images            wrapper.queryAll('img.selected').removeClass('selected');        }        //Check if the target is an image and select it.        if (e.target.test('#yui-main .yui-g ul li img')) {            e.target.addClass('selected');        }    }, document, 'mouseup', '*');        //Listen for all clicks on the '#photoList li' selector    Y.on('delegate', function(e) {        //Prevent the click        e.halt();        //Remove all the selected items        e.currentTarget.get('parentNode').queryAll('li.selected').removeClass('selected');        //Add the selected class to the one that one clicked        e.currentTarget.addClass('selected');        //The "All Photos" link was clicked        if (e.currentTarget.hasClass('all')) {            //Remove all the hidden classes            wrapper.queryAll('li').removeClass('hidden');        } else {            //Another "album" was clicked, get its id            var c = e.currentTarget.get('id');            //Hide all items by adding the hidden class            wrapper.queryAll('li').addClass('hidden');            //Now, find all the items with the class name the same as the album id            //and remove the hidden class            wrapper.queryAll('li.' + c).removeClass('hidden');        }    }, document, 'click', '#photoList li');    //Stop the drag with the escape key    Y.get(document).on('keypress', function(e) {        //The escape key was pressed        if ((e.keyCode === 27) || (e.charCode === 27)) {            //We have an active Drag            if (Y.DD.DDM.activeDrag) {                //Stop the drag                Y.DD.DDM.activeDrag.stopDrag();            }        }    });    //On the drag:mouseDown add the selected class    Y.DD.DDM.on('drag:mouseDown', function(e) {        e.target.get('node').queryAll('img').addClass('selected');    });    //On drag start, get all the selected elements    //Add the count to the proxy element and offset it to the cursor.    Y.DD.DDM.on('drag:start', function(e) {        //How many items are selected        var count = wrapper.queryAll('img.selected').size();        //Set the style on the proxy node        e.target.get('dragNode').setStyles({            height: '25px', width: '25px'        }).set('innerHTML', '<span>' + count + '</span>');        //Offset the dragNode        e.target.deltaXY = [25, 5];    });    //We dropped on a drop target    Y.DD.DDM.on('drag:drophit', function(e) {        //get the images that are selected.        var imgs = wrapper.queryAll('img.selected'),            //The xy position of the item we dropped on            toXY = e.drop.get('node').getXY();         imgs.each(function(node) {            //Clone the image, position it on top of the original and animate it to the drop target            node.get('parentNode').addClass(e.drop.get('node').get('id'));            var n = node.cloneNode().set('id', '').setStyle('position', 'absolute');            Y.get('body').appendChild(n);            n.setXY(node.getXY());            new Y.Anim({                node: n,                to: {                    height: 20, width: 20, opacity: 0,                    top: toXY[1], left: toXY[0]                },                from: {                    width: node.get('offsetWidth'),                    height: node.get('offsetHeight')                },                duration: .5            }).run();        });        //Update the count        var count = wrapper.queryAll('li.' + e.drop.get('node').get('id')).size();        e.drop.get('node').query('span').set('innerHTML', '(' + count + ')');    });    //Add drop support to the albums    Y.all('#photoList li').each(function(node) {        if (!node.hasClass('all')) {            //make all albums Drop Targets except the all photos.            node.plug(Y.Plugin.Drop);        }    });});

    YUI().use('node', 'anim', 'dd', 'yql', 'slider', 'stylesheet', function(Y) {
        //Get a reference to the wrapper to use later and add a loading class to it.
        var wrapper = Y.get('#yui-main .yui-g ul').addClass('loading');
        //Set its height to the height of the viewport so we can scroll it.
        wrapper.setStyle('height', (wrapper.get('winHeight') - 50 )+ 'px');
        Y.on('windowresize', function() { wrapper.setStyle('height', (wrapper.get('winHeight') - 50 )+ 'px'); });
        //Make the YQL query.
        new Y.yql('select * from flickr.photos.search(100) where text="openhacklondon" and safe_search = 1 and media = "photos" and extras = "o_dims" and ((o_width = "1600" and o_height = "1200") or (o_width = "1200" and o_height = "1600") or (o_width = "800" and o_height = "600") or (o_width = "600" and o_height = "800"))', function(e) {
            if (e.query) {
                var photos = e.query.results.photo;
                //Walk the returned photos array
                Y.each(photos, function(v, k) {
                    //Create our URL
                    var url = 'http:/'+'/static.flickr.com/' + v.server + '/' + v.id + '_' + v.secret + '_m.jpg',
                        //Create the image and the LI
                        li = Y.Node.create('<li class="loading"><img src="' + url + '" title="' + v.title + '"></li>'),
                        //Get the image from the LI
                        img = li.get('firstChild');
                    //Append the li to the wrapper
                    wrapper.appendChild(li);
                    //This little hack moves the tall images to the bottom of the list
                    //So they float better ;)
                    img.on('load', function() {
                        //Is the height longer than the width?
                        var c = ((this.get('height') > this.get('width')) ? 'tall' : 'wide');
                        this.addClass(c);
                        if (c === 'tall') {
                            //Move it to the end of the list.
                            this.get('parentNode.parentNode').removeChild(this.get('parentNode'));
                            wrapper.appendChild(this.get('parentNode'));
                        }
                        this.get('parentNode').removeClass('loading');
                    });
                });
                //Get all the newly added li's
                wrapper.queryAll('li').each(function(node) {
                    //Plugin the Drag plugin
                    this.plug(Y.Plugin.Drag, {
                        offsetNode: false
                    });
                    //Plug the Proxy into the DD object
                    this.dd.plug(Y.Plugin.DDProxy, {
                        resizeFrame: false,
                        moveOnEnd: false,
                        borderStyle: 'none'
                    });
                });
                //Create and render the slider
                var sl = new Y.Slider({
                    railSize: '200px', value: 40, max: 70, min: 5,
                    thumbImage: assetsDir + 'css/thumb-classic-x.png'
                }).render('.horiz_slider');
                //Listen for the change
                sl.after('valueChange',function (e) {
                    //Insert a dynamic stylesheet rule
                    var sheet = new Y.StyleSheet('image_slider');
                    sheet.set('#yui-main .yui-g ul li', {
                        width: (e.newVal / 2) + '%'
                    });
                });
                //Remove the DDM as a bubble target..
                sl._dd.removeTarget(Y.DD.DDM);
                //Remove the wrappers loading class
                wrapper.removeClass('loading');
                Y.get('#ft').removeClass('loading');
            }
        });
        //Listen for all mouseups on the document (selecting/deselecting images)
        Y.on('delegate', function(e) {
            if (!e.shiftKey) {
                //No shift key - remove all selected images
                wrapper.queryAll('img.selected').removeClass('selected');
            }
            //Check if the target is an image and select it.
            if (e.target.test('#yui-main .yui-g ul li img')) {
                e.target.addClass('selected');
            }
        }, document, 'mouseup', '*');
        //Listen for all clicks on the '#photoList li' selector
        Y.on('delegate', function(e) {
            //Prevent the click
            e.halt();
            //Remove all the selected items
            e.currentTarget.get('parentNode').queryAll('li.selected').removeClass('selected');
            //Add the selected class to the one that one clicked
            e.currentTarget.addClass('selected');
            //The "All Photos" link was clicked
            if (e.currentTarget.hasClass('all')) {
                //Remove all the hidden classes
                wrapper.queryAll('li').removeClass('hidden');
            } else {
                //Another "album" was clicked, get its id
                var c = e.currentTarget.get('id');
                //Hide all items by adding the hidden class
                wrapper.queryAll('li').addClass('hidden');
                //Now, find all the items with the class name the same as the album id
                //and remove the hidden class
                wrapper.queryAll('li.' + c).removeClass('hidden');
            }
        }, document, 'click', '#photoList li');
        //Stop the drag with the escape key
        Y.get(document).on('keypress', function(e) {
            //The escape key was pressed
            if ((e.keyCode === 27) || (e.charCode === 27)) {
                //We have an active Drag
                if (Y.DD.DDM.activeDrag) {
                    //Stop the drag
                    Y.DD.DDM.activeDrag.stopDrag();
                }
            }
        });
        //On the drag:mouseDown add the selected class
        Y.DD.DDM.on('drag:mouseDown', function(e) {
            e.target.get('node').queryAll('img').addClass('selected');
        });
        //On drag start, get all the selected elements
        //Add the count to the proxy element and offset it to the cursor.
        Y.DD.DDM.on('drag:start', function(e) {
            //How many items are selected
            var count = wrapper.queryAll('img.selected').size();
            //Set the style on the proxy node
            e.target.get('dragNode').setStyles({
                height: '25px', width: '25px'
            }).set('innerHTML', '<span>' + count + '</span>');
            //Offset the dragNode
            e.target.deltaXY = [25, 5];
        });
        //We dropped on a drop target
        Y.DD.DDM.on('drag:drophit', function(e) {
            //get the images that are selected.
            var imgs = wrapper.queryAll('img.selected'),
                //The xy position of the item we dropped on
                toXY = e.drop.get('node').getXY();

            imgs.each(function(node) {
                //Clone the image, position it on top of the original and animate it to the drop target
                node.get('parentNode').addClass(e.drop.get('node').get('id'));
                var n = node.cloneNode().set('id', '').setStyle('position', 'absolute');
                Y.get('body').appendChild(n);
                n.setXY(node.getXY());
                new Y.Anim({
                    node: n,
                    to: {
                        height: 20, width: 20, opacity: 0,
                        top: toXY[1], left: toXY[0]
                    },
                    from: {
                        width: node.get('offsetWidth'),
                        height: node.get('offsetHeight')
                    },
                    duration: .5
                }).run();
            });
            //Update the count
            var count = wrapper.queryAll('li.' + e.drop.get('node').get('id')).size();
            e.drop.get('node').query('span').set('innerHTML', '(' + count + ')');
        });
        //Add drop support to the albums
        Y.all('#photoList li').each(function(node) {
            if (!node.hasClass('all')) {
                //make all albums Drop Targets except the all photos.
                node.plug(Y.Plugin.Drop);
            }
        });
    });

YUI().use('node', 'anim', 'dd', 'yql', 'slider', 'stylesheet', function(Y) { //Get a reference to the wrapper to use later and add a loading class to it. var wrapper = Y.get('#yui-main .yui-g ul').addClass('loading'); //Set its height to the height of the viewport so we can scroll it. wrapper.setStyle('height', (wrapper.get('winHeight') - 50 )+ 'px'); Y.on('windowresize', function() { wrapper.setStyle('height', (wrapper.get('winHeight') - 50 )+ 'px'); }); //Make the YQL query. new Y.yql('select * from flickr.photos.search(100) where text="openhacklondon" and safe_search = 1 and media = "photos" and extras = "o_dims" and ((o_width = "1600" and o_height = "1200") or (o_width = "1200" and o_height = "1600") or (o_width = "800" and o_height = "600") or (o_width = "600" and o_height = "800"))', function(e) { if (e.query) { var photos = e.query.results.photo; //Walk the returned photos array Y.each(photos, function(v, k) { //Create our URL var url = 'http:/'+'/static.flickr.com/' + v.server + '/' + v.id + '_' + v.secret + '_m.jpg', //Create the image and the LI li = Y.Node.create('<li class="loading"><img src="' + url + '" title="' + v.title + '"></li>'), //Get the image from the LI img = li.get('firstChild'); //Append the li to the wrapper wrapper.appendChild(li); //This little hack moves the tall images to the bottom of the list //So they float better ;) img.on('load', function() { //Is the height longer than the width? var c = ((this.get('height') > this.get('width')) ? 'tall' : 'wide'); this.addClass(c); if (c === 'tall') { //Move it to the end of the list. this.get('parentNode.parentNode').removeChild(this.get('parentNode')); wrapper.appendChild(this.get('parentNode')); } this.get('parentNode').removeClass('loading'); }); }); //Get all the newly added li's wrapper.queryAll('li').each(function(node) { //Plugin the Drag plugin this.plug(Y.Plugin.Drag, { offsetNode: false }); //Plug the Proxy into the DD object this.dd.plug(Y.Plugin.DDProxy, { resizeFrame: false, moveOnEnd: false, borderStyle: 'none' }); }); //Create and render the slider var sl = new Y.Slider({ railSize: '200px', value: 40, max: 70, min: 5, thumbImage: assetsDir + 'css/thumb-classic-x.png' }).render('.horiz_slider'); //Listen for the change sl.after('valueChange',function (e) { //Insert a dynamic stylesheet rule var sheet = new Y.StyleSheet('image_slider'); sheet.set('#yui-main .yui-g ul li', { width: (e.newVal / 2) + '%' }); }); //Remove the DDM as a bubble target.. sl._dd.removeTarget(Y.DD.DDM); //Remove the wrappers loading class wrapper.removeClass('loading'); Y.get('#ft').removeClass('loading'); } }); //Listen for all mouseups on the document (selecting/deselecting images) Y.on('delegate', function(e) { if (!e.shiftKey) { //No shift key - remove all selected images wrapper.queryAll('img.selected').removeClass('selected'); } //Check if the target is an image and select it. if (e.target.test('#yui-main .yui-g ul li img')) { e.target.addClass('selected'); } }, document, 'mouseup', '*'); //Listen for all clicks on the '#photoList li' selector Y.on('delegate', function(e) { //Prevent the click e.halt(); //Remove all the selected items e.currentTarget.get('parentNode').queryAll('li.selected').removeClass('selected'); //Add the selected class to the one that one clicked e.currentTarget.addClass('selected'); //The "All Photos" link was clicked if (e.currentTarget.hasClass('all')) { //Remove all the hidden classes wrapper.queryAll('li').removeClass('hidden'); } else { //Another "album" was clicked, get its id var c = e.currentTarget.get('id'); //Hide all items by adding the hidden class wrapper.queryAll('li').addClass('hidden'); //Now, find all the items with the class name the same as the album id //and remove the hidden class wrapper.queryAll('li.' + c).removeClass('hidden'); } }, document, 'click', '#photoList li'); //Stop the drag with the escape key Y.get(document).on('keypress', function(e) { //The escape key was pressed if ((e.keyCode === 27) || (e.charCode === 27)) { //We have an active Drag if (Y.DD.DDM.activeDrag) { //Stop the drag Y.DD.DDM.activeDrag.stopDrag(); } } }); //On the drag:mouseDown add the selected class Y.DD.DDM.on('drag:mouseDown', function(e) { e.target.get('node').queryAll('img').addClass('selected'); }); //On drag start, get all the selected elements //Add the count to the proxy element and offset it to the cursor. Y.DD.DDM.on('drag:start', function(e) { //How many items are selected var count = wrapper.queryAll('img.selected').size(); //Set the style on the proxy node e.target.get('dragNode').setStyles({ height: '25px', width: '25px' }).set('innerHTML', '<span>' + count + '</span>'); //Offset the dragNode e.target.deltaXY = [25, 5]; }); //We dropped on a drop target Y.DD.DDM.on('drag:drophit', function(e) { //get the images that are selected. var imgs = wrapper.queryAll('img.selected'), //The xy position of the item we dropped on toXY = e.drop.get('node').getXY(); imgs.each(function(node) { //Clone the image, position it on top of the original and animate it to the drop target node.get('parentNode').addClass(e.drop.get('node').get('id')); var n = node.cloneNode().set('id', '').setStyle('position', 'absolute'); Y.get('body').appendChild(n); n.setXY(node.getXY()); new Y.Anim({ node: n, to: { height: 20, width: 20, opacity: 0, top: toXY[1], left: toXY[0] }, from: { width: node.get('offsetWidth'), height: node.get('offsetHeight') }, duration: .5 }).run(); }); //Update the count var count = wrapper.queryAll('li.' + e.drop.get('node').get('id')).size(); e.drop.get('node').query('span').set('innerHTML', '(' + count + ')'); }); //Add drop support to the albums Y.all('#photoList li').each(function(node) { if (!node.hasClass('all')) { //make all albums Drop Targets except the all photos. node.plug(Y.Plugin.Drop); } }); });

Copyright © 2009 Yahoo! Inc. All rights reserved.

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