Drag to Select 1.1

Created Monday 6th of April 2009 by Andreas Lagerkvist
Copyright © 2008 Andreas Lagerkvist (andreaslagerkvist.com)

Please have a look at the "Other Resources" for bug reports or further help on jQuery. Do not post bug reports or feature requests as comments to unrelated articles. If bug reporting on jquery.com fails, e-mail me.

What it Does

Use this plug-in to allow your users to select certain elements by dragging a "select box". Works very similar to how you can drag-n-select files and folders in most OS:es.

How to Use

$('#my-files').dragToSelect(selectables: 'li'); would make every li in the #my-files-element selectable by dragging. The li:s will recieve a "selected"-class when they are within range of the select box when user drops.

Make sure a parent-element of the selectables has position: relative as well as overflow: auto or scroll.

Example

  • Lamp and Mates
  • The Cottage - Winter time
  • PS2

Example Code

HTML

<div id="jquery-drag-to-select-example">
<
ul>
    <
li><img src="http://exscale.se/__files/3d/lamp-and-mates/lamp-and-mates-01_small.jpg" alt="Lamp and Mates" /></li>
    <
li><img src="http://exscale.se/__files/3d/stugan-winter_small.jpg" alt="The Cottage - Winter time" /></li>
    <
li><img src="http://exscale.se/__files/3d/ps2_small.jpg" alt="PS2" /></li>
</
ul>
</
div>

JS

$('#jquery-drag-to-select-example').dragToSelect({
    
selectables'li'
    
onHide: function () {
        
alert($('#jquery-drag-to-select-example li.selected').length ' selected');
    }
});

Source Code

