jQuery Mobile tap and taphold sensitivity issue in iOS - jquery-mobile

In my jQuery Mobile app, I want to use tap and taphold events. I tried using the standard approach of binding event handlers to these events but in case of taphold event, the tap event was always firing so I used the following approach which I found on stackoverflow here:
jQuery calling click event after taphold event
$("#list li").live('vmousedown vmouseup', function (event)
{
if (event.type == 'vmousedown')
{
tapTime = new Date().getTime();
}
else
{
//event.type == 'vmouseup'
//here you can check how long the `tap` was to determine what do do
duration = (new Date().getTime() - tapTime);
//The tap code
if(duration >250 && duration <750)
{
}
//The taphold code
else if (duration >=750) {
}
Now, on an iPhone with iOS 5, I am having the problem that the tap event is being fired and an item is selected when I scroll down a list. I tried to increase the duration for tap event but it seems to have no effect in iOS. Any suggestions?

[Tried and Tested]
I checked jQuery Mobile's implementation. They are firing the 'tap' event after 'taphold' every time on 'vmouseup'.
Workaround would be not to fire the 'tap' event if the 'taphold' has been fired. Create a custom event or modify the source as per you need as follows:
$.event.special.tap = {
tapholdThreshold: 750,
setup: function() {
var thisObject = this,
$this = $( thisObject );
$this.bind( "vmousedown", function( event ) {
if ( event.which && event.which !== 1 ) {
return false;
}
var origTarget = event.target,
origEvent = event.originalEvent,
/****************Modified Here**************************/
tapfired = false,
timer;
function clearTapTimer() {
clearTimeout( timer );
}
function clearTapHandlers() {
clearTapTimer();
$this.unbind( "vclick", clickHandler )
.unbind( "vmouseup", clearTapTimer );
$( document ).unbind( "vmousecancel", clearTapHandlers );
}
function clickHandler( event ) {
clearTapHandlers();
// ONLY trigger a 'tap' event if the start target is
// the same as the stop target.
/****************Modified Here**************************/
//if ( origTarget === event.target) {
if ( origTarget === event.target && !tapfired) {
triggerCustomEvent( thisObject, "tap", event );
}
}
$this.bind( "vmouseup", clearTapTimer )
.bind( "vclick", clickHandler );
$( document ).bind( "vmousecancel", clearTapHandlers );
timer = setTimeout( function() {
tapfired = true;/****************Modified Here**************************/
triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) );
}, $.event.special.tap.tapholdThreshold );
});
}
};

Related

OpenLayers 3 - SelectInteraction Event Not Firing

I am trying to fire the select event for a selectInteraction. Here is the code I have so far:
// create and instance of the selectInteraction
var selectInteraction = new ol.interaction.Select( {
layers: myLayers
} );
// add select event handler
// NOT BEING CALLED WHEN FEATURES ARE PUSHED TO SELECTED ARRAY
selectInteraction.on( "select", function ( evt ) {
var selected = evt.selected;
var deselected = evt.deselected;
selected.forEach( function( feature ) {
feature.setStyle( myCustomStyleFunction );
} );
deselected.forEach( function( feature ) {
feature.setStyle( null );
} );
}, selectInteraction );
// add the interaction to the map
myMap.getInteractions().extend( [ selectInteraction ] );
// function called with feature to be selected
function programmaticallySelectFeature( feature ) {
// get the selectInteraction for the map
myMap.getInteractions().forEach( function ( interaction ) {
if ( interaction instanceof ol.interaction.Select ) {
selectInteraction = interaction;
}
});
// push the feature to the selectInteraction
selectInteraction.getFeatures().push( feature );
}
I understand that the select event is not firing when features are pushed to the selected array. Otherwise it works as expected. So how can get this to work? Can I listen for another event perhaps?
you can listen to the events click or singleclick on the map, and push the returned feature in the selected features:
map.on('click', function(evt){
var feature = map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
return feature;
});
if(feature){
selectInteraction.getFeatures().push(feature);
}
});
this of course assuming you want to select features with a click

JqueryUI Detect when a group of items are on their droppable target areas

