I want to call a function when I have a textfield focused and then unfocus it (whether I press TAB or click elsewhere with the mouse) and I used this code:
$("#settings_view #my_profile_div input").focus(function() {
$(this).blur(function() {
change_my_profile();
});
});
When I first run it (have a field focused then unfocus it) it runs one time as expected. However, the second time it calls the function change_my_profile twice. The third time it ran 3 times and so on.
What is the problem here and how do I solve it? (I tried with 'throw' after change_my_profile and then it only ran one time, but I want to locate the problem anyway).
it is binding a blur event every time a focus event is initiated, that's why you are getting multiple executions
try
$(this).bind("blur",function(){
change_my_profile(this);
})
and then in your change_my_profile function do the following
function change_my_profile(el){
$(el).unbind("blur");
//rest of the change_my_profile code goes here
}
The .focus() and .blur() functions assign handlers to the 'focus' and 'blur' events repsectively. So every time the user focuses the textbox, your code is adding a new event handler to the 'blur' event. What you want is:
$("#settings_view #my_profile_div input").blur(change_my_profile);
You need to remove the event handler after successful execution. Otherwise, you are stacking handler upon handler and they all get triggered. I think in JQuery that is done using unbind()
Your code is asking jQuery to add (append) an onBlur event handler to an input field every time the user enters the field. So, your same event handler function gets appended over and over again. Are you simply trying to trigger a function to run when the user moves out of a field? If that is the case, you can simply use .blur to attach the onBlur handler once.
Related
This is my startQuiz() function which is bounded to the start button.
I click the start button to set the display of my quiz to flex. The issue here is with the submit button.
When I click the submit button and run submit(), everything works out and 1 is logged into the console.
The issue arises when I run closeQuiz() which simply changes the quiz display back to none. After running startQuiz() to reset the display to flex, running the submit() causes the console to log twice.
This pattern continues in where each time I run closeQuiz() and reopen the quiz, submit() ends up running more and more times.
Please help me to run submit() only once and thank you.
function startQuiz(){
quizBox.classList.remove("hide");
populateAnswers();
}
function closeQuiz(){
quizBox.classList.add("hide");
}
function populateAnswers(){
document.getElementById("submit").addEventListener("click" , () => {
submit();}
)
}
function submit(){
console.log(1)
}
Everytime you run startQuiz(), an event listener is being added to submit button. First time when startQuiz() is invoked, you add an event listener. After closeQuiz() when you call startQuiz() to reset display to flex, an event listener is added to submit button for second time which causes the console to be logged twice with 1 and so on.
Add event listener to submit button only once initially or remove event listener when you call closeQuiz().
The issue is because in your code whenever populateAnswers is being called a new Event listener for click is being added to the element with id submit since the listener is being added as an anonymous function. Because anonymous functions are not identical even if defined using the SAME unchanging source-code simply called repeatedly, even if in a loop. So every time one more function is being added as a new listener.
In order to resolve the issue send submit method reference itself as a listener, which will not add multiple listeners even though the function gets called multiple times. Because If multiple identical EventListeners are registered on the same EventTarget with the same parameters, the duplicate instances are discarded. They do not cause the EventListener to be called twice, and they do not need to be removed manually with the removeEventListener() method.
By changing the code with the below implementation will resolve the issue that you are facing.
function populateAnswers(){
document.getElementById("submit").addEventListener("click" , submit)
}
Hope this helps.
I am using a simplified example to describe the issue I am facing.
I have the following HTML markup:
<input ng-model="something" style="margin-top:8px;"/>
And, I have two HTML buttons:
<button id='submit'>Save</button>
<button id='btnGetAnalyzerInput'>Generate Analyzer File </button>
I used jQuery's change event on my input (to track whether any changes have been made to the input - by maintaining a simple JS variable).
When the user clicks "Generate Analyzer file button", what I want to is this:
Look up the JS variable to find out whether any changes have been made.
If yes, then prompt the user to save changes (window.dialog)
However, I find that when the focus is still on the input element, and when the button is clicked, the click event runs before the OnChange event. In all other cases, it is the OnChange event which gets fired before the click event (and so my code works as expected).
Is there any way to ensure that for such a scenario, the click event runs after the onChange event?
I am using Google Chrome to test my application.
Note :
Both events work as expected - the OnChange event gets fired when the textbox loses focus.
I can't use the keypress event since I want to track changes.
You could have the click event call the same function as the OnChange event. Something like this:
function OnChange(){
//Do stuff for on change;
}
function ClickEvent(){
OnChange();
//continue with generate stuff
}
You you may need to set up and pass in arguments to the OnChange function, depending on how you are accessing the data you need. If you need more guidance, post more of your code.
I have this input form and I want to save the value of the input whenever the user either fires an on-submit or an on-blur event.
And I have the problem, that whenever the user fires the on-submit, naturally the on-blur event is also fired. Thus two events with the same content is fired. (Not a big problem, but still).
I've searched for solutions and found a lot for jQuery, and I believe that I need a raw javascript solution for this.
Here is my form:
<form method="post" on-submit="doneEditAction">
<input
type="text"
value="{{editValue::input}}"
id="editItemInputField"
on-keyup="editKeyupAction"
on-blur="editBlur">
<button type="submit">edit</button>
</form>
This form fires the doneEditAction event when I submit the form. But at the same time the editBlur event gets also fired, which should do the same as the doneEditAction event, to save the value of the input.
editBlur Event
editBlur: function (e) {
this.doneEditAction(e);
this.editing = false;
}
doneEditAction Event
doneEditAction: function (e) {
e.preventDefault();
console.log(this.editingValue);
this.editing = false;
}
HERE ARE MY QUESTIONS:
How do I make the form not fire the on-blur event, when the form is submitted? Or
How do I make the form fire always only one event? Or, see edit,
Does it even matter at all (from a performance perspective) if two identical events are fired?
EDIT
Just saw that the Polymer TodoMVC and they also fire two events when you try to edit it. Proof:
Does that mean, that it actually doesn't matter, if two same events are fired?
Since the on-blur event fires automatically everytime the on-submit event is fired, the doneEdit event handler is executed twice.
And since the doneEdit event handler sets the editing property to false twice, there is a simple solution to make sure the doneEdit event is executed only once.
In doneEdit we check if the editing is true and only then perform any action we want, setting the editing value to false.
doneEdit(function) {
if(this.editing === true) {
this.editing = false;
console.log(this.editingValue);
}
}
Thus when the doneEdit handler will be called the second time due to the on-blur event, this.editing is already set to false and console.log() is not executed twice.
Thanks to the PolymerTodoMVC source code.
I have a textarea or input, and I change the text, and then click a link or button (without tabbing off the input), only the change event fires, not the click event. I want them both to fire:
Enter some text and then click the link. We want f1 and f2 to appear !
<br />
<input onchange="f1();" value="input text" />
<br />
click me
function f1() {
alert("f1");
return true;
}
function f2() {
alert("f2");
return true;
}
http://jsfiddle.net/paull3876/vrcfherp/3/
I've tried it with jquery and normal js as above, and I've tried setTimeouts inside the functions, I've tried input and textarea, but whatever I do, only f1 fires.
UPDATE 1
So we've established that alerts kill any subsequent events - good. Fiddle
Now the challenge is, how to stack up these events in an object so each event can fire an alert(or confirm, or ...) and NOT block any future events. I'm just trying different ideas. More to come...
UPDATE 2
I wrote some code to stack up the functions and then execute them at the end. Its not beautiful (and it should be wrapped in a class) but it works:
http://jsfiddle.net/paull3876/vrcfherp/9/
This behavior is due to the blocking mode of alert.
Browser will trigger the events one after the another. In this case the priority must be
onChange event of <input>
onClick event of <a>
but when it first executes onChange of input, it encouters alert which blocks rest of the things, hence the event onClick of anchor tag is not triggered.
Check this if you change from alert to console.log
alert() is modal and because input loses focus on other element mousedown, there is no click event fired.
So start using console for debugging purpose.
I’m running into this issue where a single action by the user is supposed to trigger two events but it only triggers the first one.
The scenario:
A user enters some text into a special field that modifies the layout on focusout , after entering the text, without leaving the field, they click a button.
What’s happening?
I have a focusout event on a text box and click event on a button. What I see is the focusout event gets fired but the click event never does.
I’ve encapsulated this in a jsfiddle:
http://jsfiddle.net/fCz6X/13/
$('#theText').focusout(function (){
$("#focusevent").text("Focusevent");
console.log("focus");
});
$('#theButton').click(function (){
$("#clickevent").text("Clickevent");
console.log("click");
});
So if you click in the text field then click the button I’d expect both events to fire, but we only see the focus out event.
I put in a temporary fix for this by having the mousedown event fire the button instead of a click event (this fires before the focusout event) but that is causing some other behaviors and issues that I don’t want to see. Due to those I think optimal solution is finding a way to get the focusout and click events to both fire. Does anyone have thoughts on how to fix this problem?
Edit: After seeing initial responses I dug a little deeper, the issue here is that the focusout event is changing the page layout which very slightly pushes the location of the button down. The click event triggers after the focusout is done but since the button is no longer in the exact same location, nothing happens.
Here is an updated fiddle that shows my problem
http://jsfiddle.net/fCz6X/11/
It's because you're calling alert - the focusout event fires, but before the browser recognizes you've clicked the button, the alert box blocks it.
Change your event handler to console.log or something else that's non-obtrusive and you'll be ok.
It is the Alert that is blocking.
Some browser security prevents firing too many window.alert at the time.
When trying with other triggers, it looks. You may try console.log()
$('#theText').on("focusout",function (){
$("#theText").val($("#theText").val()+"flb");
});
$('#theButton').on("click",function (){
$("#theText").val($("#theText").val()+"but");
});
I believe this is because the focusout event fires first, executing the handler, and the alert then prevents the browser from recognizing the click.
Try again with console.log instead of alert - it's less invasive.
As Joe said, the blocking alert call is what is breaking the event. Using a non-blocking call you will see both events.
If you really need to perform an alert like this, though, you can defer calling 'alert' until later using setTimeout()
$('#theText').focusout(function (){
setTimeout(function() { // alert after all events have resolved
alert("focus left text box");
}, 0);
});
Edit: In your updated fiddle the reason the click event never fires is because no click event occurs. If you move the button out from under the mouse on mousedown, there is no followup mouseup which is what initiates the 'click' event.
You may need to reconsider other aspects of your design. Your solution of using 'mousedown' is the best you can achieve because it's the only event that actually occurs.