")
.css("position", "absolute")
.appendTo(iframe.parent())
.outerWidth(iframe.outerWidth())
.outerHeight(iframe.outerHeight())
.offset(iframe.offset())[0];
});
},
_unblockFrames: function () {
if (this.iframeBlocks) {
this.iframeBlocks.remove();
delete this.iframeBlocks;
}
},
_blurActiveElement: function (event) {
var activeElement = $.ui.safeActiveElement(this.document[0]),
target = $(event.target);
// Don't blur if the event occurred on an element that is within
// the currently focused element
// See #10527, #12472
if (target.closest(activeElement).length) {
return;
}
// Blur any element that currently has focus, see #4261
$.ui.safeBlur(activeElement);
},
_mouseStart: function (event) {
var o = this.options;
//Create and append the visible helper
this.helper = this._createHelper(event);
this._addClass(this.helper, "ui-draggable-dragging");
//Cache the helper size
this._cacheHelperProportions();
//If ddmanager is used for droppables, set the global draggable
if ($.ui.ddmanager) {
$.ui.ddmanager.current = this;
}
/*
* - Position generation -
* This block generates everything position related - it's the core of draggables.
*/
//Cache the margins of the original element
this._cacheMargins();
//Store the helper's css position
this.cssPosition = this.helper.css("position");
this.scrollParent = this.helper.scrollParent(true);
this.offsetParent = this.helper.offsetParent();
this.hasFixedAncestor = this.helper.parents().filter(function () {
return $(this).css("position") === "fixed";
}).length > 0;
//The element's absolute position on the page minus margins
this.positionAbs = this.element.offset();
this._refreshOffsets(event);
//Generate the original position
this.originalPosition = this.position = this._generatePosition(event, false);
this.originalPageX = event.pageX;
this.originalPageY = event.pageY;
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
//Set a containment if given in the options
this._setContainment();
//Trigger event + callbacks
if (this._trigger("start", event) === false) {
this._clear();
return false;
}
//Recache the helper size
this._cacheHelperProportions();
//Prepare the droppable offsets
if ($.ui.ddmanager && !o.dropBehaviour) {
$.ui.ddmanager.prepareOffsets(this, event);
}
// Execute the drag once - this causes the helper not to be visible before getting its
// correct position
this._mouseDrag(event, true);
// If the ddmanager is used for droppables, inform the manager that dragging has started
// (see #5003)
if ($.ui.ddmanager) {
$.ui.ddmanager.dragStart(this, event);
}
return true;
},
_refreshOffsets: function (event) {
this.offset = {
top: this.positionAbs.top - this.margins.top,
left: this.positionAbs.left - this.margins.left,
scroll: false,
parent: this._getParentOffset(),
relative: this._getRelativeOffset()
};
this.offset.click = {
left: event.pageX - this.offset.left,
top: event.pageY - this.offset.top
};
},
_mouseDrag: function (event, noPropagation) {
// reset any necessary cached properties (see #5009)
if (this.hasFixedAncestor) {
this.offset.parent = this._getParentOffset();
}
//Compute the helpers position
this.position = this._generatePosition(event, true);
this.positionAbs = this._convertPositionTo("absolute");
//Call plugins and callbacks and use the resulting position if something is returned
if (!noPropagation) {
var ui = this._uiHash();
if (this._trigger("drag", event, ui) === false) {
this._mouseUp(new $.Event("mouseup", event));
return false;
}
this.position = ui.position;
}
this.helper[0].style.left = this.position.left + "px";
this.helper[0].style.top = this.position.top + "px";
if ($.ui.ddmanager) {
$.ui.ddmanager.drag(this, event);
}
return false;
},
_mouseStop: function (event) {
//If we are using droppables, inform the manager about the drop
var that = this,
dropped = false;
if ($.ui.ddmanager && !this.options.dropBehaviour) {
dropped = $.ui.ddmanager.drop(this, event);
}
//if a drop comes from outside (a sortable)
if (this.dropped) {
dropped = this.dropped;
this.dropped = false;
}
if ((this.options.revert === "invalid" && !dropped) ||
(this.options.revert === "valid" && dropped) ||
this.options.revert === true || ($.isFunction(this.options.revert) &&
this.options.revert.call(this.element, dropped))
) {
$(this.helper).animate(
this.originalPosition,
parseInt(this.options.revertDuration, 10),
function () {
if (that._trigger("stop", event) !== false) {
that._clear();
}
}
);
} else {
if (this._trigger("stop", event) !== false) {
this._clear();
}
}
return false;
},
_mouseUp: function (event) {
this._unblockFrames();
// If the ddmanager is used for droppables, inform the manager that dragging has stopped
// (see #5003)
if ($.ui.ddmanager) {
$.ui.ddmanager.dragStop(this, event);
}
// Only need to focus if the event occurred on the draggable itself, see #10527
if (this.handleElement.is(event.target)) {
// The interaction is over; whether or not the click resulted in a drag,
// focus the element
this.element.trigger("focus");
}
return $.ui.mouse.prototype._mouseUp.call(this, event);
},
cancel: function () {
if (this.helper.is(".ui-draggable-dragging")) {
this._mouseUp(new $.Event("mouseup", { target: this.element[0] }));
} else {
this._clear();
}
return this;
},
_getHandle: function (event) {
return this.options.handle ?
!!$(event.target).closest(this.element.find(this.options.handle)).length :
true;
},
_setHandleClassName: function () {
this.handleElement = this.options.handle ?
this.element.find(this.options.handle) : this.element;
this._addClass(this.handleElement, "ui-draggable-handle");
},
_removeHandleClassName: function () {
this._removeClass(this.handleElement, "ui-draggable-handle");
},
_createHelper: function (event) {
var o = this.options,
helperIsFunction = $.isFunction(o.helper),
helper = helperIsFunction ?
$(o.helper.apply(this.element[0], [event])) :
(o.helper === "clone" ?
this.element.clone().removeAttr("id") :
this.element);
if (!helper.parents("body").length) {
helper.appendTo((o.appendTo === "parent" ?
this.element[0].parentNode :
o.appendTo));
}
// Http://bugs.jqueryui.com/ticket/9446
// a helper function can return the original element
// which wouldn't have been set to relative in _create
if (helperIsFunction && helper[0] === this.element[0]) {
this._setPositionRelative();
}
if (helper[0] !== this.element[0] &&
!(/(fixed|absolute)/).test(helper.css("position"))) {
helper.css("position", "absolute");
}
return helper;
},
_setPositionRelative: function () {
if (!(/^(?:r|a|f)/).test(this.element.css("position"))) {
this.element[0].style.position = "relative";
}
},
_adjustOffsetFromHelper: function (obj) {
if (typeof obj === "string") {
obj = obj.split(" ");
}
if ($.isArray(obj)) {
obj = { left: +obj[0], top: +obj[1] || 0 };
}
if ("left" in obj) {
this.offset.click.left = obj.left + this.margins.left;
}
if ("right" in obj) {
this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
}
if ("top" in obj) {
this.offset.click.top = obj.top + this.margins.top;
}
if ("bottom" in obj) {
this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
}
},
_isRootNode: function (element) {
return (/(html|body)/i).test(element.tagName) || element === this.document[0];
},
_getParentOffset: function () {
//Get the offsetParent and cache its position
var po = this.offsetParent.offset(),
document = this.document[0];
// This is a special case where we need to modify a offset calculated on start, since the
// following happened:
// 1. The position of the helper is absolute, so it's position is calculated based on the
// next positioned parent
// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
// the document, which means that the scroll is included in the initial calculation of the
// offset of the parent, and never recalculated upon drag
if (this.cssPosition === "absolute" && this.scrollParent[0] !== document &&
$.contains(this.scrollParent[0], this.offsetParent[0])) {
po.left += this.scrollParent.scrollLeft();
po.top += this.scrollParent.scrollTop();
}
if (this._isRootNode(this.offsetParent[0])) {
po = { top: 0, left: 0 };
}
return {
top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
};
},
_getRelativeOffset: function () {
if (this.cssPosition !== "relative") {
return { top: 0, left: 0 };
}
var p = this.element.position(),
scrollIsRootNode = this._isRootNode(this.scrollParent[0]);
return {
top: p.top - (parseInt(this.helper.css("top"), 10) || 0) +
(!scrollIsRootNode ? this.scrollParent.scrollTop() : 0),
left: p.left - (parseInt(this.helper.css("left"), 10) || 0) +
(!scrollIsRootNode ? this.scrollParent.scrollLeft() : 0)
};
},
_cacheMargins: function () {
this.margins = {
left: (parseInt(this.element.css("marginLeft"), 10) || 0),
top: (parseInt(this.element.css("marginTop"), 10) || 0),
right: (parseInt(this.element.css("marginRight"), 10) || 0),
bottom: (parseInt(this.element.css("marginBottom"), 10) || 0)
};
},
_cacheHelperProportions: function () {
this.helperProportions = {
width: this.helper.outerWidth(),
height: this.helper.outerHeight()
};
},
_setContainment: function () {
var isUserScrollable, c, ce,
o = this.options,
document = this.document[0];
this.relativeContainer = null;
if (!o.containment) {
this.containment = null;
return;
}
if (o.containment === "window") {
this.containment = [
$(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
$(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
$(window).scrollLeft() + $(window).width() -
this.helperProportions.width - this.margins.left,
$(window).scrollTop() +
($(window).height() || document.body.parentNode.scrollHeight) -
this.helperProportions.height - this.margins.top
];
return;
}
if (o.containment === "document") {
this.containment = [
0,
0,
$(document).width() - this.helperProportions.width - this.margins.left,
($(document).height() || document.body.parentNode.scrollHeight) -
this.helperProportions.height - this.margins.top
];
return;
}
if (o.containment.constructor === Array) {
this.containment = o.containment;
return;
}
if (o.containment === "parent") {
o.containment = this.helper[0].parentNode;
}
c = $(o.containment);
ce = c[0];
if (!ce) {
return;
}
isUserScrollable = /(scroll|auto)/.test(c.css("overflow"));
this.containment = [
(parseInt(c.css("borderLeftWidth"), 10) || 0) +
(parseInt(c.css("paddingLeft"), 10) || 0),
(parseInt(c.css("borderTopWidth"), 10) || 0) +
(parseInt(c.css("paddingTop"), 10) || 0),
(isUserScrollable ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) -
(parseInt(c.css("borderRightWidth"), 10) || 0) -
(parseInt(c.css("paddingRight"), 10) || 0) -
this.helperProportions.width -
this.margins.left -
this.margins.right,
(isUserScrollable ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) -
(parseInt(c.css("borderBottomWidth"), 10) || 0) -
(parseInt(c.css("paddingBottom"), 10) || 0) -
this.helperProportions.height -
this.margins.top -
this.margins.bottom
];
this.relativeContainer = c;
},
_convertPositionTo: function (d, pos) {
if (!pos) {
pos = this.position;
}
var mod = d === "absolute" ? 1 : -1,
scrollIsRootNode = this._isRootNode(this.scrollParent[0]);
return {
top: (
// The absolute mouse position
pos.top +
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.top * mod +
// The offsetParent's offset without borders (offset + border)
this.offset.parent.top * mod -
((this.cssPosition === "fixed" ?
-this.offset.scroll.top :
(scrollIsRootNode ? 0 : this.offset.scroll.top)) * mod)
),
left: (
// The absolute mouse position
pos.left +
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.left * mod +
// The offsetParent's offset without borders (offset + border)
this.offset.parent.left * mod -
((this.cssPosition === "fixed" ?
-this.offset.scroll.left :
(scrollIsRootNode ? 0 : this.offset.scroll.left)) * mod)
)
};
},
_generatePosition: function (event, constrainPosition) {
var containment, co, top, left,
o = this.options,
scrollIsRootNode = this._isRootNode(this.scrollParent[0]),
pageX = event.pageX,
pageY = event.pageY;
// Cache the scroll
if (!scrollIsRootNode || !this.offset.scroll) {
this.offset.scroll = {
top: this.scrollParent.scrollTop(),
left: this.scrollParent.scrollLeft()
};
}
/*
* - Position constraining -
* Constrain the position to a mix of grid, containment.
*/
// If we are not dragging yet, we won't check for options
if (constrainPosition) {
if (this.containment) {
if (this.relativeContainer) {
co = this.relativeContainer.offset();
containment = [
this.containment[0] + co.left,
this.containment[1] + co.top,
this.containment[2] + co.left,
this.containment[3] + co.top
];
} else {
containment = this.containment;
}
if (event.pageX - this.offset.click.left < containment[0]) {
pageX = containment[0] + this.offset.click.left;
}
if (event.pageY - this.offset.click.top < containment[1]) {
pageY = containment[1] + this.offset.click.top;
}
if (event.pageX - this.offset.click.left > containment[2]) {
pageX = containment[2] + this.offset.click.left;
}
if (event.pageY - this.offset.click.top > containment[3]) {
pageY = containment[3] + this.offset.click.top;
}
}
if (o.grid) {
//Check for grid elements set to 0 to prevent divide by 0 error causing invalid
// argument errors in IE (see ticket #6950)
top = o.grid[1] ? this.originalPageY + Math.round((pageY -
this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
pageY = containment ? ((top - this.offset.click.top >= containment[1] ||
top - this.offset.click.top > containment[3]) ?
top :
((top - this.offset.click.top >= containment[1]) ?
top - o.grid[1] : top + o.grid[1])) : top;
left = o.grid[0] ? this.originalPageX +
Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] :
this.originalPageX;
pageX = containment ? ((left - this.offset.click.left >= containment[0] ||
left - this.offset.click.left > containment[2]) ?
left :
((left - this.offset.click.left >= containment[0]) ?
left - o.grid[0] : left + o.grid[0])) : left;
}
if (o.axis === "y") {
pageX = this.originalPageX;
}
if (o.axis === "x") {
pageY = this.originalPageY;
}
}
return {
top: (
// The absolute mouse position
pageY -
// Click offset (relative to the element)
this.offset.click.top -
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.top -
// The offsetParent's offset without borders (offset + border)
this.offset.parent.top +
(this.cssPosition === "fixed" ?
-this.offset.scroll.top :
(scrollIsRootNode ? 0 : this.offset.scroll.top))
),
left: (
// The absolute mouse position
pageX -
// Click offset (relative to the element)
this.offset.click.left -
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.left -
// The offsetParent's offset without borders (offset + border)
this.offset.parent.left +
(this.cssPosition === "fixed" ?
-this.offset.scroll.left :
(scrollIsRootNode ? 0 : this.offset.scroll.left))
)
};
},
_clear: function () {
this._removeClass(this.helper, "ui-draggable-dragging");
if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
this.helper.remove();
}
this.helper = null;
this.cancelHelperRemoval = false;
if (this.destroyOnClear) {
this.destroy();
}
},
// From now on bulk stuff - mainly helpers
_trigger: function (type, event, ui) {
ui = ui || this._uiHash();
$.ui.plugin.call(this, type, [event, ui, this], true);
// Absolute position and offset (see #6884 ) have to be recalculated after plugins
if (/^(drag|start|stop)/.test(type)) {
this.positionAbs = this._convertPositionTo("absolute");
ui.offset = this.positionAbs;
}
return $.Widget.prototype._trigger.call(this, type, event, ui);
},
plugins: {},
_uiHash: function () {
return {
helper: this.helper,
position: this.position,
originalPosition: this.originalPosition,
offset: this.positionAbs
};
}
});
$.ui.plugin.add("draggable", "connectToSortable", {
start: function (event, ui, draggable) {
var uiSortable = $.extend({}, ui, {
item: draggable.element
});
draggable.sortables = [];
$(draggable.options.connectToSortable).each(function () {
var sortable = $(this).sortable("instance");
if (sortable && !sortable.options.disabled) {
draggable.sortables.push(sortable);
// RefreshPositions is called at drag start to refresh the containerCache
// which is used in drag. This ensures it's initialized and synchronized
// with any changes that might have happened on the page since initialization.
sortable.refreshPositions();
sortable._trigger("activate", event, uiSortable);
}
});
},
stop: function (event, ui, draggable) {
var uiSortable = $.extend({}, ui, {
item: draggable.element
});
draggable.cancelHelperRemoval = false;
$.each(draggable.sortables, function () {
var sortable = this;
if (sortable.isOver) {
sortable.isOver = 0;
// Allow this sortable to handle removing the helper
draggable.cancelHelperRemoval = true;
sortable.cancelHelperRemoval = false;
// Use _storedCSS To restore properties in the sortable,
// as this also handles revert (#9675) since the draggable
// may have modified them in unexpected ways (#8809)
sortable._storedCSS = {
position: sortable.placeholder.css("position"),
top: sortable.placeholder.css("top"),
left: sortable.placeholder.css("left")
};
sortable._mouseStop(event);
// Once drag has ended, the sortable should return to using
// its original helper, not the shared helper from draggable
sortable.options.helper = sortable.options._helper;
} else {
// Prevent this Sortable from removing the helper.
// However, don't set the draggable to remove the helper
// either as another connected Sortable may yet handle the removal.
sortable.cancelHelperRemoval = true;
sortable._trigger("deactivate", event, uiSortable);
}
});
},
drag: function (event, ui, draggable) {
$.each(draggable.sortables, function () {
var innermostIntersecting = false,
sortable = this;
// Copy over variables that sortable's _intersectsWith uses
sortable.positionAbs = draggable.positionAbs;
sortable.helperProportions = draggable.helperProportions;
sortable.offset.click = draggable.offset.click;
if (sortable._intersectsWith(sortable.containerCache)) {
innermostIntersecting = true;
$.each(draggable.sortables, function () {
// Copy over variables that sortable's _intersectsWith uses
this.positionAbs = draggable.positionAbs;
this.helperProportions = draggable.helperProportions;
this.offset.click = draggable.offset.click;
if (this !== sortable &&
this._intersectsWith(this.containerCache) &&
$.contains(sortable.element[0], this.element[0])) {
innermostIntersecting = false;
}
return innermostIntersecting;
});
}
if (innermostIntersecting) {
// If it intersects, we use a little isOver variable and set it once,
// so that the move-in stuff gets fired only once.
if (!sortable.isOver) {
sortable.isOver = 1;
// Store draggable's parent in case we need to reappend to it later.
draggable._parent = ui.helper.parent();
sortable.currentItem = ui.helper
.appendTo(sortable.element)
.data("ui-sortable-item", true);
// Store helper option to later restore it
sortable.options._helper = sortable.options.helper;
sortable.options.helper = function () {
return ui.helper[0];
};
// Fire the start events of the sortable with our passed browser event,
// and our own helper (so it doesn't create a new one)
event.target = sortable.currentItem[0];
sortable._mouseCapture(event, true);
sortable._mouseStart(event, true, true);
// Because the browser event is way off the new appended portlet,
// modify necessary variables to reflect the changes
sortable.offset.click.top = draggable.offset.click.top;
sortable.offset.click.left = draggable.offset.click.left;
sortable.offset.parent.left -= draggable.offset.parent.left -
sortable.offset.parent.left;
sortable.offset.parent.top -= draggable.offset.parent.top -
sortable.offset.parent.top;
draggable._trigger("toSortable", event);
// Inform draggable that the helper is in a valid drop zone,
// used solely in the revert option to handle "valid/invalid".
draggable.dropped = sortable.element;
// Need to refreshPositions of all sortables in the case that
// adding to one sortable changes the location of the other sortables (#9675)
$.each(draggable.sortables, function () {
this.refreshPositions();
});
// Hack so receive/update callbacks work (mostly)
draggable.currentItem = draggable.element;
sortable.fromOutside = draggable;
}
if (sortable.currentItem) {
sortable._mouseDrag(event);
// Copy the sortable's position because the draggable's can potentially reflect
// a relative position, while sortable is always absolute, which the dragged
// element has now become. (#8809)
ui.position = sortable.position;
}
} else {
// If it doesn't intersect with the sortable, and it intersected before,
// we fake the drag stop of the sortable, but make sure it doesn't remove
// the helper by using cancelHelperRemoval.
if (sortable.isOver) {
sortable.isOver = 0;
sortable.cancelHelperRemoval = true;
// Calling sortable's mouseStop would trigger a revert,
// so revert must be temporarily false until after mouseStop is called.
sortable.options._revert = sortable.options.revert;
sortable.options.revert = false;
sortable._trigger("out", event, sortable._uiHash(sortable));
sortable._mouseStop(event, true);
// Restore sortable behaviors that were modfied
// when the draggable entered the sortable area (#9481)
sortable.options.revert = sortable.options._revert;
sortable.options.helper = sortable.options._helper;
if (sortable.placeholder) {
sortable.placeholder.remove();
}
// Restore and recalculate the draggable's offset considering the sortable
// may have modified them in unexpected ways. (#8809, #10669)
ui.helper.appendTo(draggable._parent);
draggable._refreshOffsets(event);
ui.position = draggable._generatePosition(event, true);
draggable._trigger("fromSortable", event);
// Inform draggable that the helper is no longer in a valid drop zone
draggable.dropped = false;
// Need to refreshPositions of all sortables just in case removing
// from one sortable changes the location of other sortables (#9675)
$.each(draggable.sortables, function () {
this.refreshPositions();
});
}
}
});
}
});
$.ui.plugin.add("draggable", "cursor", {
start: function (event, ui, instance) {
var t = $("body"),
o = instance.options;
if (t.css("cursor")) {
o._cursor = t.css("cursor");
}
t.css("cursor", o.cursor);
},
stop: function (event, ui, instance) {
var o = instance.options;
if (o._cursor) {
$("body").css("cursor", o._cursor);
}
}
});
$.ui.plugin.add("draggable", "opacity", {
start: function (event, ui, instance) {
var t = $(ui.helper),
o = instance.options;
if (t.css("opacity")) {
o._opacity = t.css("opacity");
}
t.css("opacity", o.opacity);
},
stop: function (event, ui, instance) {
var o = instance.options;
if (o._opacity) {
$(ui.helper).css("opacity", o._opacity);
}
}
});
$.ui.plugin.add("draggable", "scroll", {
start: function (event, ui, i) {
if (!i.scrollParentNotHidden) {
i.scrollParentNotHidden = i.helper.scrollParent(false);
}
if (i.scrollParentNotHidden[0] !== i.document[0] &&
i.scrollParentNotHidden[0].tagName !== "HTML") {
i.overflowOffset = i.scrollParentNotHidden.offset();
}
},
drag: function (event, ui, i) {
var o = i.options,
scrolled = false,
scrollParent = i.scrollParentNotHidden[0],
document = i.document[0];
if (scrollParent !== document && scrollParent.tagName !== "HTML") {
if (!o.axis || o.axis !== "x") {
if ((i.overflowOffset.top + scrollParent.offsetHeight) - event.pageY <
o.scrollSensitivity) {
scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
} else if (event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
}
}
if (!o.axis || o.axis !== "y") {
if ((i.overflowOffset.left + scrollParent.offsetWidth) - event.pageX <
o.scrollSensitivity) {
scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
} else if (event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
}
}
} else {
if (!o.axis || o.axis !== "x") {
if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
} else if ($(window).height() - (event.pageY - $(document).scrollTop()) <
o.scrollSensitivity) {
scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
}
}
if (!o.axis || o.axis !== "y") {
if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
scrolled = $(document).scrollLeft(
$(document).scrollLeft() - o.scrollSpeed
);
} else if ($(window).width() - (event.pageX - $(document).scrollLeft()) <
o.scrollSensitivity) {
scrolled = $(document).scrollLeft(
$(document).scrollLeft() + o.scrollSpeed
);
}
}
}
if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
$.ui.ddmanager.prepareOffsets(i, event);
}
}
});
$.ui.plugin.add("draggable", "snap", {
start: function (event, ui, i) {
var o = i.options;
i.snapElements = [];
$(o.snap.constructor !== String ? (o.snap.items || ":data(ui-draggable)") : o.snap)
.each(function () {
var $t = $(this),
$o = $t.offset();
if (this !== i.element[0]) {
i.snapElements.push({
item: this,
width: $t.outerWidth(), height: $t.outerHeight(),
top: $o.top, left: $o.left
});
}
});
},
drag: function (event, ui, inst) {
var ts, bs, ls, rs, l, r, t, b, i, first,
o = inst.options,
d = o.snapTolerance,
x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
for (i = inst.snapElements.length - 1; i >= 0; i--) {
l = inst.snapElements[i].left - inst.margins.left;
r = l + inst.snapElements[i].width;
t = inst.snapElements[i].top - inst.margins.top;
b = t + inst.snapElements[i].height;
if (x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
!$.contains(inst.snapElements[i].item.ownerDocument,
inst.snapElements[i].item)) {
if (inst.snapElements[i].snapping) {
(inst.options.snap.release &&
inst.options.snap.release.call(
inst.element,
event,
$.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })
));
}
inst.snapElements[i].snapping = false;
continue;
}
if (o.snapMode !== "inner") {
ts = Math.abs(t - y2) <= d;
bs = Math.abs(b - y1) <= d;
ls = Math.abs(l - x2) <= d;
rs = Math.abs(r - x1) <= d;
if (ts) {
ui.position.top = inst._convertPositionTo("relative", {
top: t - inst.helperProportions.height,
left: 0
}).top;
}
if (bs) {
ui.position.top = inst._convertPositionTo("relative", {
top: b,
left: 0
}).top;
}
if (ls) {
ui.position.left = inst._convertPositionTo("relative", {
top: 0,
left: l - inst.helperProportions.width
}).left;
}
if (rs) {
ui.position.left = inst._convertPositionTo("relative", {
top: 0,
left: r
}).left;
}
}
first = (ts || bs || ls || rs);
if (o.snapMode !== "outer") {
ts = Math.abs(t - y1) <= d;
bs = Math.abs(b - y2) <= d;
ls = Math.abs(l - x1) <= d;
rs = Math.abs(r - x2) <= d;
if (ts) {
ui.position.top = inst._convertPositionTo("relative", {
top: t,
left: 0
}).top;
}
if (bs) {
ui.position.top = inst._convertPositionTo("relative", {
top: b - inst.helperProportions.height,
left: 0
}).top;
}
if (ls) {
ui.position.left = inst._convertPositionTo("relative", {
top: 0,
left: l
}).left;
}
if (rs) {
ui.position.left = inst._convertPositionTo("relative", {
top: 0,
left: r - inst.helperProportions.width
}).left;
}
}
if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
(inst.options.snap.snap &&
inst.options.snap.snap.call(
inst.element,
event,
$.extend(inst._uiHash(), {
snapItem: inst.snapElements[i].item
})));
}
inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
}
}
});
$.ui.plugin.add("draggable", "stack", {
start: function (event, ui, instance) {
var min,
o = instance.options,
group = $.makeArray($(o.stack)).sort(function (a, b) {
return (parseInt($(a).css("zIndex"), 10) || 0) -
(parseInt($(b).css("zIndex"), 10) || 0);
});
if (!group.length) { return; }
min = parseInt($(group[0]).css("zIndex"), 10) || 0;
$(group).each(function (i) {
$(this).css("zIndex", min + i);
});
this.css("zIndex", (min + group.length));
}
});
$.ui.plugin.add("draggable", "zIndex", {
start: function (event, ui, instance) {
var t = $(ui.helper),
o = instance.options;
if (t.css("zIndex")) {
o._zIndex = t.css("zIndex");
}
t.css("zIndex", o.zIndex);
},
stop: function (event, ui, instance) {
var o = instance.options;
if (o._zIndex) {
$(ui.helper).css("zIndex", o._zIndex);
}
}
});
var widgetsDraggable = $.ui.draggable;
/*!
* jQuery UI Droppable 1.12.1
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
//>>label: Droppable
//>>group: Interactions
//>>description: Enables drop targets for draggable elements.
//>>docs: http://api.jqueryui.com/droppable/
//>>demos: http://jqueryui.com/droppable/
$.widget("ui.droppable", {
version: "1.12.1",
widgetEventPrefix: "drop",
options: {
accept: "*",
addClasses: true,
greedy: false,
scope: "default",
tolerance: "intersect",
// Callbacks
activate: null,
deactivate: null,
drop: null,
out: null,
over: null
},
_create: function () {
var proportions,
o = this.options,
accept = o.accept;
this.isover = false;
this.isout = true;
this.accept = $.isFunction(accept) ? accept : function (d) {
return d.is(accept);
};
this.proportions = function ( /* valueToWrite */) {
if (arguments.length) {
// Store the droppable's proportions
proportions = arguments[0];
} else {
// Retrieve or derive the droppable's proportions
return proportions ?
proportions :
proportions = {
width: this.element[0].offsetWidth,
height: this.element[0].offsetHeight
};
}
};
this._addToManager(o.scope);
o.addClasses && this._addClass("ui-droppable");
},
_addToManager: function (scope) {
// Add the reference and positions to the manager
$.ui.ddmanager.droppables[scope] = $.ui.ddmanager.droppables[scope] || [];
$.ui.ddmanager.droppables[scope].push(this);
},
_splice: function (drop) {
var i = 0;
for (; i < drop.length; i++) {
if (drop[i] === this) {
drop.splice(i, 1);
}
}
},
_destroy: function () {
var drop = $.ui.ddmanager.droppables[this.options.scope];
this._splice(drop);
},
_setOption: function (key, value) {
if (key === "accept") {
this.accept = $.isFunction(value) ? value : function (d) {
return d.is(value);
};
} else if (key === "scope") {
var drop = $.ui.ddmanager.droppables[this.options.scope];
this._splice(drop);
this._addToManager(value);
}
this._super(key, value);
},
_activate: function (event) {
var draggable = $.ui.ddmanager.current;
this._addActiveClass();
if (draggable) {
this._trigger("activate", event, this.ui(draggable));
}
},
_deactivate: function (event) {
var draggable = $.ui.ddmanager.current;
this._removeActiveClass();
if (draggable) {
this._trigger("deactivate", event, this.ui(draggable));
}
},
_over: function (event) {
var draggable = $.ui.ddmanager.current;
// Bail if draggable and droppable are same element
if (!draggable || (draggable.currentItem ||
draggable.element)[0] === this.element[0]) {
return;
}
if (this.accept.call(this.element[0], (draggable.currentItem ||
draggable.element))) {
this._addHoverClass();
this._trigger("over", event, this.ui(draggable));
}
},
_out: function (event) {
var draggable = $.ui.ddmanager.current;
// Bail if draggable and droppable are same element
if (!draggable || (draggable.currentItem ||
draggable.element)[0] === this.element[0]) {
return;
}
if (this.accept.call(this.element[0], (draggable.currentItem ||
draggable.element))) {
this._removeHoverClass();
this._trigger("out", event, this.ui(draggable));
}
},
_drop: function (event, custom) {
var draggable = custom || $.ui.ddmanager.current,
childrenIntersection = false;
// Bail if draggable and droppable are same element
if (!draggable || (draggable.currentItem ||
draggable.element)[0] === this.element[0]) {
return false;
}
this.element
.find(":data(ui-droppable)")
.not(".ui-draggable-dragging")
.each(function () {
var inst = $(this).droppable("instance");
if (
inst.options.greedy &&
!inst.options.disabled &&
inst.options.scope === draggable.options.scope &&
inst.accept.call(
inst.element[0], (draggable.currentItem || draggable.element)
) &&
intersect(
draggable,
$.extend(inst, { offset: inst.element.offset() }),
inst.options.tolerance, event
)
) {
childrenIntersection = true;
return false;
}
});
if (childrenIntersection) {
return false;
}
if (this.accept.call(this.element[0],
(draggable.currentItem || draggable.element))) {
this._removeActiveClass();
this._removeHoverClass();
this._trigger("drop", event, this.ui(draggable));
return this.element;
}
return false;
},
ui: function (c) {
return {
draggable: (c.currentItem || c.element),
helper: c.helper,
position: c.position,
offset: c.positionAbs
};
},
// Extension points just to make backcompat sane and avoid duplicating logic
// TODO: Remove in 1.13 along with call to it below
_addHoverClass: function () {
this._addClass("ui-droppable-hover");
},
_removeHoverClass: function () {
this._removeClass("ui-droppable-hover");
},
_addActiveClass: function () {
this._addClass("ui-droppable-active");
},
_removeActiveClass: function () {
this._removeClass("ui-droppable-active");
}
});
var intersect = $.ui.intersect = (function () {
function isOverAxis(x, reference, size) {
return (x >= reference) && (x < (reference + size));
}
return function (draggable, droppable, toleranceMode, event) {
if (!droppable.offset) {
return false;
}
var x1 = (draggable.positionAbs ||
draggable.position.absolute).left + draggable.margins.left,
y1 = (draggable.positionAbs ||
draggable.position.absolute).top + draggable.margins.top,
x2 = x1 + draggable.helperProportions.width,
y2 = y1 + draggable.helperProportions.height,
l = droppable.offset.left,
t = droppable.offset.top,
r = l + droppable.proportions().width,
b = t + droppable.proportions().height;
switch (toleranceMode) {
case "fit":
return (l <= x1 && x2 <= r && t <= y1 && y2 <= b);
case "intersect":
return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half
x2 - (draggable.helperProportions.width / 2) < r && // Left Half
t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half
y2 - (draggable.helperProportions.height / 2) < b); // Top Half
case "pointer":
return isOverAxis(event.pageY, t, droppable.proportions().height) &&
isOverAxis(event.pageX, l, droppable.proportions().width);
case "touch":
return (
(y1 >= t && y1 <= b) || // Top edge touching
(y2 >= t && y2 <= b) || // Bottom edge touching
(y1 < t && y2 > b) // Surrounded vertically
) && (
(x1 >= l && x1 <= r) || // Left edge touching
(x2 >= l && x2 <= r) || // Right edge touching
(x1 < l && x2 > r) // Surrounded horizontally
);
default:
return false;
}
};
})();
/*
This manager tracks offsets of draggables and droppables
*/
$.ui.ddmanager = {
current: null,
droppables: { "default": [] },
prepareOffsets: function (t, event) {
var i, j,
m = $.ui.ddmanager.droppables[t.options.scope] || [],
type = event ? event.type : null, // workaround for #2317
list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();
droppablesLoop: for (i = 0; i < m.length; i++) {
// No disabled and non-accepted
if (m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],
(t.currentItem || t.element)))) {
continue;
}
// Filter out elements in the current dragged item
for (j = 0; j < list.length; j++) {
if (list[j] === m[i].element[0]) {
m[i].proportions().height = 0;
continue droppablesLoop;
}
}
m[i].visible = m[i].element.css("display") !== "none";
if (!m[i].visible) {
continue;
}
// Activate the droppable if used directly from draggables
if (type === "mousedown") {
m[i]._activate.call(m[i], event);
}
m[i].offset = m[i].element.offset();
m[i].proportions({
width: m[i].element[0].offsetWidth,
height: m[i].element[0].offsetHeight
});
}
},
drop: function (draggable, event) {
var dropped = false;
// Create a copy of the droppables in case the list changes during the drop (#9116)
$.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function () {
if (!this.options) {
return;
}
if (!this.options.disabled && this.visible &&
intersect(draggable, this, this.options.tolerance, event)) {
dropped = this._drop.call(this, event) || dropped;
}
if (!this.options.disabled && this.visible && this.accept.call(this.element[0],
(draggable.currentItem || draggable.element))) {
this.isout = true;
this.isover = false;
this._deactivate.call(this, event);
}
});
return dropped;
},
dragStart: function (draggable, event) {
// Listen for scrolling so that if the dragging causes scrolling the position of the
// droppables can be recalculated (see #5003)
draggable.element.parentsUntil("body").on("scroll.droppable", function () {
if (!draggable.options.refreshPositions) {
$.ui.ddmanager.prepareOffsets(draggable, event);
}
});
},
drag: function (draggable, event) {
// If you have a highly dynamic page, you might try this option. It renders positions
// every time you move the mouse.
if (draggable.options.refreshPositions) {
$.ui.ddmanager.prepareOffsets(draggable, event);
}
// Run through all droppables and check their positions based on specific tolerance options
$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function () {
if (this.options.disabled || this.greedyChild || !this.visible) {
return;
}
var parentInstance, scope, parent,
intersects = intersect(draggable, this, this.options.tolerance, event),
c = !intersects && this.isover ?
"isout" :
(intersects && !this.isover ? "isover" : null);
if (!c) {
return;
}
if (this.options.greedy) {
// find droppable parents with same scope
scope = this.options.scope;
parent = this.element.parents(":data(ui-droppable)").filter(function () {
return $(this).droppable("instance").options.scope === scope;
});
if (parent.length) {
parentInstance = $(parent[0]).droppable("instance");
parentInstance.greedyChild = (c === "isover");
}
}
// We just moved into a greedy child
if (parentInstance && c === "isover") {
parentInstance.isover = false;
parentInstance.isout = true;
parentInstance._out.call(parentInstance, event);
}
this[c] = true;
this[c === "isout" ? "isover" : "isout"] = false;
this[c === "isover" ? "_over" : "_out"].call(this, event);
// We just moved out of a greedy child
if (parentInstance && c === "isout") {
parentInstance.isout = false;
parentInstance.isover = true;
parentInstance._over.call(parentInstance, event);
}
});
},
dragStop: function (draggable, event) {
draggable.element.parentsUntil("body").off("scroll.droppable");
// Call prepareOffsets one final time since IE does not fire return scroll events when
// overflow was caused by drag (see #5003)
if (!draggable.options.refreshPositions) {
$.ui.ddmanager.prepareOffsets(draggable, event);
}
}
};
// DEPRECATED
// TODO: switch return back to widget declaration at top of file when this is removed
if ($.uiBackCompat !== false) {
// Backcompat for activeClass and hoverClass options
$.widget("ui.droppable", $.ui.droppable, {
options: {
hoverClass: false,
activeClass: false
},
_addActiveClass: function () {
this._super();
if (this.options.activeClass) {
this.element.addClass(this.options.activeClass);
}
},
_removeActiveClass: function () {
this._super();
if (this.options.activeClass) {
this.element.removeClass(this.options.activeClass);
}
},
_addHoverClass: function () {
this._super();
if (this.options.hoverClass) {
this.element.addClass(this.options.hoverClass);
}
},
_removeHoverClass: function () {
this._super();
if (this.options.hoverClass) {
this.element.removeClass(this.options.hoverClass);
}
}
});
}
var widgetsDroppable = $.ui.droppable;
/*!
* jQuery UI Resizable 1.12.1
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
//>>label: Resizable
//>>group: Interactions
//>>description: Enables resize functionality for any element.
//>>docs: http://api.jqueryui.com/resizable/
//>>demos: http://jqueryui.com/resizable/
//>>css.structure: ../../themes/base/core.css
//>>css.structure: ../../themes/base/resizable.css
//>>css.theme: ../../themes/base/theme.css
$.widget("ui.resizable", $.ui.mouse, {
version: "1.12.1",
widgetEventPrefix: "resize",
options: {
alsoResize: false,
animate: false,
animateDuration: "slow",
animateEasing: "swing",
aspectRatio: false,
autoHide: false,
classes: {
"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
},
containment: false,
ghost: false,
grid: false,
handles: "e,s,se",
helper: false,
maxHeight: null,
maxWidth: null,
minHeight: 10,
minWidth: 10,
// See #7960
zIndex: 90,
// Callbacks
resize: null,
start: null,
stop: null
},
_num: function (value) {
return parseFloat(value) || 0;
},
_isNumber: function (value) {
return !isNaN(parseFloat(value));
},
_hasScroll: function (el, a) {
if ($(el).css("overflow") === "hidden") {
return false;
}
var scroll = (a && a === "left") ? "scrollLeft" : "scrollTop",
has = false;
if (el[scroll] > 0) {
return true;
}
// TODO: determine which cases actually cause this to happen
// if the element doesn't have the scroll set, see if it's possible to
// set the scroll
el[scroll] = 1;
has = (el[scroll] > 0);
el[scroll] = 0;
return has;
},
_create: function () {
var margins,
o = this.options,
that = this;
this._addClass("ui-resizable");
$.extend(this, {
_aspectRatio: !!(o.aspectRatio),
aspectRatio: o.aspectRatio,
originalElement: this.element,
_proportionallyResizeElements: [],
_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
});
// Wrap the element if it cannot hold child nodes
if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) {
this.element.wrap(
$("
").css({
position: this.element.css("position"),
width: this.element.outerWidth(),
height: this.element.outerHeight(),
top: this.element.css("top"),
left: this.element.css("left")
})
);
this.element = this.element.parent().data(
"ui-resizable", this.element.resizable("instance")
);
this.elementIsWrapper = true;
margins = {
marginTop: this.originalElement.css("marginTop"),
marginRight: this.originalElement.css("marginRight"),
marginBottom: this.originalElement.css("marginBottom"),
marginLeft: this.originalElement.css("marginLeft")
};
this.element.css(margins);
this.originalElement.css("margin", 0);
// support: Safari
// Prevent Safari textarea resize
this.originalResizeStyle = this.originalElement.css("resize");
this.originalElement.css("resize", "none");
this._proportionallyResizeElements.push(this.originalElement.css({
position: "static",
zoom: 1,
display: "block"
}));
// Support: IE9
// avoid IE jump (hard set the margin)
this.originalElement.css(margins);
this._proportionallyResize();
}
this._setupHandles();
if (o.autoHide) {
$(this.element)
.on("mouseenter", function () {
if (o.disabled) {
return;
}
that._removeClass("ui-resizable-autohide");
that._handles.show();
})
.on("mouseleave", function () {
if (o.disabled) {
return;
}
if (!that.resizing) {
that._addClass("ui-resizable-autohide");
that._handles.hide();
}
});
}
this._mouseInit();
},
_destroy: function () {
this._mouseDestroy();
var wrapper,
_destroy = function (exp) {
$(exp)
.removeData("resizable")
.removeData("ui-resizable")
.off(".resizable")
.find(".ui-resizable-handle")
.remove();
};
// TODO: Unwrap at same DOM position
if (this.elementIsWrapper) {
_destroy(this.element);
wrapper = this.element;
this.originalElement.css({
position: wrapper.css("position"),
width: wrapper.outerWidth(),
height: wrapper.outerHeight(),
top: wrapper.css("top"),
left: wrapper.css("left")
}).insertAfter(wrapper);
wrapper.remove();
}
this.originalElement.css("resize", this.originalResizeStyle);
_destroy(this.originalElement);
return this;
},
_setOption: function (key, value) {
this._super(key, value);
switch (key) {
case "handles":
this._removeHandles();
this._setupHandles();
break;
default:
break;
}
},
_setupHandles: function () {
var o = this.options, handle, i, n, hname, axis, that = this;
this.handles = o.handles ||
(!$(".ui-resizable-handle", this.element).length ?
"e,s,se" : {
n: ".ui-resizable-n",
e: ".ui-resizable-e",
s: ".ui-resizable-s",
w: ".ui-resizable-w",
se: ".ui-resizable-se",
sw: ".ui-resizable-sw",
ne: ".ui-resizable-ne",
nw: ".ui-resizable-nw"
});
this._handles = $();
if (this.handles.constructor === String) {
if (this.handles === "all") {
this.handles = "n,e,s,w,se,sw,ne,nw";
}
n = this.handles.split(",");
this.handles = {};
for (i = 0; i < n.length; i++) {
handle = $.trim(n[i]);
hname = "ui-resizable-" + handle;
axis = $("
");
this._addClass(axis, "ui-resizable-handle " + hname);
axis.css({ zIndex: o.zIndex });
this.handles[handle] = ".ui-resizable-" + handle;
this.element.append(axis);
}
}
this._renderAxis = function (target) {
var i, axis, padPos, padWrapper;
target = target || this.element;
for (i in this.handles) {
if (this.handles[i].constructor === String) {
this.handles[i] = this.element.children(this.handles[i]).first().show();
} else if (this.handles[i].jquery || this.handles[i].nodeType) {
this.handles[i] = $(this.handles[i]);
this._on(this.handles[i], { "mousedown": that._mouseDown });
}
if (this.elementIsWrapper &&
this.originalElement[0]
.nodeName
.match(/^(textarea|input|select|button)$/i)) {
axis = $(this.handles[i], this.element);
padWrapper = /sw|ne|nw|se|n|s/.test(i) ?
axis.outerHeight() :
axis.outerWidth();
padPos = ["padding",
/ne|nw|n/.test(i) ? "Top" :
/se|sw|s/.test(i) ? "Bottom" :
/^e$/.test(i) ? "Right" : "Left"].join("");
target.css(padPos, padWrapper);
this._proportionallyResize();
}
this._handles = this._handles.add(this.handles[i]);
}
};
// TODO: make renderAxis a prototype function
this._renderAxis(this.element);
this._handles = this._handles.add(this.element.find(".ui-resizable-handle"));
this._handles.disableSelection();
this._handles.on("mouseover", function () {
if (!that.resizing) {
if (this.className) {
axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
}
that.axis = axis && axis[1] ? axis[1] : "se";
}
});
if (o.autoHide) {
this._handles.hide();
this._addClass("ui-resizable-autohide");
}
},
_removeHandles: function () {
this._handles.remove();
},
_mouseCapture: function (event) {
var i, handle,
capture = false;
for (i in this.handles) {
handle = $(this.handles[i])[0];
if (handle === event.target || $.contains(handle, event.target)) {
capture = true;
}
}
return !this.options.disabled && capture;
},
_mouseStart: function (event) {
var curleft, curtop, cursor,
o = this.options,
el = this.element;
this.resizing = true;
this._renderProxy();
curleft = this._num(this.helper.css("left"));
curtop = this._num(this.helper.css("top"));
if (o.containment) {
curleft += $(o.containment).scrollLeft() || 0;
curtop += $(o.containment).scrollTop() || 0;
}
this.offset = this.helper.offset();
this.position = { left: curleft, top: curtop };
this.size = this._helper ? {
width: this.helper.width(),
height: this.helper.height()
} : {
width: el.width(),
height: el.height()
};
this.originalSize = this._helper ? {
width: el.outerWidth(),
height: el.outerHeight()
} : {
width: el.width(),
height: el.height()
};
this.sizeDiff = {
width: el.outerWidth() - el.width(),
height: el.outerHeight() - el.height()
};
this.originalPosition = { left: curleft, top: curtop };
this.originalMousePosition = { left: event.pageX, top: event.pageY };
this.aspectRatio = (typeof o.aspectRatio === "number") ?
o.aspectRatio :
((this.originalSize.width / this.originalSize.height) || 1);
cursor = $(".ui-resizable-" + this.axis).css("cursor");
$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
this._addClass("ui-resizable-resizing");
this._propagate("start", event);
return true;
},
_mouseDrag: function (event) {
var data, props,
smp = this.originalMousePosition,
a = this.axis,
dx = (event.pageX - smp.left) || 0,
dy = (event.pageY - smp.top) || 0,
trigger = this._change[a];
this._updatePrevProperties();
if (!trigger) {
return false;
}
data = trigger.apply(this, [event, dx, dy]);
this._updateVirtualBoundaries(event.shiftKey);
if (this._aspectRatio || event.shiftKey) {
data = this._updateRatio(data, event);
}
data = this._respectSize(data, event);
this._updateCache(data);
this._propagate("resize", event);
props = this._applyChanges();
if (!this._helper && this._proportionallyResizeElements.length) {
this._proportionallyResize();
}
if (!$.isEmptyObject(props)) {
this._updatePrevProperties();
this._trigger("resize", event, this.ui());
this._applyChanges();
}
return false;
},
_mouseStop: function (event) {
this.resizing = false;
var pr, ista, soffseth, soffsetw, s, left, top,
o = this.options, that = this;
if (this._helper) {
pr = this._proportionallyResizeElements;
ista = pr.length && (/textarea/i).test(pr[0].nodeName);
soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height;
soffsetw = ista ? 0 : that.sizeDiff.width;
s = {
width: (that.helper.width() - soffsetw),
height: (that.helper.height() - soffseth)
};
left = (parseFloat(that.element.css("left")) +
(that.position.left - that.originalPosition.left)) || null;
top = (parseFloat(that.element.css("top")) +
(that.position.top - that.originalPosition.top)) || null;
if (!o.animate) {
this.element.css($.extend(s, { top: top, left: left }));
}
that.helper.height(that.size.height);
that.helper.width(that.size.width);
if (this._helper && !o.animate) {
this._proportionallyResize();
}
}
$("body").css("cursor", "auto");
this._removeClass("ui-resizable-resizing");
this._propagate("stop", event);
if (this._helper) {
this.helper.remove();
}
return false;
},
_updatePrevProperties: function () {
this.prevPosition = {
top: this.position.top,
left: this.position.left
};
this.prevSize = {
width: this.size.width,
height: this.size.height
};
},
_applyChanges: function () {
var props = {};
if (this.position.top !== this.prevPosition.top) {
props.top = this.position.top + "px";
}
if (this.position.left !== this.prevPosition.left) {
props.left = this.position.left + "px";
}
if (this.size.width !== this.prevSize.width) {
props.width = this.size.width + "px";
}
if (this.size.height !== this.prevSize.height) {
props.height = this.size.height + "px";
}
this.helper.css(props);
return props;
},
_updateVirtualBoundaries: function (forceAspectRatio) {
var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
o = this.options;
b = {
minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
};
if (this._aspectRatio || forceAspectRatio) {
pMinWidth = b.minHeight * this.aspectRatio;
pMinHeight = b.minWidth / this.aspectRatio;
pMaxWidth = b.maxHeight * this.aspectRatio;
pMaxHeight = b.maxWidth / this.aspectRatio;
if (pMinWidth > b.minWidth) {
b.minWidth = pMinWidth;
}
if (pMinHeight > b.minHeight) {
b.minHeight = pMinHeight;
}
if (pMaxWidth < b.maxWidth) {
b.maxWidth = pMaxWidth;
}
if (pMaxHeight < b.maxHeight) {
b.maxHeight = pMaxHeight;
}
}
this._vBoundaries = b;
},
_updateCache: function (data) {
this.offset = this.helper.offset();
if (this._isNumber(data.left)) {
this.position.left = data.left;
}
if (this._isNumber(data.top)) {
this.position.top = data.top;
}
if (this._isNumber(data.height)) {
this.size.height = data.height;
}
if (this._isNumber(data.width)) {
this.size.width = data.width;
}
},
_updateRatio: function (data) {
var cpos = this.position,
csize = this.size,
a = this.axis;
if (this._isNumber(data.height)) {
data.width = (data.height * this.aspectRatio);
} else if (this._isNumber(data.width)) {
data.height = (data.width / this.aspectRatio);
}
if (a === "sw") {
data.left = cpos.left + (csize.width - data.width);
data.top = null;
}
if (a === "nw") {
data.top = cpos.top + (csize.height - data.height);
data.left = cpos.left + (csize.width - data.width);
}
return data;
},
_respectSize: function (data) {
var o = this._vBoundaries,
a = this.axis,
ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width),
ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width),
isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
dw = this.originalPosition.left + this.originalSize.width,
dh = this.originalPosition.top + this.originalSize.height,
cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
if (isminw) {
data.width = o.minWidth;
}
if (isminh) {
data.height = o.minHeight;
}
if (ismaxw) {
data.width = o.maxWidth;
}
if (ismaxh) {
data.height = o.maxHeight;
}
if (isminw && cw) {
data.left = dw - o.minWidth;
}
if (ismaxw && cw) {
data.left = dw - o.maxWidth;
}
if (isminh && ch) {
data.top = dh - o.minHeight;
}
if (ismaxh && ch) {
data.top = dh - o.maxHeight;
}
// Fixing jump error on top/left - bug #2330
if (!data.width && !data.height && !data.left && data.top) {
data.top = null;
} else if (!data.width && !data.height && !data.top && data.left) {
data.left = null;
}
return data;
},
_getPaddingPlusBorderDimensions: function (element) {
var i = 0,
widths = [],
borders = [
element.css("borderTopWidth"),
element.css("borderRightWidth"),
element.css("borderBottomWidth"),
element.css("borderLeftWidth")
],
paddings = [
element.css("paddingTop"),
element.css("paddingRight"),
element.css("paddingBottom"),
element.css("paddingLeft")
];
for (; i < 4; i++) {
widths[i] = (parseFloat(borders[i]) || 0);
widths[i] += (parseFloat(paddings[i]) || 0);
}
return {
height: widths[0] + widths[2],
width: widths[1] + widths[3]
};
},
_proportionallyResize: function () {
if (!this._proportionallyResizeElements.length) {
return;
}
var prel,
i = 0,
element = this.helper || this.element;
for (; i < this._proportionallyResizeElements.length; i++) {
prel = this._proportionallyResizeElements[i];
// TODO: Seems like a bug to cache this.outerDimensions
// considering that we are in a loop.
if (!this.outerDimensions) {
this.outerDimensions = this._getPaddingPlusBorderDimensions(prel);
}
prel.css({
height: (element.height() - this.outerDimensions.height) || 0,
width: (element.width() - this.outerDimensions.width) || 0
});
}
},
_renderProxy: function () {
var el = this.element, o = this.options;
this.elementOffset = el.offset();
if (this._helper) {
this.helper = this.helper || $("
");
this._addClass(this.helper, this._helper);
this.helper.css({
width: this.element.outerWidth(),
height: this.element.outerHeight(),
position: "absolute",
left: this.elementOffset.left + "px",
top: this.elementOffset.top + "px",
zIndex: ++o.zIndex //TODO: Don't modify option
});
this.helper
.appendTo("body")
.disableSelection();
} else {
this.helper = this.element;
}
},
_change: {
e: function (event, dx) {
return { width: this.originalSize.width + dx };
},
w: function (event, dx) {
var cs = this.originalSize, sp = this.originalPosition;
return { left: sp.left + dx, width: cs.width - dx };
},
n: function (event, dx, dy) {
var cs = this.originalSize, sp = this.originalPosition;
return { top: sp.top + dy, height: cs.height - dy };
},
s: function (event, dx, dy) {
return { height: this.originalSize.height + dy };
},
se: function (event, dx, dy) {
return $.extend(this._change.s.apply(this, arguments),
this._change.e.apply(this, [event, dx, dy]));
},
sw: function (event, dx, dy) {
return $.extend(this._change.s.apply(this, arguments),
this._change.w.apply(this, [event, dx, dy]));
},
ne: function (event, dx, dy) {
return $.extend(this._change.n.apply(this, arguments),
this._change.e.apply(this, [event, dx, dy]));
},
nw: function (event, dx, dy) {
return $.extend(this._change.n.apply(this, arguments),
this._change.w.apply(this, [event, dx, dy]));
}
},
_propagate: function (n, event) {
$.ui.plugin.call(this, n, [event, this.ui()]);
(n !== "resize" && this._trigger(n, event, this.ui()));
},
plugins: {},
ui: function () {
return {
originalElement: this.originalElement,
element: this.element,
helper: this.helper,
position: this.position,
size: this.size,
originalSize: this.originalSize,
originalPosition: this.originalPosition
};
}
});
/*
* Resizable Extensions
*/
$.ui.plugin.add("resizable", "animate", {
stop: function (event) {
var that = $(this).resizable("instance"),
o = that.options,
pr = that._proportionallyResizeElements,
ista = pr.length && (/textarea/i).test(pr[0].nodeName),
soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height,
soffsetw = ista ? 0 : that.sizeDiff.width,
style = {
width: (that.size.width - soffsetw),
height: (that.size.height - soffseth)
},
left = (parseFloat(that.element.css("left")) +
(that.position.left - that.originalPosition.left)) || null,
top = (parseFloat(that.element.css("top")) +
(that.position.top - that.originalPosition.top)) || null;
that.element.animate(
$.extend(style, top && left ? { top: top, left: left } : {}), {
duration: o.animateDuration,
easing: o.animateEasing,
step: function () {
var data = {
width: parseFloat(that.element.css("width")),
height: parseFloat(that.element.css("height")),
top: parseFloat(that.element.css("top")),
left: parseFloat(that.element.css("left"))
};
if (pr && pr.length) {
$(pr[0]).css({ width: data.width, height: data.height });
}
// Propagating resize, and updating values for each animation step
that._updateCache(data);
that._propagate("resize", event);
}
}
);
}
});
$.ui.plugin.add("resizable", "containment", {
start: function () {
var element, p, co, ch, cw, width, height,
that = $(this).resizable("instance"),
o = that.options,
el = that.element,
oc = o.containment,
ce = (oc instanceof $) ?
oc.get(0) :
(/parent/.test(oc)) ? el.parent().get(0) : oc;
if (!ce) {
return;
}
that.containerElement = $(ce);
if (/document/.test(oc) || oc === document) {
that.containerOffset = {
left: 0,
top: 0
};
that.containerPosition = {
left: 0,
top: 0
};
that.parentData = {
element: $(document),
left: 0,
top: 0,
width: $(document).width(),
height: $(document).height() || document.body.parentNode.scrollHeight
};
} else {
element = $(ce);
p = [];
$(["Top", "Right", "Left", "Bottom"]).each(function (i, name) {
p[i] = that._num(element.css("padding" + name));
});
that.containerOffset = element.offset();
that.containerPosition = element.position();
that.containerSize = {
height: (element.innerHeight() - p[3]),
width: (element.innerWidth() - p[1])
};
co = that.containerOffset;
ch = that.containerSize.height;
cw = that.containerSize.width;
width = (that._hasScroll(ce, "left") ? ce.scrollWidth : cw);
height = (that._hasScroll(ce) ? ce.scrollHeight : ch);
that.parentData = {
element: ce,
left: co.left,
top: co.top,
width: width,
height: height
};
}
},
resize: function (event) {
var woset, hoset, isParent, isOffsetRelative,
that = $(this).resizable("instance"),
o = that.options,
co = that.containerOffset,
cp = that.position,
pRatio = that._aspectRatio || event.shiftKey,
cop = {
top: 0,
left: 0
},
ce = that.containerElement,
continueResize = true;
if (ce[0] !== document && (/static/).test(ce.css("position"))) {
cop = co;
}
if (cp.left < (that._helper ? co.left : 0)) {
that.size.width = that.size.width +
(that._helper ?
(that.position.left - co.left) :
(that.position.left - cop.left));
if (pRatio) {
that.size.height = that.size.width / that.aspectRatio;
continueResize = false;
}
that.position.left = o.helper ? co.left : 0;
}
if (cp.top < (that._helper ? co.top : 0)) {
that.size.height = that.size.height +
(that._helper ?
(that.position.top - co.top) :
that.position.top);
if (pRatio) {
that.size.width = that.size.height * that.aspectRatio;
continueResize = false;
}
that.position.top = that._helper ? co.top : 0;
}
isParent = that.containerElement.get(0) === that.element.parent().get(0);
isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));
if (isParent && isOffsetRelative) {
that.offset.left = that.parentData.left + that.position.left;
that.offset.top = that.parentData.top + that.position.top;
} else {
that.offset.left = that.element.offset().left;
that.offset.top = that.element.offset().top;
}
woset = Math.abs(that.sizeDiff.width +
(that._helper ?
that.offset.left - cop.left :
(that.offset.left - co.left)));
hoset = Math.abs(that.sizeDiff.height +
(that._helper ?
that.offset.top - cop.top :
(that.offset.top - co.top)));
if (woset + that.size.width >= that.parentData.width) {
that.size.width = that.parentData.width - woset;
if (pRatio) {
that.size.height = that.size.width / that.aspectRatio;
continueResize = false;
}
}
if (hoset + that.size.height >= that.parentData.height) {
that.size.height = that.parentData.height - hoset;
if (pRatio) {
that.size.width = that.size.height * that.aspectRatio;
continueResize = false;
}
}
if (!continueResize) {
that.position.left = that.prevPosition.left;
that.position.top = that.prevPosition.top;
that.size.width = that.prevSize.width;
that.size.height = that.prevSize.height;
}
},
stop: function () {
var that = $(this).resizable("instance"),
o = that.options,
co = that.containerOffset,
cop = that.containerPosition,
ce = that.containerElement,
helper = $(that.helper),
ho = helper.offset(),
w = helper.outerWidth() - that.sizeDiff.width,
h = helper.outerHeight() - that.sizeDiff.height;
if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) {
$(this).css({
left: ho.left - cop.left - co.left,
width: w,
height: h
});
}
if (that._helper && !o.animate && (/static/).test(ce.css("position"))) {
$(this).css({
left: ho.left - cop.left - co.left,
width: w,
height: h
});
}
}
});
$.ui.plugin.add("resizable", "alsoResize", {
start: function () {
var that = $(this).resizable("instance"),
o = that.options;
$(o.alsoResize).each(function () {
var el = $(this);
el.data("ui-resizable-alsoresize", {
width: parseFloat(el.width()), height: parseFloat(el.height()),
left: parseFloat(el.css("left")), top: parseFloat(el.css("top"))
});
});
},
resize: function (event, ui) {
var that = $(this).resizable("instance"),
o = that.options,
os = that.originalSize,
op = that.originalPosition,
delta = {
height: (that.size.height - os.height) || 0,
width: (that.size.width - os.width) || 0,
top: (that.position.top - op.top) || 0,
left: (that.position.left - op.left) || 0
};
$(o.alsoResize).each(function () {
var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
css = el.parents(ui.originalElement[0]).length ?
["width", "height"] :
["width", "height", "top", "left"];
$.each(css, function (i, prop) {
var sum = (start[prop] || 0) + (delta[prop] || 0);
if (sum && sum >= 0) {
style[prop] = sum || null;
}
});
el.css(style);
});
},
stop: function () {
$(this).removeData("ui-resizable-alsoresize");
}
});
$.ui.plugin.add("resizable", "ghost", {
start: function () {
var that = $(this).resizable("instance"), cs = that.size;
that.ghost = that.originalElement.clone();
that.ghost.css({
opacity: 0.25,
display: "block",
position: "relative",
height: cs.height,
width: cs.width,
margin: 0,
left: 0,
top: 0
});
that._addClass(that.ghost, "ui-resizable-ghost");
// DEPRECATED
// TODO: remove after 1.12
if ($.uiBackCompat !== false && typeof that.options.ghost === "string") {
// Ghost option
that.ghost.addClass(this.options.ghost);
}
that.ghost.appendTo(that.helper);
},
resize: function () {
var that = $(this).resizable("instance");
if (that.ghost) {
that.ghost.css({
position: "relative",
height: that.size.height,
width: that.size.width
});
}
},
stop: function () {
var that = $(this).resizable("instance");
if (that.ghost && that.helper) {
that.helper.get(0).removeChild(that.ghost.get(0));
}
}
});
$.ui.plugin.add("resizable", "grid", {
resize: function () {
var outerDimensions,
that = $(this).resizable("instance"),
o = that.options,
cs = that.size,
os = that.originalSize,
op = that.originalPosition,
a = that.axis,
grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
gridX = (grid[0] || 1),
gridY = (grid[1] || 1),
ox = Math.round((cs.width - os.width) / gridX) * gridX,
oy = Math.round((cs.height - os.height) / gridY) * gridY,
newWidth = os.width + ox,
newHeight = os.height + oy,
isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
isMinWidth = o.minWidth && (o.minWidth > newWidth),
isMinHeight = o.minHeight && (o.minHeight > newHeight);
o.grid = grid;
if (isMinWidth) {
newWidth += gridX;
}
if (isMinHeight) {
newHeight += gridY;
}
if (isMaxWidth) {
newWidth -= gridX;
}
if (isMaxHeight) {
newHeight -= gridY;
}
if (/^(se|s|e)$/.test(a)) {
that.size.width = newWidth;
that.size.height = newHeight;
} else if (/^(ne)$/.test(a)) {
that.size.width = newWidth;
that.size.height = newHeight;
that.position.top = op.top - oy;
} else if (/^(sw)$/.test(a)) {
that.size.width = newWidth;
that.size.height = newHeight;
that.position.left = op.left - ox;
} else {
if (newHeight - gridY <= 0 || newWidth - gridX <= 0) {
outerDimensions = that._getPaddingPlusBorderDimensions(this);
}
if (newHeight - gridY > 0) {
that.size.height = newHeight;
that.position.top = op.top - oy;
} else {
newHeight = gridY - outerDimensions.height;
that.size.height = newHeight;
that.position.top = op.top + os.height - newHeight;
}
if (newWidth - gridX > 0) {
that.size.width = newWidth;
that.position.left = op.left - ox;
} else {
newWidth = gridX - outerDimensions.width;
that.size.width = newWidth;
that.position.left = op.left + os.width - newWidth;
}
}
}
});
var widgetsResizable = $.ui.resizable;
/*!
* jQuery UI Selectable 1.12.1
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
//>>label: Selectable
//>>group: Interactions
//>>description: Allows groups of elements to be selected with the mouse.
//>>docs: http://api.jqueryui.com/selectable/
//>>demos: http://jqueryui.com/selectable/
//>>css.structure: ../../themes/base/selectable.css
var widgetsSelectable = $.widget("ui.selectable", $.ui.mouse, {
version: "1.12.1",
options: {
appendTo: "body",
autoRefresh: true,
distance: 0,
filter: "*",
tolerance: "touch",
// Callbacks
selected: null,
selecting: null,
start: null,
stop: null,
unselected: null,
unselecting: null
},
_create: function () {
var that = this;
this._addClass("ui-selectable");
this.dragged = false;
// Cache selectee children based on filter
this.refresh = function () {
that.elementPos = $(that.element[0]).offset();
that.selectees = $(that.options.filter, that.element[0]);
that._addClass(that.selectees, "ui-selectee");
that.selectees.each(function () {
var $this = $(this),
selecteeOffset = $this.offset(),
pos = {
left: selecteeOffset.left - that.elementPos.left,
top: selecteeOffset.top - that.elementPos.top
};
$.data(this, "selectable-item", {
element: this,
$element: $this,
left: pos.left,
top: pos.top,
right: pos.left + $this.outerWidth(),
bottom: pos.top + $this.outerHeight(),
startselected: false,
selected: $this.hasClass("ui-selected"),
selecting: $this.hasClass("ui-selecting"),
unselecting: $this.hasClass("ui-unselecting")
});
});
};
this.refresh();
this._mouseInit();
this.helper = $("
");
this._addClass(this.helper, "ui-selectable-helper");
},
_destroy: function () {
this.selectees.removeData("selectable-item");
this._mouseDestroy();
},
_mouseStart: function (event) {
var that = this,
options = this.options;
this.opos = [event.pageX, event.pageY];
this.elementPos = $(this.element[0]).offset();
if (this.options.disabled) {
return;
}
this.selectees = $(options.filter, this.element[0]);
this._trigger("start", event);
$(options.appendTo).append(this.helper);
// position helper (lasso)
this.helper.css({
"left": event.pageX,
"top": event.pageY,
"width": 0,
"height": 0
});
if (options.autoRefresh) {
this.refresh();
}
this.selectees.filter(".ui-selected").each(function () {
var selectee = $.data(this, "selectable-item");
selectee.startselected = true;
if (!event.metaKey && !event.ctrlKey) {
that._removeClass(selectee.$element, "ui-selected");
selectee.selected = false;
that._addClass(selectee.$element, "ui-unselecting");
selectee.unselecting = true;
// selectable UNSELECTING callback
that._trigger("unselecting", event, {
unselecting: selectee.element
});
}
});
$(event.target).parents().addBack().each(function () {
var doSelect,
selectee = $.data(this, "selectable-item");
if (selectee) {
doSelect = (!event.metaKey && !event.ctrlKey) ||
!selectee.$element.hasClass("ui-selected");
that._removeClass(selectee.$element, doSelect ? "ui-unselecting" : "ui-selected")
._addClass(selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting");
selectee.unselecting = !doSelect;
selectee.selecting = doSelect;
selectee.selected = doSelect;
// selectable (UN)SELECTING callback
if (doSelect) {
that._trigger("selecting", event, {
selecting: selectee.element
});
} else {
that._trigger("unselecting", event, {
unselecting: selectee.element
});
}
return false;
}
});
},
_mouseDrag: function (event) {
this.dragged = true;
if (this.options.disabled) {
return;
}
var tmp,
that = this,
options = this.options,
x1 = this.opos[0],
y1 = this.opos[1],
x2 = event.pageX,
y2 = event.pageY;
if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 });
this.selectees.each(function () {
var selectee = $.data(this, "selectable-item"),
hit = false,
offset = {};
//prevent helper from being selected if appendTo: selectable
if (!selectee || selectee.element === that.element[0]) {
return;
}
offset.left = selectee.left + that.elementPos.left;
offset.right = selectee.right + that.elementPos.left;
offset.top = selectee.top + that.elementPos.top;
offset.bottom = selectee.bottom + that.elementPos.top;
if (options.tolerance === "touch") {
hit = (!(offset.left > x2 || offset.right < x1 || offset.top > y2 ||
offset.bottom < y1));
} else if (options.tolerance === "fit") {
hit = (offset.left > x1 && offset.right < x2 && offset.top > y1 &&
offset.bottom < y2);
}
if (hit) {
// SELECT
if (selectee.selected) {
that._removeClass(selectee.$element, "ui-selected");
selectee.selected = false;
}
if (selectee.unselecting) {
that._removeClass(selectee.$element, "ui-unselecting");
selectee.unselecting = false;
}
if (!selectee.selecting) {
that._addClass(selectee.$element, "ui-selecting");
selectee.selecting = true;
// selectable SELECTING callback
that._trigger("selecting", event, {
selecting: selectee.element
});
}
} else {
// UNSELECT
if (selectee.selecting) {
if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
that._removeClass(selectee.$element, "ui-selecting");
selectee.selecting = false;
that._addClass(selectee.$element, "ui-selected");
selectee.selected = true;
} else {
that._removeClass(selectee.$element, "ui-selecting");
selectee.selecting = false;
if (selectee.startselected) {
that._addClass(selectee.$element, "ui-unselecting");
selectee.unselecting = true;
}
// selectable UNSELECTING callback
that._trigger("unselecting", event, {
unselecting: selectee.element
});
}
}
if (selectee.selected) {
if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
that._removeClass(selectee.$element, "ui-selected");
selectee.selected = false;
that._addClass(selectee.$element, "ui-unselecting");
selectee.unselecting = true;
// selectable UNSELECTING callback
that._trigger("unselecting", event, {
unselecting: selectee.element
});
}
}
}
});
return false;
},
_mouseStop: function (event) {
var that = this;
this.dragged = false;
$(".ui-unselecting", this.element[0]).each(function () {
var selectee = $.data(this, "selectable-item");
that._removeClass(selectee.$element, "ui-unselecting");
selectee.unselecting = false;
selectee.startselected = false;
that._trigger("unselected", event, {
unselected: selectee.element
});
});
$(".ui-selecting", this.element[0]).each(function () {
var selectee = $.data(this, "selectable-item");
that._removeClass(selectee.$element, "ui-selecting")
._addClass(selectee.$element, "ui-selected");
selectee.selecting = false;
selectee.selected = true;
selectee.startselected = true;
that._trigger("selected", event, {
selected: selectee.element
});
});
this._trigger("stop", event);
this.helper.remove();
return false;
}
});
/*!
* jQuery UI Sortable 1.12.1
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
//>>label: Sortable
//>>group: Interactions
//>>description: Enables items in a list to be sorted using the mouse.
//>>docs: http://api.jqueryui.com/sortable/
//>>demos: http://jqueryui.com/sortable/
//>>css.structure: ../../themes/base/sortable.css
var widgetsSortable = $.widget("ui.sortable", $.ui.mouse, {
version: "1.12.1",
widgetEventPrefix: "sort",
ready: false,
options: {
appendTo: "parent",
axis: false,
connectWith: false,
containment: false,
cursor: "auto",
cursorAt: false,
dropOnEmpty: true,
forcePlaceholderSize: false,
forceHelperSize: false,
grid: false,
handle: false,
helper: "original",
items: "> *",
opacity: false,
placeholder: false,
revert: false,
scroll: true,
scrollSensitivity: 20,
scrollSpeed: 20,
scope: "default",
tolerance: "intersect",
zIndex: 1000,
// Callbacks
activate: null,
beforeStop: null,
change: null,
deactivate: null,
out: null,
over: null,
receive: null,
remove: null,
sort: null,
start: null,
stop: null,
update: null
},
_isOverAxis: function (x, reference, size) {
return (x >= reference) && (x < (reference + size));
},
_isFloating: function (item) {
return (/left|right/).test(item.css("float")) ||
(/inline|table-cell/).test(item.css("display"));
},
_create: function () {
this.containerCache = {};
this._addClass("ui-sortable");
//Get the items
this.refresh();
//Let's determine the parent's offset
this.offset = this.element.offset();
//Initialize mouse events for interaction
this._mouseInit();
this._setHandleClassName();
//We're ready to go
this.ready = true;
},
_setOption: function (key, value) {
this._super(key, value);
if (key === "handle") {
this._setHandleClassName();
}
},
_setHandleClassName: function () {
var that = this;
this._removeClass(this.element.find(".ui-sortable-handle"), "ui-sortable-handle");
$.each(this.items, function () {
that._addClass(
this.instance.options.handle ?
this.item.find(this.instance.options.handle) :
this.item,
"ui-sortable-handle"
);
});
},
_destroy: function () {
this._mouseDestroy();
for (var i = this.items.length - 1; i >= 0; i--) {
this.items[i].item.removeData(this.widgetName + "-item");
}
return this;
},
_mouseCapture: function (event, overrideHandle) {
var currentItem = null,
validHandle = false,
that = this;
if (this.reverting) {
return false;
}
if (this.options.disabled || this.options.type === "static") {
return false;
}
//We have to refresh the items data once first
this._refreshItems(event);
//Find out if the clicked node (or one of its parents) is a actual item in this.items
$(event.target).parents().each(function () {
if ($.data(this, that.widgetName + "-item") === that) {
currentItem = $(this);
return false;
}
});
if ($.data(event.target, that.widgetName + "-item") === that) {
currentItem = $(event.target);
}
if (!currentItem) {
return false;
}
if (this.options.handle && !overrideHandle) {
$(this.options.handle, currentItem).find("*").addBack().each(function () {
if (this === event.target) {
validHandle = true;
}
});
if (!validHandle) {
return false;
}
}
this.currentItem = currentItem;
this._removeCurrentsFromItems();
return true;
},
_mouseStart: function (event, overrideHandle, noActivation) {
var i, body,
o = this.options;
this.currentContainer = this;
//We only need to call refreshPositions, because the refreshItems call has been moved to
// mouseCapture
this.refreshPositions();
//Create and append the visible helper
this.helper = this._createHelper(event);
//Cache the helper size
this._cacheHelperProportions();
/*
* - Position generation -
* This block generates everything position related - it's the core of draggables.
*/
//Cache the margins of the original element
this._cacheMargins();
//Get the next scrolling parent
this.scrollParent = this.helper.scrollParent();
//The element's absolute position on the page minus margins
this.offset = this.currentItem.offset();
this.offset = {
top: this.offset.top - this.margins.top,
left: this.offset.left - this.margins.left
};
$.extend(this.offset, {
click: { //Where the click happened, relative to the element
left: event.pageX - this.offset.left,
top: event.pageY - this.offset.top
},
parent: this._getParentOffset(),
// This is a relative to absolute position minus the actual position calculation -
// only used for relative positioned helper
relative: this._getRelativeOffset()
});
// Only after we got the offset, we can change the helper's position to absolute
// TODO: Still need to figure out a way to make relative sorting possible
this.helper.css("position", "absolute");
this.cssPosition = this.helper.css("position");
//Generate the original position
this.originalPosition = this._generatePosition(event);
this.originalPageX = event.pageX;
this.originalPageY = event.pageY;
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
//Cache the former DOM position
this.domPosition = {
prev: this.currentItem.prev()[0],
parent: this.currentItem.parent()[0]
};
// If the helper is not the original, hide the original so it's not playing any role during
// the drag, won't cause anything bad this way
if (this.helper[0] !== this.currentItem[0]) {
this.currentItem.hide();
}
//Create the placeholder
this._createPlaceholder();
//Set a containment if given in the options
if (o.containment) {
this._setContainment();
}
if (o.cursor && o.cursor !== "auto") { // cursor option
body = this.document.find("body");
// Support: IE
this.storedCursor = body.css("cursor");
body.css("cursor", o.cursor);
this.storedStylesheet =
$("").appendTo(body);
}
if (o.opacity) { // opacity option
if (this.helper.css("opacity")) {
this._storedOpacity = this.helper.css("opacity");
}
this.helper.css("opacity", o.opacity);
}
if (o.zIndex) { // zIndex option
if (this.helper.css("zIndex")) {
this._storedZIndex = this.helper.css("zIndex");
}
this.helper.css("zIndex", o.zIndex);
}
//Prepare scrolling
if (this.scrollParent[0] !== this.document[0] &&
this.scrollParent[0].tagName !== "HTML") {
this.overflowOffset = this.scrollParent.offset();
}
//Call callbacks
this._trigger("start", event, this._uiHash());
//Recache the helper size
if (!this._preserveHelperProportions) {
this._cacheHelperProportions();
}
//Post "activate" events to possible containers
if (!noActivation) {
for (i = this.containers.length - 1; i >= 0; i--) {
this.containers[i]._trigger("activate", event, this._uiHash(this));
}
}
//Prepare possible droppables
if ($.ui.ddmanager) {
$.ui.ddmanager.current = this;
}
if ($.ui.ddmanager && !o.dropBehaviour) {
$.ui.ddmanager.prepareOffsets(this, event);
}
this.dragging = true;
this._addClass(this.helper, "ui-sortable-helper");
// Execute the drag once - this causes the helper not to be visiblebefore getting its
// correct position
this._mouseDrag(event);
return true;
},
_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;
}
// Only put the placeholder inside the current Container, skip all
// items from other containers. This works because when moving
// an item from one container to another the
// currentContainer is switched before the placeholder is moved.
//
// Without this, moving items in "sub-sortables" can cause
// the placeholder to jitter between the outer and inner container.
if (item.instance !== this.currentContainer) {
continue;
}
// Cannot intersect with itself
// no useless actions that have been done before
// no action if the item moved is the parent of the item checked
if (itemElement !== this.currentItem[0] &&
this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
!$.contains(this.placeholder[0], itemElement) &&
(this.options.type === "semi-dynamic" ?
!$.contains(this.element[0], itemElement) :
true
)
) {
this.direction = intersection === 1 ? "down" : "up";
if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
this._rearrange(event, item);
} else {
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;
},
_mouseStop: function (event, noPropagation) {
if (!event) {
return;
}
//If we are using droppables, inform the manager about the drop
if ($.ui.ddmanager && !this.options.dropBehaviour) {
$.ui.ddmanager.drop(this, event);
}
if (this.options.revert) {
var that = this,
cur = this.placeholder.offset(),
axis = this.options.axis,
animation = {};
if (!axis || axis === "x") {
animation.left = cur.left - this.offset.parent.left - this.margins.left +
(this.offsetParent[0] === this.document[0].body ?
0 :
this.offsetParent[0].scrollLeft
);
}
if (!axis || axis === "y") {
animation.top = cur.top - this.offset.parent.top - this.margins.top +
(this.offsetParent[0] === this.document[0].body ?
0 :
this.offsetParent[0].scrollTop
);
}
this.reverting = true;
$(this.helper).animate(
animation,
parseInt(this.options.revert, 10) || 500,
function () {
that._clear(event);
}
);
} else {
this._clear(event, noPropagation);
}
return false;
},
cancel: function () {
if (this.dragging) {
this._mouseUp(new $.Event("mouseup", { target: null }));
if (this.options.helper === "original") {
this.currentItem.css(this._storedCSS);
this._removeClass(this.currentItem, "ui-sortable-helper");
} else {
this.currentItem.show();
}
//Post deactivating events to containers
for (var i = this.containers.length - 1; i >= 0; i--) {
this.containers[i]._trigger("deactivate", null, this._uiHash(this));
if (this.containers[i].containerCache.over) {
this.containers[i]._trigger("out", null, this._uiHash(this));
this.containers[i].containerCache.over = 0;
}
}
}
if (this.placeholder) {
//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
// it unbinds ALL events from the original node!
if (this.placeholder[0].parentNode) {
this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
}
if (this.options.helper !== "original" && this.helper &&
this.helper[0].parentNode) {
this.helper.remove();
}
$.extend(this, {
helper: null,
dragging: false,
reverting: false,
_noFinalSort: null
});
if (this.domPosition.prev) {
$(this.domPosition.prev).after(this.currentItem);
} else {
$(this.domPosition.parent).prepend(this.currentItem);
}
}
return this;
},
serialize: function (o) {
var items = this._getItemsAsjQuery(o && o.connected),
str = [];
o = o || {};
$(items).each(function () {
var res = ($(o.item || this).attr(o.attribute || "id") || "")
.match(o.expression || (/(.+)[\-=_](.+)/));
if (res) {
str.push(
(o.key || res[1] + "[]") +
"=" + (o.key && o.expression ? res[1] : res[2]));
}
});
if (!str.length && o.key) {
str.push(o.key + "=");
}
return str.join("&");
},
toArray: function (o) {
var items = this._getItemsAsjQuery(o && o.connected),
ret = [];
o = o || {};
items.each(function () {
ret.push($(o.item || this).attr(o.attribute || "id") || "");
});
return ret;
},
/* Be careful with the following core functions */
_intersectsWith: function (item) {
var x1 = this.positionAbs.left,
x2 = x1 + this.helperProportions.width,
y1 = this.positionAbs.top,
y2 = y1 + this.helperProportions.height,
l = item.left,
r = l + item.width,
t = item.top,
b = t + item.height,
dyClick = this.offset.click.top,
dxClick = this.offset.click.left,
isOverElementHeight = (this.options.axis === "x") || ((y1 + dyClick) > t &&
(y1 + dyClick) < b),
isOverElementWidth = (this.options.axis === "y") || ((x1 + dxClick) > l &&
(x1 + dxClick) < r),
isOverElement = isOverElementHeight && isOverElementWidth;
if (this.options.tolerance === "pointer" ||
this.options.forcePointerForContainers ||
(this.options.tolerance !== "pointer" &&
this.helperProportions[this.floating ? "width" : "height"] >
item[this.floating ? "width" : "height"])
) {
return isOverElement;
} else {
return (l < x1 + (this.helperProportions.width / 2) && // Right Half
x2 - (this.helperProportions.width / 2) < r && // Left Half
t < y1 + (this.helperProportions.height / 2) && // Bottom Half
y2 - (this.helperProportions.height / 2) < b); // Top Half
}
},
_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 this.floating ?
((horizontalDirection === "right" || verticalDirection === "down") ? 2 : 1)
: (verticalDirection && (verticalDirection === "down" ? 2 : 1));
},
_intersectsWithSides: function (item) {
var isOverBottomHalf = this._isOverAxis(this.positionAbs.top +
this.offset.click.top, item.top + (item.height / 2), item.height),
isOverRightHalf = this._isOverAxis(this.positionAbs.left +
this.offset.click.left, item.left + (item.width / 2), item.width),
verticalDirection = this._getDragVerticalDirection(),
horizontalDirection = this._getDragHorizontalDirection();
if (this.floating && horizontalDirection) {
return ((horizontalDirection === "right" && isOverRightHalf) ||
(horizontalDirection === "left" && !isOverRightHalf));
} else {
return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) ||
(verticalDirection === "up" && !isOverBottomHalf));
}
},
_getDragVerticalDirection: function () {
var delta = this.positionAbs.top - this.lastPositionAbs.top;
return delta !== 0 && (delta > 0 ? "down" : "up");
},
_getDragHorizontalDirection: function () {
var delta = this.positionAbs.left - this.lastPositionAbs.left;
return delta !== 0 && (delta > 0 ? "right" : "left");
},
refresh: function (event) {
this._refreshItems(event);
this._setHandleClassName();
this.refreshPositions();
return this;
},
_connectWith: function () {
var options = this.options;
return options.connectWith.constructor === String ?
[options.connectWith] :
options.connectWith;
},
_getItemsAsjQuery: function (connected) {
var i, j, cur, inst,
items = [],
queries = [],
connectWith = this._connectWith();
if (connectWith && connected) {
for (i = connectWith.length - 1; i >= 0; i--) {
cur = $(connectWith[i], this.document[0]);
for (j = cur.length - 1; j >= 0; j--) {
inst = $.data(cur[j], this.widgetFullName);
if (inst && inst !== this && !inst.options.disabled) {
queries.push([$.isFunction(inst.options.items) ?
inst.options.items.call(inst.element) :
$(inst.options.items, inst.element)
.not(".ui-sortable-helper")
.not(".ui-sortable-placeholder"), inst]);
}
}
}
}
queries.push([$.isFunction(this.options.items) ?
this.options.items
.call(this.element, null, { options: this.options, item: this.currentItem }) :
$(this.options.items, this.element)
.not(".ui-sortable-helper")
.not(".ui-sortable-placeholder"), this]);
function addItems() {
items.push(this);
}
for (i = queries.length - 1; i >= 0; i--) {
queries[i][0].each(addItems);
}
return $(items);
},
_removeCurrentsFromItems: function () {
var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
this.items = $.grep(this.items, function (item) {
for (var j = 0; j < list.length; j++) {
if (list[j] === item.item[0]) {
return false;
}
}
return true;
});
},
_refreshItems: function (event) {
this.items = [];
this.containers = [this];
var i, j, cur, inst, targetData, _queries, item, queriesLength,
items = this.items,
queries = [[$.isFunction(this.options.items) ?
this.options.items.call(this.element[0], event, { item: this.currentItem }) :
$(this.options.items, this.element), this]],
connectWith = this._connectWith();
//Shouldn't be run the first time through due to massive slow-down
if (connectWith && this.ready) {
for (i = connectWith.length - 1; i >= 0; i--) {
cur = $(connectWith[i], this.document[0]);
for (j = cur.length - 1; j >= 0; j--) {
inst = $.data(cur[j], this.widgetFullName);
if (inst && inst !== this && !inst.options.disabled) {
queries.push([$.isFunction(inst.options.items) ?
inst.options.items
.call(inst.element[0], event, { item: this.currentItem }) :
$(inst.options.items, inst.element), inst]);
this.containers.push(inst);
}
}
}
}
for (i = queries.length - 1; i >= 0; i--) {
targetData = queries[i][1];
_queries = queries[i][0];
for (j = 0, queriesLength = _queries.length; j < queriesLength; j++) {
item = $(_queries[j]);
// Data for target checking (mouse manager)
item.data(this.widgetName + "-item", targetData);
items.push({
item: item,
instance: targetData,
width: 0, height: 0,
left: 0, top: 0
});
}
}
},
refreshPositions: function (fast) {
// Determine whether items are being displayed horizontally
this.floating = this.items.length ?
this.options.axis === "x" || this._isFloating(this.items[0].item) :
false;
//This has to be redone because due to the item being moved out/into the offsetParent,
// the offsetParent's position will change
if (this.offsetParent && this.helper) {
this.offset.parent = this._getParentOffset();
}
var i, item, t, p;
for (i = this.items.length - 1; i >= 0; i--) {
item = this.items[i];
//We ignore calculating positions of all connected containers when we're not over them
if (item.instance !== this.currentContainer && this.currentContainer &&
item.item[0] !== this.currentItem[0]) {
continue;
}
t = this.options.toleranceElement ?
$(this.options.toleranceElement, item.item) :
item.item;
if (!fast) {
item.width = t.outerWidth();
item.height = t.outerHeight();
}
p = t.offset();
item.left = p.left;
item.top = p.top;
}
if (this.options.custom && this.options.custom.refreshContainers) {
this.options.custom.refreshContainers.call(this);
} else {
for (i = this.containers.length - 1; i >= 0; i--) {
p = this.containers[i].element.offset();
this.containers[i].containerCache.left = p.left;
this.containers[i].containerCache.top = p.top;
this.containers[i].containerCache.width =
this.containers[i].element.outerWidth();
this.containers[i].containerCache.height =
this.containers[i].element.outerHeight();
}
}
return this;
},
_createPlaceholder: function (that) {
that = that || this;
var className,
o = that.options;
if (!o.placeholder || o.placeholder.constructor === String) {
className = o.placeholder;
o.placeholder = {
element: function () {
var nodeName = that.currentItem[0].nodeName.toLowerCase(),
element = $("<" + nodeName + ">", that.document[0]);
that._addClass(element, "ui-sortable-placeholder",
className || that.currentItem[0].className)
._removeClass(element, "ui-sortable-helper");
if (nodeName === "tbody") {
that._createTrPlaceholder(
that.currentItem.find("tr").eq(0),
$("
", that.document[0]).appendTo(element)
);
} else if (nodeName === "tr") {
that._createTrPlaceholder(that.currentItem, element);
} else if (nodeName === "img") {
element.attr("src", that.currentItem.attr("src"));
}
if (!className) {
element.css("visibility", "hidden");
}
return element;
},
update: function (container, p) {
// 1. If a className is set as 'placeholder option, we don't force sizes -
// the class is responsible for that
// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
// class name is specified
if (className && !o.forcePlaceholderSize) {
return;
}
//If the element doesn't have a actual height by itself (without styles coming
// from a stylesheet), it receives the inline height from the dragged item
if (!p.height()) {
p.height(
that.currentItem.innerHeight() -
parseInt(that.currentItem.css("paddingTop") || 0, 10) -
parseInt(that.currentItem.css("paddingBottom") || 0, 10));
}
if (!p.width()) {
p.width(
that.currentItem.innerWidth() -
parseInt(that.currentItem.css("paddingLeft") || 0, 10) -
parseInt(that.currentItem.css("paddingRight") || 0, 10));
}
}
};
}
//Create the placeholder
that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
//Append it after the actual current item
that.currentItem.after(that.placeholder);
//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
o.placeholder.update(that, that.placeholder);
},
_createTrPlaceholder: function (sourceTr, targetTr) {
var that = this;
sourceTr.children().each(function () {
$("| | ", that.document[0])
.attr("colspan", $(this).attr("colspan") || 1)
.appendTo(targetTr);
});
},
_contactContainers: function (event) {
var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
floating, axis,
innermostContainer = null,
innermostIndex = null;
// Get innermost container that intersects with item
for (i = this.containers.length - 1; i >= 0; i--) {
// Never consider a container that's located within the item itself
if ($.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 &&
$.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;
}
}
}
// If no intersecting containers found, return
if (!innermostContainer) {
return;
}
// Move the item into the container if it's not there already
if (this.containers.length === 1) {
if (!this.containers[innermostIndex].containerCache.over) {
this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
this.containers[innermostIndex].containerCache.over = 1;
}
} else {
// When entering a new container, we will find the item with the least distance and
// append our item near it
dist = 10000;
itemWithLeastDistance = null;
floating = innermostContainer.floating || this._isFloating(this.currentItem);
posProperty = floating ? "left" : "top";
sizeProperty = floating ? "width" : "height";
axis = floating ? "pageX" : "pageY";
for (j = this.items.length - 1; j >= 0; j--) {
if (!$.contains(
this.containers[innermostIndex].element[0], this.items[j].item[0])
) {
continue;
}
if (this.items[j].item[0] === this.currentItem[0]) {
continue;
}
cur = this.items[j].item.offset()[posProperty];
nearBottom = false;
if (event[axis] - cur > this.items[j][sizeProperty] / 2) {
nearBottom = true;
}
if (Math.abs(event[axis] - cur) < dist) {
dist = Math.abs(event[axis] - cur);
itemWithLeastDistance = this.items[j];
this.direction = nearBottom ? "up" : "down";
}
}
//Check if dropOnEmpty is enabled
if (!itemWithLeastDistance && !this.options.dropOnEmpty) {
return;
}
if (this.currentContainer === this.containers[innermostIndex]) {
if (!this.currentContainer.containerCache.over) {
this.containers[innermostIndex]._trigger("over", event, this._uiHash());
this.currentContainer.containerCache.over = 1;
}
return;
}
itemWithLeastDistance ?
this._rearrange(event, itemWithLeastDistance, null, true) :
this._rearrange(event, null, this.containers[innermostIndex].element, true);
this._trigger("change", event, this._uiHash());
this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
this.currentContainer = this.containers[innermostIndex];
//Update the placeholder
this.options.placeholder.update(this.currentContainer, this.placeholder);
this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
this.containers[innermostIndex].containerCache.over = 1;
}
},
_createHelper: function (event) {
var o = this.options,
helper = $.isFunction(o.helper) ?
$(o.helper.apply(this.element[0], [event, this.currentItem])) :
(o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
//Add the helper to the DOM if that didn't happen already
if (!helper.parents("body").length) {
$(o.appendTo !== "parent" ?
o.appendTo :
this.currentItem[0].parentNode)[0].appendChild(helper[0]);
}
if (helper[0] === this.currentItem[0]) {
this._storedCSS = {
width: this.currentItem[0].style.width,
height: this.currentItem[0].style.height,
position: this.currentItem.css("position"),
top: this.currentItem.css("top"),
left: this.currentItem.css("left")
};
}
if (!helper[0].style.width || o.forceHelperSize) {
helper.width(this.currentItem.width());
}
if (!helper[0].style.height || o.forceHelperSize) {
helper.height(this.currentItem.height());
}
return helper;
},
_adjustOffsetFromHelper: function (obj) {
if (typeof obj === "string") {
obj = obj.split(" ");
}
if ($.isArray(obj)) {
obj = { left: +obj[0], top: +obj[1] || 0 };
}
if ("left" in obj) {
this.offset.click.left = obj.left + this.margins.left;
}
if ("right" in obj) {
this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
}
if ("top" in obj) {
this.offset.click.top = obj.top + this.margins.top;
}
if ("bottom" in obj) {
this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
}
},
_getParentOffset: function () {
//Get the offsetParent and cache its position
this.offsetParent = this.helper.offsetParent();
var po = this.offsetParent.offset();
// This is a special case where we need to modify a offset calculated on start, since the
// following happened:
// 1. The position of the helper is absolute, so it's position is calculated based on the
// next positioned parent
// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
// the document, which means that the scroll is included in the initial calculation of the
// offset of the parent, and never recalculated upon drag
if (this.cssPosition === "absolute" && this.scrollParent[0] !== this.document[0] &&
$.contains(this.scrollParent[0], this.offsetParent[0])) {
po.left += this.scrollParent.scrollLeft();
po.top += this.scrollParent.scrollTop();
}
// This needs to be actually done for all browsers, since pageX/pageY includes this
// information with an ugly IE fix
if (this.offsetParent[0] === this.document[0].body ||
(this.offsetParent[0].tagName &&
this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
po = { top: 0, left: 0 };
}
return {
top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
};
},
_getRelativeOffset: function () {
if (this.cssPosition === "relative") {
var p = this.currentItem.position();
return {
top: p.top - (parseInt(this.helper.css("top"), 10) || 0) +
this.scrollParent.scrollTop(),
left: p.left - (parseInt(this.helper.css("left"), 10) || 0) +
this.scrollParent.scrollLeft()
};
} else {
return { top: 0, left: 0 };
}
},
_cacheMargins: function () {
this.margins = {
left: (parseInt(this.currentItem.css("marginLeft"), 10) || 0),
top: (parseInt(this.currentItem.css("marginTop"), 10) || 0)
};
},
_cacheHelperProportions: function () {
this.helperProportions = {
width: this.helper.outerWidth(),
height: this.helper.outerHeight()
};
},
_setContainment: function () {
var ce, co, over,
o = this.options;
if (o.containment === "parent") {
o.containment = this.helper[0].parentNode;
}
if (o.containment === "document" || o.containment === "window") {
this.containment = [
0 - this.offset.relative.left - this.offset.parent.left,
0 - this.offset.relative.top - this.offset.parent.top,
o.containment === "document" ?
this.document.width() :
this.window.width() - this.helperProportions.width - this.margins.left,
(o.containment === "document" ?
(this.document.height() || document.body.parentNode.scrollHeight) :
this.window.height() || this.document[0].body.parentNode.scrollHeight
) - this.helperProportions.height - this.margins.top
];
}
if (!(/^(document|window|parent)$/).test(o.containment)) {
ce = $(o.containment)[0];
co = $(o.containment).offset();
over = ($(ce).css("overflow") !== "hidden");
this.containment = [
co.left + (parseInt($(ce).css("borderLeftWidth"), 10) || 0) +
(parseInt($(ce).css("paddingLeft"), 10) || 0) - this.margins.left,
co.top + (parseInt($(ce).css("borderTopWidth"), 10) || 0) +
(parseInt($(ce).css("paddingTop"), 10) || 0) - this.margins.top,
co.left + (over ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) -
(parseInt($(ce).css("borderLeftWidth"), 10) || 0) -
(parseInt($(ce).css("paddingRight"), 10) || 0) -
this.helperProportions.width - this.margins.left,
co.top + (over ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) -
(parseInt($(ce).css("borderTopWidth"), 10) || 0) -
(parseInt($(ce).css("paddingBottom"), 10) || 0) -
this.helperProportions.height - this.margins.top
];
}
},
_convertPositionTo: function (d, pos) {
if (!pos) {
pos = this.position;
}
var mod = d === "absolute" ? 1 : -1,
scroll = this.cssPosition === "absolute" &&
!(this.scrollParent[0] !== this.document[0] &&
$.contains(this.scrollParent[0], this.offsetParent[0])) ?
this.offsetParent :
this.scrollParent,
scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
return {
top: (
// The absolute mouse position
pos.top +
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.top * mod +
// The offsetParent's offset without borders (offset + border)
this.offset.parent.top * mod -
((this.cssPosition === "fixed" ?
-this.scrollParent.scrollTop() :
(scrollIsRootNode ? 0 : scroll.scrollTop())) * mod)
),
left: (
// The absolute mouse position
pos.left +
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.left * mod +
// The offsetParent's offset without borders (offset + border)
this.offset.parent.left * mod -
((this.cssPosition === "fixed" ?
-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
scroll.scrollLeft()) * mod)
)
};
},
_generatePosition: function (event) {
var top, left,
o = this.options,
pageX = event.pageX,
pageY = event.pageY,
scroll = this.cssPosition === "absolute" &&
!(this.scrollParent[0] !== this.document[0] &&
$.contains(this.scrollParent[0], this.offsetParent[0])) ?
this.offsetParent :
this.scrollParent,
scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
// This is another very weird special case that only happens for relative elements:
// 1. If the css position is relative
// 2. and the scroll parent is the document or similar to the offset parent
// we have to refresh the relative offset during the scroll so there are no jumps
if (this.cssPosition === "relative" && !(this.scrollParent[0] !== this.document[0] &&
this.scrollParent[0] !== this.offsetParent[0])) {
this.offset.relative = this._getRelativeOffset();
}
/*
* - Position constraining -
* Constrain the position to a mix of grid, containment.
*/
if (this.originalPosition) { //If we are not dragging yet, we won't check for options
if (this.containment) {
if (event.pageX - this.offset.click.left < this.containment[0]) {
pageX = this.containment[0] + this.offset.click.left;
}
if (event.pageY - this.offset.click.top < this.containment[1]) {
pageY = this.containment[1] + this.offset.click.top;
}
if (event.pageX - this.offset.click.left > this.containment[2]) {
pageX = this.containment[2] + this.offset.click.left;
}
if (event.pageY - this.offset.click.top > this.containment[3]) {
pageY = this.containment[3] + this.offset.click.top;
}
}
if (o.grid) {
top = this.originalPageY + Math.round((pageY - this.originalPageY) /
o.grid[1]) * o.grid[1];
pageY = this.containment ?
((top - this.offset.click.top >= this.containment[1] &&
top - this.offset.click.top <= this.containment[3]) ?
top :
((top - this.offset.click.top >= this.containment[1]) ?
top - o.grid[1] : top + o.grid[1])) :
top;
left = this.originalPageX + Math.round((pageX - this.originalPageX) /
o.grid[0]) * o.grid[0];
pageX = this.containment ?
((left - this.offset.click.left >= this.containment[0] &&
left - this.offset.click.left <= this.containment[2]) ?
left :
((left - this.offset.click.left >= this.containment[0]) ?
left - o.grid[0] : left + o.grid[0])) :
left;
}
}
return {
top: (
// The absolute mouse position
pageY -
// Click offset (relative to the element)
this.offset.click.top -
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.top -
// The offsetParent's offset without borders (offset + border)
this.offset.parent.top +
((this.cssPosition === "fixed" ?
-this.scrollParent.scrollTop() :
(scrollIsRootNode ? 0 : scroll.scrollTop())))
),
left: (
// The absolute mouse position
pageX -
// Click offset (relative to the element)
this.offset.click.left -
// Only for relative positioned nodes: Relative offset from element to offset parent
this.offset.relative.left -
// The offsetParent's offset without borders (offset + border)
this.offset.parent.left +
((this.cssPosition === "fixed" ?
-this.scrollParent.scrollLeft() :
scrollIsRootNode ? 0 : scroll.scrollLeft()))
)
};
},
_rearrange: function (event, i, a, hardRefresh) {
a ? a[0].appendChild(this.placeholder[0]) :
i.item[0].parentNode.insertBefore(this.placeholder[0],
(this.direction === "down" ? 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);
}
});
},
_clear: function (event, noPropagation) {
this.reverting = false;
// We delay all events that have to be triggered to after the point where the placeholder
// has been removed and everything else normalized again
var i,
delayedTriggers = [];
// We first have to update the dom position of the actual currentItem
// Note: don't do it if the current item is already removed (by a user), or it gets
// reappended (see #4088)
if (!this._noFinalSort && this.currentItem.parent().length) {
this.placeholder.before(this.currentItem);
}
this._noFinalSort = null;
if (this.helper[0] === this.currentItem[0]) {
for (i in this._storedCSS) {
if (this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
this._storedCSS[i] = "";
}
}
this.currentItem.css(this._storedCSS);
this._removeClass(this.currentItem, "ui-sortable-helper");
} else {
this.currentItem.show();
}
if (this.fromOutside && !noPropagation) {
delayedTriggers.push(function (event) {
this._trigger("receive", event, this._uiHash(this.fromOutside));
});
}
if ((this.fromOutside ||
this.domPosition.prev !==
this.currentItem.prev().not(".ui-sortable-helper")[0] ||
this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
// Trigger update callback if the DOM position has changed
delayedTriggers.push(function (event) {
this._trigger("update", event, this._uiHash());
});
}
// Check if the items Container has Changed and trigger appropriate
// events.
if (this !== this.currentContainer) {
if (!noPropagation) {
delayedTriggers.push(function (event) {
this._trigger("remove", event, this._uiHash());
});
delayedTriggers.push((function (c) {
return function (event) {
c._trigger("receive", event, this._uiHash(this));
};
}).call(this, this.currentContainer));
delayedTriggers.push((function (c) {
return function (event) {
c._trigger("update", event, this._uiHash(this));
};
}).call(this, this.currentContainer));
}
}
//Post events to containers
function delayEvent(type, instance, container) {
return function (event) {
container._trigger(type, event, instance._uiHash(instance));
};
}
for (i = this.containers.length - 1; i >= 0; i--) {
if (!noPropagation) {
delayedTriggers.push(delayEvent("deactivate", this, this.containers[i]));
}
if (this.containers[i].containerCache.over) {
delayedTriggers.push(delayEvent("out", this, this.containers[i]));
this.containers[i].containerCache.over = 0;
}
}
//Do what was originally in plugins
if (this.storedCursor) {
this.document.find("body").css("cursor", this.storedCursor);
this.storedStylesheet.remove();
}
if (this._storedOpacity) {
this.helper.css("opacity", this._storedOpacity);
}
if (this._storedZIndex) {
this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
}
this.dragging = false;
if (!noPropagation) {
this._trigger("beforeStop", event, this._uiHash());
}
//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
// it unbinds ALL events from the original node!
this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
if (!this.cancelHelperRemoval) {
if (this.helper[0] !== this.currentItem[0]) {
this.helper.remove();
}
this.helper = null;
}
if (!noPropagation) {
for (i = 0; i < delayedTriggers.length; i++) {
// Trigger all delayed events
delayedTriggers[i].call(this, event);
}
this._trigger("stop", event, this._uiHash());
}
this.fromOutside = false;
return !this.cancelHelperRemoval;
},
_trigger: function () {
if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
this.cancel();
}
},
_uiHash: function (_inst) {
var inst = _inst || this;
return {
helper: inst.helper,
placeholder: inst.placeholder || $([]),
position: inst.position,
originalPosition: inst.originalPosition,
offset: inst.positionAbs,
item: inst.currentItem,
sender: _inst ? _inst.element : null
};
}
});
}));