哇,经过长时间的调试和尝试各种方法后,我认识到问题不在于Ajax请求,而是事件处理程序本身:
.on(hideEvent, this.targetId, this, function(e) {
var _self = e.data;
if(_self.isVisible()) {
_self.hide();
}
});
正如您所看到的,如果小部件在之前可见,那么它只是被隐藏了。如果您将鼠标移出得太快,现在可能会发生两件事情:
在这种情况下,事件被丢弃,面板保持可见状态。由于动画被排队,因此只需删除if语句即可解决问题。我通过替换整个bindEvents
方法来实现此操作:
PrimeFaces.widget.OverlayPanel.prototype.bindEvents = function() {
this.target.data('primefaces-overlay-target', this.id).find('*').data('primefaces-overlay-target', this.id);
if(this.cfg.showEvent == this.cfg.hideEvent) {
var event = this.cfg.showEvent;
$(document).off(event, this.targetId).on(event, this.targetId, this, function(e) {
e.data.toggle();
});
}
else {
var showEvent = this.cfg.showEvent + '.ui-overlay',
hideEvent = this.cfg.hideEvent + '.ui-overlay';
$(document).off(showEvent + ' ' + hideEvent, this.targetId).on(showEvent, this.targetId, this, function(e) {
var _self = e.data;
if(!_self.isVisible()) {
_self.show();
}
})
.on(hideEvent, this.targetId, this, function(e) {
var _self = e.data;
_self.hide();
});
}
this.bindKeyEvents();
var _self = this;
$(document.body).bind('mousedown.ui-overlay', function (e) {
if(_self.jq.hasClass('ui-overlay-hidden')) {
return;
}
var target = $(e.target);
if(_self.target.is(target)||_self.target.has(target).length > 0) {
return;
}
var offset = _self.jq.offset();
if(e.pageX < offset.left ||
e.pageX > offset.left + _self.jq.outerWidth() ||
e.pageY < offset.top ||
e.pageY > offset.top + _self.jq.outerHeight()) {
_self.hide();
}
});
var resizeNS = 'resize.' + this.id;
$(window).unbind(resizeNS).bind(resizeNS, function() {
if(_self.jq.hasClass('ui-overlay-visible')) {
_self.hide();
}
});
};
在加载时执行此代码,问题就会消失。
尽管您要替换js代码,但您可以利用这个机会实现一个非常好的功能。通过在事件处理程序中使用超时,可以轻松地实现一个小延迟,不仅可以提高用户体验(不再出现成千上万的弹出窗口),而且还可以减少网络流量:
$(document).off(showEvent + ' ' + hideEvent, this.targetId).on(showEvent, this.targetId, this, function(e) {
var _self = e.data;
_self.timer = setTimeout( function(){
if(!_self.isVisible()) {
_self.show();
}
}, 300);
})
.on(hideEvent, this.targetId, this, function(e) {
var _self = e.data;
clearTimeout(_self.timer);
_self.hide();
});
当然,你可以使用全局变量来控制延迟时间。如果你想要更加灵活的方法,你需要重写OverlayPanelRender
中的encodeScript
方法以传输额外的属性。然后你可以通过_self.cfg.delay
来访问它。但请注意,你还需要替换组件模型OverlayPanel
并为其提供额外的属性。