Bug Tracker

Ticket #12031 (closed feature: migrated)

Opened 2 years ago

Last modified 2 months ago

Allow objects as event handlers

Reported by: petka_antonov@… Owned by: dmethvin
Priority: low Milestone: 1.12/2.2
Component: event Version: 1.7.2
Keywords: Cc:
Blocking: Blocked by:

Description

Doing OOP with jQuery events requires a lot of $.proxy boilerplate. the .addEventListener interface allows passing an object as a handler like so:

function SomeWidget( elem ) {
	this.elem = elem;
}

SomeWidget.prototype = {
	constructor: SomeWidget,

	renderTo: function( target ) {
		$(target).append(this.elem);
		this.elem.addEventListener( "click", this );
		this.elem.addEventListener( "mousemove", this );
	},

	mousemove: function( e ) {

	},

	click: function( e ) {

	},

	handleEvent: function( e ) {
		return this[e.type].apply( this, arguments );
	}
};

With jQuery you have to do this:

function SomeWidget( elem ) {
	this.elem = elem;
	//Each method needs to be bound to the instance. This also has overhead of creating many functions.
	this.mousemove = $.proxy( this.mousemove, this );
	this.click = $.proxy( this.click, this );
}

SomeWidget.prototype = {
	constructor: SomeWidget,

	renderTo: function( target ) {
		$(target).append(this.elem);
		$(this.elem).on( {
			click: this.click,
			mousemove: this.mousemove
		});
	},

	mousemove: function( e ) {

	},

	click: function( e ) {

	}
};

With jQuery supporting objects as event handlers, it would work like:

function SomeWidget( elem ) {
	this.elem = elem;
}

SomeWidget.prototype = {
	constructor: SomeWidget,

	renderTo: function( target ) {
		$(target).append(this.elem);
		$(this.elem).on( "click mousemove", this );
	},

	mousemove: function( e ) {

	},

	click: function( e ) {

	},

	handleEvent: function( e ) {
		return this[e.type].apply( this, arguments );
	}
};

And that's it. No $.proxy hacks, no redundant creation of functions just to retain binding.

Change History

comment:1 Changed 2 years ago by dmethvin

  • Status changed from new to open

Worth thinking about so I'll leave it open.

comment:2 Changed 2 years ago by dmethvin

  • Component changed from unfiled to event

comment:3 Changed 2 years ago by rwaldron

I'm into this

 http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventListener

@dmethvin - if you don't mind, I'd like to prototype this one :)

Last edited 2 years ago by rwaldron (previous) (diff)

comment:4 Changed 2 years ago by rwaldron

  • Owner set to rwaldron
  • Status changed from open to assigned

comment:5 Changed 2 years ago by rwaldron

note to self...

 .on({ click: fn }) 

Has to support handling:

// delegated events
.on({ click: fn }, "div");

// data object events
.on({ click: fn }, "div", dataobject);

comment:6 Changed 2 years ago by dmethvin

  • Type changed from enhancement to feature

Bulk change from enhancement to feature.

comment:7 Changed 2 years ago by mikesherov

  • Priority changed from undecided to low

comment:8 Changed 15 months ago by gnarf

  • Owner changed from rwaldron to gnarf

comment:9 Changed 15 months ago by dmethvin

gnarf and I talked about this in Austin. It would be a very low-level public interface, ideally the current event features would be built on top of it. Essentially replace  this function so we don't go to the current jQuery dispatcher and instead use a caller-supplied dispatching object. That would provide users with low-overhead ways to handle high-frequency events like scroll or mousemove (or the upcoming pointermove) by avoiding jQuery.event.fix() for example.

comment:10 Changed 15 months ago by gibson042

A good implementation would make something like  https://github.com/jquery/jquery/pull/1367/files significantly more lightweight.

comment:11 Changed 10 months ago by dmethvin

  • Owner changed from gnarf to dmethvin

comment:12 Changed 10 months ago by dmethvin

  • Milestone changed from None to 1.12/2.2

comment:13 Changed 9 months ago by dmethvin

Additional note re #14953, can we have a way to do capturing here? As I understand the .addEventListener interface it seems like all the events in the attached object would be capturing.

comment:14 Changed 9 months ago by petka_antonov@…

In addEventListener the optional useCapture parameter defines whether capturing is in use regardless if you use a function or an object as a handler. The default is false so in the example all events are bubbling.

comment:15 Changed 5 months ago by dmethvin

Re rwaldron's comment 5 above, I am thinking this interface will be low level enough that we will not support any type of enhancement. That includes special events, delegation, fixing, or additional data. To get those things you'll either need to do them yourself or use the standard interfaces.

For the additional data issue, it's probably not an issue since the this points to an object you get to populate. The other features cost execution time and one of the reasons for this interface is to provide a clean way to get performance when you don't need things like event normalization across browsers.

comment:16 Changed 2 months ago by m_gol

  • Status changed from assigned to closed
  • Resolution set to migrated
Note: See TracTickets for help on using tickets.