Pressing escape on a jquery autocomplete control - javascript

I have a set of fields. In read mode, they display as text within a table cell. Double clicking the cell puts the record in edit mode. Pressing "enter" while in edit mode commits the change. Pressing "esc" in edit mode returns to read mode without changing the data.
Now, each field has a jQuery UI autocomplete control added. When the autocomplete menu is visible, I want "enter" to behave as it normally does for autocomplete (replace the value in the input with the selected menu value and close the autocomplete menu) without commiting the change/returning to edit mode. And when pressing escape, if the menu is open, perform the usual autocomplete functions (return the edit field to its previous value and close the menu) without returning to read mode.
I have placed a demo of my problem here. Currently, if you press "enter" on one of the autocomplete menu items, autocomplete does its thing AND the changes are committed immediately. Pressing escape closes the autocomplete menu AND cancels edit mode.

Use the open and close events of the autocomplete to unbind/rebind your custom behavior so that it occurs only when the autocomplete menu is not open. This will keep the events from getting confused. My working code follows:
function enterEditMode() {
$("#output").append("<div>enter edit</div>");
$("#read").hide();
$("#edit").val($("#read").text()).show().focus();
}
function exitEditMode() {
$("#output").append("<div>exit edit</div>");
$("#read").show();
$("#edit").hide();
}
function commitChanges() {
$("#output").append("<div>commit</div>");
$("#read").text($("#edit").val());
exitEditMode();
}
function handleKeydown(event) {
$("#output").append("<div>handle keydown:"+event.which+"</div>");
if (event.keyCode === 27) { exitEditMode(); }
else if (event.keyCode === 13) { commitChanges(); }
}
$(function() {
$("#read").bind("dblclick", enterEditMode);
$("#edit").bind("keydown", handleKeydown).autocomplete({
source: ["this", "that", "the other"],
open: function(){ $("#edit").unbind("keydown", handleKeydown); },
close: function(){ $("#edit").bind("keydown", handleKeydown); }
});
});
The working jsfiddle is here.

You can use the select and close events to renter edit mode
close: function(event, ui) { enterEditMode()},
select: function(event, ui) { enterEditMode()}
Here they are in your code:
function enterEditMode() {
$("#read").hide();
$("#edit").show().focus();
}
function exitEditMode() {
$("#read").show();
$("#edit").hide();
}
function commitChanges() {
$("#read").text($("#edit").val());
exitEditMode();
}
$(function() {
$("#read").dblclick(enterEditMode);
$("#edit").keydown(function(event) {
if (event.keyCode === 27) exitEditMode();
else if (event.keyCode === 13) commitChanges();
}).autocomplete({
source: ["this", "that", "the other"],
close: function(event, ui) { enterEditMode()},
select: function(event, ui) { enterEditMode()}
});
});
Working Example:
http://jsfiddle.net/9unaU/6/
Update:
Made another change to ensure autocomplete is hidden on exitEditMode
function exitEditMode() {
$("#read").show();
$("#edit, .autocomplete").hide();
}
Working Example:
http://jsfiddle.net/9unaU/7/
Update 2:
Edited the if statement so it only commits if the autocomplete is hidden
if (event.keyCode === 27) exitEditMode();
else if (event.keyCode === 13 && ($('.autocomplete').is(':hidden'))) commitChanges();
Working Example 2:
http://jsfiddle.net/9unaU/10/

Related

In jquery how can i use .change to enable a button immediately?

I've a simple form with a text input and a button disabled, this button can be enabled if i write on input text, keyup() is the best way but when i use right click and paste this event isn't called and doesn't trigger that event. So i tried event change(), it's work but not immediately, i must unfocus the input text for have the button enabled. How can i enable this button immediately with copy and paste?
$(document).ready(function () {
$('#id_input').bind('keyup paste click', function () {
if ($('#id_input').val().length === 6 ){
$('#btnSubmit').removeAttr('disabled');
}
else
$('#btnSubmit').attr('disabled', 'disabled');
});
});
Rory is right that your code should work in general especially if you paste using Ctrl + V.
I assume that you experience the issue only if you paste using right-click and then select Paste from the context menu.
Try to monitor the property changes:
$(document).ready(function() {
$('#id_input').bind('input propertychange', function() {
if ($('#id_input').val().length === 6) {
$('#btnSubmit').removeAttr('disabled');
} else
$('#btnSubmit').attr('disabled', 'disabled');
});
});
You need to use the onpaste event.
$(document).ready(function () {
$('#id_input').bind('keyup onpaste click', function () {
if ($('#id_input').val().length === 6 ){
$('#btnSubmit').removeAttr('disabled');
} else {
$('#btnSubmit').attr('disabled', 'disabled');
}
});
});

