In jQuery plugins, which way do you think it's best to allow a function to be hooked in your plugin - trough triggers, or options (arguments) passed in the plugin function?
$.trigger('myplugin_completed', someData);
$(document).bind('myplugin_completed', function(event, someData){ ... });
vs
myPluginOptions.onComplete(someData);
$('.stuff').myPlugin({onComplete: function(someData){ ... }});
Solution
I think the best solution - at least in the case you described (maybe not in all the possible cases) - is to combine both in the following way:
$('.stuff').myPlugin(/* some options here */);
$('.stuff').trigger('myplugin.completed', someData);
and this line:
$('.stuff').on('myplugin.completed', function(event, someData){
/* callback code */
});
is responsible for binding the event handler. It can be called also when someone passes onComplete callback within options when initializing your plugin (of course selector should be adjusted to meet the one used by the code initializing your pugin).
Summary
To sum up, you could:
create your own event (completed),
use your plugin's namespace for this event / plugin (in this case myplugin),
use .on() function (available and preferred since jQuery 1.7),
if onComplete option is passed to your plugin, there is no problem in binding it within the code initializing the plugin (so from within the plugin, using the .on() function, binding event handler to your event name within your even namespace).
I will vote for the second option, because in this way one can control the onComplete event, and it is binded only to the element. Binding it to documents it is not good, because one can do $(document).unbind(), that unbind all events.
I think both ways are good and none of them has big advantage over another.
For example, jQuery UI use callback for options and event triggers for actual events such as start/stop dragging.
But, by creating event triggers in code you create maybe more flexible way to add more event handlers, without modyfing existing code. I mean when you got callbacks, it goes this way:
{onComplete: function(someData){ action_1; }}
If you need some extra actions you write them into existion function or put functions inside:
{onComplete: function(){ action_1; action_2 }}
or
{onComplete: function(){ action_1; function_2(); }}
function_2(){ action_2 };
For comparison using events it would be like:
$('selector').on('myplugin_completed.myplugin', function_1 })
Extra actions:
$('selector').on('myplugin_completed.myplugin_extra', function_2 })
If you don't need some actions you can unbind only them.
$('selector').off('myplugin_completed.myplugin_extra');
There are differences between them, but usually it depends on particular situation, which one is better;
Related
Comming from a c# background, I just want to create an event in a certain point of my code, soas to be dispatched elsewere, meaning that if in some part of the code there has been a subscription, this delegate function is called.
So I tried to do:
function myFunction() {
console.log("delegated call achieved!");
}
const myEvent = new Event('onMyConditionIsMet', myFunction, false);
//at this point the program the subscription takes place
function whatever1() {
//...not meaningfull code
myEvent.addEventListener('onMyConditionIsMet');
//myEvent += myFunction; c# way subscription in case it makes sense
}
//at this point in the program, event subscription is checked and
//delegate func run in case there has been a subscription
function whatever2() {
//...not meaningfull code
myEvent?.invoke(); // ?.invoke(); would be the c# way to do it.
}
All the examples I found are related to DOM events, but my case would be for events I create myself, think these are called synthetic events.
Another assumption I make in this question is that there would be no arguments in the delegate call function, so, just to be clear with the naming, it would be a delegate with no arguments. Just pointing this because in c# events are just delegate funcs with no arguments, so a specific type of delegate. Not sure if this works the same way in Javscript.
What would be the approach to do this? (Meaning creating a simple event instance, subscribing, and executing the delegated code if there is any subscription)?
I think the functionality you are looking for can be best obtained by using OOP/Classes.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#prototype_methods
Edit: see this also - "event" is deprecated, what should be used instead?
At the company I work, we've decided to extract most of our Marionette.js code and split them up into several Rails Gems.
At this moment, I've managed to split up Marionette Controllers and Views. Some of the stuff inside Marionette Controllers are necessary for most of our eCommerce apps, so I extracted this JavaScript code into a few Gems. We'll then be able to use the stuff we've already split up into Gems and override / extend Controllers/Views when necessary.
For app-wide actions, we use Backbone.Wreqr. An example of an event handler found in one of our Gems:
Backbone.Wreqr.radio.commands.setHandler('product', 'show', function (slug) {
API.showSingleProduct(slug);
App.navigate("/products/" + slug);
});
However, for some of our apps, we'll need to override this handler to make it work with some custom stuff in our project.
Imagine I want to modify the above handler to something like this:
Backbone.Wreqr.radio.commands.setHandler('product', 'show', function (slug, color) {
API.showSingleProduct(slug, color);
App.navigate("/products/" + slug);
});
When I add such an event handler in our base project, the event will be called twice. I actually only need the last (customized) event handler to be fired.
Is there any way to override existing Backbone.Wreqr events? Or should I remove the previous handlers every time I want to customize the behaviour of a previous handler?
There's no need to remove the previous handler, setting a new one effectively overrides any handler assigned to the same namespace.
Your code should work in terms of registering a single handler, the problem must be somewhere else.
I'm working with a 3rd party product where I am extending the UI with my own custom functionality. Within part of that I need to call an event after the UI has been updated with an AJAX call. Luckily the app fires a call to a Custom Event using the Prototype JS library after the call is complete, like this:
$(document.body).fire("ns:customevent");
If I add my own custom event with the same name then this works as expected
$(document).observe("ns:customevent", function(event) {
//do custom stuff here
});
[I could not get $(document.body).observe() to work here but I don't think that really matters.]
My concern here is that there may be other parts of the app that have registered functions against that event, and I am (blindly) overwriting them with my own, which will lead to issues further down the line.
Does Prototype append custom functions even though they have the same name or does it in fact overwrite them? If it does overwrite them then how can I append my function to anything that is already existing? Is there anyway of viewing what
I would imagine something like this, but I hardly know Protoype and my JS is very rusty these days.
var ExistingCustomEvent = $(document.body).Events["ns:customevent"];
$(document).observe("ns:customevent", function(event) {
ExistingCustomEvent();
//do custom stuff here
});
I can't add my event handler or add in code to call my own function, I want to try avoiding the 3rd party library (if that would even be possible).
Thanks.
As an FYI for anyone else that stumbles upon this question, following the comment from Pointy it turns out that Prototype does append the functions to the custom event.
I verified this by trying the following and both alerts fired.
$(document).observe("ns:customevent", function(event) {
alert("ALERT 1");
});
$(document).observe("ns:customevent", function(event) {
alert("ALERT 2");
});
Great :)
I'm trying to understand what the differences are (if any) between these 2 ways of calling JavaScript/jQuery functions.
Method 1, in document.ready():
$('body').on('click', 'a.popup', popup);
then
function popup() {
$(this) // do something
}
Method 2, in document.ready():
popup();
then
function popup() {
$("a.popup").click(function (e) {
// do something here
});
}
All advice appreciated.
In method 2, the popup function is likely to be called only once, otherwise you attach the same function onclick several times, which propably is not what you want.
Therefore there is no great benefit in writing the popup function's body elsewhere than directly in document.ready().
Advantage of method 1 is if you want to attach the same function to various events and/or various elements, e.g. onclick, onmousemove etc. This way you won't have to write the function's body twice.
In short, i don't see benefits in method 2, whereas i see some in method 1.
I'm not quite sure, but I think you're asking what the difference between calling the jQuery .on() method and the jQuery .click() method, right?
As in:
$someEl.on('click', someFunc);
// or
$someEl.click(someFunc);
Like this, both are pretty much equivalent. However with the .on() method you have the opportunity to introduce namespacing (explained in the first link) to your element's events. Like so:
$someEl.on('click.do1', someFunc1);
$someEl.on('click.do2', someFunc2);
So if in a later progress you want to remove or trigger only one of your callback functions (someFunc1, someFunc2), you'll be able to do so by calling:
$someEl.off('click.do1');
$someEl.trigger('click.do2');
Hope this helps
Is there a way to tell the browser to run an addtional java script function on an event such as 'window.resize' instead of overwriting what is already there?
Using jquery's
$(window).resize(<something>);
Seems to replace what is already there. Is there a way to tell it to do something in addition?
Is this a poor design / wrong way to do it?
I wouldn't think that jQuery would break what's there, but you could wrap the functions in a single function:
// if a function already exists...
if( window.onresize ) {
var prev_func = window.onresize; // cache the old function
window.onresize = function( event ) { // new function for resize
prev_func.call( window, event ); // call the old one, setting the
// context (for "strict mode") and
// passing on the event object
// call your code or function
};
}
EDIT: Fixed it to use onresize instead of resize.
EDIT2: Missed one! Fixed.
If you're using jQuery to bind all event handlers, then you're not breaking anything. jQuery supports multiple handlers for same event.
But if other code (not using jQuery) binds to the event, then you'll overwrite handler with your statement. The solution will be: always use jQuery for event binding or try to save old handler (see patrick dw's answer).
See element.addEventListener (element.attachEvent in IE 8 and under):
// Standards
if (window.addEventListener){
window.addEventListener("resize", callOnResize, false);
// IE 8 and under
} else if (window.attachEvent){
window.attachEvent('resize', callOnResize);
}
function callOnResize() {
console.log("resized");
}
Keep in mind this is pure JavaScript—jQuery (and pretty much any big JS library) has a method to handle creating standards and IE handlers without you needing to write each. Still, it's good to know what's happening behind the scenes.
jQuery and all other frameworks supporting custom events attach a function to the event of the elem (or observe it). That function then triggers all functions that have been bound (using bind) for a specific event type.
domelement.addEventListener does not override an other function and your function added can't be removed by other (bad) javascript, except when it would know the exact footprint of your function.