I have 4 drag and drop items, they thay all drag and dropp onto their targets, but should then fire off a 'welldone' event and the part is not working. I've had some help but can;t get this working, what am I doing wrong?
// insert code to be run when the symbol is created here
yepnope({nope:['scripts/jquery-ui-1.10.3.custom.min.js','scripts/jquery.ui.touch-punch.min.js'], complete: init})
// Initial state: not dropped
sym.setVariable("dropped", "false");
function init(){
//Use Jquery code for draggable and droppable
//Drag it
sym.$('scrambled_egg').draggable({opacity:.5, revert:'invalid'});
//Drop it on the target
sym.$('scrambled_target').droppable({
accept:sym.$("scrambled_egg"),
drop: function () {
sym.getSymbol("scrambled_egg").play();
// Store that you dropped it
sym.setVariable("dropped", "true");
// Call a function to check if all the symbols are dropped
// and fire event "done"
checkIfAllDropped();
}
}
);
//Snap back to default state
sym.$('scrambled_default').droppable({
accept:sym.$("scrambled_target"),
drop: function () {
// Back to not dropped state
sym.setVariable("dropped", "false");
}
}
);
//End code chunk
//Use Jquery code for draggable and droppable
//Drag it
sym.$('fried_egg').draggable({opacity:.5, revert:'invalid'});
//Drop it on the target
sym.$('fried_target').droppable({
accept:sym.$("fried_egg"),
drop: function () {
sym.getSymbol("fried_egg").play();
// Store that you dropped it
sym.setVariable("dropped", "true");
// Call a function to check if all the symbols are dropped
// and fire event "done"
checkIfAllDropped();
}
}
);
//Snap back to default state
sym.$('fried_default').droppable({
accept:sym.$("fried_target"),
drop: function () {
// Back to not dropped state
sym.setVariable("dropped", "false");
}
}
);
//End code chunk
//Use Jquery code for draggable and droppable
//Drag it
sym.$('poached_egg').draggable({opacity:.5, revert:'invalid'});
//Drop it on the target
sym.$('poached_target').droppable({
accept:sym.$("poached_egg"),
drop: function () {
sym.getSymbol("poached_egg").play();
// Store that you dropped it
sym.setVariable("dropped", "true");
// Call a function to check if all the symbols are dropped
// and fire event "done"
checkIfAllDropped();
}
}
);
//Snap back to default state
sym.$('poached_default').droppable({
accept:sym.$("poached_target"),
drop: function () {
// Back to not dropped state
sym.setVariable("dropped", "false");
}
}
);
//End code chunk
//Use Jquery code for draggable and droppable
//Drag it
sym.$('boiled_egg').draggable({opacity:.5, revert:'invalid'});
//Drop it on the target
sym.$('boiled_target').droppable({
accept:sym.$("boiled_egg"),
drop: function () {
sym.getSymbol("boiled_egg").play();
// Store that you dropped it
sym.setVariable("dropped", "true");
// Call a function to check if all the symbols are dropped
// and fire event "done"
checkIfAllDropped();
}
}
);
//Snap back to default state
sym.$('boiled_default').droppable({
accept:sym.$("boiled_target"),
drop: function () {
// Back to not dropped state
sym.setVariable("dropped", "false");
}
}
);
//End code chunk
}
checkIfAllDropped = function(){
var stage = AdobeEdge.getComposition("How_do_you_eat_yours").getStage();
var sym1 = stage.getSymbol("scrambled_target");
var sym2 = stage.getSymbol("fried_target");
var sym2 = stage.getSymbol("boiled_target");
var sym2 = stage.getSymbol("poached_target");
if(sym1.getVariable("dropped") === "true" &&
sym2.getVariable("dropped") === "true" &&
sym3.getVariable("dropped") === "true" &&
sym4.getVariable("dropped") === "true"){
// Fire event done!
stage.play("welldone");
}
};
I would do it this way: every time you drop an element you store this event somewhere and you check if all the elements are dropped.
For example:
// Initial state: not dropped
sym.setVariable("dropped", "false");
sym.$('scrambled_target').droppable({
accept:sym.$("scrambled_egg"),
drop: function () {
sym.getSymbol("scrambled_egg").play();
// Store that you dropped it
sym.setVariable("dropped", "true");
// Call a function to check if all the symbols are dropped
// and fire event "done"
checkIfAllDropped();
}
}
);
sym.$('scrambled_default').droppable({
accept:sym.$("scrambled_egg"),
drop: function () {
// Back to not dropped state
// EDIT HERE! Dind't get that sym was your stage.
// AND EDIT EVERYWHERE ELSE.
sym.getSymbol("scrambled_egg").setVariable("dropped", "false");
}
}
);
The checkIfAllDropped() function will look something like this:
checkIfAllDropped = function(){
var stage = AdobeEdge.getComposition("COMPOSITION_CLASS_NAME").getStage();
var sym1 = stage.getSymbol("sym1");
var sym2 = stage.getSymbol("sym2");
if(sym1.getVariable("dropped") === "true" &&
sym2.getVariable("dropped") === "true"){
// Fire event done!
stage.play("done");
}
};
Be careful on your checkIfAllDropped function you are assigning var sym2 multiple times.
checkIfAllDropped = function(){
var stage = AdobeEdge.getComposition("How_do_you_eat_yours").getStage();
var sym1 = stage.getSymbol("scrambled_target");
// Here...
var sym2 = stage.getSymbol("fried_target");
// Here...
var sym2 = stage.getSymbol("boiled_target");
// Here...
var sym2 = stage.getSymbol("poached_target");
if(sym1.getVariable("dropped") === "true" &&
sym2.getVariable("dropped") === "true" &&
sym3.getVariable("dropped") === "true" &&
sym4.getVariable("dropped") === "true"){
// Fire event done!
stage.play("welldone");
}
};
Please debug your code before posting it again!

