NewsBlur/media/js/jquery.nestedSortable.js
2010-04-13 16:33:43 -04:00

99 lines
No EOL
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

$.fn.nestedSortable = function(options) {
var settings = $.extend({
nestable: 'li',
container: 'ul',
indent: 30,
handle: null,
opacity: 1,
placeholderClass: 'placeholder',
appendTo: 'parent',
start: function() {},
stop: function() {},
drag: function() {}
}, options);
settings.snapTolerance = settings.indent * 0.4;
this.each(function() {
// The top level nestable list container
var root = $(this);
// Placed to preview the location of the dragged element
var placeholder = $('<div class="' + settings.placeholderClass + '"></div>');
// Use the onmouse over live event in order to bind to nestables as they are created
root.find(settings.nestable).live("mouseover", function() {
if (!$(this).data("nestable")) {
$(this).draggable({
opacity: settings.opacity,
handle: settings.handle,
appendTo: settings.appendTo,
helper: function() {
// Create a helper that is a clone of the original (with a few little tweaks)
return $(this).clone().width($(this).width()).addClass("helper");
},
start: function() {
// Hide the original and initialize the placeholder ontop of the starting position
$(this).hide().after(placeholder);
// Run a custom start function specitifed in the settings
settings.start.apply(this);
},
stop: function(event, ui) {
// Replace the placeholder with the original
placeholder.after($(this).show()).remove();
// Run a custom stop function specitifed in the settings
settings.stop.apply(this);
},
drag: function (event, ui) {
// Find the nestable item underneath the helper being dragged
var largestY = 0;
var underItems = $.grep(root.find(settings.nestable), function(item) {
// Is the item being checked underneath the one being dragged?
if(!(($(item).offset().top < ui.position.top) && ($(item).offset().top > largestY))) {
return false;
}
// Is the item being checked on the same nesting level as the dragged item?
if ($(item).offset().left - settings.snapTolerance >= ui.position.left) {
return false;
}
// Make sure the itme being checked is not part of the helper
if (ui.helper.find($(item)).length) {
return false;
}
// If we've got this far, its a match
largestY = $(item).offset().top;
return true;
});
var underItem = underItems.length ? $(underItems.pop()) : null;
// Position the placeholder if appropriate
if (underItem !== null) {
// Should the dragged item be nested
if (underItem.offset().left + settings.indent settings.snapTolerance < ui.position.left) {
underItem.children(settings.container).prepend(placeholder);
} else {
underItem.after(placeholder);
}
// If there is no item underneath, it still might be over the very first list item
} else {
var firstItem = root.find(settings.nestable + ":first");
if ((firstItem.offset().top < ui.position.top + $(this).height()) && (firstItem.offset().top > ui.position.top)) {
firstItem.closest(settings.container).prepend(placeholder);
}
}
// Run a custom drag function specitifed in the settings
settings.drag.apply(this);
}
}).data("nestable", true);
}
});
});
return this;
};