jQuery.fn.dragToSelect = function (conf) {
    var 
typeof(conf) == 'object' conf : {};

    
// Config
    
var config jQuery.extend({
        
className:        'jquery-drag-to-select'
        
activeClass:    'active'
        
disabledClass:    'disabled'
        
selectedClass:    'selected'
        
scrollTH:        10
        
percentCovered:    25
        
selectables:    false
        
autoScroll:        false
        
selectOnMove:    false
        
onShow:            function () {return true;}, 
        
onHide:            function () {return true;}, 
        
onRefresh:        function () {return true;}
    }, 
c);

    var 
realParent    jQuery(this);
    var 
parent        realParent;

    do {
        if (/
auto|scroll|hidden/.test(parent.css('overflow'))) {
            break;
        }
        
parent parent.parent();
    } while (
parent[0].parentNode);

    
// Does user want to disable dragToSelect
    
if (conf == 'disable') {
        
parent.addClass(config.disabledClass);
        return 
this;
    }
    else if (
conf == 'enable') {
        
parent.removeClass(config.disabledClass);
        return 
this;
    }

    var 
parentOffset    parent.offset();
    var 
parentDim        = {
        
left:    parentOffset.left
        
top:    parentOffset.top
        
width:    parent.width(), 
        
height:    parent.height()
    };

    
// Current origin of select box
    
var selectBoxOrigin = {
        
left:    0
        
top:    0
    
};

    
// Create select box
    
var selectBox jQuery('<div/>')
                        .
appendTo(parent)
                        .
attr('class'config.className)
                        .
css('position''absolute');

    
// Shows the select box
    
var showSelectBox = function (e) {
        if (
parent.is('.' config.disabledClass)) {
            return;
        }

        
selectBoxOrigin.left    e.pageX parentDim.left parent[0].scrollLeft;
        
selectBoxOrigin.top        e.pageY parentDim.top parent[0].scrollTop;

        var 
css = {
            
left:        selectBoxOrigin.left 'px'
            
top:        selectBoxOrigin.top 'px'
            
width:        '1px'
            
height:        '1px'
        
};
        
selectBox.addClass(config.activeClass).css(css);

        
config.onShow();
    };

    
// Refreshes the select box dimensions and possibly position
    
var refreshSelectBox = function (e) {
        if (!
selectBox.is('.' config.activeClass) || parent.is('.' config.disabledClass)) {
            return;
        }

        var 
left        e.pageX parentDim.left parent[0].scrollLeft;
        var 
top            e.pageY parentDim.top parent[0].scrollTop;
        var 
newLeft        left;
        var 
newTop        top;
        var 
newWidth    selectBoxOrigin.left newLeft;
        var 
newHeight    selectBoxOrigin.top newTop;

        if (
left selectBoxOrigin.left) {
            
newLeft        selectBoxOrigin.left;
            
newWidth    left selectBoxOrigin.left;
        }

        if (
top selectBoxOrigin.top) {
            
newTop        selectBoxOrigin.top;
            
newHeight    top selectBoxOrigin.top;
        }

        var 
css = {
            
left:    newLeft 'px'
            
top:    newTop 'px'
            
width:    newWidth 'px'
            
height:    newHeight 'px'
        
};
        
selectBox.css(css);

        
config.onRefresh();
    };

    
// Hides the select box
    
var hideSelectBox = function (e) {
        if (!
selectBox.is('.' config.activeClass) || parent.is('.' config.disabledClass)) {
            return;
        }
        if (
config.onHide(selectBox) !== false) {
            
selectBox.removeClass(config.activeClass);
        }
    };

    
// Scrolls parent if needed
    
var scrollPerhaps = function (e) {
        if (!
selectBox.is('.' config.activeClass) || parent.is('.' config.disabledClass)) {
            return;
        }

        
// Scroll down
        
if ((e.pageY config.scrollTH) > (parentDim.top parentDim.height)) {
            
parent[0].scrollTop += config.scrollTH;
        }
        
// Scroll up
        
if ((e.pageY config.scrollTH) < parentDim.top) {
            
parent[0].scrollTop -= config.scrollTH;
        }
        
// Scroll right
        
if ((e.pageX config.scrollTH) > (parentDim.left parentDim.width)) {
            
parent[0].scrollLeft += config.scrollTH;
        }
        
// Scroll left
        
if ((e.pageX config.scrollTH) < parentDim.left) {
            
parent[0].scrollLeft -= config.scrollTH;
        }
    };

    
// Selects all the elements in the select box's range
    
var selectElementsInRange = function () {
        if (!
selectBox.is('.' config.activeClass) || parent.is('.' config.disabledClass)) {
            return;
        }

        var 
selectables        realParent.find(config.selectables);
        var 
selectBoxOffset    selectBox.offset();
        var 
selectBoxDim    = {
            
left:    selectBoxOffset.left
            
top:    selectBoxOffset.top
            
width:    selectBox.width(), 
            
height:    selectBox.height()
        };

        
selectables.each(function (i) {
            var 
el            = $(this);
            var 
elOffset    el.offset();
            var 
elDim        = {
                
left:    elOffset.left
                
top:    elOffset.top
                
width:    el.width(), 
                
height:    el.height()
            };

            if (
percentCovered(selectBoxDimelDim) > config.percentCovered) {
                
el.addClass(config.selectedClass);
            }
            else {
                
el.removeClass(config.selectedClass);
            }
        });
    };

    
// Returns the amount (in %) that dim1 covers dim2
    
var percentCovered = function (dim1dim2) {
        
// The whole thing is covering the whole other thing
        
if (
            (
dim1.left <= dim2.left) && 
            (
dim1.top <= dim2.top) && 
            ((
dim1.left dim1.width) >= (dim2.left dim2.width)) && 
            ((
dim1.top dim1.height) > (dim2.top dim2.height))
        ) {
            return 
100;
        }
        
// Only parts may be covered, calculate percentage
        
else {
            
dim1.right        dim1.left dim1.width;
            
dim1.bottom        dim1.top dim1.height;
            
dim2.right        dim2.left dim2.width;
            
dim2.bottom        dim2.top dim2.height;

            var 
Math.max(dim1.leftdim2.left);
            var 
Math.min(dim1.rightdim2.right);
            var 
Math.max(dim1.topdim2.top);
            var 
Math.min(dim1.bottomdim2.bottom);

            if (
>= && >= l) {
            
/*    $('<div/>').appendTo(document.body).css({
                    background:    'red', 
                    position:    'absolute',
                    left:        l + 'px', 
                    top:        t + 'px', 
                    width:        (r - l) + 'px', 
                    height:        (b - t) + 'px', 
                    zIndex:        100
                }); */

                
var percent = (((l) * (t)) / (dim2.width dim2.height)) * 100;

            
//    alert(percent + '% covered')

                
return percent;
            }
        }
        
// Nothing covered, return 0
        
return 0;
    };

    
// Do the right stuff then return this
    
selectBox
        
.mousemove(function (e) {
            
refreshSelectBox(e);

            if (
config.selectables && config.selectOnMove) {            
                
selectElementsInRange();
            }

            if (
config.autoScroll) {
                
scrollPerhaps(e);
            }

            
e.preventDefault();
        })
        .
mouseup(function(e) {
            if (
config.selectables) {            
                
selectElementsInRange();
            }

            
hideSelectBox(e);

            
e.preventDefault();
        });

    if (
jQuery.fn.disableTextSelect) {
        
parent.disableTextSelect();
    }

    
parent
        
.mousedown(function (e) {
            
// Make sure user isn't clicking scrollbar (or disallow clicks far to the right actually)
            
if ((e.pageX 20) > jQuery(document.body).width()) {
                return;
            }

            
showSelectBox(e);

            
e.preventDefault();
        })
        .
mousemove(function (e) {
            
refreshSelectBox(e);

            if (
config.selectables && config.selectOnMove) {            
                
selectElementsInRange();
            }

            if (
config.autoScroll) {
                
scrollPerhaps(e);
            }

            
e.preventDefault();
        })
        .
mouseup(function (e) {
            if (
config.selectables) {            
                
selectElementsInRange();
            }

            
hideSelectBox(e);

            
e.preventDefault();
        });

    
// Be nice
    
return this;
};

Download

Plug-in

Requires

Random jQuery Plug-ins

  • Colour Picker

    Use this plug-in on a normal <select>-element filled with colours to turn it in to a colour-picker widget that allows users to view all the colours in...

    Details

  • Ajax Loader

    Use this plug-in when you want to inform your visitors that a certain part of your page is currently loading. The plug-in adds a faded 'loading-div' o...

    Details

  • Code Block Toolbar

    If you post code-examples on your site you can use this plug-in to add some nifty buttons below each code-example that allows the user to, for example...

    Details

More Plug-ins

Recent Comments

  1. Mickodemus on "I'm In Thailand!"

    Seems splendilicious mate! I can't wait to get a d...

  2. Andreas on "aFramework's Dynamic Admin: aDynAdmin"

    Hehe, it was only a few hours work and I had code-...

  3. Bojan on "aFramework's Dynamic Admin: aDynAdmin"

    Hehe, weren't you supposed to be in thailand and n...

Page cached. Loaded in: 0.2515 second(s)