What is the easiest way to pass an element as the first argument to event handlers in JavaScript?

I know that changing the value of this parameter to an element that receives an event in the event handling functions is very useful. However, I would like my functions to always be called in my application context, and not in the context of the element. Thus, I can use them as event handlers in other ways, for example, in setTimeout calls.

So, the code is as follows:

window.app = (function () { var that = { millerTime: function () {}, changeEl: function (el) { el = el || this; // rest of code... that.millerTime(); } }; return that; }()); 

may be as follows:

 window.app = (function () { return { millerTime: function () {}, changeEl: function (el) { // rest of code... this.millerTime(); } }; }()); 

The first way looks confusing. Is there a good easy way to pass an element that takes an event as its first argument (preferably an element wrapped in jQuery) to my event-handling function and call in the application context? Let's say I bind a bunch of event handlers using jQuery. I don't want to enable anonymous functions all the time:

 $('body').on('click', function (event) { app.changeEl.call(app, $(this), event); // would be nice to get event too }); 

I need a single function that takes care of all this. At the moment, I feel like not getting around the anonymous function, but I just want to see if anyone has a solution.

My attempt:

 function overrideContext (event, fn) { if (!(this instanceof HTMLElement) || typeof event === 'undefined' ) { return overrideContext; } // at this point we know jQuery called this function // ?? var el = $(this); fn.call(app, el, event); } $('body').on('click', overrideContext(undefined, app.changeEl)); 

Using Function.prototype.bind (which I am new to), I still cannot get the element:

 window.app = (function () { return { millerTime: function () {}, changeEl: function (el) { // rest of code... console.log(this); // app this.millerTime(); } }; }()); function overrideContext (evt, fn) { var el = $(this); // $(Window) console.log(arguments); // [undefined, app.changeEl, p.Event] fn.call(app, el, event); } $('body').on('click', overrideContext.bind(null, undefined, app.changeEl)); 

Using $('body').on('click', overrideContext.bind(app.changeEl)); instead, it points to my app.changeEl function, and the length of the arguments is 1 and contains only p.Event. I still cannot get the item in any instance.

+4
source share
1 answer

The definition of such a function should give you what you want:

 function wrap(func) { // Return the function which is passed to `on()`, which does the hard work. return function () { // This gets called when the event is fired. Call the handler // specified, with it context set to `window.app`, and pass // the jQuery element (`$(this)`) as it first parameter. func.call(window.app, $(this) /*, other parameters (e?)*/); } } 

Then you will use it like this:

 $('body').on('click', wrap(app.changeEl)); 

See Function.call() for more information.


In addition, I would like to recommend against this approach. Familiar JavaScript programmers expect the context to change in timeouts and event handlers. Distracting this fundamental from them, I, like me, will leave you in the Sahara without a compass.

+3
source

All Articles