我花了大約兩週的時間處理這個問題的各種解決方案。下面的代碼在我正在構建的應用程序中爲我工作。請注意,它只處理垂直堆疊和垂直滾動的可排序項目。它可能會被修改來處理橫向排序,但是我沒有嘗試,因爲它不適合我的用例。
您可以像使用可排序的那樣使用它,只需$('。ulClass')。boundedSortable();
(function($) {
$.widget("ui.boundedSortable", $.ui.sortable, {
widgetEventPrefix: "sort",
_init: function() {
this.element.data("sortable", this.element.data("boundedSortable"));
return $.ui.sortable.prototype._init.apply(this, arguments);
},
_create:function() {
var ret = $.ui.sortable.prototype._create.apply(this, arguments);
this.containerCache.sortable = this;
return ret;
},
refreshPositions:function(fast){
$.ui.sortable.prototype.refreshPositions.apply(this, arguments);
_.each(this.items, function(item){
var element = item.item[0];
var offset = item.item.offset();
var points = [[offset.left + 1, offset.top + 1],
[offset.left + (item.width/2), offset.top + (item.height/2)],
[offset.left + item.width - 1, offset.top + 1],
[offset.left + item.width - 1, offset.top + item.height - 1]];
item.visible = _.any(points, function(point){
var visibleElement = $.elementFromPoint(point[0], point[1]);
if(element === visibleElement || (visibleElement && $.contains(element, visibleElement))){
return true;
}
return false;
});
}, this);
_.each(this.containers, function(container){
var parent = container.element;
var cache = container.containerCache;
while((parent = parent.parent()) && parent.length){
parent = $(parent);
var offset = parent.offset();
var parentHeight = parent.height();
if(cache.height > parentHeight){
cache.height = Math.round(parentHeight);
}
if(offset && cache.top < offset.top){
cache.top = offset.top;
}
}
}, this);
return this;
},
_intersectsWithPointer: function (item) {
var ret = $.ui.sortable.prototype._intersectsWithPointer.apply(this, arguments);
if(ret){
if(!item.visible){
return false;
}
}
return ret;
},
_clear: function(){
if(!(this.placeholder && this.placeholder[0].parentNode)){
this.placeholder = [{parentNode:{removeChild:function(){}}}];
this.placeholder.before = function(){};
}
return $.ui.sortable.prototype._clear.apply(this, arguments);
},
_contactContainers: function(event) {
/** directly from jQuery source **/
// get innermost container that intersects with item
var innermostContainer = null, innermostIndex = null;
for (var i = this.containers.length - 1; i >= 0; i--){
// never consider a container that's located within the item itself
if($.ui.contains(this.currentItem[0], this.containers[i].element[0])){
continue;
}
if(this._intersectsWith(this.containers[i].containerCache)) {
// if we've already found a container and it's more "inner" than this, then continue
if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0])){
continue;
}
innermostContainer = this.containers[i];
innermostIndex = i;
} else {
// container doesn't intersect. trigger "out" event if necessary
if(this.containers[i].containerCache.over) {
this.containers[i]._trigger("out", event, this._uiHash(this));
this.containers[i].containerCache.over = 0;
}
}
}
/** end direct copy from jQuery source*/
if(!innermostContainer){
if (this.placeholder) {
if(this.placeholder[0].parentNode) {
this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
}
}
this.currentContainer = null;
return;
}
return $.ui.sortable.prototype._contactContainers.apply(this, arguments);
}
});
})(jQuery);
(function ($){
var check=false, isRelative=true;
$.elementFromPoint = function(x,y)
{
var elemFromPtFunc = null;
if(document.getElementFromPoint){
elemFromPtFunc = _.bind(document.getElementFromPoint, document);
}else if(document.elementFromPoint){
elemFromPtFunc = _.bind(document.elementFromPoint, document);
}
if(!elemFromPtFunc) {
console.error('no element from point?');
return null;
}
var scrollTop = $(document).scrollTop();
var scrollLeft = $(document).scrollLeft();
return elemFromPtFunc(x - scrollLeft,y - scrollTop);
};
})(jQuery);
我相信這是一個錯誤排序將被固定在2.0 – veblock
我可能不理解的問題非常好,但你在想是這樣的:http://jsfiddle.net/W8xHh/1/ –
@ RyanOlds不幸的是,你的編輯不允許項目被丟棄。 –