I have an editable input component, which has an isEditable state.
By clicking outside the input field, I use #blur event.
By clicking on the enter key, I trigger another event.
Both methods use the same logic, and after the logic finishes, I set the isEditable to false. In this case, somehow the blur event is triggered. (I guess because the input field disappears (I guess because it uses v-if="isEditable").
Is there any way to prevent blur to be triggered by changing the state programatically?
If hiding the div activates the blur event, then you can just make the keypress Enter event hide the div, your logic will be executed only once in both cases.
Before :
#blur="myLogic"
#keyup.enter="myLogic"
After :
#blur="myLogic"
#keyup.enter="willActivateBlur"
// methods
willActivateBlur: function() {
this.isEditable = false
}
Edit : Wait, did you say "click on the enter key" ?... I got confused, are you clicking or pressing a key ?
If your problem is using #blur and #click at the same time, a lot of questions were asked about this already, such as this one.
Related
I'm making an Autocomplete component in React which shows a dropdown of suggested completions as you type into a text box. Clicking on a suggestion should fire a callback, and the dropdown should disappear when the text box loses focus. The problem is that the onBlur event for the text box fires before the onClick event for the the suggestion, so what happens is:
Click on item
Text box loses focus => this.setState(this.getInitialState())
Component rerenders, with no suggestions box because state has been cleared
The click event lands on the empty space where the suggestion item used to be
What's the best way to solve this without resorting to a hack like onBlur={() => setTimeout(() => this.setState(this.getInitialState()), 100)}?
Found a very simple solution: the mousedown event fires for the result item being clicked before blur fires for the text input. Furthermore if the mousedown callback calls event.preventDefault(), it prevents the blur event from firing for the input, but doesn't prevent the future click event from firing on the result item once mouseup occurs. So, long story short, simply adding this handler to the result item fixes everything: onMouseDown={event => event.preventDefault()}
Looks like there's an open source Autocomplete component and they had to tackle this exact problem.
I have added change event on the input field so that whenever user enters the text into it, so other task should happen, it works but when i click outside the input field.I don't know whether it is default behavior or i am doing some thing wrong. I tried using keyup and keydown events and it works as expect.
Please suggest.
Here is my code:
$("#mobile-number").on('change',function(){
// some other code
});
The change event fires when an elements value changes.
For select boxes, checkboxes, and radio buttons, the event is fired immediately when the user makes a selection with the mouse, but for the other element types the event is deferred until the element loses focus.
In other words, on an input, the change event fires when the element loses focus, not when you type, and that is the default behaviour.
That's why there are key events as well, and on modern browsers you can catch most changes to an input with the input event
$("#mobile-number").on('input',function(){ ...
Yes, it is the desired behavior.
Change Event
The change event is fired for , , and
elements when a change to the element's value is committed by the
user. Unlike the input event, the change event is not necessarily
fired for each change to an element's value.
Depending on the kind of form element being changed and the way the
user interacts with the element, the change event fires at a different
moment:
When the element is activated (by clicking or using the keyboard) for and ;
When the user commits the change explicitly (e.g. by selecting a value from a 's dropdown with a mouse click, by selecting a
date from a date picker for , by selecting a file
in the file picker for , etc.);
When the element loses focus after its value was changed, but not commited (e.g. after editing the value of or ).
Try using input event:
$(function() {
$("#mobile-number").on('input', function() {
$("#copy").val(this.value);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type='text' id='mobile-number' />
<input type='text' id='copy' readonly/>
Try this:( If i really understand your problem )
jQuery(document).on('change', '#mobile-number', function() {
// some other code
});
for type event:
jQuery(document).on('keyup', '#mobile-number', function() {
// some other code
});
You should provide your selector to the .on function:
$(document).on('change', '#mobile-number', function() {
// some other code
});
It appears that the Blur event stops the click event handler from working? I have a combo box where the options only appear when the text field has focus. Choosing an option link should cause an event to occur.
I have a fiddle example here: http://jsfiddle.net/uXq5p/6/
To reproduce:
Select the text box
Links appear
Click a link
The blur even occurs and the links disappear
Nothing else happens.
Expected behavior:
On step 5, after blur occurs, the click even should also then fire. How do I make that happen?
UPDATE:
After playing with this for a while, it seems that someone has gone to great lengths to prevent an already-occurred click event from being handled if a blur event makes the clicked element Un-clickable.
For example:
$('#ShippingGroupListWrapper').css('left','-20px');
works just fine, but
$('#ShippingGroupListWrapper').css('left','-2000px');
prevents the click event.
This appears to be a bug in Firefox, since making an element un-clickable should prevent future clicks, but not cancel ones that have already occurred when it could be clicked.
Other things that prevent the click event from processing:
$('#ShippingGroupListWrapper').css('z-index','-20');
$('#ShippingGroupListWrapper').css('display','none');
$('#ShippingGroupListWrapper').css('visibility','hidden');
$('#ShippingGroupListWrapper').css('opacity','.5');
I've found a few other questions on this site that are having similar problems. There seem to be two solutions floating around:
Use a delay. This is bad because it creates a race condition between the hiding and the click event handler. Its also sloppy.
Use the mousedown event. But this isn't a great solution either since click is the correct event for a link. The behavior of mousedown is counter-intuitive from a UX perspective, particularly since you can't cancel the click by moving the mouse off the element before releasing the button.
I can think of a few more.
3.Use mouseover and mouseout on the link to enable/disable the blur event for the field. This doesn't work with keyboard tabing since the mouse is not involved.
4.The best solution would be something like:
$('#ShippingGroup').blur(function()
{
if($(document.activeElement) == $('.ShippingGroupLinkList'))
return; // The element that now has focus is a link, do nothing
$('#ShippingGroupListWrapper').css('display','none'); // hide it.
}
Unfortunately, $(document.activeElement) seems to always return the body element, not the one that was clicked. But maybe if there was a reliable way to know either 1. which element now has focus or two, which element caused the blur (not which element is blurring) from within the blur handler. Also, is there any other event (besides mousedown) that fires before blur?
click event triggers after the blur so the link gets hidden. Instead of click use mousedown it will work.
$('.ShippingGroupLinkList').live("mousedown", function(e) {
alert('You wont see me if your cursor was in the text box');
});
Other alternative is to have some delay before you hide the links on blur event. Its upto you which approach to go for.
Demo
You could try the mousedown event instead of click.
$('.ShippingGroupLinkList').live("mousedown", function(e) {
alert('You wont see me if your cursor was in the text box');
});
This is clearly not the best solution as a mousedown event is not achieved the same way for the user than a click event. Unfortunately, the blur event will cancel out mouseup events as well.
Performing an action that should happen on a click on a mousedown is bad UX. Instead, what's a click effectively made up of? A mousedown and a mouseup.
Therefore, stop the propagation of the mousedown event in the mousedown handler, and perform the action in the mouseup handler.
An example in ReactJS:
<a onMouseDown={e => e.preventDefault()}
onMouseUp={() => alert("CLICK")}>
Click me!
</a>
4.The best solution would be something like:
$('#ShippingGroup').blur(function()
{
if($(document.activeElement) == $('.ShippingGroupLinkList'))
return; // The element that now has focus is a link, do nothing
$('#ShippingGroupListWrapper').css('display','none'); // hide it.
}
Unfortunately, $(document.activeElement) seems to always return the
body element, not the one that was clicked. But maybe if there was a
reliable way to know either 1. which element now has focus or two,
which element caused the blur (not which element is blurring) from
within the blur handler.
What you may be looking for is e.relatedTarget. So when clicking the link, e.relatedTarget should get populated with the link element, so in your blur handler, you can choose not to hide the container if the element clicked is within the container (or compare it directly with the link):
$('#ShippingGroup').blur(function(e)
{
if(!e.relatedTarget || !e.currentTarget.contains(e.relatedTarget)) {
// Alt: (!e.relatedTarget || $(e.relatedTarget) == $('.ShippingGroupLinkList'))
$('#ShippingGroupListWrapper').css('display','none'); // hide it.
}
}
(relatedTarget may not be supported in older browsers for blur events, but it appears to work in latest Chrome, Firefox, and Safari)
If this.menuTarget.classList.add("hidden") is the blur behavior that hides the clickable menu, then I succeeded by waiting 100ms before invoking it.
setTimeout(() => {
this.menuTarget.classList.add()
}, 100)
This allowed the click event to be processed upon the menuTarget DOM before it was hidden.
I know this is a later reply, but I had this same issue, and a lot of these solutions didn't really work in my scenario. mousedown is not functional with forms, it can cause the enter key functionality to change on the submit button. Instead, you can set a variable _mouseclick true in the mousedown, check it in the blur, and preventDefault() if it's true. Then, in the mouseup set the variable false. I did not see issues with this, unless someone can think of any.
I have faced a similar issue while using jQuery blur, click handlers where I had an input name field and a Save button. Used blur event to populate name into a title placeholder. But when we click save immediately after typing the name, only the blur event gets fired and the save btn click event is disregarded.
The hack I used was to tap into the event object we get from blur event and check for event.relatedTarget.
PFB the code that worked for me:
$("#inputName").blur(function (event) {
title = event.target.value;
//since blur stops an immediate click event from firing - Firing click event here
if (event.relatedTarget ? event.relatedTarget.id == "btnSave" : false) {
saveBtn();
}
});
$("#btnSave").click(SaveBtn)
As already discussed in this thread - this is due to blur event blocking click event when fired simultaneously. So I have a click event registered for Save Btn calling a function which is also called when blur event's related Target is the Save button to compensate for the click event not firing.
Note: Didnt notice this issue while using native onclick and onblur handlers - tested in html.
I have an input element on a form along with a submit button.
I want to run the change event on the input element all whenever a change occurs. The problem is if end user changes text and clicks submit button the code in the change event doesn't run.
Immediately after user clicks the submit button, the form submits (like the change is not getting time to run, the same occurs with blur or focus out).
My controls can be placed on any form, and I do not control the click event of the button.
Help please
If you're wanting to catch whenever input in a textbox is changed try this in the document.ready
$("input[type='text']").change( function() {
$("#SubmitButton").attr('disabled', 'disabled');
// check input ($(this).val()) for validity here
// after text is updated..etc, enable the button
$("#SubmitButton").removeAttr('disabled');
});
may be you want use event.preventDefault
Expanding on #Aleks G's comment, the best thing for you to do is trigger your change handling on more than just the change event. Beyond keyup, I've found you also need to be careful to handle pasting with the mouse (doesn't trigger the keyup or change event):
yourInput.bind('change keyup paste', function() {
// Your code
});
I have a textbox that is wired up using jQuery UI 1.8.4 autocomplete. I have the select event wired up so when the user chooses an item from the list it calls another JavaScript function that issues an ajax request to save the data and update an XML document.
On the same textbox there is an onBlur event so that if the user manually types the data in and tabs off the textbox without choosing an autocomplete item it also performs the update.
When the user selects an item from the autocomplete list it causes onBlur to fire which overrides the select event, thus the only data that gets updated is whatever is in the textbox that the user typed, and since the select event doesn't fire the contents of the textbox don't get updated.
I've tried using the change event with the same results.
Is there a way to ensure the select event gets fired and also implement some functionality that will emulate an onBlur in the case where a user types the value in rather than selecting it?
The problem is when the user interacts with the autocomplete menu, the textbox loses focus and the blur event fires. There is no way to really detect if the user is in the autocomplete control unless the component tells you that.
If the autocomplete control you are using does not have methods to tell you when it is closed, than you are probably stuck with using a setTimeout to wait a bit before you fire your code.
I think The onselect is always fired
"BUT" its fired only after onblur event of the textbox.
And this happens only when you use the mouse to select the autocomplete item and not through selecting the item by keyboard.
You may undo the update made on onblur with the select event depending on wether mouse click or keyboard select is made.
select: function (event, ui) {
if (event.originalEvent.originalEvent.type == 'click') {
//undo the onblur event happened by an ajax call here
//$("#txtbox").val() will still be available to do an undo
}
//do the actual onselect function here
}