1114

Is there a way to have keyup, keypress, blur, and change events call the same function in one line or do I have to do them separately?

The problem I have is that I need to validate some data with a db lookup and would like to make sure validation is not missed in any case, whether it is typed or pasted into the box.

isherwood
  • 58,414
  • 16
  • 114
  • 157
shaneburgess
  • 15,702
  • 15
  • 47
  • 66

13 Answers13

2048

You can use .on() to bind a function to multiple events:

$('#element').on('keyup keypress blur change', function(e) {
    // e.type is the type of event fired
});

Or just pass the function as the parameter to normal event functions:

var myFunction = function() {
   ...
}

$('#element')
    .keyup(myFunction)
    .keypress(myFunction)
    .blur(myFunction)
    .change(myFunction)
Tatu Ulmanen
  • 123,288
  • 34
  • 187
  • 185
  • 4
    With space separated events how do you also include name spacing? `.on('keyup.foo keypress.foo blur.foo change.foo', …)` or `.on('keyup keypress blur change .foo', …)`? – Sukima Dec 14 '15 at 14:48
  • 29
    Problem with this is that myFunction will probably get called multiple times, which you might want to prevent. – Esger Jan 21 '16 at 09:51
  • 2
    How can I pass parameter in this function? – HalfWebDev May 26 '16 at 07:45
  • 1
    @Esger Anyway to do this? In mobile, I always need to `on('click tap', e => {...})`. The listener may be triggered twice, I just wanna trigger once, how can I code in the listener function? – tomision Nov 10 '16 at 14:34
  • 9
    @Tomlsion Maybe add a className 'busy' to the element in the called function, and then `$('#element:not(.busy)').on('keyup keypress blur change', function(e){…});` Finally remove the className 'busy'. – Esger Dec 04 '16 at 21:57
  • @kushalvm you define an anonymous function that calls the function with arguments: `$("#element").change(function(){myFunction(param1, param2)})` – Sdlion Dec 21 '17 at 20:35
  • In answer to @TomIsion's question of two years ago (for future readers): There is, `$('#element").one('click tap', e => {…})` that, if I read the docs right, executes the code once per event type. – Dave Land Aug 25 '18 at 00:56
  • @DaveLand I tried with `$(document).one('ajaxSuccess ajaxComplete', function()` and it triggered twice... – Barbz_YHOOL Apr 20 '21 at 00:45
  • This wont work on a different element, meaning you will not be able to use this method if you want << $('#elementXX').on('click') >> to reuse the function – Mbotet May 24 '22 at 09:04
  • Some modification `$( document ).on( 'keyup keypress blur change', 'input[name="some_name"]', myFunction ); ` But, yes, the function starts multiple times. – Andris Sep 14 '22 at 03:37
69

As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document. For earlier versions, the .bind() method is used for attaching an event handler directly to elements.

$(document).on('mouseover mouseout',".brand", function () {
  $(".star").toggleClass("hovered");
})
bluish
  • 26,356
  • 27
  • 122
  • 180
lesyk
  • 3,979
  • 3
  • 25
  • 39
  • 1
    This is done for a delegated event, it will work, but it's not the simplest way of doing it, nor the most efficient. – Ben Taliadoros Apr 08 '14 at 15:19
  • 1
    Event delegation is important, and may (or may not) be required depending on when the script is loaded / run, and if the elements exist in the DOM at the time the script is loaded / run. – random_user_name Jan 11 '17 at 16:57
58

I was looking for a way to get the event type when jQuery listens for several events at once, and Google put me here.

So, for those interested, event.type is my answer :

$('#element').on('keyup keypress blur change', function(event) {
    alert(event.type); // keyup OR keypress OR blur OR change
});

More info in the jQuery doc.

Alain Tiemblo
  • 36,099
  • 17
  • 121
  • 153
27

You can use bind method to attach function to several events. Just pass the event names and the handler function as in this code:

$('#foo').bind('mouseenter mouseleave', function() {
  $(this).toggleClass('entered');
});

Another option is to use chaining support of jquery api.

Giorgi
  • 30,270
  • 13
  • 89
  • 125
  • 12
    As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document. – Dzhuneyt Aug 25 '13 at 18:25
24

Is there a way to have keyup, keypress, blur, and change events call the same function in one line?

It's possible using .on(), which accepts the following structure: .on( events [, selector ] [, data ], handler ), so you can pass multiple events to this method. In your case it should look like this:

$('#target').on('keyup keypress blur change', function(e) {
    // "e" is an event, you can detect the type of event using "e.type"
});

And here is the live example:

