Tab Keydown event for HTML5 Date inputs - javascript

I'm having a problem capturing Tab Keydown events on date inputs. Say I have a form with five inputs, the first and last of which are date inputs (the html here is for reference... I know it's missing ID, tabindex, etc.):
<form id="heyImAForm">
<input type="date" id="in1" />
<input type="text" id="notimportant2" />
<input type="text" id="notimportant3" />
<input type="text" id="notimportant4" />
<input type="date" id="in5" />
</div>
What I'd like to do is call a method when the user Shift-Tabs out of the first input, and when the user Tabs out of the last input.
The problem is, I'd like to preserve the native Tab key behavior for date inputs, which is to move between days/months/years. So, something like this:
$('#in1').keydown(function(e) {
if (e.which == 9 && e.shiftKey) {
doAThing();
}
});
$('#in5').keydown(function(e) {
if (e.which == 9) {
doADifferentThing();
}
});
.... "works", but effectively kills that native Tab key behavior. So, long story short, is there a way to only trigger the Tab key event if the focus shifts away from the date input, as opposed to moving between day/month/year?

After trying a few things I think the best solution would be what you see here but please read on to get a full understanding of what I am doing. We are setting the focusout when the user hits shift-tab on the first element or shift without tab on the second element. We must unbind this action if the user hit something else so we don't fire the action if they shift-tab but stay within the element then shift out of it. So try something like this:
$('#in1').keydown(function(e) {
if (e.which == 9 && e.shiftKey) {
$(document).mousedown(function(){
$('#in1').unbind('focusout');
$(document).unbind('mousedown');
});
$('#in1').focusout(function(){
doAThing();
});
} else {
$('#in1').unbind('focusout');
$(document).unbind('mousedown');
}
});
$('#in5').keydown(function(e) {
if (e.which == 9 && !e.shiftKey) {
$(document).mousedown(function(){
$('#in5').unbind('focusout');
$(document).unbind('mousedown');
});
$('#in5').focusout(function(){
doADifferentThing();
});
} else {
$('#in5').unbind('focusout');
$(document).unbind('mousedown');
}
});
You can see we are also setting mousedown of the entire document when the shift-tab(in1) or tab-without-shift(in5) is being hit. In the mousedown we are unbinding the focusout so if the focus leaves because of a mouse click we don't fire doAThing(). We also unbind mousedown on the document because you don't want it firing every time the user clicks after tabbing(in5) or shift-tabbing(in1) on those elements.
You may also be interested in seeing what I did on this fiddle. This isn't the best solution because the setTimeout's can cause some problems and undesired effect in many cases.
Also, in your provided code the closing tag should be </form> not </div>.

Related

Javascript - Using EventListener with Tab Key and Focus Function

I have been searching and have not found any particular thread that addresses my issue.
I am trying to either write an event listener or a conditional action with JavaScript that reacts when a user selects the TAB key and shifts focus to the appropriate element on screen.
Current DIV id has focus on screen => id="Slide14549accStr2"
When the user selects the TAB key, I want the user's focus to immediately shift to DIV id "Titleinformation_tb". I am unable to change the TabIndex in the HTML to do this the normal way, so I am left with using javascript in some form.
Here is what I have so far.
document.getElementById('Slide14549accStr2').addEventListener('keydown') {
if event.keyCode == 9) {
var elem =
document.getElementById('Titleinformation_tb');
$(elem).focus();
};
I would appreciate any help and feedback.
If you just fix all the syntax errors, it works just fine, but you should be preventing the default action as well, to make sure it doesn't tab to the next element
document.getElementById('Slide14549accStr2').addEventListener('keydown', function(event) {
if (event.keyCode == 9) {
event.preventDefault();
var elem = document.getElementById('Titleinformation_tb');
elem.focus();
}
});
<input id="Slide14549accStr2" placeholder="Focus this, and tab out">
<br><br><br>
<input><input><input>
<br><br><br>
<input id="Titleinformation_tb" placeholder="Should go here">
You were missing the function call.
document.getElementById('Slide14549accStr2')
.addEventListener('keydown',function(e){
if (event.keyCode == 9){
var elem = document.getElementById('Titleinformation_tb');
$(elem).focus();
}
});

jQuery keypress to work normally except hitting enter

