I found this nice plugin for jQuery that will allow users to press ENTER instead of TAB to navigate through form elements. It makes use of the specified tabindex to transfer focus. I modified it a little to make it work when:
- The next element is disabled (next means next tabindex)
- The tabindex specified was not defined
- Includes textarea and links
When it cannot focus on the next element, it will loop 3 times until it will find a focusable element.
/*
* Copyright (c) 2007 Betha Sidik (bethasidik at gmail dot com)
* Licensed under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
* This plugin developed based on jquery-numeric.js developed by Sam Collett (http://www.texotela.co.uk)
*/
/*
* Change the behaviour of enter key pressed in web based to be tab key
* So if this plugin used, a enter key will be a tab key
* User must explicitly give a tabindex in element such as text or select
* this version will assumed one form in a page
* applied to element text and select
*
*/
/*
* I modified the plugin to work for my need
* This will work even if the next tabindex is non-existent, or disabled so
* it will find the very next element on the tabindex series until the maximum tabindex
* which must be defined manually.
*
* ALL CREDITS GOES TO THE ORIGINAL AUTHOR
*/
jQuery.fn.enter2tab = function()
{
this.keypress(function(e){
// get key pressed (charCode from Mozilla/Firefox and Opera / keyCode in IE)
var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
var tmp = null;
var maxTabIndex = 96;
// get tabindex from which element keypressed
var nTabIndex=this.tabIndex+1;
// get element type (text or select)
var myNode=this.nodeName.toLowerCase();
// allow enter/return key (only when in an input box or select)
if(nTabIndex > 0 && key == 13 && nTabIndex <= maxTabIndex && ((myNode == "textarea") || (myNode == "input") || (myNode == "select") || (myNode == "a")))
{
for (var x=0; x<3; x++)
{
tmp = $("a[tabIndex='"+nTabIndex+"'],textarea[tabIndex='"+nTabIndex+"'],select[tabIndex='"+nTabIndex+"'],input[tabIndex='"+nTabIndex+"']").get(0);
if (typeof tmp != "undefined" && !$(tmp).attr("disabled"))
{
$(tmp).focus();
return false;
//break;
}
else
{
nTabIndex++;
}
}
return false;
}
else if(key == 13)
{
return false;
}
})
return this;
}
[/sourcecode]
To apply it on the form:
[sourcecode language='js']
$("input").enter2tab();
$("select").enter2tab();
$("textarea").enter2tab();
$("a.dp-choose-date").enter2tab();
[/sourcecode]
Matching all input, select, textarea and links.
I updated the code to work with jQuery 1.3 and shortened it to work better without a need for a tab index limit.
jQuery.fn.tabEnter = function() {
this.keypress(function(e){
// get key pressed (charCode from Mozilla/Firefox and Opera / keyCode in IE)
var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
if(key == 13) {
// get tabindex from which element keypressed
var ntabindex = parseInt($(this).attr("tabindex")) + 1;
$("[tabindex=" + ntabindex + "]").focus();
return false;
}
});
}
Example HTML elements:
Just change the “tabindex” value on each input to be incremental.
Then to initialize tabs on enter:
$("[tabindex]").tabEnter();
Wow, great!
I made the following mods to enable the focus to cycle through all the targeted elements, i.e. when at last field in form and user presses ENTER, the focus shifts back to the first field in the form instead of staying stuck in the last field. This also gets rid of the annoyance when tabbing through form fields, the focus goes outside the form after tabbing out of the last form field and into the web browser address field, etc.
MOD 1 :: Change function sig to accept a min and max tabindex val:
jQuery.fn.enter2tab = function(minTabIndex, maxTabIndex) {
MOD 2 :: remarked out the “var maxTabIndex = 96” statement at line 34
MOD 3 :: inserted at line 38:
if (nTabIndex > maxTabIndex) {
// circle back around to the first input/select/textarea element
nTabIndex = minTabIndex;
}
Then, in HTML or ASP.NET code-behind, for example:
$(document).ready(function() {
$('input').enter2tab(1, 5);
});
I hope someone else finds this helpful.
Thanks for dropping by Nathan, good thing you used it.
Here is my code for doing the same thing. It has to work with large excel-like pages where cells can be added dynamically, and where tabindex may or may not be used. Hence elements with the same or without tabindex has to be tabbed in document order.
Key details:
* stable sort elements after tabindex and document order
* narrow selector context to the current and next tr for speed
$("form").keydown(function(e){
if (e.which != 13) return; // ENTER
if (e.target.type == "textarea" || e.target.type == "button") return;
if ($("input[type=submit]", this).length == 1) return; // autosubmit form
var nextTabbable = null;
var $tr = $(e.target).closest("tr, form");
var narrowContext = $tr.length && e.target.tabIndex == undefined && !$tr.is("form");
if (narrowContext) nextTabbable = getNextTabbable($tr.add($tr.next()), e.target);
if (!nextTabbable) nextTabbable = getNextTabbable(this, e.target);
if (nextTabbable) {
if (nextTabbable.type == "text" && nextTabbable.value != "") nextTabbable.select();
nextTabbable.focus();
return false;
}
});
function getNextTabbable(ctx, current) {
//var $t = $("input, select, textarea", ctx).filter("[tabindex!=-1]:visible").not(":disabled"); slower
var $t = $("input[tabindex!=-1]:visible, select[tabindex!=-1]:visible, textarea[tabindex!=-1]:visible", ctx).not(":disabled");
var docIndex = {};
$t.each(function(i,e){ docIndex[e] = i });
$sorted = $t.sort(function(a,b){ return a.tabIndex==b.tabIndex ? docIndex[a]
Wow, why not make it a jQuery plugin instead? Thanks for posting your code.
Lazyness I guess.. plus I havn’t had the need to reuse the code elsewhere
Yeah, because for simplicity (and most of my projects) did not require such specs. Anyway, we can just rely on the document order and let CSS position them 😀
Where is example and complete script for this. Thank you for this articel. I just looking for better script to switch ENTER key to TAB key.
hi Mobil…
There is no sample or demo for this post but the script was the one posted above with very short example of how to apply them on the form.
Problem with .keypress and .change events…
I’ve included the published code above to convert enter2tab. Works great! Thank you!
But then I added an isFieldDirty, isTabDirty, isFormDirty setup. Basically when an input is “changed” I add a dirty class to the field, its tab, and to the form. For debugging purposes, I have a visible field with an id=”FormDirtyFields” to show the count as thing progress:
var dirtyInputTriggered = 0;
$('input').change(function(event) {
if ($(event.target).hasClass('notDirty')) {
dirtyInputTriggered++;
$(event.target).removeClass('notDirty').addClass('isDirty');
$("#FormDirtyFields").val(dirtyInputTriggered);
$tid = $(event.target).attr('tabID');
//$("#FormDirtyFields").val($tid);
if ($tid) {
$tabhtml = $("#"+$tid).html();
if ( !$("#"+$tid).hasClass("tabIsDirty" )) {
$("#"+$tid).addClass("tabIsDirty");
$tabtext = $tabhtml.replace("", '');
//$tabtext = $tabhtml.replace('', "*");
$("#"+$tid).html($tabtext);
}
if ( !$("#formLegend").hasClass("formIsDirty") ) {
$("#formLegend").addClass("formIsDirty");
$newlegend = $("#formLegend").html().replace(")", ") ± ");
$("#formLegend").html($newlegend);
}
}
}
});
My problem is: The .keypress works fine, except the .change event does not occur when enter is used… it only occurs when I tab to leave an input field. Is there something I’m missing on the event firing order?
Thanks in advance,
Greg
Hello…
I misspoke before… The .change event was fired using Tab and Mouse Clicks.
To temporarily fix my issue I’ve included the following code just before the two $(tmp).focus() calls:
if($(e.target).attr("defaultValue") != $(e.target).val()) {
$(e.target).change();
}
This works, but it seems odd that the jQuery .change event would not be fired when we program (force) a focus change.
Look forward to your input… Thanks!
Greg
Hi Greg,
I haven’t experienced much of that scenario. How about using a function as another step for your
dirty
triggering logic, instead of putting them directly on the event. That way, you can just call the function when the event is fired or when you want to call it explicitly in case enter2tab conflicts when your change event.