I have a <form> containing two text <input>s side-by-side. When both of these inputs lose focus, I want to do some stuff (send an Ajax request to server and replace them with something else in the DOM). However if I click or tab from one of the inputs to the other, I don't want to do those things.
Setting an onBlur event handler on the <form> element works fine using my setup, but there doesn't seem to be any way to determine if the other form input is my next target. If I examine document.activeElement in my handler, it points to the <body> element (in Chrome) at that point. Only afterwards does it change to the other input.
Is there any way to reliably do what I'm asking? Solutions involving jQuery or other libraries are fine.
So it turns out that event.relatedTarget was what I was looking for - this will return the DOM node receiving focus on a blur event, so it's just a matter of setting a conditional to see if it matches the other field.
However, while this works great in Chrome, relatedTarget currently isn't implemented properly in other browsers. Apparently there's a couple of workarounds:
In IE11, document.activeElement does actually get set to the receiving element at the time the event fires, so you can use that.
In Firefox, apparently event.explicitOriginalTarget can be used instead.
Try ..
Set a global variable that stores what you last blurred from. Call it x.
Set a blur event on all elements, and set x to the last element you blurred from.
Set a focus event on all elements, and if x is not one of your two elements, then run your script.
Give to them both ids, like this:
<input id="id1" />
<input id="id2" />
Then, with jQuery, you can call blur() nested with the two ids.
$('#id1').blur(function(){
$('#id2').blur(function(){
//do your thing
});
});
Related
In my focus manager I need to store some info on the last focus and blur. I need to delegate this hook to body, but if I use * as a filter I will receive the focus event for every parent item of the actual thing getting focus.
Realistically, I could make a filter to accept something like a, input, button ... etc, but also I need to refine it to a:not([tabindex]=-1), *[tabindex!=-1] etc.
But this gets complicated when one considers disabled controls. Is there a jQuery selector for :focusable, or how do I work around this? I could debounce my function, but even that is iffy.
EDIT:
Alright, my bad, I think what I am looking for here is :tabbable.
you can check focus by using: $("yourselector").is( ":focus" )
If you want to stop bubbling up to the dom just return false in your function after doing your stuff.enter code here
I've encountered a weird issue - accessing any DOM element's outerHeight, or simply logging that element to browser's console in a blur event seems to cancel the click event that caused the blur - when some special criteria is met.
Here's what I'm trying to do:
There are 2 inputs, first is initially visible, the other hidden
When the first input receives focus, the 2nd input will be shown
When the 2nd input receives focus, it remains shown
When both inputs lose focus, and none of them are focused, the 2nd input will be hidden
However, it seems that when I simply try to do something like $('body')[0].outerHeight in my blur event handler, the second input never receives the click or focus. Since it's too much to simply write down, here's a link to JSFiddle that demonstrates the issue: http://jsfiddle.net/7K2Ha/3/
Note - it happens the same with plain JS
Can anybody explain why this happens and are there ways around this?
Firstly, you bind focus/blur events to all .jq inputs. And then you add next event handlers (which means, that all of them will be executed - including the first one, which removes the has-focus class).
Check this fiddle, line 20: fiddle here.
$('#input3').unbind('blur').on('blur', //...
The problem is not specific to offsetHeight, and I believe if you comment out that line you don't get the effect simply because the browser will not call an empty function block for performance/optimizer reasons.
It seems to come down to the execution order of the events (especially problematic when more than one jquery event of the same type is wired up).
Check out what happens when you wire up the blur/mouseover/etc. events that all $('input.jq') elements have in common at the very end: http://jsfiddle.net/7K2Ha/6/
All I did was move the topmost javascript block to the bottom, and suddenly it works. In that case, the focus event seems to occur before the blur event. Notice how before the focus would never be called.
As a more robust solution, I'd only work with one event that covers both:
$('input.jq')
.on('focus', function() {
// get focus'ed elements parent
var thisParent = $(this).parent('div')
thisParent.addClass('has-focus');
// get all other parents
var otherParents = $('input.jq').parent('div').not(thisParent);
otherParents.removeClass('has-focus');
})
See updated JSfiddle.
I have a large form that contains several text input fields. Essentially, I need to handle the onchange event for all fields and the onblur events for some fields. When a change is made to a field and the field loses focus, both events fire (which is the correct behavior). The only issue is that I would like to handle the onblur
event before I handle the onchange event.
After some testing in ie and Firefox, it seems that the default behavior is to fire the onchange event before onblur. I have been using the following code as a test...
<html>
<body >
<input type="text" value="here is a text field" onchange="console.log('Change Event!')" onblur="console.log('Blur Event!')" >
</body>
</html>
Which brings me to my questions:
It seems that this behavior is consistent across browsers. Why does onchange fire first?
Since I cannot handle the onblur event for every input element, is there a way I can get onblur to fire before handling the onchange event?
The reason onchange fires first is that once the element loses focus (i.e. 'blurs') the change is usually complete (I say usually because a script can still change the element without user interaction).
For those elements that need onblur handled first, you can disable the onchange handler and fire the onchange (or even a custom event) from the onblur handler. This will ensure the correct order even though it is more work. To detect change, you can use a state variable for that field.
As a general remark though, the need for such synchronicity is a sign that the approach you are using to solve whatever problem you are solving might need more work even though sometimes it cannot be avoided. If you are sure this is the only way, try one of these methods!
EDIT: Just to elaborate on the last point, you would have to follow some assumptions about your event model. Are you assuming that each change event is followed by a blur and goes unprocessed otherwise, or would you like to process each change but those that are followed by a blurget further processing after whatever onblur does with them? In any case if you want to enforce the order the handlers would need access to a common resource (global variable, property, etc.). Are there other event types you might want to use? (input?). Finally, this link has some details for the change event for Mozilla browsers:
https://developer.mozilla.org/en-US/docs/Web/Reference/Events/change.
The third 'bullet' addresses the issue of event order.
This is a bit of hack, but it seems to do the trick on most browsers:
<input type="text" value="Text Input" onchange="setTimeout(function(){console.log('Change Event!')}, 0);" onblur="console.log('Blur Event!');" />
You can see a fiddle of it in action here: http://jsfiddle.net/XpPhE/
Here is a little background information on the setTimeout(function, 0) trick: http://javascript.info/tutorial/events-and-timing-depth
Hope that helps :)
I've been endlessly looking for a working way to automate a mouse click on a specific element using javascript (I'm making a user-script). The structure is like the below:
<div id="elementContainer">
<div class="item1" style="width: 50px; height: 50px;">AutoClick Here!</div>
</div>
item1 is the thing I want to automate a click on. I've tried lots of approaches, e.g. getting the element and creating/initialising/dispatching a 'click' event on it, calling .click() on it etc, but to be honest I'm new to javascript and don't hugely know what I'm doing!
I can happily get the element and make changes to it (like changing the innerHTML), but want to be able to simulate/automate a click on it too. I would be very grateful for any advice on how to proceed.
Many thanks in advance!
Calling .click() on the element should work just fine.
var container = document.getElementById('elementContainer'),
innerDiv = container.getElementsByClassName('item1');
innerDiv.click();
That said:
The click method is intended to be used with INPUT elements of type button, checkbox, radio, reset or submit. Gecko does not implement the click method on other elements that might be expected to respond to mouse–clicks such as links (A elements), nor will it necessarily fire the click event of other elements.
Non–Gecko DOMs may behave differently.
When a click is used with elements that support it (e.g. one of the INPUT types listed above), it also fires the element's click event which will bubble up to elements higher up the document tree (or event chain) and fire their click events too. However, bubbling of a click event will not cause an A element to initiate navigation as if a real mouse-click had been received.
Have you bound any click event handlers to that <div>?
Read this: http://www.howtocreate.co.uk/tutorials/javascript/domevents
My site has an input box, which has a onkeydown event that merely alerts the value of the input box.
Unfortunately the value of the input does not include the changes due to the key being pressed.
For example for this input box:
<input onkeydown="alert(this.value)" type="text" value="cow" />
The default value is "cow". When you press the key s in the input, you get an alert("cow") instead of an alert("cows"). How can I make it alert("cows") without using onkeyup? I don't want to use onkeyup because it feels less responsive.
One partial solution is to detect the key pressed and then append it to the input's value, but this doesn't work in all cases such as if you have the text in the input highlighted and then you press a key.
Anyone have a complete solution to this problem?
NOTE: It's over a decade (!!) since I wrote this answer. The input event has become ubiquitous, and should be used instead of this hack.
What does keydown/keyup even mean for tablet and voice input devices?
The event handler only sees the content before the change is applied, because the mousedown and input events give you a chance to block the event before it gets to the field.
You can work around this limitation by giving the browser a chance to update the field's contents before grabbing its value - the simplest way is to use a small timeout before checking the value.
A minimal example is:
<input id="e"
onkeydown="window.setTimeout( function(){ alert(e.value) }, 1)"
type="text" value="cow" />
This sets a 1ms timeout that should happen after the keypress and keydown handlers have let the control change its value. If your monitor is refreshing at 60fps then you've got 16ms of wiggle room before it lags 2 frames.
A more complete example (which doesn't rely on named access on the Window object would look like:
var e = document.getElementById('e');
var out = document.getElementById('out');
e.addEventListener('input', function(event) {
window.setTimeout(function() {
out.value = event.target.value;
}, 1);
});
<input type="text" id="e" value="cow">
<input type="text" id="out" readonly>
When you run the above snippet, try some of the following:
Put the cursor at the start and type
Paste some content in the middle of the text box
Select a bunch of text and type to replace it
Please, try to use oninput event.
Unlike onkeydown, onkeypress events this event updates control's value property.
<input id="txt1" value="cow" oninput="alert(this.value);" />
Note that in newer browsers you'll be able to use the new HTML5 "input" event (https://developer.mozilla.org/en-US/docs/DOM/window.oninput) for this. Most non-IE browsers have supported this event for a long time (see compatibility table in the link); for IE it's version >/9 only unfortunately.
keyup/down events are handled differently in different browsers. The simple solution is to use a library like mootools, which will make them behave the same, deal with propagation and bubbling, and give you a standard "this" in the callback.
To my knowledge you can't do that with a standard input control unless you roll your own.
Jquery is the optimal way of doing this. Please reference the following below:
let fieldText = $('#id');
let fieldVal = fieldText.val();
fieldText.on('keydown', function() {
fieldVal.val();
});