I would like to trigger a click if enter is pressed inside an input tag, but would like to have the default event strategy in all other cases. I have tried it this way:
$("#keywords").keypress(function(e) {
if (e.charCode === 13) {
$("#campus-search").click();
} else {
$("#keywords").val($("#keywords").val() + String.fromCharCode(e.charCode));
}
});
It works, but I am still not satisfied, because when I click inside the input somewhere in the middle of text or press the left button, or home button and then try to type some text, it will show it at the end of the input, which is bad user-experience. Can I keep the input to work in the default way except the case when enter is pressed?
I think what you are looking for is this:
$(document).ready(function () {
$("#test").keyup(function (event) {
if (event.keyCode == 13) {
$("#campus-search").click();
}
});
$("#campus-search").click(function () {
console.log("BUTTON IS CLICKED");
});
});
The input will act completely normal and everything works on default, unless when you press the enter button (keyCode = 13), then the button .click() event will be triggered.
Working Fiddle: http://jsfiddle.net/Mz2g8/3/
————
# Update: Just one hint for the code in your question, do not use charCode, as it is deprecated.
This feature has been removed from the Web. Though some browsers may still support it, it is in the process of being dropped. Do not use it in old or new projects. Pages or Web apps using it may break at any time.
(E.g. charCode does not work with FF v29.0.1)
And something different but important to know:
charCode is never set in the keydown and keyup events. In these cases, keyCode is set instead.
Source: https://developer.mozilla.org/en-US/docs/Web/API/event.charCode
This should work
$("#keywords").keypress(function(e) {
if (e.charCode === 13) {
e.preventDefault(); // prevent default action of the event if the event is keypress of enter key
$("#campus-search").click();
} else {
$("#keywords").val($("#keywords").val() + String.fromCharCode(e.charCode));
}
});
I think you can eliminate the else clause entirely to get your desired result.
Look at this jsfiddle.
The keypress function does not capture non-printing keys, such as shift, esc, delete, and enter, so the best way to go about this would be have two event handlers: one for keypress, as you have defined above, and one for keydown that checks for the charCode 13 and then performs the click() event on $(#campus-search) if that keycode is passed (by an enter press).
Demo
This is what you are looking for:
HTML:
<input id="keywords" type="text" value="" />
<input id="campus-search" type="button" value="Campus Search" />
JavaScript / jQuery:
$("#keywords").keypress(function (e) {
if (e.charCode === 13) {
$("#campus-search").click();
} else {
$("#keywords").val($("#keywords").val() + String.fromCharCode(e.charCode));
}
});
$("#campus-search").on("click", function () {
alert("Searching..");
});
Live Demo

IE bug triggers click for 2 buttons?

I am trying to trigger the submit button when a user presses enter. Works great for all browsers except Internet Explorer 9. Strange thing is that IE insists on also triggering the click for another button I never told it to. Am I doing something wrong or how to fix this?
Below is my code. Pressing enter in IE triggers the submit click as expected, but for some reason also triggers the "some button" click (even without my keypress listener):
$('input[type=submit]').click(function () {
alert('Submit click');
});
//SIMULATE CLICK IF ENTER PRESSED IN SEARCH
$('input[type=text]').keypress(function (event) {
var keycode = event.keyCode || event.which;
if (keycode == 13) $('input[type=submit]').click();
});
//ROUTE CLEAR HANDLER
$('button').click(function () {
alert('Button click');
});
You can see the bug in action here: http://jsfiddle.net/h64xD/
Here are a couple of things to consider:
IE9 counts the <button/> element as type="submit" by default. So to make it non-submit, you have to be explicit:
<button type="button">Some button</button>
If you do that, you will notice that the emulated click event now doesn't trigger the <button/> but still fires 2 events. The reason is that, because you haven't explicitly defined a <form/> element, IE9 assumes the controls as being in a form, and thus pressing enter in the textbox triggers 2 events:
the one that you are emulating
the default form submit button behaviour
So again to get around this issue, you have to be explicit:
<button type="button">Some button</button>
<form><input type="text" /></form>
<input type="submit" value="Submit" />
Now, these are the reasons that you are seeing the behaviour in IE. #MrSlayer's answer caters to the second issue of stopping the keypress event after you have satisfactorily handled it, using preventDefault()
The Enter key has a default behavior to submit, so you need to prevent the default behavior from executing. Because the button tag is, by default, type="submit" it is executing that button when the Enter key is pressed.
//SIMULATE CLICK IF ENTER PRESSED IN SEARCH
$('input[type=text]').keypress(function (event) {
var keycode = event.keyCode || event.which;
if (keycode == 13)
{
event.preventDefault();
$('input[type=submit]').click();
}
});
How about triggering the form's submit instead of a button click?
$('input[type=text]').keypress(function(e) {
var keycode = event.keyCode || event.which,
frm = $(this).closest('form');
if (keycode == 13) {
e.stopPropagation();
frm.submit();
return false;
}
return true;
});
--EDIT--
Updated Slightly to stop the event propagation.
First off, you don't need to manually attach an event to submit a form when the user presses enter - the browser already handles that.
Oddly enough, this was to do with the order of the elements, implicit form-associations, as well as the fact that IE handles buttons as submit elements.
Try swapping the order of these buttons to see what I mean:
<input type="text" />
<input type="submit" value="Submit" />
<button>Some button</button>
Naturally, the browser is already instructed to listen to respond to the Enter on a text-input. This results in the browser clicking the associated submit button. Further, since you haven't explicitly provided a form, or associated elements with one another via their form attribute, the browser is attempting to make that relationship for you.
In your code, the <button> element was assumed to be the submit button of the text-input (because it was the first submit button in the implicit form). As such, anytime you press Enter on the text-input, the browser naturally raises the click event of the associated button.
If you re-order the elements, as I have above, we see the opposite take place. IE associates the other <input> element with the text-box. And pressing Enter on the text-box implicitly raises the click event on the submit input.
You can confirm this behavior by comparing the .form attributes of various elements. For instance, adding some id values will give us easier access to these:
<button id="fiz">Some Button</button>
<input id="foo" type="text" />
<input id="bar" type="submit" value="Submit" />
Then run some quick comparisons:
var button = document.getElementById("fiz");
var text = document.getElementById("foo");
var submit = document.getElementById("bar");
button.form === text.form; // true
submit.form === text.form; // true
button.form === submit.form; // true
So in the end, it's up to you to remove the ambiguity between the two buttons, by declaring the <button> element to be type='button', or by placing it after the intended submit button.

Javascript change event on input element fires on only losing focus

I have an input element and I want to keep checking the length of the contents and whenever the length becomes equal to a particular size, I want to enable the submit button, but I am facing a problem with the onchange event of Javascript as the event fires only when the input element goes out of scope and not when the contents change.
<input type="text" id="name" onchange="checkLength(this.value)" />
----onchange does not fire on changing contents of name, but only fires when name goes out of focus.
Is there something I can do to make this event work on content change? or some other event I can use for this?
I found a workaround by using the onkeyup function, but that does not fire when we select some content from the auto completer of the browser.
I want something which can work when the content of the field change whether by keyboard or by mouse... any ideas?
(function () {
var oldVal;
$('#name').on('change textInput input', function () {
var val = this.value;
if (val !== oldVal) {
oldVal = val;
checkLength(val);
}
});
}());
This will catch change, keystrokes, paste, textInput, input (when available). And not fire more than necessary.
http://jsfiddle.net/katspaugh/xqeDj/
References:
textInput — a W3C DOM Level 3 event type. http://www.w3.org/TR/DOM-Level-3-Events/#events-textevents
A user agent must dispatch this event when one or more characters have
been entered. These characters may originate from a variety of
sources, e.g., characters resulting from a key being pressed or
released on a keyboard device, from the processing of an input method
editor, or resulting from a voice command. Where a “paste” operation
generates a simple sequence of characters, i.e., a text passage
without any structure or style information, this event type should be
generated as well.
input — an HTML5 event type.
Fired at controls when the user changes the value
Firefox, Chrome, IE9 and other modern browsers support it.
This event occurs immediately after modification, unlike the onchange event, which occurs when the element loses focus.
It took me 30 minutes to find it, but this is working in June 2019.
<input type="text" id="myInput" oninput="myFunction()">
and if you want to add an event listener programmatically in js
inputElement.addEventListener("input", event => {})
As an extention to katspaugh's answer, here's a way to do it for multiple elements using a css class.
$('.myclass').each(function(){
$(this).attr('oldval',$(this).val());
});
$('.myclass').on('change keypress paste focus textInput input',function(){
var val = $(this).val();
if(val != $(this).attr('oldval') ){
$(this).attr('oldval',val);
checkLength($(this).val());
}
});
Do it the jQuery way:
<input type="text" id="name" name="name"/>
$('#name').keyup(function() {
alert('Content length has changed to: '+$(this).val().length);
});
You can use onkeyup
<input id="name" onkeyup="checkLength(this.value)" />
You would have to use a combination of onkeyup and onclick (or onmouseup) if you want to catch every possibility.
<input id="name" onkeyup="checkLength(this.value)" onmouseup="checkLength(this.value)" />
Here is another solution I develop for the same problem. However I use many input boxes so I keep old value as an user-defined attribute of the elements itself: "data-value". Using jQuery it is so easy to manage.
$(document).delegate('.filterBox', 'keyup', { self: this }, function (e) {
var self = e.data.self;
if (e.keyCode == 13) {
e.preventDefault();
$(this).attr('data-value', $(this).val());
self.filterBy(this, true)
}
else if (e.keyCode == 27) {
$(this).val('');
$(this).attr('data-value', '');
self.filterBy(this, true)
}
else {
if ($(this).attr('data-value') != $(this).val()) {
$(this).attr('data-value', $(this).val());
self.filterBy(this);
}
}
});
here is, I used 5-6 input boxes have class 'filterBox',
I make filterBy method run only if data-value is different than its own value.

Javascript Events: How to trigger event when ALT+NUM character is entered

I first used the onKeyUp event to detect input changes in a textbox. However, when the user enters in a French character using ALT+Num, the event doesn't detect the change until i enter the next character...
Which event should I be using to detect the special character changes. I've tried onChange but does not seem to be working.
I've tried using onkeypress event because I notice that it triggers it after i release the ALT key, however even though once the ALT is release, the onkeypress is triggered and you see the accented character, but when I use this.value for the inputbox, it only registers up to and before the new ALT+Num character is input.
for example: i entered vidé, but the search would not dynamically find vidé, but only vid because the é has not been saved in the - this.value yet, until another key event is triggered.
Hence I was wondering if there's way to simulate/send a key press to trigger it.
FINALLY FIGURED IT OUT!! :D
here's the code, however the String converting event.which code does not work on the jsFiddle though, nonetheless the code works :)
$('#i').keydown(function() {
document.getElementById('j').value = "down";
$('#k').val($('#i').val())
});
$('#i').keyup(function() {
document.getElementById('j').value = "up";
$('#k').val($('#i').val())
});
$('#i').keypress(function(event) {
$('#k').val(String.fromCharCode(event.keycode));
});
$('#i').change(function() {
document.getElementById('j').value = "change";
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="i" type="text" /><br />
<input id="j" type="text" />
<input id="k" type="text" />
View on JSFiddle
use keyup. The new character will not be added until the user releases the ALT key and at that point the keyup event will fire.
There's a reference at http://unixpapa.com/js/key.html which might be a good idea to have a look at, and according to section 2.1, ALT should generate a keydown and keyup in modern browsers..
I would suggest you use jQuery or a similar library to ease the issues you're facing cross-browser. Have a look at http://jsfiddle.net/qvDbu/1/ for a proof of concept which works fine.
Keypress is not triggered by only modifier-presses, so that's probably the way to go, it allows you to pick up the character entered as well, rather then which key is pressed. Edit: Seems to not be the case in Fx that keypress is triggered by modifiers, but I'm not able to reproduce actually loosing any characters.
The character entered with the ALT+NUM combination will only be added to the input element's value after the keyup event triggers, so you won't be able to read it in that event handler.
In order to solve this problem you could set a timeout on the ALT keyup event before reading the input element's value:
$('input').on('keyup', function (e) {
var _this = this;
var ALT_KEY_CODE = 18;
if (e.which == ALT_KEY_CODE) {
setTimeout(function () {
handleKeyup.call(_this , e);
}, 1);
} else {
handleKeyup.call(_this , e);
}
});
function handleKeyup (e) {
// $(this).val() now holds the ALT+NUM char
}
You need to bind onkeypress, which won't fire until you finish entering the alt code.
document.getElementById('input').onkeypress = function() {
alert('fired');
}
<input id='input' type='text' />
View on JSFiddle

Categories

Resources