jQuery 1.7+ and changing live() to on()

Since as of jQuery 1.7, the .live() method is deprecated, I’ve been trying to convert one of my plugins to use on(), but I keep getting similar errors no matter what I try. The error says, “selection.value is undefined”.

The old code that worked in older versions of jQuery was like this:


/* Monitor events on designated elements */
$(this)
/* Keyup and blur events necessary to handle pasted data */
.live('keyup blur', function() {
	/* If a character is being limited */
	if (this.value.search(regex) != '-1') {
		/* Remove the character from the input */
		this.value = this.value.replace(regex, '');
	}
})
/* Disable right clicks to prevent pasting via context menu */
.live('contextmenu',function () {return false});

and the new code is like this:


// Hold this in a variable for use in on()
var selection = $(this);

/* Monitor events on designated elements */
$(document)
/* Keyup and blur events necessary to handle pasted data */
.on( 'keyup blur', selection, function() {
	/* If a character is being limited */
	if (selection.value.search(regex) != '-1') {
		/* Remove the character from the input */
		selection.value = selection.value.replace(regex, '');
	}
})
/* Disable right clicks to prevent pasting via context menu */
.on( 'contextmenu', selection, function () {return false});

Why isn’t selection defined? What can I do here?

I think the selector needs to be a string. But in your case, I don’t know if you need it at all. It looks like you only care about the keyup and blur events on a single element, in which case you can just do this:


$(this).on('keyup blur', function () {
    // ...
});

However, if that doesn’t work and you still want to use a selector, I don’t think there’s any simple method that creates a selector for an element on the fly. You’ll have to create one on your own. If, for example, the element has an id…


var selector = '#' + this.id;
$(document).on('keyup blur', selector, function () {
    // ...
});

Do either of these suggestions help?

Well, if you are familiar with live(), it was able to attach an event handler to elements that were dynamically created in the future, and that’s essential to some parts of my application. With basic usage of on(), as you suggest in the first example, the attaching only happens to current elements. The code in your second example doesn’t work. If I use console.log() on selector immediately after setting it, it is undefined. This is how the plugin is used by the way:


$('.first_name, .last_name').disableChars({limit_to:"alpha",allow:" /.()-,'"});

What is “this” referring to? Because the original advice still stands (I think): You need to use a string for the selector.

The problem using a string is that that string is dynamic. Here’s what I did to get it working; I added a second parameter to the plugin function. Instead of calling the plugin using

$.(‘#id’).disableChars({limit_to:“alpha”,allow:" /.()-,'"});

Now I am calling it like this:

$.(document).disableChars(‘#id’, {limit_to:“alpha”,allow:" /.()-,'"});

The plugin is initialized like this:

$.fn.disableChars = function(element, options) {

And the code I needed help with turns into this:


/* Monitor events on designated elements */
$(document)
/* Keyup and blur events necessary to handle pasted data */
.on( 'keyup blur', element, function() {

	/* If a character is being limited */
	if (this.value.search(regex) != '-1') {
		/* Remove the character from the input */
		this.value = this.value.replace(regex, '');
	}
})
/* Disable right clicks to prevent pasting via context menu */
.on( 'contextmenu', element, function () {return false});

Thanks for your time.

Any specific reason you’re not using .delegate()?
That also works on both current and future elements, and is more lightweight because it only binds an event to 1 element, instead of binding an element to each and every node it should apply to.

According to the delegate page:

As of jQuery 1.7, .delegate() has been superseded by the .on() method. For earlier versions, however, it remains the most effective means to use event delegation.

So I was thinking it is better to change to on() before delegate is deprecated.

Yikes I missed that. You’re right, forget I ever said it :blush:

To get back to the original question, selection is a jQuery object, not a DOM Node. Have you tried .val() instead of .value ?

Yes, I’ve tried it that way. If I do that, then the dynamically created form elements throw an error because selection has no value. The solution I came up with above is the only one that works. Just seems like a quick fix and not an elegant solution.