Defining and triggering custom events on custom module in YUI3 - javascript

This is how we can create a custom module in YUI3,
<script type="text/javascript">
YUI.add('my-module', function (Y) {
// Write your module code here, and make your module available on the Y
// object if desired.
Y.MyModule = {
sayHello: function () {
console.log('Hello!');
}
};
});
</script>
But now I would like to, on this module, define some custom events and later trigger them, I just couldn't find any information about this on the YUI3 official website.
How can we actually do this?

Custom events are actually pretty important throughout YUI. This documentation page describes them in detail: http://yuilibrary.com/yui/docs/event-custom/. Read this page and some of the examples in the sidebar.
The easiest and simplest way to fire a custom event is to fire it from the Y, as in Y.fire("myEvent"). However, if you want to fire an event from your object, you would need to give your object the EventTarget API and call this.fire("myEvent"). Most people do this by extending Y.Base, which includes Y.EventTarget. See http://yuilibrary.com/yui/docs/base/ -- if you extend Base, you get a fire() method, the ability to listen for events with on() or after(), plus lots of other goodies.

Related

Forcing modules to have a specific function. eg implement an interface?

Simple in java, but how do I ensure the modules that are registering with my event bus for topic notifications have the required callback method on them?
All my modules are following the revealing module pattern and as such are defined like the following
namespace = (function() {
//Private stuff
return {
method1 : method1
}
})();
I just need to ensure the module has a notify method on it which takes a single argument. The module can be responsible for unmarshalling the payload data into the format it is expecting
Thanks
I really want to help but I'm not sure I understand your terminology. I'll answer based on my limited understanding and adjust as necessary
Sounds to me like you want to make sure the object returned has a property called notify on it, which is a function that accepts one function parameter only. If this is correct, there are two places you can ensure all modules meet your requirement.
Inside the Event Bus
If you wrote the event bus, you can write a few lines of code inside it to make sure that if a module doesn't come with the 'notify' property on it, the event bus will not subscribe the module to the event. Something like this:
if( typeof module.notify !== 'function' ){
// do error handling then ...
return false;
}
External Function for Registering Modules to Event Bus
If you didn't write the event bus, you can create an external function that is responsible for ensuring the standard. Think of it as a wrapper around #1.
function registerToEventBus( module, event ){
if( typeof module.notify !== 'function' ){
// do error handling then ...
return false;
}
// register event to event bus then ...
return true;
}
Personally I'd recommend using #2
That way you wouldn't need to know a thing about the event bus itself to implement this.
You get the added benefit of being able to keep the event bus strictly for events and not complicate it by adding the module format enforcement into it.
You will be able to take the event bus as is to another project, drop it in and edit your enforcer function to meet this project's specificiations with absolutely no risk of breaking the event bus accidentally.
I hope this helps. If there's any place I misunderstood you, let me know and I'll give it my best shot to fix.

Possible to extend JQueryEventObject in TypeScript

I've only just started with Typescript but I'm wondering if it is possible to extend the JQueryEventObject with a new method - I'd like to add a cancel method that sets the event to stop bubbling and propagating.
If my understanding is correct, there is no way to do this using TypeScript because the JQueryEventObject is merely an interface created to provide an intellisense of what is available on the event object provided to an event. However, I may be wrong and if someone has got a solution, then I'd appreciate someone sharing that with me.
You are correct that the typescript definition is an interface, however, you can extend it, and you can also extend the runtime to add the new function. There are two things that need to be done:
make typescript aware of the new function
make the new function available at runtime inside jQuery
Here is a code sample that does both:
// PatchJquery.ts
// Include the generated .js file for this, after jQuery, in some html file.
/// <reference path="typedef/jquery/jquery.d.ts" />
// Runtime patch: Assume jQuery is already defined in the global scope
// and patch its Event prototype.
jQuery.Event.prototype.cancel = function() {
console.log("Someone wants me to cancel this event!",this);
}
// Define the extended typescript interface
interface ExtJQueryEventObject extends JQueryEventObject {
cancel():void;
}
// Test
$(function() {
var body:JQuery = $("body");
body.on('click', (e:ExtJQueryEventObject) => {
e.cancel();
});
});
Note that if you wanted, say, an actual click event, you would need to define an extended interface for JQueryMouseEventObject. You would need to do this for all of the different JQuery event types. Alternatively, you could just modify jquery.d.ts to add your new function to BaseJQueryEventObject.
(BTW, jQuery has stopPropagation() and stopImmediatePropagation(), which might do what you want already)