Dynamically focus out blur contenteditable

http://codepen.io/anon/pen/rhnuE
I'm using JS Hotkeys from - https://github.com/jeresig/jquery.hotkeys
What I'm trying to do is deselect/focusout a focused contenteditable element. I also want the default focus dotted line to be removed when you click out of the element all called from the [Esc] key when pressed.
If anyone can help it'd be greatly appreciated.
$(document).ready(function() {
// Shortcut to deselect element
$(document).bind('keydown', 'esc', function() {
$('.box').focusout();
});
});
Try using
$('.box').blur()
instead of foucusout() it works fine for me.
$(document).ready(function() {
$(document).keyup(function(e) {
if (e.keyCode == 27) { // Key 27 is the same as Esc
$('#formId').blur();
}
});
});

How to trigger Click on enter button?

I am working on a search component in which auto suggestion comes when you type just like google. when i am clicking on autosuggestion it search fine. but when i use enter button instead of click it doesn't work. here is my code for click
function initSearchAutoClickable(resize, emchange){
$("body").on("click", ".ui-menu-item > a", function (event) {
$('.search .search-go').trigger('click');
});
}
Does anyone have idea how to make the same for enter button. .search-go is button on which search fires
Use keyup event and check the pressed button by keyCode or which
$("body").on("keyup", ".ui-menu-item > a", function (event) {
if(event.which == 13 || event.keyCode == 13){
$('.search .search-go').trigger('click');
}
});
Write code with :
$(document).keypress(function (event) {
if (event.which == 13) //Event for "Enter" key
{
//Write your code here.
}
});
If I understood you, you want to run the same code but when you press Enter, right?
So you need to do:
// Attach event Keypress to your search text box
$(someElementWhereYouPressEnter).on('keypress', onKeyPress);
// Handle keypress - check if is enter
function onKeyPress(e) {
if ( e.which == 13 ) {
// handle Enter press
$('.search .search-go').trigger('click');
}
}
Hope this will help you.
Here u have example. This must work.
http://jsfiddle.net/TDf9p/
Look on this:
$(Input).autocomplete({
source: function (request, response) {
do something
},
select: function (event, ui) {
do something
}
, change: function (event, ui) {
do something
}
, focus: function (event, ui) {
do something
}
Try use some event and do what u need in event. Debug your code and look when u want do something.
If this not help look here:
http://api.jqueryui.com/autocomplete/#event-search

How to bind an event to Tabbing Off an element?

I'm using the following for a dropdown:
/* recurse through dropdown menus */
$('.dropdown').each(function() {
/* track elements: menu, parent */
var dropdown = $(this);
var menu = dropdown.next('div.dropdown-menu'), parent = dropdown.parent();
/* function that shows THIS menu */
var showMenu = function() {
hideMenu();
showingDropdown = dropdown.addClass('dropdown-active');
showingMenu = menu.show();
showingParent = parent;
};
/* function to show menu when clicked */
dropdown.bind('click',function(e) {
if(e) e.stopPropagation();
if(e) e.preventDefault();
showMenu();
});
/* function to show menu when someone tabs to the box */
dropdown.bind('focus',function() {
showMenu();
});
});
/* hide when clicked outside */
$(document.body).bind('click',function(e) {
if(showingParent) {
var parentElement = showingParent[0];
if(!$.contains(parentElement,e.target) || !parentElement == e.target) {
hideMenu();
}
}
});
Notice:
$(document.body).bind('click',function(e) {
The problem is that the dropdown opens on click or when you tab to it. But it only closes on click, not when you tab out.
How can I bind an event to mean "tabbing out" ,losing focus, so the dropdown closes?
Thanks
You could trigger a click outside when you press the tab key. Like this:
$('#your_dropdown').bind('keydown', function(e) {
var keyCode = e.keyCode || e.which;
if (keyCode == 9) { //If it's the tab key
$("body").click(); //Force a click outside the dropdown, so it forces a close
}
});
Hope this helps. Cheers
Try the blur event, which will be triggered when the control loses focus (i.e., when the user clicks outside the control or uses the keyboard to tab to the next control).
Put something like this just after your existing focus binding:
dropdown.bind('blur',function() {
// whatever tests you want
hideMenu();
});
(You shouldn't then need the separate click binding that you're currently using to hide the menu.)
P.S. You might also consider focusout, which is similar to blur except that it bubbles.
Seems like you're looking for the onblur event?

jquery-ui Dialog: Make a button in the dialog the default action (Enter key)

In a jquery modal dialog, is there a way to select a button as the default action (action to execute when the user presses enter)?
Example of jquery web site:
jquery dialog modal message
In the example above the dialog closes when the user presses Esc. I would like the "Ok" button action to be called when the user presses Enter.
In your dialog's open function, you can focus the button:
$("#myDialog").dialog({
open: function() {
$(this).parents('.ui-dialog-buttonpane button:eq(0)').focus();
}
});
Change the :eq(0) if it's at a different index, or find by name, etc.
I like this one (it is working for me), which leaves the focus where I wanted to be (a text box)
$("#logonDialog").keydown(function (event) {
if (event.keyCode == $.ui.keyCode.ENTER) {
$(this).parent()
.find("button:eq(0)").trigger("click");
return false;
}
});
However, this is working just for one button (Ok button), if needed ':eq(n)' could be set to select other button.
Note: I added a new line returning false to prevent event bubbling when the enter key is handled, I hope it helps better than before.
try this way:
$("#myDialog").dialog({
open: function() {
$(this).siblings('.ui-dialog-buttonpane').find('button:eq(1)').focus();
}
});
This other stackoverflow question should get you where you want:
$('#DialogTag').keyup(function(e) {
if (e.keyCode == 13) {
//Close dialog and/or submit here...
}
});
Another option that gives you more control over all buttons in the dialog is to add them as an array of buttons. Then in the open event you can get the buttons by id and do whatever you want (including set the focus)
$('#myDialog').dialog({
buttons: [
{
id: "btnCancel",
text: "Cancel",
click: function(){
$(this).dialog('close');
}
},
{
id: "btnOne",
text: "Print One",
click: function () {
SomeFunction(1);
}
},
{
id: "btnTwo",
text: "Print Two",
click: function(){
SomeFunction(0);
}
}
],
open: function () {
if ($('#hiddenBool').val() != 'True') {
$('#btnOne').hide();
}
$("#btnTwo").focus();
}
});
A slight variation to use the buttons name as the selector. It reads a little better but there is obvious duplication with the button text string. Refactor to taste.
$("#confirm-dialog").dialog({
buttons: {
"Cancel" : function(){},
"OK" : function(){}
},
open: function() {
$(this).siblings('.ui-dialog-buttonpane').find("button:contains('OK')").focus();
}
});
The simplest way would be to use the submit action on a form within the dialog, however:
I did not want to require a form within dialog (N.B. different browsers handle the enter key differently, and some do not always do a submit on enter).
I wanted this to work if the user clicks in the title pane or button pane prior to pressing enter.
I wanted to make a library method that I can use for ANY
jQueryUI dialog.
The company I work for is 'EBL' and I avoid global scope...hence the prefix on the functions below:
EBL.onUiDialogOpen = function (event, ui, hideX, actionFirstButtonOnEnterKey) {
if (hideX) {
// There is no option to hide the 'X' so override.
$(".ui-dialog-titlebar-close").hide();
}
if (actionFirstButtonOnEnterKey) {
/* (event.target) will give the div that will become the content
of a UI dialog, once div is 'opened' is it surrounded by a
parent div that contains title and buttonpane divs as well as
content div - so I use .parent()
...The keyup function is binded to all descendants, therefore:
-We need the e.stopPropagation() line.
-This code is NOT what you want if you DON'T want enter
key to initiate first button regardless of selected control.
*/
$(event.target).parent().bind('keydown.justWhileOpen', function (e) {
if (e.keyCode === $.ui.keyCode.ENTER) {
e.stopPropagation();
$(event.target).next('.ui-dialog-buttonpane')
.find('button:first').click();
}
});
}
};
...works in combination with:
EBL.onUiDialogClose = function (event, ui) {
// Remove keyup handler when we close dialog
$(event.target).parent().unbind('.justWhileOpen');
};
You do not need the .onUiDialogClose if you are using a dynamically created div and destroying it afterwards.
You can see below how I use these library functions when initialising a non-dynamic dialog...
$('#divName').dialog({
//...
open: function (event, ui) { EBL.onUiDialogOpen(event, ui, false, true); },
close: function (event, ui) { EBL.onUiDialogClose(event, ui); },
//...
});
So far I have tested this in IE9 and latest chrome/firefox.
You should validate the dialog as neccessary in your 'Ok' function.
I'm using version 1.10.0. I could not get it to work with open but with focus. This focuses the second button:
focus: function(){
$(this).siblings('.ui-dialog-buttonpane').find('button:eq(1)').focus();
}
$("#logonDialog").keydown(function (event) {if (event.keyCode == 13) {
$(this).parent().find("button:eq(0)").trigger("click");
return false;
}
});
This worked for me within the dialog using jquery 1.10.2
dialog({
focus: function() {
$(this).on("keyup", function(e) {
if (e.keyCode === 13) {
$(this).parent().find("button:eq(1)").trigger("click");
return false;
}
});
},
more options...
This simple piece of code styles your buttons and sets the default to the last one:
open: function(){
$buttonPane = $(this).next();
$buttonPane.find('button:first').addClass('accept').addClass('ui-priority-secondary');
$buttonPane.find('button:last').addClass('cancel').addClass('ui-state-default');
$buttonPane.find('button:last').focus();
},
In my case, none of the answers worked because I called .dialog on an empty div and added my buttons dynamically, so the $(this).html() would return nothing. So I couldn't call methods like parent() or siblings() and expect something in return. What I did was select the ui-dialog-buttonpane class directly and find the button element from there
HTML
<div id = "dialogexample">
</div>
Jquery
$("#dialogexample").dialog({
autoOpen: false,
modal: true,
open: function () {
$('.ui-dialog-buttonpane').find('#otherbutton').focus();
}
});
var buttons = {
"MyButton" : {
text: "Do Stuff",
id: "dostuffbutton"
},
"OtherButton" : {
text: "Other Stuff",
id: "otherbutton"
}
}
$("#dialogexample").dialog("option", "buttons", buttons);
$("#dialogexample").dialog("open"); //the second (otherbutton), instead of
//the first (dostuffbutton) button should be focused
I know this is an old thread, but I was searching for this exact functionality and was able to implement what I think is the best solution as I found all of the above to fall short a little.
It is a combination of two answers above. Using an ID rather than relying on the find() function to find the button element always seems to be a much better choice to me.
Also explicitly looking for the enter key to be pressed allows us to set focus to whatever element we want when the dialog is opened if desired. This just seems to allow for the most flexibility while satisfying the desire of triggering a specific button as 'default' when the enter key is pressed. I have also implemented a 'cancel' default as well.
I hope this helps others looking for a good 'default' button solution for dialogs.
$("#LoginBox").dialog({
open: function(){
$(this).keydown(function (event) {
if (event.keyCode == 13) {
$("#LogInButton").trigger("click");
return false;
}
if (event.keyCode == 27) {
$("#CancelButton").trigger("click");
return false;
}
});
},
close: function(){
$(this).dialog("destroy");
},
buttons: [
{
id: "LogInButton",
text: "Log In",
click: function(){
//button functionality goes here
$(this).dialog("destroy");
}
},
{
id: "CancelButton",
text: "Cancel",
click: function(){
$(this).dialog("destroy");
}
}
]
});
You should to use :tabbable selector and index of your button (0 is [X] button, yours started from 1)
open: function() {
var tb = $(":tabbable", this.parentNode);
if(tb.length>1) {
tb[1].focus();
}
}

Categories