Reputation: 2866
I have a textbox and a Jquery UI dialog. When a user is done typing into the textbox and presses Enter, I want to display the dialog. In order to accomplish that I use the following code:
$(document).ready(function () {
var helpDial = $('#helpDialog');
var input = $('#helpSearch');
helpDial.dialog({
width: 800,
autoOpen: false,
modal: true,
title: "Templates",
position: [165, 158]
});
input.focusin(function () {
helpDial.dialog('close');
}).focusout(function () {
helpDial.dialog('open');
}).on('keypress', function (e) {
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 13) {
input.focusout();
return false;
}
});
});
<input id="helpSearch" />
<div id="helpDialog"></div>
The problem is that when I press Enter, the focusout
is called twice, one from the input.focusout()
and the second time right after the helpDial.dialog('open')
in the focusout
event handler. This causes two background overlays to be created, and when I close the dialog, one overlay remains visible.
What am I doing wrong? Is there a better way to handle this scenario -- 'an enter pressed in a textfield opens a jQuery dialog'. Thanks.
Upvotes: 4
Views: 9168
Reputation: 1010
I wanted to trigger the focusout event at a place where I did not have access to the focusout event handler so I couldn't just call the function.
The way I solved it was by creating a dummy focusable input field, focusing it and then removing it. This causes the focusout event to be triggered only once.
// Create a focusable dummy input element
let dummyInput = document.createElement('input');
document.body.appendChild(dummyInput);
// Triggers focusout event
dummyInput.focus();
// Remove the dummy input element
document.body.removeChild(dummyInput);
Upvotes: 0
Reputation: 13360
The only way to prevent an event from firing is to unbind the event handler. Or, depending on the situation, take differential action based on information available at the time the event fires.
The focusout
event is triggered any time the element loses the focus. In this case, every time the user clicks on the textbox, a focusin
event is triggered. As soon as the cursor leaves the textbox (which happens when the dialog box is opened), the focusout
event is triggered.
The problem with your code is that you forcibly call the focusout
event, and then the focusout
event is called naturally when you open the dialog. So, change your code as follows:
$(document).ready(function () {
var helpDial = $('#helpDialog');
var input = $('#helpSearch');
helpDial.dialog({
width: 800,
autoOpen: false,
modal: true,
title: "Templates",
position: [165, 158]
});
input.on('focusin', function () {
input.on("focusout", textboxFocusOut);
}).on('keypress', function (e) {
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 13) {
textboxFocusOut();
}
});
function textboxFocusOut() {
input.off("focusout", textboxFocusOut);
helpDial.dialog('open');
}
});
What this code is doing is binding a function to focusout
within the focusin
handler. If the user navigates away from the textbox, the focusout
event handler will be called, which immediately unbinds the focusout
event (to prevent binding the function multiple times). If the user hits the enter key, then the function is called manually, which removes the focusout
event handler before opening the dialog to prevent triggering the focusout
event from firing automatically when the dialog opens.
Upvotes: 6
Reputation: 15609
The most obvious solution might be using a variable like enter_pressed
to inform the focusout
function:
$(function () {
var helpDial = $('#helpDialog'),
input = $('#helpSearch'),
enter_pressed = false;
helpDial.dialog({
width: 800,
autoOpen: false,
modal: true,
title: "Templates",
position: [165, 158]
});
input.on('focusout', function () {
if( !enter_pressed ) {
helpDial.dialog('open');
} else {
enter_pressed = false;
}
}).on('keypress', function (e) {
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 13) {
enter_pressed = true;
helpDial.dialog('open');
}
});
});
http://jsfiddle.net/joplomacedo/7Fpm4/7/
However, I believe there's a cleaner solution. I'll try and come up with it.
Aside
Is the .focusin event handler really needed?
Upvotes: 3
Reputation: 5820
http://jsfiddle.net/7Fpm4/2/ i updated your example, just changed input.focusin(function () into input.change(function ()
Upvotes: 0