I have a jQuery UI dialog box with a form. I would like to simulate a click on one of the dialog's buttons so you don't have to use the mouse or tab over to it. In other words, I want it to act like a regular GUI dialog box where simulates hitting the "OK" button.
I assume this might be a simple option with the dialog, but I can't find it in the jQuery UI documentation. I could bind each form input with keyup() but didn't know if there was a simpler/cleaner way. Thanks.
I don't know if there's an option in the jQuery UI widget, but you could simply bind the keypress event to the div that contains your dialog...
$('#DialogTag').keypress(function(e) {
if (e.keyCode == $.ui.keyCode.ENTER) {
//Close dialog and/or submit here...
}
});
This'll run no matter what element has the focus in your dialog, which may or may not be a good thing depending on what you want.
If you want to make this the default functionality, you can add this piece of code:
// jqueryui defaults
$.extend($.ui.dialog.prototype.options, {
create: function() {
var $this = $(this);
// focus first button and bind enter to it
$this.parent().find('.ui-dialog-buttonpane button:first').focus();
$this.keypress(function(e) {
if( e.keyCode == $.ui.keyCode.ENTER ) {
$this.parent().find('.ui-dialog-buttonpane button:first').click();
return false;
}
});
}
});
Here's a more detailed view of what it would look like:
$( "#dialog-form" ).dialog({
buttons: { … },
open: function() {
$("#dialog-form").keypress(function(e) {
if (e.keyCode == $.ui.keyCode.ENTER) {
$(this).parent().find("button:eq(0)").trigger("click");
}
});
};
});
I have summed up the answers above & added important stuff
$(document).delegate('.ui-dialog', 'keyup', function(e) {
var target = e.target;
var tagName = target.tagName.toLowerCase();
tagName = (tagName === 'input' && target.type === 'button')
? 'button'
: tagName;
isClickableTag = tagName !== 'textarea' &&
tagName !== 'select' &&
tagName !== 'button';
if (e.which === $.ui.keyCode.ENTER && isClickableTag) {
$(this).find('.ui-dialog-buttonset button').eq(0).trigger('click');
return false;
}
});
Advantages:
Disallow enter key on non compatible elements like textarea , select , button or inputs with type button , imagine user clicking enter on textarea and get the form submitted instead of getting new line!
The binding is done once , avoid using the dialog 'open' callback to bind enter key to avoid binding the same function again and again each time the dialog is 'open'ed
Avoid changing existing code as some answers above suggest
Use 'delegate' instead of the deprecated 'live' & avoid using the new 'on' method to allow working with older versions of jquery
Because we use delegate , that mean the code above can be written even before initializing dialog. you can also put it in head tag even without $(document).ready
Also delegate will bind only one handler to document and will not bind handler to each dialog as in some code above , for more efficiency
Works even with dynamically generated dialogs like $('<div><input type="text"/></div>').dialog({buttons: .});
Worked with ie 7/8/9!
Avoid using the slow selector :first
Avoid using hacks like in answers here to make a hidden submit button
Disadvantages:
Run the first button as the default one , you can choose another button with eq() or call a function inside the if statement
All of dialogs will have same behavior you can filter it by making your selector more specific ie '#dialog' instead of '.ui-dialog'
I know the question is old but I have had the same need, so, I shared the solution I've used.
$('#dialogBox').dialog('open');
$('.ui-dialog-buttonpane > button:last').focus();
It works beautifully with the latest version of JQuery UI (1.8.1).
You may also use :first instead of :last depending on which button you want to set as the default.
This solution, compared to the selected one above, has the advantage of showing which button is the default one for the user. The user can also TAB between buttons and pressing ENTER will click the button currently under focus.
Cheers.
Ben Clayton's is the neatest and shortest and it can be placed at the top of your index page before any jquery dialogs have been initialized. However, i'd like to point out that ".live" has been deprecated. The preferred action is now ".on". If you want ".on" to function like ".live", you'll have to use delegated events to attach the event handler. Also, a few other things...
I prefer to use the ui.keycode.ENTER method to test for the enter
key since you don't have to remember the actual key code.
Using "$('.ui-dialog-buttonpane button:first', $(this))" for the
click selector makes the whole method generic.
You want to add "return false;" to prevent default and stop
propagation.
In this case...
$('body').on('keypress', '.ui-dialog', function(event) {
if (event.keyCode === $.ui.keyCode.ENTER) {
$('.ui-dialog-buttonpane button:first', $(this)).click();
return false;
}
});
A crude but effective way to make this work more generically:
$.fn.dlg = function(options) {
return this.each(function() {
$(this).dialog(options);
$(this).keyup(function(e){
if (e.keyCode == 13) {
$('.ui-dialog').find('button:first').trigger('click');
}
});
});
}
Then when you create a new dialog you can do this:
$('#a-dialog').mydlg({...options...})
And use it like a normal jquery dialog thereafter:
$('#a-dialog').dialog('close')
There are ways to improve that to make it work in more special cases. With the above code it will automatically pick the first button in the dialog as the button to trigger when enter is hit. Also it assumes that there is only one active dialog at any given time which may not be the case. But you get the idea.
Note: As mentioned above, the button that is pressed on enter is dependent on your setup. So, in some cases you would want to use the :first selector in .find method and in others you may want to use the :last selector.
Rather than listening for key codes like in this answer (which I couldn't get to work) you can bind to the submit event of the form within the dialog and then do this:
$("#my_form").parents('.ui-dialog').first().find('.ui-button').first().click();
So, the whole thing would look like this
$("#my_form").dialog({
open: function(){
//Clear out any old bindings
$("#my_form").unbind('submit');
$("#my_form").submit(function(){
//simulate click on create button
$("#my_form").parents('.ui-dialog').first().find('.ui-button').first().click();
return false;
});
},
buttons: {
'Create': function() {
//Do something
},
'Cancel': function() {
$(this).dialog('close');
}
}
});
Note that different browsers handle the enter key differently, and some do not always do a submit on enter.
I don't know about simpler, but ordinarily you would track which button has the current focus. If the focus is changed to a different control, then the "button focus" would remain on the button that had focus last. Ordinarily, the "button focus" would start on your default button. Tabbing to a different button would change the "button focus". You'd have to decide if navigating to a different form element would reset the "button focus" to the default button again. You'll also probably need some visual indicator other than the browser default to indicate the focused button as it loses the real focus in the window.
Once you have the button focus logic down and implemented, then I would probably add a key handler to the dialog itself and have it invoke the action associated with the currently "focused" button.
EDIT: I'm making the assumption that you want to be able hit enter anytime you are filling out form elements and have the "current" button action take precedence. If you only want this behavior when the button is actually focused, my answer is too complicated.
I found this solution, it work's on IE8, Chrome 23.0 and Firefox 16.0
It's based on Robert Schmidt comment.
$("#id_dialog").dialog({
buttons: [{
text: "Accept",
click: function() {
// My function
},
id: 'dialog_accept_button'
}]
}).keyup(function(e) {
if (e.keyCode == $.ui.keyCode.ENTER)
$('#dialog_accept_button').click();
});
I hope it help anyone.
Sometimes we forget the fundamental of what the browser already supports:
<input type="submit" style="visibility:hidden" />
This will cause the ENTER key to submit the form.
I did such way... ;) Hope it will helpful for somebody..
$(window).keypress(function(e) {
if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
$(".ui-dialog:visible").find('.ui-dialog-buttonpane').find('button:first').click();
return false;
}
});
This should work to trigger the click of the button's click handler. this example assumes you have already set up the form in the dialog to use the jquery.validate plugin. but could be easily adapted.
open: function(e,ui) {
$(this).keyup(function(e) {
if (e.keyCode == 13) {
$('.ui-dialog-buttonpane button:last').trigger('click');
}
});
},
buttons: {
"Submit Form" : function() {
var isValid = $('#yourFormsID').valid();
// if valid do ajax call
if(isValid){
//do your ajax call here. with serialize form or something...
}
}
I realise there are a lot of answers already, but I reckon naturally that my solution is the neatest, and possibly the shortest. It has the advantage that it works on any dialogs created any time in the future.
$(".ui-dialog").live("keyup", function(e) {
if (e.keyCode === 13) {
$('.ok-button', $(this) ).first().click();
}
});
Here is what I did:
myForm.dialog({
"ok": function(){
...blah...
}
Cancel: function(){
...blah...
}
}).keyup(function(e){
if( e.keyCode == 13 ){
$(this).parent().find('button:nth-child(1)').trigger("click");
}
});
In this case, myForm is a jQuery object containing the form's html (note, there aren't any "form" tags in there... if you put those in the whole screen will refresh when you press "enter").
Whenever the user presses "enter" from within the form it will be the equivalent of clicking the "ok" button.
This also avoids the issue of having the form open with the "ok" button already highlighted. While that would be good for forms with no fields, if you need the user to fill in stuff, then you probably want the first field to be highlighted.
done and done
$('#login input').keyup(function(e) {
if (e.keyCode == 13) {
$('#login form').submit();
}
}
if you know the button element selector :
$('#dialogBox').dialog('open');
$('#okButton').focus();
Should do the trick for you. This will focus the ok button, and enter will 'click' it, as you would expect. This is the same technique used in native UI dialogs.
$("#LogOn").dialog({
modal: true,
autoOpen: false,
title: 'Please Log On',
width: 370,
height: 260,
buttons: { "Log On": function () { alert('Hello world'); } },
open: function() { $(this).parents('.ui-dialog-buttonpane button:eq(0)').focus();}
});
I found a quite simple solution for this problem:
var d = $('<div title="My dialog form"><input /></div>').dialog(
buttons: [{
text: "Ok",
click: function(){
// do something
alert('it works');
},
className: 'dialog_default_button'
}]
});
$(d).find('input').keypress(function(e){
if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
e.preventDefault();
$('.dialog_default_button').click();
}
});
$('#DialogID').dialog("option", "buttons")["TheButton"].apply()
This worked great for me..
None of these solutions seemed to work for me in IE9. I ended up with this..
$('#my-dialog').dialog({
...
open: function () {
$(this).parent()
.find("button:eq(0)")
.focus()
.keyup(function (e) {
if (e.keyCode == $.ui.keyCode.ENTER) {
$(this).trigger("click");
};
});
}
});
Below body is used because dialog DIV added on body,so body now listen the keyboard event. It tested on IE8,9,10, Mojila, Chrome.
open: function() {
$('body').keypress(function (e) {
if (e.keyCode == 13) {
$(this).parent().find(".ui-dialog-buttonpane button:eq(0)").trigger("click");
return false;
}
});
}
Because I don't have enough reputation to post comments.
$(document).delegate('.ui-dialog', 'keyup', function(e) {
var tagName = e.target.tagName.toLowerCase();
tagName = (tagName === 'input' && e.target.type === 'button') ? 'button' : tagName;
if (e.which === $.ui.keyCode.ENTER && tagName !== 'textarea' && tagName !== 'select' && tagName !== 'button') {
$(this).find('.ui-dialog-buttonset button').eq(0).trigger('click');
return false;
} else if (e.which === $.ui.keyCode.ESCAPE) {
$(this).close();
}
});
Modified answer by Basemm #35 too add in Escape to close the dialog.
It works fine Thank You!!!
open: function () {
debugger;
$("#dialogDiv").keypress(function (e) {
if (e.keyCode == 13) {
$(this).parent().find("#btnLoginSubmit").trigger("click");
}
});
},
Give your buttons classes and select them the usual way:
$('#DialogTag').dialog({
closeOnEscape: true,
buttons: [
{
text: 'Cancel',
class: 'myCancelButton',
click: function() {
// Close dialog fct
}
},
{
text: 'Ok',
class: 'myOKButton',
click: function() {
// OK fct
}
}
],
open: function() {
$(document).keyup(function(event) {
if (event.keyCode === 13) {
$('.myOKButton').click();
}
});
}
});
Related
I am trying to call a function scheduleAdd when the enter button is hit, but I only want it to work if an input with the id 'addSchedule' is in focus. Here's what I have:
$('#addSchedule').focus(function(e) {
var evt = e || window.event;
if(evt.keyCode == 13) {scheduleAdd};
});
I know the code inside the .focus works, because I tried it on its own and it triggers the function scheduleAdd when the enter key is hit. How can I make this conditional on 'addSchedule' being in focus?
Also, more generally, I was wondering if there's a standard way to ascribe event handlers conditional on a second event, such as nesting .on() or something.
Thanks.
Demo on fiddle
HTML:
<form>
<input id="addSchedule" type="text" />
</form>
Javascript:
$('#addSchedule').keydown(function (event) {
if (event.which == 13) {
event.preventDefault(); // This will prevent the page refresh.
scheduleAdd();
}
function scheduleAdd() {
alert("Add the schedule");
}
});
Simply the keydown event, and decide to do something or nothing based on whether the current element has the specified id:
$(document).on("keydown", function() {
if (!$("#addSchedule").is(":focus")) return;
// do stuff
});
Alternatively you can also check for the identity of the focused element with document.activeElement.id === "addSchedule" if you don't mind that's not enough jQuery. ;-)
I have an editable element inside a div which itself is clickable. Whenever I click the x-editable anchor element, the click bubbles up the DOM and triggers a click on the parent div. How can I prevent that? I know it's possible to stop this with jQuery's stopPropagation() but where would I call this method?
Here's the JSFiddle with the problem: http://jsfiddle.net/4RZvV/ . To replicate click on the editable values and you'll see that the containing div will catch a click event. This also happens when I click anywhere on the x-editable popup and I'd like to prevent that as well.
EDIT after lightswitch05 answer
I have multiple dynamic DIVs which should be selectable so I couldn't use a global variable. I added an attribute to the .editable-click anchors which get's changed instead.
editable-active is used to know if the popup is open or not
editable-activateable is used instead to know if that .editable-click anchor should be treated like it is
$(document).on('shown', "a.editable-click[editable-activateable]", function(e, reason) {
return $(this).attr("editable-active", true);
});
$(document).on('hidden', "a.editable-click[editable-activateable]", function(e, reason) {
return $(this).removeAttr("editable-active");
});
The check is pretty much like you've described it
$(document).on("click", ".version", function() {
$this = $(this)
// Check that the xeditable popup is not open
if($this.find("a[editable-active]").length === 0) { // means that editable popup is not open so we can do the stuff
// ... do stuff ...
}
})
For the click on the links, simply catch the click event and stop it:
$("a.editable-click").click(function(e){
e.stopPropagation();
});
The clicks within X-editable are a bit trickier. One way is to save a flag on weather the X-editable window is open or not, and only take action if X-editable is closed
var editableActive = false;
$("a.editable-click").on('shown', function(e, reason) {
editableActive = true;
});
$("a.editable-click").on('hidden', function(e, reason) {
editableActive = false;
});
$("div.version").click(function(e) {
var $this;
$this = $(this);
if(editableActive === false){
if ($this.hasClass("selected")) {
$(this).removeClass("selected");
} else {
$(this).addClass("selected");
}
}
});
Fixed Fiddle
It's not pretty, but we solved this problem with something like:
$('.some-class').click(function(event) {
if(event.target.tagName === "A" || event.target.tagName === "INPUT" || event.target.tagName === "BUTTON"){
return;
}
We're still looking for a solution that doesn't require a specific list of tagNames that are okay to click on.
There are similar questions but they could not help me solve this.
When the dialog opens and I press enter, I want this to be equivalent to closing the dialog.
I have written the following but it does not work. Instead, at every ENTER, the focus stays on the element that triggers the opening of the dialog, giving rise to multiple instances.
Thanks
var $dialogError = $('<div id="dialogError"></div>').html(vGraph.getLastErrorMsg()).dialog({
autoOpen: false,
open: function() {
$("#dialogError").keydown(function(e) {
alert("enter");
if (e.keyCode == $.ui.keyCode.ENTER) {
$(this).dialog("close");
}
});
},
title: 'Error'
});
$dialogError.dialog('open');
Maybe set the focus to the dialogError element using $('#dialogError').focus(); after opening the dialog, that way the focus is no longer on the element that opened the dialog, and it will capture the enter key.
$(document).on('keypress', function(event) {
if (event.keyCode == $.ui.keyCode.ENTER) {
$('#dialogError').dialog('close');
}
});
This will work regardless of whether the dialog has focus or not which is probably what you want. This code will execute when the dialog is not open, but running $('#dialogError').dialog('close'); will have no adverse effects.
Example - http://jsfiddle.net/tj_vantoll/x32zC/1
try returning false from the keydown handler:
open: function() {
$("#dialogError").keydown(function(e) {
alert("enter");
if (e.keyCode == $.ui.keyCode.ENTER) {
$(this).dialog("close");
return false;
}
});
},
how can i activate the readonly back after finishing the edit of the input ?
this is my code for now :
<script type="text/javascript">
$(document).ready(function () {
$("input").bind('click focus', function(){
$('input').each(function(){
$(this).attr("readonly", false);
});
});
});
</script>
an input like this :
<input type="text" class="m" readonly="readonly" id="anchor_text">
i think something with focusout, i need to put readonly back when i go to the next input, so the edited input can't be change unless i hit again click on it.
try:
$("input").bind('click focus', function(){
$(this).attr("readonly", false);
}).bind('blur', function(){
$(this).attr("readonly", true);
});
demo : http://jsfiddle.net/DkCvu/1/
I'm sorry, but I'm struggling to see the point of this. If I get this right, you want the input field not to be editable until it is clicked or selected by the user (which is basically how input fields work anyhow: you can't change their value unless you select them). After these input fields loose their focus, they should go back to being read only. If this is the case, you're over complicating things. However, that is none of my business. The best way to get this done IMO, is by delegating the event.
I therefore put together a couple of fiddles, on pure JS, on jQuery. Both are far from perfect, but should help you on your way.
Regular JS (fiddle here):
var dv = document.getElementById('inputDiv');
if (!dv.addEventListener)
{
dv.attachEvent('onfocusin',switchRO);
dv.attachEvent('onfocusout',switchRO);
}
else
{
dv.addEventListener('focus',switchRO,true);
dv.addEventListener('blur',switchRO,true);
}
function switchRO (e)
{
var self;
e = e || window.event;
self = e.target || e.srcElement;
if (self.tagName.toLowerCase() === 'input')
{
switch (e.type)
{
case 'onfocusin':
case 'focus':
self.removeAttribute('readonly');
break;
default:
self.setAttribute('readonly','readonly');
}
}
return true;
}
In jQuery, this might look something like this (jQuery with .on, jsfiddle here):
$('#inputDiv input').on(
{
focus: function()
{
$(this).removeAttr('readonly');
},
blur: function()
{
$(this).attr('readonly','readonly');
}
});
I posted both jQuery and pure JS, because I find it both informative and educational to know what goes on behind the screens in jQuery.
Just a quick question, I seem to do this a lot:
$saveBtn.bind("click keypress", function(e)
{
if (e.type != "keypress" || e.keyCode == 13)
{
// Do something...
return false;
}
});
Is there a quicker way to bind an 'action' listener to a button? I want to always ensure my buttons with event listeners fire on both clicks and the enter key...this seems like it'd be a fairly common thing to want to do but found nothing on google. Any thoughts?
Thanks.
The click event doesn't actually handle the keypress in every case, it's the button that is making the click event work. When you use a div with a tabindex attribute to make it keyboard accessible, the click handler will not trigger when you press enter.
HTML
<div id="click-only" tabindex="0">Submit click only</div>
<div id="click-and-press" tabindex="0">Submit click and press</div>
jQuery
$("#click-only").click(function (e) {
addToBody(); // Only works on click
});
$("#click-and-press").bind("click keypress", handleClickAndPress(function (e) {
addToBody(); // Works on click and keypress
}));
function addToBody() {
$("body").append($("<p/>").text("Submitted"));
}
function handleClickAndPress(myfunc) {
return function (e) {
if (e.type != "keypress" || e.keyCode == 13) {
myfunc(e);
}
};
}
So to answer the question, I don't think there is a better way (that works in every case) other than yoda2k's solution.
By binding it with click will do the job, no need for keep press. Example
You could create a second function which handles the additional logic and pass your function as a parameter:
function handleClickAndPress(myfunc)
{
return function (e) {
if (e.type != "keypress" || e.keyCode == 13) {
myfunc(e);
}
};
}
$saveBtn.bind("click keypress", handleClickAndPress(function (e) {
// do your stuff here
}));
If it's part of a form you could just listen for the "submit" event?