Tinyscrollbar and tab key interaction - javascript

How to solve the issue with tab key interaction with tinyscrollbar. When I press tab key to jump to input which is not in view, I get destroyed layout, scroll bars go away, etc. How to solve that?

This is what I have done: Add a tabindex attribute to the element, so that the element can receive focus state from the tab key or mouse click:
<div class="scroll-area" tabindex="1">
<div class="viewport">
<div class="overview">
… CONTENT …
</div>
</div>
<div class="scrollbar">
<span class="track"><span class="thumb"></span></span>
</div>
</div>
Next, I create this function inside the TinyScrollbar plugin to add keyboard support and enable the keyboard navigation on :focus:
$.fn.tinyscrollbar = function(params) {
var options = $.extend({}, $.tiny.scrollbar.options, params),
$this = this;
$this.each(function() {
$(this).data('tsb', new Scrollbar($(this), options));
// Enable keyboard support on focus
$this.on('focus', function () {
$(this).on('keydown', function (e) {
if (e.keyCode == 38 || e.keyCode == 37) {
$(this).tinyscrollbar_keystep(40); // step 40px on single keypress
return false;
} else if (e.keyCode == 40 || e.keyCode == 39) {
$(this).tinyscrollbar_keystep(-40); // step -40px on single keypress
return false;
}
});
});
});
return $this;
};
Then, create .tinyscrollbar_keystep() for updating the scroll step below the .tinyscrollbar_update():
$.fn.tinyscrollbar_update = function(sScroll) {
return $(this).data('tsb').update(sScroll);
};
// Add this functionality for scroll update on keypress (in this case)
$.fn.tinyscrollbar_keystep = function(sScroll) {
return $(this).data('tsb').keystep(sScroll);
};
And .keystep function after initialize()
function initialize() { … }
this.keystep = function(sScroll) {
if (oContent.ratio < 1) {
iScroll -= sScroll;
iScroll = Math.min((oContent[options.axis] - oViewport[options.axis]), Math.max(0, iScroll));
oThumb.obj.css(sDirection, iScroll / oScrollbar.ratio);
oContent.obj.css(sDirection, - iScroll);
}
};
Demo: http://jsbin.com/zaqogidexese/1/edit

I have similar situation here and this is my solution for form input fields:
$(document).on('keydown',function(e) {
switch (e.keyCode ? e.keyCode : e.which) {
case 9: // Tab
if (e.target.localName == 'input') {
content.tinyscrollbar_update($(e.target).position().top);
}
break;
}
});
if you have any wrapper element for each input, update the ".position().top" to ".parent().position().top"

Related

Pressing space on iframe scrolls parent page down, how to prevent that without breaking keyup event

