Adesh M
Adesh M

Reputation: 444

Simple event system using JavaScript (ES5) - JS Custom Event

Instructions:

  1. make this code work without modifying snippet it in any way.
  2. Use only plain old JavaScript and no third-party libraries.
  3. Write new code that enables the code below to work properly.

Hint: Feel free to extend native objects... even though it's typically a bad practice.

// Start with an object, any object
var myObject = {};


// Register an event on your object using
// an `on` method
myObject.on('myEvent', function(data) {
    // Log the data passed to the callback
    console.log(data);
});

// Trigger the event using a `trigger` method.
// Include some data when you trigger the event.
myObject.trigger('myEvent', {
    company: 'ABC Corp',
    location: 'WTC Bangalore, IN',
    website: 'http://abc.co'
});
 
// Register a different event
myObject.on('yourEvent', function() {
    console.log('yourEvent fired');
});

// Trigger the new event
myObject.trigger('yourEvent');

// Trigger all existing events using a special
// "star" identifier.
myObject.trigger('*');

// Remove one event by name
myObject.off('myEvent');

// Since we've removed the event, this should
// do nothing
myObject.trigger('myEvent');

// Remove all existing events
myObject.off();

// Since we've removed all events, this should
// do nothing
myObject.trigger('*');

Everything else went well. I'm unable to get "arguments" while implementing myObject.trigger("*"); unable to read arguments object / parameters while implementing "*" and hence throw undefined.

My JSFiddle

Upvotes: 2

Views: 1519

Answers (2)

Ward D.S.
Ward D.S.

Reputation: 558

Disclaimer I obviously dont know what school you go to or anything, but please don't fool yourself trying to fool your teachers. With a few simple questions they'll know if you understand the material or not, and if you show up with a good answer but no knowledge to back it up, they will know what's up. I'm not accusing you of this, just a friendly word of advice of someone who has had good connections with his teachers after graduating last year ;)

So, how do we do this? Basically, you will have to add some functionality to the prototype of object, at least if you want this to affect all objects made afterwards. You can always create your own class and add the function to that prototype if you only want that class to have this functionality.

We need 3 functions added to the prototype, on, off and trigger of course. On top of that we add one extra property called events, initially an empty object. You can look at the raw code for all these in the jsfiddle, I will only go through the structure and logic of the code here.

events will hold all the handlers (functions) associated with each event. When adding an event for the first time, we add a eventName property to the events object, the value for this property is initially an empty array.

on will find (or create) the array linked to eventName in events, and push the function into the array (note we do not call the function at this time, we simply store the reference to the function in the array).

off will iterate the array of eventName, and if it finds the same function (note the ===), remove it from the array.

trigger will iterate the array of eventName and call each function. Note that the function is called with the this keyword in the function set to the object, and with the same parameters as the trigger function was called (except eventName, the first parameter, which is filtered out). Yes that means you can pass as many parameters as you want to trigger(), and they will all be passed to each handler.

I won't go into detail what things like splice, slice, ===, arguments and apply do exactly, I'm sure you can find more and better information about that elsewhere on the world wide interwebs.

There's a lot more you can do for this, like making the events object invisible through some nice uses of scoping, but that wasn't part of the question so I didn't bother with that.

If you have any more questions after looking through this, feel free to ask. I also didn't test it extensively so if you find any bugs, let me know.

EDIT: I didn't read through the comments at first, but I now also added support for the '*' wildcard. Basically the functions now check for the wildcard and will iterate all eventNames on the event object when removing or triggering. You can also remove all functions for an event by not giving a function or by giving the same wildcard, but with an eventName.

EDIT2: had some bugs running the teacher's code, realized I forgot to check for hasOwnProperty while iterating. Look that one up, it's very important when working with prototypes! I now put in the teacher's code in my jsfiddle, to show you that it works :)

jsfiddle with own code

jsfiddle with teacher code

EDIT3 - about the 'undefined' log.

The teacher's code calls .trigger 5 times, and you should see 4 console logs and as far as I can tell, they are all correct.Let me run through each trigger, and the subsequent console logs.

  1. You add a handler to myEvent, which logs the first parameter
  2. You trigger myEvent, with parameter => The parameter (the object), is logged.
  3. You add a handler to yourEvent, which logs a hardcoded string.
  4. You trigger yourEvent, no parameter => The hardcoded string is logged'
  5. You trigger * with no parameter, all handlers run => undefined is logged, since no parameters were given, data in myEvent's handler is undefined. The hardcoded string is also logged
  6. You remove the myEvent handler, trigger myEvent and confirm no functions are called
  7. You remove all event handlers, trigger * and confirm no functions are called from any events.

I honestly don't know what you expected to happen on step 5, since you give no parameter, the data is assigned undefined, that's intended behaviour.

If you want to merge the data given in step 2 so it remains on the object, then instruct so in your handler. (for example, iterate all properties of data and add them to this, then log this). Right now you simply pass it data, it gets logged, and then thrown away. You can also add a parameter in step 5, and then all handlers will receive it (including the yourEvent handlers, but that one doesn't assign nor use it).

Upvotes: 3

Paul Booblick
Paul Booblick

Reputation: 363

document.getElementById("myBtn").addEventListener("click", displayDate);

Upvotes: 0

Related Questions