$.widget('custom.sortableGrid', $.ui.sortable, { // A Hack of the base code so it puts the place holder in the right place
_onRightSide: function(item, event){
return this._isOverAxis(
event.pageX,
item.left + (item.width/2),
item.width/2
);
},
_intersectsWithPointer: function(item) {
var verticalDirection, horizontalDirection,
isOverElementHeight = (this.options.axis === "x") ||
this._isOverAxis(
this.positionAbs.top + this.offset.click.top, item.top, item.height),
isOverElementWidth = (this.options.axis === "y") ||
this._isOverAxis(
this.positionAbs.left + this.offset.click.left, item.left, item.width),
isOverElement = isOverElementHeight && isOverElementWidth;
if (!isOverElement) {
return false;
}
verticalDirection = this._getDragVerticalDirection();
horizontalDirection = this._getDragHorizontalDirection();
return (horizontalDirection === "right" || verticalDirection === "down") ? 2 : 1;
},
_mouseDrag: function(event) {
var i, item, itemElement, intersection,
o = this.options,
scrolled = false;
//Compute the helpers position
this.position = this._generatePosition(event);
this.positionAbs = this._convertPositionTo("absolute");
if (!this.lastPositionAbs) {
this.lastPositionAbs = this.positionAbs;
}
//Do scrolling
if (this.options.scroll) {
if (this.scrollParent[ 0 ] !== this.document[ 0 ] &&
this.scrollParent[ 0 ].tagName !== "HTML") {
if ((this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight) -
event.pageY < o.scrollSensitivity) {
this.scrollParent[ 0 ].scrollTop =
scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
} else if (event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
this.scrollParent[ 0 ].scrollTop =
scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
}
if ((this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth) -
event.pageX < o.scrollSensitivity) {
this.scrollParent[ 0 ].scrollLeft = scrolled =
this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
} else if (event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
this.scrollParent[ 0 ].scrollLeft = scrolled =
this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
}
} else {
if (event.pageY - this.document.scrollTop() < o.scrollSensitivity) {
scrolled = this.document.scrollTop(this.document.scrollTop() - o.scrollSpeed);
} else if (this.window.height() - (event.pageY - this.document.scrollTop()) <
o.scrollSensitivity) {
scrolled = this.document.scrollTop(this.document.scrollTop() + o.scrollSpeed);
}
if (event.pageX - this.document.scrollLeft() < o.scrollSensitivity) {
scrolled = this.document.scrollLeft(
this.document.scrollLeft() - o.scrollSpeed
);
} else if (this.window.width() - (event.pageX - this.document.scrollLeft()) <
o.scrollSensitivity) {
scrolled = this.document.scrollLeft(
this.document.scrollLeft() + o.scrollSpeed
);
}
}
if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
$.ui.ddmanager.prepareOffsets(this, event);
}
}
//Regenerate the absolute position used for position checks
this.positionAbs = this._convertPositionTo("absolute");
//Set the helper position
if (!this.options.axis || this.options.axis !== "y") {
this.helper[ 0 ].style.left = this.position.left + "px";
}
if (!this.options.axis || this.options.axis !== "x") {
this.helper[ 0 ].style.top = this.position.top + "px";
}
//Rearrange
for (i = this.items.length - 1; i >= 0; i--) {
//Cache variables and intersection, continue if no intersection
item = this.items[ i ];
itemElement = item.item[ 0 ];
intersection = this._intersectsWithPointer(item);
if (!intersection) {
continue;
}
this.direction = this._onRightSide(item, event) === true ? "right" : "left";
this._rearrange(event, item);
if (!this._intersectsWithSides(item)) {
break;
}
this._trigger("change", event, this._uiHash());
break;
}
//Post events to containers
this._contactContainers(event);
//Interconnect with droppables
if ($.ui.ddmanager) {
$.ui.ddmanager.drag(this, event);
}
//Call callbacks
this._trigger("sort", event, this._uiHash());
this.lastPositionAbs = this.positionAbs;
return false;
},
_rearrange: function(event, i, a, hardRefresh) {
a ? a[ 0 ].appendChild(this.placeholder[ 0 ]) :
i.item[ 0 ].parentNode.insertBefore(
this.placeholder[ 0 ],
(this.direction === "left" ? i.item[ 0 ] : i.item[ 0 ].nextSibling)
);
//Various things done here to improve the performance:
// 1. we create a setTimeout, that calls refreshPositions
// 2. on the instance, we have a counter variable, that get's higher after every append
// 3. on the local scope, we copy the counter variable, and check in the timeout,
// if it's still the same
// 4. this lets only the last addition to the timeout stack through
this.counter = this.counter ? ++this.counter : 1;
var counter = this.counter;
this._delay(function() {
if (counter === this.counter) {
//Precompute after each DOM insertion, NOT on mousemove
this.refreshPositions(!hardRefresh);
}
});
}
});