Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery Sortable without jQuery UI

I am in need of "Sortable Drag & Drop" functionality and I'm using jQuery. I can't really use jQuery UI, because for this project it would be an overhead (I'd need to add many KB of JS and CSS only to use small part of functionality).

Is there any plugin that you could recommend or maybe a simple implementation path, that I can follow?

The solution must be as lightweight as possible, preferably based on jQuery/Sizzle or pure JavaScript.

like image 389
Misha Reyzlin Avatar asked Jan 11 '11 13:01

Misha Reyzlin


7 Answers

For future generations: http://dragsort.codeplex.com/

A demo: http://cleesh.org/example (couldn't find one on the development website).

Minified it comes to 9KB in size.

like image 158
Dominik Avatar answered Nov 14 '22 19:11

Dominik


You can build your own JQuery download on jqueryui.com without all the css/theme information. You can also strip out the widgets and effects and just use draggable/droppable.

Comes to about 30KB all in. Still too large?

like image 26
Chris Avatar answered Nov 14 '22 19:11

Chris


Here is another one for future generations: http://johnny.github.com/jquery-sortable/.

It's only dependency is jQuery, has a nice feature set and comes in at 8kb minified.

like image 20
p.kelly Avatar answered Nov 14 '22 18:11

p.kelly


a lot of time since this was asked, so maybe if you are thinking about an alternative to jquery UI this is a really good and easy to implement http://rubaxa.github.io/Sortable/

like image 38
ncubica Avatar answered Nov 14 '22 17:11

ncubica


If you're sure not using a customized, minified and gzipped version jQueryUI which you can maintain and update...

...maybe one of the plugins from the following blog post fits your favor:

"17 jQuery Plugins for Easy and Efficient Reordering and Filtering Page Elements" http://www.tripwiremagazine.com/2010/03/17-jquery-plugins-for-easy-and-efficient-reordering-and-filtering-page-elements.html

examples from the blogpost: "List Reorder" (<10KB) or "Sortable table rows with jQuery – Draggable rows" (<3KB)

like image 29
gabel Avatar answered Nov 14 '22 18:11

gabel


If you look at the jQuery UI source, jquery.ui.sortable.js is a separate file, which I believe depends only on jquery.ui.core.js, jquery.ui.widget.js and jquery.ui.mouse.js, although I haven't tested this. However, this still weighs in at 36KB minified.

like image 41
Michael Mior Avatar answered Nov 14 '22 19:11

Michael Mior


You can try mine (http://jsfiddle.net/606bs750/16/). Unlimited number of blocks you can drag and sort.

Blocks will constrain to the parent.

<div id="parent" class="parent">
    <button id="button1" class="button">Drag me 1</button>
    <button id="button2" class="button">Drag me 2</button>
    <button id="button3" class="button">Drag me 3</button>
    <button id="button4" class="button">Drag me 4</button>
</div>

JQuery (only):

$(function() {
    $('.button').mousedown(function(e) {
        if(e.which===1) {
            var button = $(this);
            var button_id = button.attr('id');
            var parent_height = button.parent().innerHeight();
            var top = parseInt(button.css('top'));
            var original_ypos = button.position().top; //original ypos
            var drag_min_ypos = 0-original_ypos;
            var drag_max_ypos = parent_height-original_ypos-button.outerHeight();
            var drag_start_ypos = e.clientY;
            var my_ypos = original_ypos;
            //Set current order for all
            $('.button').each(function(i) { $(this).attr('data-order',(i+1)); });
            var prev_button = button.prev('.button'); var next_button = button.next('.button');
            var prev_button_ypos = prev_button.length>0 ? prev_button.position().top : '';
            var next_button_ypos = next_button.length>0 ? next_button.position().top : '';
            $('#log1').text('mousedown '+button_id+' original_ypos: '+original_ypos);
            $('#log2').text('');
            $('#log3').text('');
            $(window).on('mousemove',function(e) {
                //Move and constrain
                button.addClass('drag');
                var direction = my_ypos>button.position().top ? 'up' : 'down';
                var new_top = top+(e.clientY-drag_start_ypos);
                my_ypos = button.position().top;
                button.css({top:new_top+'px'});
                if(new_top<drag_min_ypos) { button.css({top:drag_min_ypos+'px'}); }
                if(new_top>drag_max_ypos) { button.css({top:drag_max_ypos+'px'}); }
                $('#log2').text('mousemove new_top: '+new_top+', my_ypos: '+my_ypos+', direction: '+direction);
                //$('#log3').text('');
                //Check position over others
                if(direction=='down'&&next_button_ypos!='') {
                    if(my_ypos>next_button_ypos) { //crossed next button
                        $('#log3').text('dragged after '+next_button_ypos+' ('+next_button.attr('id')+')');
                        next_button.css({top:(parseInt(next_button.css('top'))-next_button.outerHeight(true))+'px'}); //up once
                        var tmp_order = next_button.attr('data-order');
                        next_button.attr('data-order',button.attr('data-order')); //switch order
                        button.attr('data-order',tmp_order);
                        prev_button = next_button; next_button = next_button.nextAll('.button:not(.drag)').first();
                        prev_button_ypos = prev_button.length>0 ? prev_button.position().top : '';
                        next_button_ypos = next_button.length>0 ? next_button.position().top : '';
                    }
                } else if(direction=='up'&&prev_button_ypos!='') {
                    if(my_ypos<prev_button_ypos) { //crossed prev button
                        $('#log3').text('dragged before '+prev_button_ypos+', '+prev_button.attr('id'));
                        prev_button.css({top:(parseInt(prev_button.css('top'))+prev_button.outerHeight(true))+'px'}); //down once
                        var tmp_order = prev_button.attr('data-order');
                        prev_button.attr('data-order',button.attr('data-order')); //switch order
                        button.attr('data-order',tmp_order);
                        next_button = prev_button; prev_button = prev_button.prevAll('.button:not(.drag)').first();
                        prev_button_ypos = prev_button.length>0 ? prev_button.position().top : '';
                        next_button_ypos = next_button.length>0 ? next_button.position().top : '';
                    }
                }
                $('#log4').text('prev_button_ypos: '+prev_button_ypos+' ('+prev_button.attr('id')+'), next_button_ypos: '+next_button_ypos+' ('+next_button.attr('id')+')');
            });
            $(window).on('mouseup',function(e) {
                 if(e.which===1) {
                    $('.button').removeClass('drag');
                    $(window).off('mouseup mousemove');
                    //Reorder and reposition all
                    $('.button').each(function() {
                        var this_order = parseInt($(this).attr('data-order'));
                        var prev_order = $(this).siblings('.button[data-order="'+(this_order-1)+'"]');
                        if(prev_order.length>0) { $(this).insertAfter(prev_order); }
                    });
                    $('.button').css('top','0'); $('.button').removeAttr('data-order'); //reset
                    $('#log1').text('mouseup');
                    $('#log2').text('');
                    $('#log3').text('');
                    $('#log4').text('');
                 }
            });
        }
    });
});
like image 37
Richard Avatar answered Nov 14 '22 19:11

Richard