jQuery UI multiple selectable tooltips are collapsing

I'm new to jQuery UI.
I'm trying to create a selectable jQuery UI tooltip. The tooltip is associated with the links on a page.
When the link is surrounded by just text, it works fine. But when there are few links next to each other, the functionality overlaps and tooltips don't show smoothly anymore.
you can find the code on http://jsfiddle.net/zumot/Hc3FK/2/
Below the JavaScript code
$("[title][data-scan]").bind("mouseleave", function (event) {
event.stopImmediatePropagation();
var fixed = setTimeout('$("[title][data-scan]").tooltip("close")', 100);
$(".ui-tooltip").click(function () {
alert("I am clickable");
return false;
});
$(".ui-tooltip").hover(
function () {
clearTimeout(fixed);
},
function () {
$("[title][data-scan]").tooltip("close");
});}).tooltip({
items: "img, [data-scan], [title]",
content: function () {
var element = $(this);
if (element.is("[data-scan]")) {
var text = element.attr("href");
return "<a href='http://www.google.com'>You are trying to open a tooltip <span>" + text + "</span></a>";
}
if (element.is("[title]")) {
return element.attr("title");
}
if (element.is("img")) {
return element.attr("alt");
}
},
position: {
my: "right center",
at: "left center",
delay: 200,
using: function (position, feedback) {
$(this).css(position);
$("<div>")
.addClass(feedback.vertical)
.addClass(feedback.horizontal)
.appendTo(this);
}
}});
My attempt to fix the issue was by making the variable fixed global (to make it accessible by other jQuery UI properties), and on Open event, hide any other previously opened tooltips and clear the timeout id saved in fixed variable.
You can find the solution here http://jsfiddle.net/zumot/dVGWB/
, though to see the code working properly, you'll have to run it directly on your browser.
Here's the snapshort of the fixed code.
// Make the timeout id variable global
var fixed = 0;
$("[title][data-scan]").tooltip({
items: "img, [data-scan], [title]",
content: function () {
var element = $(this);
if (element.is("[data-scan]")) {
var text = element.attr("href");
return "<a href='http://www.google.com'>You are trying to open a tooltip <span>" + text + "</span></a>";
}
if (element.is("[title]")) {
return element.attr("title");
}
if (element.is("img")) {
return element.attr("alt");
}
},
open: function (event, ui) {
// When opening a new div, hide any previously opened tooltips first.
$(".ui-tooltip:not([id=" + ui.tooltip[0].id + "])").hide();
// clear timeout as well if there's any.
if (tf > 0) {
clearTimeout(tf)
};
},
position: {
my: "right center",
at: "left center",
delay: 200,
using: function (position, feedback) {
$(this).css(position);
$("<div>")
.addClass(feedback.vertical)
.addClass(feedback.horizontal)
.appendTo(this);
}
}
}).bind("mouseleave", function (event) {
// stop defeulat behaviour
event.stopImmediatePropagation();
fixed = setTimeout('$("[title][data-scan]").tooltip("close")', 100);
$(".ui-tooltip").hover(
function () {
clearTimeout(tf);
}, function () {
$("[title][data-scan]").tooltip("close");
})
});

