I am trying to blur all the inputs on the page, to show error styling.
I am trying to follow this blur documentation.
My attempt is to grab all the inputs and then apply blur...
document.querySelectorAll('input').blur();
But I simply get the error, blur is not a function.
What is the correct approach?
First, there is no point un bluring more than one input element : only one can have focus at a time, so only one can "blur" at a time.
But for the sake of the example, here is how it could be achieved:
document.querySelectorAll('input') returns an array-like object, so:
Array.from(document.querySelectorAll('input')).forEach(el => el.blur())
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 got a form where I'm trying to do the sort of thing you often see with tags: there's a textfield for the first tag, and, if you put something into it, a new and similar textfield appears to receive another tag. And so on. I've gotten the basics of this working by setting up a jQuery .blur() handler for the textfield: after the value is entered and the user leaves the field, the handler runs and inserts the new field into the form. The handler is pretty vanilla, something like:
$('input.the_field_class').blur(function () { ... });
where .the_field_class identifies the input field(s) that collect the values.
My problem is that, while the new textfield is happily added to the form after the user enters the first value, the blur handler doesn't fire when the user enters something into the newly-added field and then leaves it. The first field continues to work properly, but the second one never works. FWIW, I've watched for and avoided any id and name clashes between the initial and added fields. I had thought that jQuery would pick up the added textfield, which has the same class markings as the first one, and handle it like the original one, but maybe I'm wrong -- do I need to poke the page or some part of it with some sort of jQuery initialization thing? Thanks!
Without seeing your code in more of its context, it's hard to know for sure, but my best guess is that you're attaching a handler to the first field, but there is no code that gets called to attach it to the new field. If that's the case, you have a few options, two of which are:
1) In your blur() handler, include code to attach the blur handler to the newly created field.
2) Use jQuery's event delegation to attach a handler to the field container, and listen for blur events on any field in the container:
<div class="tag-container">
<input class="the_field_class" /> <!-- initial tag field -->
</div>
<script>
var $tagContainer = $('.tag-container');
var createNewField = function() {
$tagContainer.append($('<input class="the_field_class" />');
};
$tagContainer.on('blur', 'input.the_field_class', createNewField());
</script>
Which is better will depend on your use case, but I'd guess that the 2nd option will be better for you, since you're unlikely to be dealing with tons of blur events coming from the container.
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 two inputs that together form a single semantic unit (think an hours and minutes input together forming a time input). If both inputs lose focus I want to call some Javascript function, but if the user merely jumps between those two, I don't want to trigger anything.
I've tried wrapping these two inputs in a div and adding an onBlur to the div, but it never triggers.
Next I tried adding onBlurs to both inputs and having them check the other's :focus attribute through jQuery, but it seems that when the onBlur triggers the next element hasn't received focus yet.
Any suggestions on how to achieve this?
EDIT: Someone questioned the purpose of this. I'd like to update a few other fields based on the values contained by both these inputs, but ideally I don't want to update the other fields if the user is still in the process of updating the second input (for instance if the user tabs from first to second input).
I made a working example here:
https://jsfiddle.net/bs38V/5/
It uses this:
$('#t1, #t2').blur(function(){
setTimeout(function(){
if(!$('#t1, #t2').is(':focus')){
alert('all good');
}
},10);
});
var focus = 0;
$(inputs).focus(function() { focus++ });
$(inputs).blur(function() {
focus--;
setTimeout(function() {
if (!focus) {
// both lost focus
}
}, 50);
});
An alternative approach is to check the relatedTarget of the blur event. As stated in the MDN documentation this will be the element which is receiving the focus (if there is one). You can handle the blur event and check if the focus has now been put in your other input. I used a data- attribute to identify them, but you could equally well use the id or some other information if it fits your situation better.
My code is from an angular project I've worked on, but the principle should translate to vanilla JS/other frameworks.
<input id="t1" data-customProperty="true" (blur)="onBlur($event)">
<input id="t2" data-customProperty="true" (blur)="onBlur($event)">
onBlur(e: FocusEvent){
const semanticUnitStillHasFocus = (val.relatedTarget as any)?.dataset?.customProperty === "true";
// Do whatever you like with this knowledge
}
What is the purpose of this behavior ?
The blur event triggers when a field looses focus, and only one field can gain focus at a time.
What you could do, in case of validation for instance, is to apply the same function on blur for both the fields and check the values of the fields altogether.
Without a context, it is difficult to help you more.
d.
So I've been working on this all day and I can't figure out how to get it to work. I have a table with TD's filled with content which is drawn from a database using a JQuery "getJSON" command. I have an event handler set-up so that when you double click a TD element, its contents become a INPUT element with the default value of the enclosing TD's previous contents.
The INPUT element is created inside a Javascript object named "Input" like so:
var Input = function() {
var obj = this;
obj.docElement = $('<input/>').attr('type', 'text').val(obj.defaultValue);
}
All of this is working so far. My problem is, I want the user to be able to hit the RETURN key while the INPUT is selected to signify they've finished editing that field. I've tried something like the following:
$(obj.docElement).bind('keydown', function(e) {
if(e.which == 13) {
// do something
}
}
This works fine for the first time you edit a field; however, if you edit a field multiple times it stops working. Also if you randomly double click TD's eventually it breaks. I tested it and determined that the INPUT element stops registering any type event, as if the "bind" no longer existed on it.
I've done lots of googling and determined that the regular JQuery "bind" handler placed on an INPUT element is unreliable. Therefore I decided to attach the event handler to the document object instead using the following:
$(document).bind('keydown', function(e) {
// do something
}
I know I can use "e.target" to get the target element that the action is executed on (and this works for me, e.target correctly refers to the INPUT element).
My question is, how do I get the object that created the INPUT element in the first place? I need to be able to execute functions contained within the corresponding "Input"
class that was used to create the INPUT element. I need to call these functions from within the "$(document).bind" function. So basically I need to be able to get an INPUT element's parent/creator Input object.
If I haven't explained anything clearly enough, just let me know. Any help in this matter would be greatly appreciated! I'm also open to suggestions for alternative methods (other than using "$(document).bind").
Thanks!
I think I understand the problem ...
You can traverse the DOM to find the parent document element, but that's not what you mean, right? You want the parent script element that has a bunch of logic that operates on the element.
I suspect that it is probably easiest to provide some sort of reference to the parent when the input element is created ... pass this to the event handler, or set it in a globally accessible location (like a current_element_parent var).
I agree with tobyhede. You can either add a custom attribute to the INPUT element that refers back to the parent, or keep a map in memory that maps the dynamically created INPUT element to the parent that created it. When you trap the Return key, simply remove the relationship from the map so it can be added again if the user clicks it again.