//Author: Ethan Atlakson
//Last Revision 10/8/2010
//multi-selectable, multi-sortable jQuery plugin
//jquery.multisortable.js
jQuery.fn.multiselectable = function(options) {
    if (!options) { options = {}; }
    options = jQuery.extend({
        click: function(event, elem) { },
		selectedClass: 'selected'
    }, options);
    return this.each(function() {
        var t = jQuery(this);

        if (!jQuery(t.children()).data('multiselectable')) {

            jQuery(t.children()).data('multiselectable', true);
            //var a = jQuery('span', t.children().children(':first-child'));
            //var b = jQuery('.descr', t.children().children(':first-child'));
            jQuery('span', t.children().children(':first-child')).click(function(e) {
                var parent = jQuery(this).parent().parent().parent();
                var myIndex = jQuery(parent.children()).index(jQuery(this).parent().parent());
                var prevIndex = jQuery(parent.children()).index(jQuery('.multiselectable-previous'));

                if (!e.ctrlKey) {jQuery('.' + options.selectedClass).removeClass(options.selectedClass); }
                if (e.shiftKey && prevIndex >= 0) {
                    jQuery('.multiselectable-previous').children(':first-child').toggleClass(options.selectedClass);
                    if (prevIndex < myIndex) {
                        jQuery(this).prevUntil('.multiselectable-previous').children(':first-child').toggleClass(options.selectedClass);
                    }
                    else {
                        jQuery(this).nextUntil('.multiselectable-previous').toggleClass(options.selectedClass);
                    }
                }
                jQuery(this).parent().toggleClass(options.selectedClass);
                jQuery('.multiselectable-previous').removeClass('multiselectable-previous');
                jQuery(this).parent().parent().addClass('multiselectable-previous');
                options.click(e, $(this));
            }).disableSelection();
            
            jQuery('.descr1', t.children().children(':first-child')).click(function(e) {
                var parent = jQuery(this).parent().parent().parent();
                var myIndex = jQuery(parent.children()).index(jQuery(this).parent().parent());
                var prevIndex = jQuery(parent.children()).index(jQuery('.multiselectable-previous'));

                if (!e.ctrlKey) {jQuery('.' + options.selectedClass).removeClass(options.selectedClass); }
                if (e.shiftKey && prevIndex >= 0) {
                    jQuery('.multiselectable-previous').children(':first-child').toggleClass(options.selectedClass);
                    if (prevIndex < myIndex) {
                        jQuery(this).prevUntil('.multiselectable-previous').children(':first-child').toggleClass(options.selectedClass);
                    }
                    else {
                        jQuery(this).nextUntil('.multiselectable-previous').toggleClass(options.selectedClass);
                    }
                }
                jQuery(this).parent().toggleClass(options.selectedClass);
                jQuery('.multiselectable-previous').removeClass('multiselectable-previous');
                jQuery(this).parent().parent().addClass('multiselectable-previous');
                options.click(e, $(this));
            }).disableSelection();
        }
    });
};

jQuery.fn.multisortable = function(options) {
    if (!options) { options = {}; }
    var settings = jQuery.extend({
        start: function(event, ui) { },
        stop: function(event, ui) { },
        sort: function(event, ui) { },
		selectedClass: 'selected',
        click: function(event, elem) { },
		placeholder: 'placeholder'
    }, options);

    return this.each(function() {
        var t = jQuery(this);
        var tagName = t.get(0).tagName;

        //enable multi-selection
        t.multiselectable({selectedClass: settings.selectedClass, click: settings.click});

        //enable sorting
        //options.cancel = tagName+':not(.'+settings.selectedClass+')';
        options.placeholder = settings.placeholder;
        options.start = function(event, ui) {
            if (ui.item.children().hasClass(settings.selectedClass)) {
                var parent = ui.item.parent();
                //assign indexes to all selected items
                jQuery('.' + settings.selectedClass).each(function(i) {
                    jQuery(this).parent().data('i', i);
                });

                // adjust placeholder size to be size of items
                //var height = jQuery('.' + settings.selectedClass, parent).length * ui.item.outerHeight();
                var height = ui.item.outerHeight();
                //jQuery('.placeholder', parent).height(height);
            }
            settings.start(event, ui);
        };

        options.stop = function(event, ui) {
            var parent = ui.item.parent();
            if (jQuery('.' + settings.selectedClass).length > 1) {
                var myIndex = ui.item.data('i');
                
                var itemsBefore =  jQuery('.' + settings.selectedClass).filter(function() {
                                        return jQuery(this).parent().data('i') < myIndex;
                                    }).parent().css('position', '');
                ui.item.before(itemsBefore);

                var itemsAfter =  jQuery('.' + settings.selectedClass).filter(function() {
                                        return jQuery(this).parent().data('i') > myIndex;
                                    }).parent().css('position', '');
                ui.item.after(itemsAfter);

                /*setTimeout(function(){
                        itemsAfter.add(itemsBefore).addClass(settings.selectedClass);                        
                    }, 0);*/
            }
            
            jQuery('.' + settings.selectedClass).each(function() {
                jQuery(this).removeClass(settings.selectedClass);
            })
            
            settings.stop(event, ui);
        };
        
        options.sort = function(event, ui) {
            var parent = ui.item.parent();
            var myIndex = ui.item.data('i');
            var top = parseInt(ui.item.css('top').replace('px', ''));
            var left = parseInt(ui.item.css('left').replace('px', ''));

            jQuery.fn.reverse = Array.prototype.reverse;
            var w = 20;
            jQuery('.' + settings.selectedClass).filter(function() {
                return jQuery(this).parent().data('i') < myIndex;
            }).reverse().each(function() {
                w += jQuery(this).parent().outerWidth();
                h += jQuery(this).parent().outerHeight();
                jQuery(this).parent().css({
                    left: left - w,
                    top: top,
                    position: 'absolute',
                    zIndex: 1000
                });
            });

            var w = ui.item.outerWidth() + 20;
            jQuery('.' + settings.selectedClass).filter(function() {
                return jQuery(this).parent().data('i') > myIndex;
            }).each(function() {
                jQuery(this).parent().css({
                    left: left + w,
                    top: top,
                    position: 'absolute',
                    zIndex: 1000
                });

                w += jQuery(this).parent().outerWidth() + 20;
            });
            settings.sort(event, ui);
        };
        
        jQuery(t).sortable(options).disableSelection();
    });
};