How to get static information about page transition ended [duplicate]

Are there any events fired by an element to check whether a css3 transition has started or end?
W3C CSS Transitions Draft
The completion of a CSS Transition generates a corresponding DOM Event. An event is fired for each property that undergoes a transition. This allows a content developer to perform actions that synchronize with the completion of a transition.
Webkit
To determine when a transition completes, set a JavaScript event listener function for the DOM event that is sent at the end of a transition. The event is an instance of WebKitTransitionEvent, and its type is webkitTransitionEnd.
box.addEventListener( 'webkitTransitionEnd',
function( event ) { alert( "Finished transition!" ); }, false );
Mozilla
There is a single event that is fired when transitions complete. In Firefox, the event is transitionend, in Opera, oTransitionEnd, and in WebKit it is webkitTransitionEnd.
Opera
There is one type of transition event
available. The oTransitionEnd event
occurs at the completion of the
transition.
Internet Explorer
The transitionend event occurs at the completion of the transition. If the transition is removed before completion, the event will not fire.
Stack Overflow: How do I normalize CSS3 Transition functions across browsers?
Update
All modern browsers now support the unprefixed event:
element.addEventListener('transitionend', callback, false);
https://caniuse.com/#feat=css-transitions
I was using the approach given by Pete, however I have now started using the following
$(".myClass").one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd',
function() {
//do something
});
Alternatively if you use bootstrap then you can simply do
$(".myClass").one($.support.transition.end,
function() {
//do something
});
This is becuase they include the following in bootstrap.js
+function ($) {
'use strict';
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
// ============================================================
function transitionEnd() {
var el = document.createElement('bootstrap')
var transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'OTransition' : 'oTransitionEnd otransitionend',
'transition' : 'transitionend'
}
for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return { end: transEndEventNames[name] }
}
}
return false // explicit for ie8 ( ._.)
}
$(function () {
$.support.transition = transitionEnd()
})
}(jQuery);
Note they also include an emulateTransitionEnd function which may be needed to ensure a callback always occurs.
// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
var called = false, $el = this
$(this).one($.support.transition.end, function () { called = true })
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
setTimeout(callback, duration)
return this
}
Be aware that sometimes this event doesn’t fire, usually in the case
when properties don’t change or a paint isn’t triggered. To ensure we
always get a callback, let’s set a timeout that’ll trigger the event
manually.
http://blog.alexmaccaw.com/css-transitions
All modern browsers now support the unprefixed event:
element.addEventListener('transitionend', callback, false);
Works in the latest versions of Chrome, Firefox and Safari. Even IE10+.
In Opera 12 when you bind using the plain JavaScript, 'oTransitionEnd' will work:
document.addEventListener("oTransitionEnd", function(){
alert("Transition Ended");
});
however if you bind through jQuery, you need to use 'otransitionend'
$(document).bind("otransitionend", function(){
alert("Transition Ended");
});
In case you are using Modernizr or bootstrap-transition.js you can simply do a change:
var transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd',
'MozTransition' : 'transitionend',
'OTransition' : 'oTransitionEnd otransitionend',
'msTransition' : 'MSTransitionEnd',
'transition' : 'transitionend'
},
transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
You can find some info here as well http://www.ianlunn.co.uk/blog/articles/opera-12-otransitionend-bugs-and-workarounds/
Just for fun, don't do this!
$.fn.transitiondone = function () {
return this.each(function () {
var $this = $(this);
setTimeout(function () {
$this.trigger('transitiondone');
}, (parseFloat($this.css('transitionDelay')) + parseFloat($this.css('transitionDuration'))) * 1000);
});
};
$('div').on('mousedown', function (e) {
$(this).addClass('bounce').transitiondone();
});
$('div').on('transitiondone', function () {
$(this).removeClass('bounce');
});
If you simply want to detect only a single transition end, without using any JS framework here's a little convenient utility function:
function once = function(object,event,callback){
var handle={};
var eventNames=event.split(" ");
var cbWrapper=function(){
eventNames.forEach(function(e){
object.removeEventListener(e,cbWrapper, false );
});
callback.apply(this,arguments);
};
eventNames.forEach(function(e){
object.addEventListener(e,cbWrapper,false);
});
handle.cancel=function(){
eventNames.forEach(function(e){
object.removeEventListener(e,cbWrapper, false );
});
};
return handle;
};
Usage:
var handler = once(document.querySelector('#myElement'), 'transitionend', function(){
//do something
});
then if you wish to cancel at some point you can still do it with
handler.cancel();
It's good for other event usages as well :)

