我曾在我的應用程序相同的問題,甚至包括觸摸一拳。我不得不做一個很好的研究,以找到停止jQuery UI拖動的問題。 發生的問題是在事件中設置了preventDefault(僅當包含錘子時),才能從jquery ui更改觸發器方法的結果。
那麼,讓我們回到一點: 你應該看到的第一種方法是_mouseMove()
,它與mousemove事件相關聯。 僅當條件(this._mouseStart(this._mouseDownEvent, event) !== false)
爲真時,纔會觸發拖動。
_mouseMove: function (event) {
// IE mouseup check - mouseup happened when mouse was out of window
if ($.ui.ie && (!document.documentMode || document.documentMode < 9) && !event.button) {
return this._mouseUp(event);
}
if (this._mouseStarted) {
this._mouseDrag(event);
return event.preventDefault();
}
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
this._mouseStarted =
(this._mouseStart(this._mouseDownEvent, event) !== false);
(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
}
return !this._mouseStarted;
}
下一個方法將創建助手(元素的克隆),在元素設置一些CSS和返回true(值我們預期),除非this._trigger("start", event)
返回false。
_mouseStart: function(event) {
var o = this.options;
//Create and append the visible helper
this.helper = this._createHelper(event);
this.helper.addClass("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();
this.offsetParent = this.helper.offsetParent();
this.offsetParentCssPosition = this.offsetParent.css("position");
//The element's absolute position on the page minus margins
this.offset = this.positionAbs = this.element.offset();
this.offset = {
top: this.offset.top - this.margins.top,
left: this.offset.left - this.margins.left
};
//Reset scroll cache
this.offset.scroll = false;
$.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(),
relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
});
//Generate the original position
this.originalPosition = this.position = 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));
//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);
}
this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
//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;
}
下面是第一個_trigger的調用,它來自於拖拽控件。
_trigger: function (type, event, ui) {
ui = ui || this._uiHash();
$.ui.plugin.call(this, type, [event, ui]);
//The absolute position has to be recalculated after plugins
if(type === "drag") {
this.positionAbs = this._convertPositionTo("absolute");
}
return $.Widget.prototype._trigger.call(this, type, event, ui);
}
此時結果將調用另一個觸發方式(此時從$ .Widget),而這也正是我們的問題點。
_trigger: function (type, event, data) {
var prop, orig,
callback = this.options[type];
data = data || {};
event = $.Event(event);
event.type = (type === this.widgetEventPrefix ?
type :
this.widgetEventPrefix + type).toLowerCase();
// the original event may come from any element
// so we need to reset the target on the new event
event.target = this.element[0];
// copy original event properties over to the new event
orig = event.originalEvent;
if (orig) {
for (prop in orig) {
if (!(prop in event)) {
event[prop] = orig[prop];
}
}
}
return !($.isFunction(callback) && callback.apply(this.element[0], [event].concat(data)) === false || event.isDefaultPrevented());
}
return !($.isFunction(callback) && callback.apply(this.element[0], [event].concat(data)) === false || event.isDefaultPrevented());
我們的問題正是在這一行。更具體的||之前event.isDefaultPrevented()
。 當包含錘子時,方法event.isDefaultPrevented()
會生成真值,一旦返回之前值被拒絕,最終值將爲假。 (不包括錘子包括event.isDefaultPrevented()
返回假如預期。) 備份在我們的_moseMouve()
,而不是調用_mouseDrag()
方法它會調用_mouseUp()
。你可以看到它會解除事件並致電_mouseStop()
。
_mouseUp: function (event) {
$(document)
.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
if (this._mouseStarted) {
this._mouseStarted = false;
if (event.target === this._mouseDownEvent.target) {
$.data(event.target, this.widgetName + ".preventClickEvent", true);
}
this._mouseStop(event);
}
return false;
}
如果通過AND(& &)改變OR(||)運算符,它會正常工作。當然,這不是一個小小的改變,我一直在測試它,直到現在我還沒有發現任何問題。行會是這樣:
return !($.isFunction(callback) && callback.apply(this.element[0], [event].concat(data)) === false && event.isDefaultPrevented());
正如我所說的,它不是100%安全的,但是到現在爲止我沒有找到一個理由讓||而不是& &。我會繼續測試幾天。 除此之外,我已經發送了一封電子郵件給jquery ui的首席開發人員詢問。
難道開發商不斷回到你定了嗎? – rickdmer
不幸的是,我發了兩封電子郵件,但我沒有得到任何回覆。不過,我保持這種改變,到目前爲止我沒有發現任何問題。 –
Upvoted的精彩,努力和搖擺 –