I'm trying to set the cursor into the input field. I'm using the functions focus() and select() but I don't know why it isn't working.
Any ideas?
<input type="text" id="test">
<p onmousedown="press()">Test</p>
<script>
function press() {
let input = document.getElementById('test');
input.focus();
input.select();
}
</script>
This was an interesting question that had me investigating a fair bit about the default behaviour of the mousedown event and the differences between that and click. Thanks!
The answer can actually be explicitly found in the Notes section of the MDN documentation for mousedown:
If you call HTMLElement.focus() from a mousedown event handler, you must call event.preventDefault() to keep the focus from leaving the HTMLElement
So to fix, do exactly that. Note that I've slightly rewritten your code in order to do that, using addEventListener to bind a JS function to the event, which then takes the event object as a parameter. (You could I think have done it your way using the global event object - but it's a bad idea to use that. Using addEventListener rather than inline JS that evaluates a string attribute and executes it as JS is also a much better, more modern approach.)
<input type="text" id="test">
<p id="button">Test</p>
<script>
button.addEventListener("mousedown", press);
function press(event) {
event.preventDefault();
let input = document.getElementById('test');
input.focus();
input.select();
}
</script>
The reason I believe this is necessary is that the mousedown event must have a default handler that causes the focus to go on that particular element - and this overrides your attempt to programatically place the focus elsewhere. I'm not 100% sure on that, but it's the most likely explanation that I can come up with.
Note that your original code works completely fine if you'd used the click event rather than mousedown - and this is more usual. The difference is that click only fires when the user releases the mouse button after the initial press, whereas mousedown fires instantly when the press happens. I can't see why this distinction would ever be important, and unless for some reason it's vital to you, I would recommend using click instead, rather than the fix above.
Related
I am experiencing the following issue: After a particular jQuery library loads, if you click on a number input arrow, the input value keeps increasing (or decreasing) until the focus is shifted outside the input element.
Binding an input event to the element showed it keeps triggering, which led me to believe some piece of code kept setting element.value in a loop. But that did not happen.
I've tracked the issue down to calling event.preventDefault() on a mouseup event.
See:
document.body.addEventListener('mouseup', (e) => {
e.preventDefault();
});
<input type="number">
Why does this happen?
I had trouble finding information by searching what causes these infinitely increasing inputs.
Only after finding the cause myself, I've found out about a similar bug that happened with preventing the default of mousemove (https://stackoverflow.com/a/37521764/6849064). Although, this one does not seem to happen anymore.
Looks like this is a Chrome (and Edge) bug. But as https://stackoverflow.com/a/65253876/6849064 said, it is actually default behavior which makes sense in the way he said it. I myself failed to find this standard behavior documented anywhere. One way to fix the problem is to stop bubbling of the event up to the document,
document.querySelector('input').addEventListener('mouseup', (e) => {
e.stopPropagation();
});
And the other is, well, not preventing default behavior.
The following issue has nothing to do with jQuery. The issue is the code is doing exactly what you wanted it to do.
In the code <input type="number" /> has got 2 events. One is 'mousedown' and second is 'mouseup'.
Consider following example: https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_event_preventdefault2
The same is represented in the example above.
What you are doing is cancelling the 2nd part, ie mouseup so if you do mousedown and cancel mouseup, then the number will:
Go on increasing if you push uparrow
Go on decreaseing if you push downarrow
The only, surprise is this would have perfect sense if you would have written the code adding event to input rather than body, but anyways seems browser by default is increasing or decreasing number -- based on event-bubbling to body.
Note: The issue is replicated below, while no jQuery has been added!
document.body.addEventListener('mouseup', (e) => {
e.preventDefault();
});
<input type="number">
I have installed two separate userscripts, each requiring to invoke some code with document.body.onkeydown. However, I've noticed that with both userscripts enabled, only the latter event handler gets called.
Apparently, both userscripts are sharing the same DOM. This is contrary to my experience with Chrome extensions, where each Chrome extension has its own sandbox.
Either way, now how do I to fix this problem? I want both handlers to fire, and remain separate from each other.
I am executing my userscripts inside an IIFE with use strict mode enabled.
Using document.body.keydown will set the callback to the keydown event. Setting it again will replace the old one. Hence the latter script's event callback gets fired.
Instead use, document.body.addEventListener(<callback>) in both so, both the events will present.
In the below example, first keydown will get overridden by the second one. The addEventListener will append an listener to the keydown event. So on pressing a only 3rd event fired. On pressing b, both 2nd and 3rd are fired.
This is because the events added via the older method is added as like attribute values. Like,
<button id="show" onclick="show()">Click</button>
Hence, it got replaced.
The addEventListener adds the listener to the list of EventListners of the DOM Object.
In the example I replaced the onclick attribute with the function hide via the older method, hence it calls only the hide method.
For more info, please refer MDN Docs
document.body.onkeydown = function(event){if(event.key=="a")console.log("keydown")};
document.body.onkeydown = function(event){if(event.key=="b")console.log("b keydown")};
document.body.addEventListener("keydown",function(){console.log("addEventListener")})
function show(){console.log("show")}
function hide(){console.log("hide")}
var element = document.getElementById("show");
element.onclick=hide;
<button id="show" onclick="show()">Click</button>
You can change them to use
document.body.addEventListener("keydown", function(){ ... })
If they use the 'this' set in the onkeydown approach, you may need to make sure that is set correctly
document.body.addEventListener("keydown", (function(){ ... }).bind(document.body))
http://jsfiddle.net/NsRyr/1/
I am totally stumped on this. Here's what I'm trying to do : I have a div element (call it #keys) that I'm using to handle keypress events.
HTML:
<div id="#keys" tabindex="1">Focus</div>
JS:
$('#keys').keydown(function () {
$('#log').append('*'); // just note that an event happened
});
This works as expected -- as long as #keys is focused, I can receive keypress events and respond to them. In addition, I can set focus to other div elements and the keypress events will no longer be handled by #keys. I can then re-focus the div (e.g., by clicking on it directly, or by responding to a click event on another DOM element) and keypress events are handled as I expect.
So far, so good. The problem that I've come across is that if I focus an input element and then try to re-focus #keys by setting a blur handler that's activated after tabbing away from the input, the #keys div does not receive focus ! It works fine if I blur away from the input by clicking, but not if I use the keyboard.
$('#input').blur(function () {
$('#log').append('blur'); // note that a blur happened
$('#keys').focus();
});
I think the essence of this question is, why doesn't my blur handler on #input seem to work properly when tabbing away from the input (but it does work properly when clicking away) ? Is this just a browser quirk ? (I am using Chrome 30.0.1599.101 on Mac OS.)
This is my first SO question regarding JS, so please let me know what additional detail I can provide to describe the situation.
(Edit : Interestingly, it seems to work fine if I shift-tab away from #input. Still confused what's happening here ; appears to be some sort of tabindex-related issue ?)
I don't have commenting privileges yet, so I'll have to answer, but please mods should change this, because it's basically a duplicate.
Here's the fix to your fiddle:
http://jsfiddle.net/NsRyr/3/
The issue (as described in this answer) is that the blur event fires before the change is done, so the focus needs to be sent down the stack to happen after. Adding a timer deals with the issue.
The line I changed was:
setTimeout($('#keys').focus.bind($('#keys')), 0);
That makes it so it'll wait until the new focus event is completed before firing off the handler.
I have an <input type=text> with focusout event handler
I have a <button> with click event handler
Focusout checks whether format in input box is correct. It does so by testing input value against a regular expression. If it fails it displays a message (a div fades-in and -out after some time) and refocuses my input by calling
window.setTimout(function() { $(this).focus(); }, 10);
since I can't refocus in focusout event handler. focusout event can't be cancelled either. Just FYI.
Click collects data from input elements and sends it using Ajax.
The problem
When user TABs their way through the form everything is fine. When a certain input box failes formatting check it gets refocused immediately after user presses TAB.
But when user doesn't use TAB but instead clicks on each individual input field everything works fine until they click the button. focusout fires and sets time-out for refocusing. Since time-out is so short focusing happens afterwards and then click event fires and issues an Ajax request.
Question
I have implemented my formatting check as an independent jQuery plugin that I want to keep that way. It uses .live() to attach focusout on all input fields with a particular attribute where format regular expression is defined.
Data submission is also generic and I don't want to make it dependant on formatting plugin. They should both stay independent.
How can I prevent click event from executing without making these two plugins dependant?
Example code I'm fiddling with
After some searching I've seen that all major browser support document.activeElement but I can't make it work in Chrome. FF and IE both report this being the active element, but Chrome always says it's BODY that is active even though click fired on the button element.
Check this code http://jsfiddle.net/Anp4b/1/ and click on the button. Test with Chrome and some other browser and see the difference.
You could use a flag...
Live demo: http://jsfiddle.net/Anp4b/4/
So your question is:
How can I prevent click event from executing without making these two plugins dependent?
Well, you obviously cannot prevent the click event. If the user wants to click the button, he will, and the click event will trigger. There's nothing you can do about that.
So the answer to the above question is: You cannot.
Based on the current conditions, you have to - inside the click handler - retrieve the validation result, and based on that result, decide if form submission should or should not occur.
JS Code:
$("#Name").focusout(function(){
var that = this;
valid = this.value.length ? true : false;
!valid && window.setTimeout(function() {
$(that).focus();
}, 0);
});
$("#Confirm").click(function(e) {
if ( !valid ) { return false; }
e.preventDefault();
alert('AJAX-TIME :)');
});
HTML Code:
<input type="text" id="Name">
<button id="Confirm">OK</button>
Is there are reason you use .focusout instead of .blur?
Using a flag is a good idea, but I would rather use a class on the element. By using classes to determine the state you can also style it accordingly. Here's my example based on your fiddle.
Another solution that hopefully gives the result you are looking for.
1) Create a named click handler:
var clickHandler = function(e){ /** submit form or whatever you want to do**/ };
$("button").click(clickHandler);
2) Add the following to the focusout event when it's failing validation:
$("button").unbind("click", clickHandler).one("click", function(){ button.click(clickHandler); return false;});
You can find an example of this here.
I met one troublesome web page whose structure is complicated. If one DIV is clicked by mouse, everything is OK. However, if it is focus-ed by javascript(i.e. divElement.focus). The layout turns to messy. This only happens in IE7/8.
So, is there any difference between click-to-focus and focus-by-javascript in IE?
Firing a Javascript focus event does not fire a click event. Without seeing the relevant code, I'm led to guess that some click handler is in place that is not being called in the case where you fire a focus event.
You might try, instead, firing a click:
var clickEvent;
if(document.createEvent) {
clickEvent = document.createEvent('click');
clickEvent.initMouseEvent('click');
divElement.dispatchEvent(clickEvent);
} else {
// Semi-pseudocode for IE, not tested, consult documentation if it fails
clickEvent = document.createEventObject();
divElement.fireEvent('onclick');
}
Or if you're into the jQuery thing:
$(divElement).click();
There's similar solutions for Prototype as well (search for Event.simulate).
The definition of the Focus action is to bring the input (keyboard or mouse) to a certain element, usually an input field. When an element gains focus, an OnFocus event is fired. When it loses focus, an OnBlur event is fired.
What you usually get by clicking is the OnClick event, which is not necessarily related to the above two.
This only happens in IE7/8.
Hmm, then I'm sure it's an IE related bug. Not surprising. If there is legitimate Javascript events involved, then they should fire uniformly across all browsers.