$('#target').on('keyup keypress blur change', function(e) {
  console.log(`"${e.type.toUpperCase()}" event happened`)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="target">
Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
P.S.
  • 15,970
  • 14
  • 62
  • 86
18

If you attach the same event handler to several events, you often run into the issue of more than one of them firing at once (e.g. user presses tab after editing; keydown, change, and blur might all fire).

It sounds like what you actually want is something like this:

$('#ValidatedInput').keydown(function(evt) {
  // If enter is pressed
  if (evt.keyCode === 13) {
    evt.preventDefault();

    // If changes have been made to the input's value, 
    //  blur() will result in a change event being fired.
    this.blur();
  }
});

$('#ValidatedInput').change(function(evt) {
  var valueToValidate = this.value;

  // Your validation callback/logic here.
});
Dave Ward
  • 59,815
  • 13
  • 117
  • 134
15

This is how i do it.

$("input[name='title']").on({
    "change keyup": function(e) {
        var slug = $(this).val().split(" ").join("-").toLowerCase();
        $("input[name='slug']").val(slug);
    },
});
Mohammad
  • 21,175
  • 15
  • 55
  • 84
Sajjad Ashraf
  • 3,754
  • 1
  • 34
  • 35
13

You could define the function that you would like to reuse as below:

var foo = function() {...}

And later you can set however many event listeners you want on your object to trigger that function using on('event') leaving a space in between as shown below:

$('#selector').on('keyup keypress blur change paste cut', foo);
KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • 3
    Generally you should explain your answer. Simply pasting code does nothing to help the OP understand their problem or your solution. – leigero Apr 08 '15 at 18:06
  • what if I need first argument in jquery event subscriber function (event)? How to use it? – Dr.X Sep 14 '18 at 06:32
  • That's ok, you can just declare the function with the event parameter and then access it from within the method. These events will pass the object in themselves. I hope this helps. var foo = function(event) { console.log(event); } $('#selector').on('keyup keypress blur change paste cut', foo); – Coder Of The Galaxy Sep 17 '18 at 14:00
7

The answer by Tatu is how I would intuitively do it, but I have experienced some problems in Internet Explorer with this way of nesting/binding the events, even though it is done through the .on() method.

I havn't been able to pinpoint exactly which versions of jQuery this is the problem with. But I sometimes see the problem in the following versions:

  • 2.0.2
  • 1.10.1
  • 1.6.4
  • Mobile 1.3.0b1
  • Mobile 1.4.2
  • Mobile 1.2.0

My workaround have been to first define the function,

function myFunction() {
    ...
}

and then handle the events individually

// Call individually due to IE not handling binds properly
$(window).on("scroll", myFunction);
$(window).on("resize", myFunction);

This is not the prettiest solution, but it works for me, and I thought I would put it out there to help others that might stumble upon this issue

Squazz
  • 3,912
  • 7
  • 38
  • 62
7
$("element").on("event1 event2 event..n", function() {
   //execution
});

This tutorial is about handling multiple events.

Guest
  • 81
  • 1
  • 1
4

It's simple to implement this with the built-in DOM methods without a big library like jQuery, if you want, it just takes a bit more code - iterate over an array of event names, and add a listener for each:

function validate(event) {
  // ...
}

const element = document.querySelector('#element');
['keyup', 'keypress', 'blur', 'change'].forEach((eventName) => {
  element.addEventListener(eventName, validate);
});

If you'd want to mimic adding to more than 1 element:

const elements = document.querySelectorAll('.commonSelector');
['keyup', 'keypress', 'blur', 'change'].forEach((eventName) => {
  elements.forEach(element => {
      element.addEventListener(eventName, validate);
  });
});
jave.web
  • 13,880
  • 12
  • 91
  • 125
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Note that **jQuery does *nothing less*** - in the end it itself goes down to `return elem.each( function() { jQuery.event.add( this, types, fn, data, selector ); } );` ([this is straight from jQuery 3.6.0 code](https://code.jquery.com/jquery-3.6.0.js)) – jave.web Aug 20 '22 at 10:18
3

Instead of:

$('#element').on('keyup keypress blur change', function(e) {
    // e.type is the type of event fired
});

You can use:

$('#element').on('input', function(e) {
    // e.type is the type of event fired
});

input is trigerred for keyup keypress blur change events even for paste!

Lrnt
  • 166
  • 1
  • 6
0

But to prevent multiple triggering:

var a;
var foo = function() {
    clearTimeout(a);
    a=setTimeout(function(){
        //your code
        console.log("Runned")
    },50);
}
$('textarea').on('blur change', foo);
Hakan
  • 240
  • 3
  • 4