A simple event system | How to?

I want to implement this interface
addListener(name, callback);
removeListener(name, [callback]); // callback is optional
trigger(name);
All events will be triggered on an internal event bus
var bus = {}
that is not part of the interface.
This is the simplest interface I could imagine that is actually useful.
However I still don't how to implement these interfaces conceptually. I've perused the backbone event system, but can't quite understand how they implement this core functionality.
I just want to write a quick 10-100 line event system that is as simple as possible and based upon the more complex Backbone event system.
You could use Backbone.Events module for it.
Stolen shamelessly from lostechies
You could use an Application level event aggregator:
MyApp = {};
MyApp.vent = _.extend({}, Backbone.Events);
MyApp.vent.on("some:event", function(){
alert("some event was fired!");
});
MyApp.vent.trigger("some:event");
Check out the minimal event bus library minibus.js. It currently has different API but might be exactly what you are looking for.
var bus = Minibus.create();
bus.on(name, callback); // add listener
bus.emit(name); // trigger event
bus.off(name); // remove listener

How to use dojo/behavior on dojo widget?

I read this article (Using dojo.behavior), and want to use the behavior module in my project as event handling module.
But I have a problem that, for DOM nodes, it works wonderful, but how can I use it on the Dojo widgets?
If I use dojo/on module, I can do it like this:
var buttonNode = dijit.byId("myButton");
on(buttonNode, "onClick", buttonHandler);
or
dijit.byId("myButton").onClick = buttonHandler;
But, if I use behavior module,
behavior.add({
"#myButton": {
onClick: buttonHandler
}
});
it doesn't work. (Of course I called behavior.apply() after I finished page render.)
The code below doesn't work either.
behavior.add({
"[widgetid='myButton']": {
onClick: buttonHandler
}
});
After some investigation, I found the reason the code above not work is because a button widget is composed by many s and an inner . And if I use the id specified by data-dojo-id, it will point to a instead of the that I hope the event bind with.
I found a solution which can walk out this situation,
behavior.add({
"[widgetid='myButton'] input": {
onclick: buttonHandler
}
}
but the css selector is too complex and it depends on what type the widget is.
Is there a good solution to apply dojo/behavior on widgets just like on dom nodes?
It looks like what you really what is to hook up an event on the widget object, but behavior is designed to access the DOM instead. So, I think you're stuck with your workaround.

Is there a way to trigger an event when inserting html?

It's for a backbone application,
I'm using Jquery html() function to insert my views templates into the layout everywhere, and I would like to be able to trigger an event each time the html() function of jQuery is called to check the html of the page.
Is there a way to do that ?
( Like App.on('html', blablabla...); )
Thank you !
As Marc B suggested DOM MutationEvents is available on some browsers (not many). By default jQuery does not fire any event when using html, but you can define your own behaviour for this, for example:
(function($) {
var html_ref = $.fn.html;
$.fn.extend({
html : function() {
$(document).trigger( 'html_change' );
return html_ref.apply(this, arguments);
}
});
})($);
It should work, didn't test it though. You can use the same with .text method. Now you can simply use:
$(document).bind( 'html_change', function() {
// Hurray! Html changed!
});
That's the idea, use it as you wish.
AFAIK, the jQuery html() method doesn't fire any subscribable events per se, but you could probably roll your own implementation of a simple Observer pattern. I use this across a large number of projects and it provides a great, clean, lightweight way to encapsulate arbitrary event handling across loosely-coupled modules.
However, this is presuming that you have programmatic control over every time the html() method is called - if not, then this would be more difficult, as there is no callback function to hook into.

Categories