Function running multiple times jQuery - javascript

Below is a function attached to the keyup event, this function works as it should on the first keyup, but on each subsequent keyup it runs the function multiple times. So for example, on first keyup event the function runs 1 time, on the 2nd keyup event the function runs 2 times, on the 3rd keyup it runs it 3 times and so on.
$(document).on('pageinit','#address_page,#edit_address_page', function(){
$(".names").focus(function() {
$(this).on('keyup', function() {
// Do Something
});
I have read other posts on this issue, but was unable to apply it to my scenario. Can someone please advise on this.

You're re-binding the keyup event every time the element is focused.
If you want to bind like that, you should also have a blur event to unbind it. Really, though, you can probably safely just bind the keyup and not worry about the focus. That element will only actually trigger a keyup WHEN it is focused.
$(".names").keyup(function () {
// do stuff
});

The problem is every time the input is focused a new keyup handler is added so try(not sure about the jquery mobile syntax and need for pageinit)
$(document).on('pageinit', '#address_page, #edit_address_page', function () {
$(this).find('.names').on('keyup', function () {
// Do Something
});
});

Related

jQuery .one() with same function for different events on different elements

I have an introduction on my page which shall disappear when a key is pressed or a certain elements is clicked on. I'll use the same function for both events but as the page is heavily modified the event shall fire only once regardless which way it was triggered.
My function:
function start() {
$('.intro').remove();
$('.something-else').show();
}
How I bind the events:
$('body').keypress(start);
$('.intro').click(start);
If the events were the same I could say
$('body, .intro').one('click', start);
If both events were to happen to the same element I could say:
$('.intro').one('click keypress', start);
How to combine both things: having different elements and different events and the function must only be called once?
The simplest solution would be to store whether your function has been called or not.
var started = false;
function start() {
if(started) return;
$('.intro').remove();
$('.something-else').show();
started = true;
}
Then your function can only be called once, every other call will be ignored.
I don't think this solution is a clean as an explicit approach, but is done using a combination of .one() and .trigger(). Because you call $(".intro").remove() on one of the bound items the event handler is implicitly unbound. Sample Fiddle
Excluding the html seen in fiddle, this is the code.
// Your event handler
function start() {
$("#intro").remove();
$("#main").show();
console.log("start handler called");
}
// Handle the keypress event
$("body").one( "keypress", start );
// Allow user to click through the intro, but trigger the keypress handler on the body which is a one-time event handler)
$("#intro").one( "click", function () { $("body").trigger( "keypress" ); });
Use two lines of code and be done ;)
$('body').one('keypress', start);
$('.intro').one('click', start);
Edit:
You should manually unbind the other callback, lest it runs later, unexpectedly.

javascript: Possible to add event handler that runs after the default behavior?

I have an event handler that I would like to have executed after the default javascript handling of that event occurs.
Is this possible?
EDIT:
For example:
everytime a keypress event is fired, i'm logging event information about that keypress(similar to console.log). Now, when I press backspace and view the fields contents via the event handler, the value of the text field produces the value without the backspace since the event handler grabs the contents of the field before the actual removal of the last letter.
I would like, in this case, for the default backspace event to occur and then have my event handler fired upon completion.
Thanks!
I believe your problem is caused by listening for the keypress event instead of the keyup event. Basically this means that you are getting the value of the textarea before the character is put in the dom.
Try changing your keypress handler to a keyup handler.
An example would be:
$('input, textarea').keyup(function(ev) {
console.log( $(this).val() );
});
Edit: Found this question which appears to be your exact problem.
I see that there was a different issue other than what is named in the question. In that regards, +1 Sam :).
However, I would like to address the question here, and not just the offshoot. There is a way to handle specific keypress events or default to one.
keypress bubbles. So use a global one, and then for anywhere you need it locally, use e.stopPropagation() in order to stop it from bubbling. Here is a demo of it working: http://jsfiddle.net/2EwhR/
here is the html:
<div id="d1">_</div>
<br><hr>
<div id="d2"><input id="i1" type="text" /></div>
js:
var d1 = document.getElementById("d1");
window.onkeypress = function(ev){
d1.innerHTML = "keyCode: " + ev.keyCode;
};
var d2 = document.getElementById("d2");
var i1 = document.getElementById("i1");
d2.onkeypress = function(ev){
d1.innerHTML = "blocked";
ev.stopPropagation();
};
This would be a way to run custom code after the event has bubbled up to the browser, i.e. the typed in value would first be added to the text field, then a second later your custom function would run. You could make this a much smaller amount of time if you wish.
$("input").on("keypress", function () {
setTimeout(function () {
alert("new value should have been already added to text field. Now we are executing some custom stuff");
}, 1000);
return true;
});
working demo

why would this jquery live enter an infinite loop, where an almost identical one does not?

I'm trying to have a form where the values are updated based on changes in either a select, or changes in a text field.
I started with
jQuery('select[name=measure]','form').live('change',function(){
alert('triggered');
});
I then added the keyup for when the user alters a text box
jQuery('select[name=measure],input[name=amount]','form').live('change keyup',function(){
alert('triggered');
});
For some reason this enters an infinite loop when I select an option, and is triggered multiple times on keyup (though not infinitely).
When I change to
...live('keyup', function()...
changes to the text-box are only triggered once.
I could split them into two seperate .live events and then create a separate function, but that doesn't seem to be efficient code.
It's attaching the change and keyup to select[name=measure] and input[name=amount].
I doubt you want the input to have a change event and the select to have a keyup event.
I recommend you separate these two live events. You probably don't need the form selector either.
$('select[name=measure]').live('change', SomeFunction);
$('input[name=amount]').live('keyup', SomeFunction);
function SomeFunction() {
// this isn't inefficient
}
working example: http://jsfiddle.net/K7586/
or you could use delegate()
$("form")
.delegate("input[name=amount]", "keyup", SomeFunction)
.delegate("select[name=measure]", "change", SomeFunction);
function SomeFunction() {
// this isn't inefficient
}

In jQuery, is there any way to only bind a click once?

I have an ajax app that will run functions on every interaction. I'd like to be able to run my setup function each time so all my setup code for that function remains encapsulated. However, binding elements more than once means that the handler will run more than once, which is obviously undesirable. Is there an elegant way in jQuery to call bind on an element more than once without the handler being called more than once?
User jQuery one function like Tom said, but unbind the handler each time before binding again. It helps to have the event handler assigned to a variable than using an anonymous function.
var handler = function(e) { // stuff };
$('#element').unbind('click', handler).one('click', handler);
//elsewhere
$('#element').unbind('click', handler).one('click', handler);
You can also do .unbind('click') to remove all click handlers attached to an element.
You could attach the event to document with the one() function:
$(document).one('click', function(e) {
// initialization here
});
Once run, this event handler is removed again so that it will not run again. However, if you need the initialization to run before the click event of some other element, we will have to think of something else. Using mousedown instead of click might work then, as the mousedown event is fired before the click event.
You can also use .off() if unbind doesn't do the trick. Make sure the selector and event given to .off exactly match the ones initially provided to .on():
$("div.selector").off("click", "a.another_selector");
$("div.selector").on("click", "a.another_selector", function(e){
This is what worked for me in resolving the same ajax reloading problem.
The answer from Chetan Sastry is what you want. Basically just call a $(element).unbind(event); before every event.
So if you have a function like loadAllButtonClicks() that contains all the
$(element).on("click", function (){});
methods for each button on your page, and you run that every time a button is clicked, this will obviously produce more than one event for each button. To solve this just add
$(element).unbind(event);
before every
$(element).on("click", function (){});
and it will unbind all events to that element, then add the one click event.

Function run multiple times on textfield focus

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.

Categories