My iframe game is reading the keyboard including space, but on some browsers (Firefox, Safari) pressing Space also scrolls my page down, that causes my game to partially go out of screen. Sometimes it seems the page even scrolls back up when some other keys are pressed...
My game handles keypresses on "keyup" event.
input.addEventListener("keyup", function (e) {
//game handles all keys including space here
}
Because of using keyup event, this answer is not suitable to prevent space ;
Pressing spacebar scrolls page down?
If I add this code, my game does not receive keyup events:
window.onkeydown = function(e) {
return !(e.keyCode == 32);
};
When I add this code above to parent html page, having ifreme, it only works if keyboard focus is clicked to parent html. When focus is inside iframe, the code does not work.
It seems above code fixed issue for Safari!
The onkeypress event fires the browser scrolling. You can call preventDefault in this event, and the keyup and keydown events will continue to fire as intended.
window.onkeypress = function(e) {
if (e.keyCode == 32) {
e.preventDefault();
}
};
window.onkeyup = function(e) {
console.log("Space key up!")
};
You need preventDefault
window.addEventListener('keydown', (e) => {
if (e.keyCode === 32) {
e.preventDefault();
}
});
See this codepen for a demo: https://codepen.io/xurei/pen/MWyveEp
You have to find the right window object first
function getIframeWindow(iframe_object) {
var doc;
if (iframe_object.contentWindow) {
return iframe_object.contentWindow;
}
if (iframe_object.window) {
return iframe_object.window;
}
if (!doc && iframe_object.contentDocument) {
doc = iframe_object.contentDocument;
}
if (!doc && iframe_object.document) {
doc = iframe_object.document;
}
if (doc && doc.defaultView) {
return doc.defaultView;
}
if (doc && doc.parentWindow) {
return doc.parentWindow;
}
return undefined;
}
var myFrame = document.getElementById('targetFrame');
var frame_win = getIframeWindow(myFrame);
and then add the listeners to stop the spacebar event from bubbling up.
if (frame_win) {
var preventSpace = (e) => {
if (e.keyCode === 32) {
e.preventDefault();
}
};
frame_win.addEventListener('keydown', preventSpace);
frame_win.addEventListener('keyup', preventSpace);
frame_win.addEventListener('keypress', preventSpace);
}

Javascript event keypress on hover

Hi I have multiple divs on the page. I want to raise an alert based on a user hovering over one of the divs and pressing control z. I need to in effect alert out what is in the span dependant upon which div the user is hovered over on.
I have tried with getbyId the problem arises with multiple elements. I am unsure if i need to bind every element.
<div class="mydiv">Keypress here!<span>test</span></div>
<div class="mydiv">Keypress here!<span>test1</span></div>
var pressed = false;
onload = function(e) {
var myElement = document.getElementsByTagName('div');
function keyaction(e, element) {
// var originator = e.target || e.srcElement;
if (e.charCode === 122 && e.ctrlKey) {
//myElement.innerHTML += String.fromCharCode(e.charCode);
alert(true);
}
}
for (var i = 0; i < myElement.length; i++) {
myElement[i].addEventListener("mouseover", function (e)
{
document.addEventListener("keypress", function(t){keyaction(t,e);}, false);
});
myElement[i].addEventListener("mouseout", function ()
{
document.removeEventListener("keypress", keyaction, false);
});
}
}
I think you are overdoing for what is needed. A simple keydown event bind on mouseover and unbind on mouseout would do the trick.
Here's an example :
<div id="wrapper">
<div class="mydiv">Keypress here!<span>test</span></div>
<div class="mydiv">Keypress here!<span>test1</span></div>
</div>
<br>
Keys Pressed :
<br>
<div id="key"></div>
$("#wrapper .mydiv").on("mouseover",function()
{
$(document).bind("keydown",function(e) {
var originator = e.keyCode || e.which;
if(e.ctrlKey)
$("#key").append(originator + ",");
});
}).on("mouseout",function()
{
$(document).unbind("keydown");
});
http://jsfiddle.net/s095evxh/2/
P.S : for some reason , Jsfiddle doesn't allow keydown event on mouseover so you might have to click manually on the div to make it work but the solution works flawless on a local system.
I would suggest that you use the normalized e.which if available. You also have code 122 which is F11 keys code not 90 related to the 'z' key.
Turn the event manager on when over and off when not per your stated desire:
$('.mydiv').on('mouseenter', function () {
$(window).on('keydown', function (e) {
var code = e.which ||e.keyCode;
$('#status').append('we:'+ code);
if (code === 90 && e.ctrlKey) {
$('#status').append('howdy');
}
});
});
$('.mydiv').on('mouseleave', function () {
$(window).off('keydown');
});
Note that I changed to post some text to a fictitious "status" div rather than your alert as that will change where the cursor hovers. Change that to some real action. There MAY be issues with the event bubbling but I will leave that determination to you.
Here is a key code list (google for more/another) https://gist.github.com/lbj96347/2567917
EDIT: simple update to push the span text into the status div:
<div class="mydiv">Keypress here!<span>test</span>
</div>
<div class="mydiv">Keypress here!<span>test1</span>
</div>
<div id="status">empty
<div>
$('.mydiv').on('mouseenter', function () {
var me = this;
$(window).on('keydown', function (e) {
var code = e.which || e.keyCode;
$('#status').append('we:' + code);
if (code === 90 && e.ctrlKey) {
$('#status').append($(me).find('span').text());
}
});
});
$('.mydiv').on('mouseleave', function () {
$(window).off('keydown');
$('#status').text('out');
});
Listen for the keypress on the window and add mouse events to the elements to toggle a variable with what element is active.
var activeElem = null;
$(".mydiv")
.on("mouseenter", function () {
activeElem = $(this);
}).on("mouseleave", function () {
if(activeElem && activeElem.is(this)) {
activeElem = null;
}
});
$(window).on("keydown", function (evt) {
if( activeElem && evt.keyCode===90 && evt.ctrlKey) {
console.log(activeElem.find("span").text());
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="mydiv">Keypress here!<span>test</span></div>
<div class="mydiv">Keypress here!<span>test1</span></div>
To prevent frequent binding/unbinding of the "keydown" handler whenever the user hovers over the <div>, I would simply keep track of the <div> currently being hovered. Something like this:
var hovering = null;
$(document)
.on('keydown', function(e) {
if (e.which === 90 && e.ctrlKey && hovering) {
console.log($('span', hovering).text());
}
})
.on('mouseover', '.mydiv', function(e) {
hovering = this;
})
.on('mouseout', '.mydiv', function() {
hovering = null;
});
.mydiv:hover {
cursor: pointer;
color: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="mydiv">Test <span>1</span></div>
<div class="mydiv">Test <span>2</span></div>
<div class="mydiv">Test <span>3</span></div>
<div class="mydiv">Test <span>4</span></div>
<div class="mydiv">Test <span>5</span></div>
I would propose the other way around. Listen for the keypress, and select the element which has the hover.
$(document).keypress(function(e) {
if (e.charCode === 26 && e.ctrlKey) {
console.log("Key pressed");
console.log($('.mydiv:hover span').html());
}
});
Codepen Demo
If I am understanding your question correctly, you are looking for the text value of the span within the hovered element. Traversing the DOM from $(this) will get you what you want.
$(".mydiv").mouseover(function (e) {
alert($(this).find('span').text());
});

Disable keyboard shortcuts when text field or textarea has focus using pure JavaScript

I have a simple script that uses left and right arrows to move to next and previous blogpost.
var nextEl = document.getElementById("pagination__next__link");
var prevEl = document.getElementById("pagination__prev__link");
document.onkeyup = function(e) {
if (nextEl !== null) {
if (e.keyCode === 37) {
window.location.href = nextEl.getAttribute('href');
}
}
if (prevEl !== null) {
if (e.keyCode === 39) {
window.location.href = prevEl.getAttribute('href');
}
}
return false;
};
But it also works when I have text input or textarea focused. What would be the best way to disable the keyboard shortcuts when focused?
Thanks!
Disable event propagation of the input to the document
nextEl.onkeyup = prevEl.onkeyup = function(e){ e.stopPropagation(); };

KeyBoard Navigation for menu using jquery

I am trying to add keyboard navigation to Menu(ul li based
) , i have bound the keydown event to menu (or should i bind keydown to the document ?)
the handler function used is given below
KeyDown: function(e) {
var toFocus = false;
if (e.keyCode == 38) {
toFocus = $((e.target/* li */).next()[0]);
}
if (e.keyCode == 40) {
toFocus = $((e.target).next()[1]);
}
if (toFocus) {
$(e.target).attr('tabIndex', '-1');
$(toFocus).attr('tabIndex', '0');
toFocus.focus();
return false;
}
}
here i get e.target as html instead of li ?
can u suggest any other way to add keyboard navigation ?
Try to use custom attribute to hold the tabid for up and down.
...KeyDown: function(e) {
var Direction;
if (e.keyCode == 38)
Direction = "toUp";
else Direction = "toDown";
var Focus = $("li[tabid=\""$(e.target.id).attr(Direction)"\"]");
Focus.focus();
}
---
<li ... tabid="1" toUp="-1" toDown= "2" />
<li ... tabid="2" toUp= "1" toDown= "3" />
<li ... tabid="3" toUp= "2" toDown= "4" />
<li ... tabid="4" toUp= "3" toDown="-1" />
The above code is just to show the idea, it is late now and I didn't have time to test it. So please don't vote me down for not working.
Hope that helps
I just wonder if, instead of doing this by your self, why not using an already existing plugin?
jQuery Keyboard Navigation
demo page here
my demo: just to add a demo page of an example
HTML
<body>
<input type="text" id="target-box" >
<ul class="list">
<li class="selected">Hello</li>
<li>World</li>
</ul>
</body>
jQuery
$(document).on('focus','#target-box', function() {
var target_box = $(this);
$(document).on('keyup', function(e) {
if(e.which == 38){ // up arrow
var selected_item = $('.selected');
if(typeof selected_item.prev()[0] !== 'undefined') {
selected_item.prev().addClass('selected');
selected_item.removeClass('selected');
}
} else if (e.which == 40) { // down arrow
var selected_item = $('.selected');
if (typeof selected_item.next()[0] !== 'undefined') {
selected_item.next().addClass('selected');
selected_item.removeClass('selected');
}
}
if (e.keyCode == 13) { // enter
target_box.val($('.selected').html());
}
});
});
CSS
.selected {
width : 50px;
background-color: gray;
}

Enter key press behaves like a Tab in Javascript

I'm looking to create a form where pressing the enter key causes focus to go to the "next" form element on the page. The solution I keep finding on the web is...
<body onkeydown="if(event.keyCode==13){event.keyCode=9; return event.keyCode}">
Unfortunately, that only seems to work in IE. So the real meat of this question is if anybody knows of a solution that works for FF and Chrome? Additionally, I'd rather not have to add onkeydown events to the form elements themselves, but if that's the only way, it will have to do.
This issue is similar to question 905222, but deserving of it's own question in my opinion.
Edit: also, I've seen people bring up the issue that this isn't good style, as it diverges from form behavior that users are used to. I agree! It's a client request :(
I used the logic suggested by Andrew which is very effective. And this is my version:
$('body').on('keydown', 'input, select', function(e) {
if (e.key === "Enter") {
var self = $(this), form = self.parents('form:eq(0)'), focusable, next;
focusable = form.find('input,a,select,button,textarea').filter(':visible');
next = focusable.eq(focusable.index(this)+1);
if (next.length) {
next.focus();
} else {
form.submit();
}
return false;
}
});
KeyboardEvent's keycode (i.e: e.keycode) depreciation notice :- https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
The simplest vanilla JS snippet I came up with:
document.addEventListener('keydown', function (event) {
if (event.keyCode === 13 && event.target.nodeName === 'INPUT') {
var form = event.target.form;
var index = Array.prototype.indexOf.call(form, event.target);
form.elements[index + 1].focus();
event.preventDefault();
}
});
Works in IE 9+ and modern browsers.
Map [Enter] key to work like the [Tab] key
I've rewritten Andre Van Zuydam's answer, which didn't work for me, in jQuery. This caputures both Enter and Shift+Enter. Enter tabs forward, and Shift+Enter tabs back.
I've also rewritten the way self is initialized by the current item in focus. The form is also selected that way. Here's the code:
// Map [Enter] key to work like the [Tab] key
// Daniel P. Clark 2014
// Catch the keydown for the entire document
$(document).keydown(function(e) {
// Set self as the current item in focus
var self = $(':focus'),
// Set the form by the current item in focus
form = self.parents('form:eq(0)'),
focusable;
// Array of Indexable/Tab-able items
focusable = form.find('input,a,select,button,textarea,div[contenteditable=true]').filter(':visible');
function enterKey(){
if (e.which === 13 && !self.is('textarea,div[contenteditable=true]')) { // [Enter] key
// If not a regular hyperlink/button/textarea
if ($.inArray(self, focusable) && (!self.is('a,button'))){
// Then prevent the default [Enter] key behaviour from submitting the form
e.preventDefault();
} // Otherwise follow the link/button as by design, or put new line in textarea
// Focus on the next item (either previous or next depending on shift)
focusable.eq(focusable.index(self) + (e.shiftKey ? -1 : 1)).focus();
return false;
}
}
// We need to capture the [Shift] key and check the [Enter] key either way.
if (e.shiftKey) { enterKey() } else { enterKey() }
});
The reason textarea
is included is because we "do" want to tab into it. Also, once in, we don't want to stop the default behavior of Enter from putting in a new line.
The reason a and button
allow the default action, "and" still focus on the next item, is because they don't always load another page. There can be a trigger/effect on those such as an accordion or tabbed content. So once you trigger the default behavior, and the page does its special effect, you still want to go to the next item since your trigger may have well introduced it.
Thank you for the good script.
I have just added the shift event on the above function to go back between elements, I thought someone may need this.
$('body').on('keydown', 'input, select, textarea', function(e) {
var self = $(this)
, form = self.parents('form:eq(0)')
, focusable
, next
, prev
;
if (e.shiftKey) {
if (e.keyCode == 13) {
focusable = form.find('input,a,select,button,textarea').filter(':visible');
prev = focusable.eq(focusable.index(this)-1);
if (prev.length) {
prev.focus();
} else {
form.submit();
}
}
}
else
if (e.keyCode == 13) {
focusable = form.find('input,a,select,button,textarea').filter(':visible');
next = focusable.eq(focusable.index(this)+1);
if (next.length) {
next.focus();
} else {
form.submit();
}
return false;
}
});
This worked for me:
$(document).on('keydown', ':tabbable', function(e) {
if (e.key === "Enter") {
e.preventDefault();
var $canfocus = $(':tabbable:visible');
var index = $canfocus.index(document.activeElement) + 1;
if (index >= $canfocus.length) index = 0;
$canfocus.eq(index).focus();
}
});
Changing this behaviour actually creates a far better user experience than the default behaviour implemented natively. Consider that the behaviour of the enter key is already inconsistent from the user's point of view, because in a single line input, enter tends to submit a form, while in a multi-line textarea, it simply adds a newline to the contents of the field.
I recently did it like this (uses jQuery):
$('input.enterastab, select.enterastab, textarea.enterastab').live('keydown', function(e) {
if (e.keyCode==13) {
var focusable = $('input,a,select,button,textarea').filter(':visible');
focusable.eq(focusable.index(this)+1).focus();
return false;
}
});
This is not terribly efficient, but works well enough and is reliable - just add the 'enterastab' class to any input element that should behave in this way.
I reworked the OPs solution into a Knockout binding and thought I'd share it. Thanks very much :-)
Here's a Fiddle
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js" type="text/javascript"></script>
</head>
<body>
<div data-bind="nextFieldOnEnter:true">
<input type="text" />
<input type="text" />
<select>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
<input type="text" />
<input type="text" />
</div>
<script type="text/javascript">
ko.bindingHandlers.nextFieldOnEnter = {
init: function(element, valueAccessor, allBindingsAccessor) {
$(element).on('keydown', 'input, select', function (e) {
var self = $(this)
, form = $(element)
, focusable
, next
;
if (e.keyCode == 13) {
focusable = form.find('input,a,select,button,textarea').filter(':visible');
var nextIndex = focusable.index(this) == focusable.length -1 ? 0 : focusable.index(this) + 1;
next = focusable.eq(nextIndex);
next.focus();
return false;
}
});
}
};
ko.applyBindings({});
</script>
</body>
</html>
Here is an angular.js directive to make enter go to the next field using the other answers as inspiration. There is some, perhaps, odd looking code here because I only use the jQlite packaged with angular. I believe most of the features here work in all browsers > IE8.
angular.module('myapp', [])
.directive('pdkNextInputOnEnter', function() {
var includeTags = ['INPUT', 'SELECT'];
function link(scope, element, attrs) {
element.on('keydown', function (e) {
// Go to next form element on enter and only for included tags
if (e.keyCode == 13 && includeTags.indexOf(e.target.tagName) != -1) {
// Find all form elements that can receive focus
var focusable = element[0].querySelectorAll('input,select,button,textarea');
// Get the index of the currently focused element
var currentIndex = Array.prototype.indexOf.call(focusable, e.target)
// Find the next items in the list
var nextIndex = currentIndex == focusable.length - 1 ? 0 : currentIndex + 1;
// Focus the next element
if(nextIndex >= 0 && nextIndex < focusable.length)
focusable[nextIndex].focus();
return false;
}
});
}
return {
restrict: 'A',
link: link
};
});
Here's how I use it in the app I'm working on, by just adding the pdk-next-input-on-enter directive on an element. I am using a barcode scanner to enter data into fields, the default function of the scanner is to emulate a keayboard, injecting an enter key after typing the data of the scanned barcode.
There is one side-effect to this code (a positive one for my use-case), if it moves focus onto a button, the enter keyup event will cause the button's action to be activated. This worked really well for my flow as the last form element in my markup is a button that I want activated once all the fields have been "tabbed" through by scanning barcodes.
<!DOCTYPE html>
<html ng-app=myapp>
<head>
<script src="angular.min.js"></script>
<script src="controller.js"></script>
</head>
<body ng-controller="LabelPrintingController">
<div class='.container' pdk-next-input-on-enter>
<select ng-options="p for p in partNumbers" ng-model="selectedPart" ng-change="selectedPartChanged()"></select>
<h2>{{labelDocument.SerialNumber}}</h2>
<div ng-show="labelDocument.ComponentSerials">
<b>Component Serials</b>
<ul>
<li ng-repeat="serial in labelDocument.ComponentSerials">
{{serial.name}}<br/>
<input type="text" ng-model="serial.value" />
</li>
</ul>
</div>
<button ng-click="printLabel()">Print</button>
</div>
</body>
</html>
Try this...
$(document).ready(function () {
$.fn.enterkeytab = function () {
$(this).on('keydown', 'input,select,text,button', function (e) {
var self = $(this)
, form = self.parents('form:eq(0)')
, focusable
, next
;
if (e.keyCode == 13) {
focusable = form.find('input,a,select').filter(':visible');
next = focusable.eq(focusable.index(this) + 1);
if (next.length) {
//if disable try get next 10 fields
if (next.is(":disabled")){
for(i=2;i<10;i++){
next = focusable.eq(focusable.index(this) + i);
if (!next.is(":disabled"))
break;
}
}
next.focus();
}
return false;
}
});
}
$("form").enterkeytab();
});
I've had a similar problem, where I wanted to press + on the numpad to tab to the next field. Now I've released a library that I think will help you.
PlusAsTab: A jQuery plugin to use the numpad plus key as a tab key equivalent.
Since you want enter/↵ instead, you can set the options. Find out which key you want to use with the jQuery event.which demo.
JoelPurra.PlusAsTab.setOptions({
// Use enter instead of plus
// Number 13 found through demo at
// https://api.jquery.com/event.which/
key: 13
});
// Matches all inputs with name "a[]" (needs some character escaping)
$('input[name=a\\[\\]]').plusAsTab();
You can try it out yourself in the PlusAsTab enter as tab demo.
function return2tab (div)
{
document.addEventListener('keydown', function (ev) {
if (ev.key === "Enter" && ev.target.nodeName === 'INPUT') {
var focusableElementsString = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]';
let ol= div.querySelectorAll(focusableElementsString);
for (let i=0; i<ol.length; i++) {
if (ol[i] === ev.target) {
let o= i<ol.length-1? ol[i+1]: o[0];
o.focus(); break;
}
}
ev.preventDefault();
}
});
}
I have it working in only JavaScript. Firefox won't let you update the keyCode, so all you can do is trap keyCode 13 and force it to focus on the next element by tabIndex as if keyCode 9 was pressed. The tricky part is finding the next tabIndex. I have tested this only on IE8-IE10 and Firefox and it works:
function ModifyEnterKeyPressAsTab(event)
{
var caller;
var key;
if (window.event)
{
caller = window.event.srcElement; //Get the event caller in IE.
key = window.event.keyCode; //Get the keycode in IE.
}
else
{
caller = event.target; //Get the event caller in Firefox.
key = event.which; //Get the keycode in Firefox.
}
if (key == 13) //Enter key was pressed.
{
cTab = caller.tabIndex; //caller tabIndex.
maxTab = 0; //highest tabIndex (start at 0 to change)
minTab = cTab; //lowest tabIndex (this may change, but start at caller)
allById = document.getElementsByTagName("input"); //Get input elements.
allByIndex = []; //Storage for elements by index.
c = 0; //index of the caller in allByIndex (start at 0 to change)
i = 0; //generic indexer for allByIndex;
for (id in allById) //Loop through all the input elements by id.
{
allByIndex[i] = allById[id]; //Set allByIndex.
tab = allByIndex[i].tabIndex;
if (caller == allByIndex[i])
c = i; //Get the index of the caller.
if (tab > maxTab)
maxTab = tab; //Get the highest tabIndex on the page.
if (tab < minTab && tab >= 0)
minTab = tab; //Get the lowest positive tabIndex on the page.
i++;
}
//Loop through tab indexes from caller to highest.
for (tab = cTab; tab <= maxTab; tab++)
{
//Look for this tabIndex from the caller to the end of page.
for (i = c + 1; i < allByIndex.length; i++)
{
if (allByIndex[i].tabIndex == tab)
{
allByIndex[i].focus(); //Move to that element and stop.
return;
}
}
//Look for the next tabIndex from the start of page to the caller.
for (i = 0; i < c; i++)
{
if (allByIndex[i].tabIndex == tab + 1)
{
allByIndex[i].focus(); //Move to that element and stop.
return;
}
}
//Continue searching from the caller for the next tabIndex.
}
//The caller was the last element with the highest tabIndex,
//so find the first element with the lowest tabIndex.
for (i = 0; i < allByIndex.length; i++)
{
if (allByIndex[i].tabIndex == minTab)
{
allByIndex[i].focus(); //Move to that element and stop.
return;
}
}
}
}
To use this code, add it to your html input tag:
<input id="SomeID" onkeydown="ModifyEnterKeyPressAsTab(event);" ... >
Or add it to an element in javascript:
document.getElementById("SomeID").onKeyDown = ModifyEnterKeyPressAsTab;
A couple other notes:
I only needed it to work on my input elements, but you could extend it to other document elements if you need to. For this, getElementsByClassName is very helpful, but that is a whole other topic.
A limitation is that it only tabs between the elements that you have added to your allById array. It does not tab around to the other things that your browser might, like toolbars and menus outside your html document. Perhaps this is a feature instead of a limitation. If you like, trap keyCode 9 and this behavior will work with the tab key too.
You can use my code below, tested in Mozilla, IE, and Chrome
// Use to act like tab using enter key
$.fn.enterkeytab=function(){
$(this).on('keydown', 'input, select,', function(e) {
var self = $(this)
, form = self.parents('form:eq(0)')
, focusable
, next
;
if (e.keyCode == 13) {
focusable = form.find('input,a,select,button').filter(':visible');
next = focusable.eq(focusable.index(this)+1);
if (next.length) {
next.focus();
} else {
alert("wd");
//form.submit();
}
return false;
}
});
}
How to Use?
$("#form").enterkeytab(); // enter key tab
If you can I would reconsider doing this: the default action of pressing <Enter> while in a form submits the form and anything you do to change this default action / expected behaviour could cause some usability issues with the site.
Vanilla js with support for Shift + Enter and ability to choose which HTML tags are focusable. Should work IE9+.
onKeyUp(e) {
switch (e.keyCode) {
case 13: //Enter
var focusableElements = document.querySelectorAll('input, button')
var index = Array.prototype.indexOf.call(focusableElements, document.activeElement)
if(e.shiftKey)
focus(focusableElements, index - 1)
else
focus(focusableElements, index + 1)
e.preventDefault()
break;
}
function focus(elements, index) {
if(elements[index])
elements[index].focus()
}
}
Here's what I came up with.
form.addEventListener("submit", (e) => { //On Submit
let key = e.charCode || e.keyCode || 0 //get the key code
if (key = 13) { //If enter key
e.preventDefault()
const inputs = Array.from(document.querySelectorAll("form input")) //Get array of inputs
let nextInput = inputs[inputs.indexOf(document.activeElement) + 1] //get index of input after the current input
nextInput.focus() //focus new input
}
}
Many answers here uses e.keyCode and e.which that are deprecated.
Instead you should use e.key === 'Enter'.
Documentation: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
I'm sorry but I can't test these snippets just now. Will come back later after testing it.
With HTML:
<body onkeypress="if(event.key==='Enter' && event.target.form){focusNextElement(event); return false;}">
With jQuery:
$(window).on('keypress', function (ev)
{
if (ev.key === "Enter" && ev.currentTarget.form) focusNextElement(ev)
}
And with Vanilla JS:
document.addEventListener('keypress', function (ev) {
if (ev.key === "Enter" && ev.currentTarget.form) focusNextElement(ev);
});
You can take focusNextElement() function from here:
https://stackoverflow.com/a/35173443/3356679
Easiest way to solve this problem with the focus function of JavaScript as follows:
You can copy and try it # home!
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<input id="input1" type="text" onkeypress="pressEnter()" />
<input id="input2" type="text" onkeypress="pressEnter2()" />
<input id="input3" type="text"/>
<script type="text/javascript">
function pressEnter() {
// Key Code for ENTER = 13
if ((event.keyCode == 13)) {
document.getElementById("input2").focus({preventScroll:false});
}
}
function pressEnter2() {
if ((event.keyCode == 13)) {
document.getElementById("input3").focus({preventScroll:false});
}
}
</script>
</body>
</html>
I had a problem to use enter key instead of Tab in React js .The solution of anjana-silva is working fine and just some small issue for input date and autocomplete as I am using MUI . So I change it a bit and add arrow keys (left/right) as well .
install jquery using npm
npm install jquery --save
write the below in App.js If you want to have this behavior In the whole of your application
import $ from 'jquery';
useEffect(() => {
$('body').on('keydown', 'input, select,button', function (e) {
if (e.keyCode === 13 || e.keyCode === 39) {
var self = $(this), form = self.parents('form:eq(0)'), focusable, next;
focusable = form.find('input,a,select,button,textarea').filter(':visible:not([readonly]):enabled');
next = focusable.eq(focusable.index(this) + 1);
if (next.length) {
next.focus();
}
return false;
}
if (e.keyCode === 37) {
var self = $(this), form = self.parents('form:eq(0)'), focusable, prev;
focusable = form.find('input,a,select,button,textarea').filter(':visible:not([readonly]):enabled');
prev = focusable.eq(focusable.index(this) - 1);
if (prev.length) {
prev.focus();
}
return false;
}
});
}, []);
I had a simular need.
Here is what I did:
<script type="text/javascript" language="javascript">
function convertEnterToTab() {
if(event.keyCode==13) {
event.keyCode = 9;
}
}
document.onkeydown = convertEnterToTab;
</script>
In all that cases, only works in Chrome and IE, I added the following code to solve that:
var key = (window.event) ? e.keyCode : e.which;
and I tested the key value on if keycode equals 13
$('body').on('keydown', 'input, select, textarea', function (e) {
var self = $(this)
, form = self.parents('form:eq(0)')
, focusable
, next
;
var key = (window.event) ? e.keyCode : e.which;
if (key == 13) {
focusable = form.find('input,a,select,button,textarea').filter(':visible');
next = focusable.eq(focusable.index(this) + 1);
if (next.length) {
next.focus();
} else {
focusable.click();
}
return false;
}
});
$("#form input , select , textarea").keypress(function(e){
if(e.keyCode == 13){
var enter_position = $(this).index();
$("#form input , select , textarea").eq(enter_position+1).focus();
}
});
You could programatically iterate the form elements adding the onkeydown handler as you go. This way you can reuse the code.

Categories

Resources