【发布时间】:2012-03-02 21:46:31
【问题描述】:
我一直在开发一个扩展 ui.mouse 的 jquery 小部件。
小部件需要通过创建元素并将它们附加到 this.element 来对鼠标事件做出反应。
如果小部件应用于不能包含子元素的 HTML 元素(例如 IMG 标记),小部件会创建代理包装元素并包装 this.element。
如果我用包装元素替换 this.element,小部件触发的事件永远不会被处理,因为小部件实例上的 .bind() 调用会将处理程序应用于原始元素,而不是包装。
如果我不将 this.element 替换为 wrapper 元素,则 ui.mouse 定义的 _mouse* 事件不会被正确调用,因为它们应用于 this.element 而不是 wrapper。
是否有一种优雅的方式以某种方式返回包装器元素,以便将后续的 bind() 调用应用于它或使 ui.mouse 原型应用于 this.element 以外的元素?
非常欢迎任何其他优雅的解决方案或建议。
这是我尝试过的两种方案。
不替换 this.element
$.widget("ui.example", ui.mouse, {
_containerElement: null,
_create: function ()
{
if (this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i))
{
this._applyContainer();
}else{
this._containerElement = this.element;
}
// Applies mouse interaction handlers to this.element
this._mouseInit();
},
_applyContainer: function ()
{
this.element.wrap("<span>");
this._containerElement = this.element.parent();
this._containerElement.css({position:'relative'});
},
_mouseStart: function (event) {
// Not always called because it handles mouse interaction with
// the IMG element rather than the wrapper element
this._trigger("mouseevent");
}
})
$("IMG").example().bind("examplemouseevent", function(){
//This fires but only when the original IMG element is clicked, not the wrapper
})
替换 this.element
$.widget("ui.example", ui.mouse, {
_create: function ()
{
if (this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i))
{
this._applyContainer();
}
// Applies mouse interaction handlers to this.element
this._mouseInit();
},
_applyContainer: function ()
{
this.element.wrap("<span>");
this.element = this.element.parent();
this.element.css({position:'relative'});
},
_mouseStart: function (event) {
// This event is never handled because it is not raised on the original element.
this._trigger("mouseevent");
}
})
$("IMG").example().bind("examplemouseevent", function(){
//This never fires because the bind is to the IMG element, not the wrapper
})
我很确定我遇到的问题是由于我理解 jquery ui.mouse 工作方式的缺陷,或者 jquery 小部件框架的限制。
用包装原始 this.element 的元素替换 this.element 是可行的,但事件不会传递给稍后绑定到小部件的处理程序。
不替换 this.element 并存储对包装器的单独引用会导致 jquery 基础 ui.mouse 的行为将事件附加到错误的元素。
代码按设计工作,我的问题是找到处理设计限制的最佳方法。
我可以看到许多解决此问题的方法。例如;在 ui.mouse 附加所需的处理程序时,对 _trigger 方法进行打孔以触发正确元素上的事件或前后交换 this.element 值。 这些以及我考虑过的任何其他方法似乎都很混乱。
我查看了本机 jquery.resizable 小部件代码,它也创建了一个包装器,但据我所知,如果它试图触发事件,它也会遇到同样的问题。
这是我第一次使用 JQuery 小部件,所以我想从 JQuery 专家那里确认我没有遗漏什么?
【问题讨论】:
-
你在什么浏览器中测试这个?我也遇到过类似的问题,原因通常是 DOM 没有及时更新。当您尝试获取 .parent() 时, 还不存在。我知道 IE 对此非常恼火,因为它只会在脚本停止运行后更新 DOM。
-
我在 Chrome、IE9、Firefox 中测试过。
-
为了排除这个不可调试的错误,我建议通过创建第二个按钮链接到单独触发的事件来测试它,该事件采用该元素的父级。如果我是对的,如果在修改 DOM 和遍历新 DOM 之间有一个沉默的时刻(脚本方面),它应该可以工作。没有其他方法可以调试它,因为您不知道浏览器何时真正更新其原始 DOM。只是一个建议:-)
标签: javascript jquery jquery-ui widget