Latency issue with Primefaces overlayPanel - loads to lazy

I am using Primefaces 3.2 with jsf 2 and glassfish 3.1.2.
I have a p:dataTable of users containing avatars of the user. Whenever the user moves the mouse over the avatar a p:overlayPanel appears with more information (lazy loaded) on the user, and disappears when the user moves the cursor away - like this:
<p:overlayPanel for="avatar" dynamic="true" showEvent="mouseover" hideEvent="mouseout" ...>
This works very well - as long as the user is "slowhanded". Whenever an user moves the cursor fast above many avatars many of the overlayPanels stay visible.
For example when the user has the cursor over the position where user avatars are displayed and uses the scroll wheel of his mouse to scroll the usertable down or up.
I believe that the overlaypanel starts to load the information dynamically (dynamic="true") from the server when showEvent="mouseover" is dispatched and displays the overlaypanel after the response from the server arrives.
This way it is not possible to detect whether the cursor is already away when the overlaypanel becomes visible - so the hideEvent="mouseout" is never dispatched.
Is there a way to make the primefaces overlaypanel appear directly on mousover, showing a loading gif and update the content into the overlaypanel when the response comes from the server.
Is this a good appraoch or does anyone know any other way to solve this nasty problem?
Thanks Pete
As my first answer is already very long and contains valid information, I decided to open a new answer presenting my final approach.
Im now using Primefaces inheritance pattern making the code alot cleaner. Also I noticed that replacing/overwriting the whole bindEvents function isnt necessary, as we can remove the old event handlers. Finally this code fixs the latest issue experienced: A hide event before ajax arrival.
PrimeFaces.widget.OverlayPanel = PrimeFaces.widget.OverlayPanel
.extend({
bindEvents : function() {
this._super();
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;
clearTimeout(_self.timer);
_self.timer = setTimeout(function() {
_self.hidden = false;
_self.show();
}, 300);
}).on(hideEvent, this.targetId, this, function(e) {
var _self = e.data;
clearTimeout(_self.timer);
_self.hidden = true;
_self.hide();
});
},
_show : function() {
if (!this.cfg.dynamic || !this.hidden) {
this._super();
}
}
});
Im sorry for the poor formatting: Eclipses fault ;)
Wow, finally after a long debuging session and testing various approaches i recognized that the problem isnt the ajax request but the event handlers itself:
.on(hideEvent, this.targetId, this, function(e) {
var _self = e.data;
if(_self.isVisible()) {
_self.hide();
}
});
As you can see, the widget is just hidden if its visible before. If your moving your mouse out too fast, now two things can happen:
The widget isnt visible at all
The animation is still going on
In this case the event is discarded and the panel stays visible. As animations are queued, one simply has to remove the if statement to fix the issue. I did this by replacing the whole bindEvents method:
PrimeFaces.widget.OverlayPanel.prototype.bindEvents = function() {
//mark target and descandants of target as a trigger for a primefaces overlay
this.target.data('primefaces-overlay-target', this.id).find('*').data('primefaces-overlay-target', this.id);
//show and hide events for target
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();
});
}
//enter key support for mousedown event
this.bindKeyEvents();
var _self = this;
//hide overlay when mousedown is at outside of overlay
$(document.body).bind('mousedown.ui-overlay', function (e) {
if(_self.jq.hasClass('ui-overlay-hidden')) {
return;
}
//do nothing on target mousedown
var target = $(e.target);
if(_self.target.is(target)||_self.target.has(target).length > 0) {
return;
}
//hide overlay if mousedown is on outside
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();
}
});
//Hide overlay on resize
var resizeNS = 'resize.' + this.id;
$(window).unbind(resizeNS).bind(resizeNS, function() {
if(_self.jq.hasClass('ui-overlay-visible')) {
_self.hide();
}
});
};
Execute this code on load and the issue should be gone.
As your replacing the js code nevertheless, you can use this oppurtunity to implement quite a nice feature. By using timeouts in the event handlers one can easily implement a little delay not just improving usability (no more thousands of popups appear) but also reducing network traffic:
$(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();
});
Ofcourse you can use a global variable to control the delay time. If you want a more flexible approach youll have to overwrite the encodeScript method in the OverlayPanelRender to transmit an additional property. You could access it then with _self.cfg.delay. Notice though that youll have to replace the component model OverlayPanel too providing it with an extra attribute.
At the same time I thank you for this brilliant solution I take the opportunity to update it for Primefaces 5.2. In our application the code broke after that upgrade.
Follows the updated code for Primefaces 5.2:
PrimeFaces.widget.OverlayPanel.prototype.bindTargetEvents = function() {
var $this = this;
//mark target and descandants of target as a trigger for a primefaces overlay
this.target.data('primefaces-overlay-target', this.id).find('*').data('primefaces-overlay-target', this.id);
//show and hide events for target
if(this.cfg.showEvent === this.cfg.hideEvent) {
var event = this.cfg.showEvent;
this.target.on(event, function(e) {
$this.toggle();
});
}
else {
var showEvent = this.cfg.showEvent + '.ui-overlaypanel',
hideEvent = this.cfg.hideEvent + '.ui-overlaypanel';
this.target
.off(showEvent + ' ' + hideEvent)
.on(showEvent, function(e) {
clearTimeout($this.timer);
$this.timer = setTimeout(function() {
$('.ui-overlaypanel').hide();
$this.hidden = false;
$this.show();
}, 500);
})
.on(hideEvent, function(e) {
clearTimeout($this.timer);
$this.timer = setTimeout(function() {
// don't hide if hovering overlay
if(! $this.jq.is(":hover")) {
$this.hide();
}
}, 100);
});
}
$this.target.off('keydown.ui-overlaypanel keyup.ui-overlaypanel').on('keydown.ui-overlaypanel', function(e) {
var keyCode = $.ui.keyCode, key = e.which;
if(key === keyCode.ENTER||key === keyCode.NUMPAD_ENTER) {
e.preventDefault();
}
})
.on('keyup.ui-overlaypanel', function(e) {
var keyCode = $.ui.keyCode, key = e.which;
if(key === keyCode.ENTER||key === keyCode.NUMPAD_ENTER) {
$this.toggle();
e.preventDefault();
}
});
};
I also added an extra feature which allows the user to move the mouse over the overlay without hiding it. It should hide when you move the mouse out of it then which I accomplished through:
<p:overlayPanel .... onShow="onShowOverlayPanel(this)" ...>
function onShowOverlayPanel(ovr) {
ovr.jq.on("mouseleave", function(e) {
ovr.jq.hide();
});
}
Hope you enjoy!
It's been a long time, but in case anyone bumps into this problem, a showDelay attribute was added to the overlayPanel to solve this problem starting from Primefaces 6.2. However, it is not in the official documentation for some reason.

Resources