Can a Javascript literal object fire events?

I have a Javascript letter:

var Toolbar = { init: function(toolbar) { this.Bar = $(toolbar); // scope is Toolbar object literal this.Bar.find('clearButton').click(function() { this.trigger('clear'); // doesn't work! this.Bar.trigger('clear'); // works! } } Toolbar.init($('div.toolbar')); Toolbar.bind('clear', function() { ... }); // doesn't work! Toolbar.Bar.bind('clear', function() { ... }); // works! 

I would like to fire the clear event on a literal object on the toolbar, and not on the toolbar DOM object referenced by the letter. Is this possible, and if so, how can I do this?

+4
source share
3 answers

This should work:

 var Toolbar = { init: function(toolbar) { this.Bar = $(toolbar); // scope is Toolbar object literal this.Bar.find('.clearButton').click($.proxy(function() { $(this).trigger('clear'); // should work now this.Bar.trigger('clear'); // still works }, this)); } }; Toolbar.init($('div.toolbar')); $(Toolbar).bind('clear', function() { console.log('Toolbar'); }); // should work now Toolbar.Bar.bind('clear', function() { console.log('Toolbar.Bar'); }); // still works 
  • You need to save the this link in the click function. I used $.proxy ; some people use var self = this;

  • Toolbar not a jQuery object, so it must be enclosed in $() to access jQuery functions. Also wrap this , which refers to a Toolbar instance in a click function.

+1
source

How about this?

 var Toolbar = { init: function(toolbar) { this.Bar = $(toolbar); // scope is Toolbar object literal this.trigger = function() { this.Bar.trigger.apply(this.Bar, arguments); }; this.bind = function() { this.Bar.bind.apply(this.Bar, arguments); }; this.Bar.find('clearButton').click(function() { this.trigger('clear'); } }; Toolbar.init(); Toolbar.bind('clear', function() { ... }); 

If you want, you can easily create a function to handle packaging; any of them, as you prefer:

 function wrapperitize(wrapper, wrappee, method /*, more_methods...*/) { wrapper[method] = function() { wrappee[method].apply(wrappee, arguments); }; for(var i = 3; i < arguments.length; ++i) wrapperitize(wrapper, wrappee, arguments[i]); } function wrapperitize(wrapper, wrappeeProp, method /*, more_methods...*/) { wrapper[method] = function() { wrapper[wrappeeProp][method].apply(wrapper[wrappeeProp], arguments); }; for(var i = 3; i < arguments.length; ++i) wrapperitize(wrapper, wrappeeProp, arguments[i]); } 

where the former will be called as wrapperitize(this, this.Bar, 'trigger', 'bind') , and the latter will be called wrapperitize(this, 'Bar', 'trigger', 'bind') (the difference is what the former will do this is a wrapper for any this.Bar for the time being, while the latter will make this a wrapper for any this.Bar , possibly sometime in the future.

(Note, by the way, a tiny bit of recursion. This is done to avoid the problem of capturing variables due to how JavaScript locks work.)

0
source

If you want you to be able to call a method in a Toolbar object, you need to define it there. If you don’t need to add so many of these methods this way, you can simply define each of them in the toolbar object itself:

 var Toolbar = { clear: function() { this.Bar.trigger('clear'); } init: function(toolbar) { this.Bar = $(toolbar); // scope is Toolbar object literal this.Bar.find('clearButton').click(function() { this.clear(); } } 

However, if you need to call so many of them, it will quickly become ugly. If you really want to be able to call all available methods of the jquery object on the toolbar object, you can try to combine all of them with a for in loop and add them to the toolbar object, but it will be tedious, annoying to read, inefficient and possibly cause some errors. I would just use $(toolbar) whenever you would like to call a method on this object, as it will get rid of all these shortcomings .: D

0
source

Source: https://habr.com/ru/post/1384435/


All Articles