Your SlideShare is downloading. ×
How Custom Events Will Save the Universe
Upcoming SlideShare
Loading in...5

Thanks for flagging this SlideShare!

Oops! An error has occurred.


Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

How Custom Events Will Save the Universe


Published on

Delivered at TXJS ( on June 5, 2010. …

Delivered at TXJS ( on June 5, 2010.

All the major frameworks support custom events. All framework authors love custom events and want you to use them. But few people actually do.

Custom events aren’t a gimmick. The ability to fire your own events — just like the browser fires click, mousemove, focus, and all the rest — can solve many of the problems large JS projects face.

We’ll look at a handful of recipes for integrating custom events into your own code. You’ll learn how to fire custom events in each of the major JavaScript frameworks, and explore the advantages that custom events have over a standard callback pattern.

Published in: Technology, Business

  • What I didnt understand from your slideshow is how custom-events make debugging easier. From my humble experience, stepping through a debugger with code that contains one or more / observe can be very cumbersome because it beomes harder to follow the flow of my code execution.
    People tend to abuse custom events for ’coupling’ object. In my opinion custom events tend to introduce bad design.. not because custom events are poorly designed but they are overused and applied in situations they shouldnt be. The reason for this probably being that they are so convenient to use. As for the project I am currently working on its littered with custom events shooting back and forward between modules and objects. It’s a nightmare to debug.. and the same can be true for unit testing when applied in a unresponsible fashion.. which often tends to be the case. Not to mention what custom events do to the readibility of your code..
    As far as document acting as an event bus, it would be more useful if you could actually see what events are send through it.. as far as I know you completely rely on good documentation.
    So overall, i very much doubt that custom events will save the universe. Maybe this was true if all developers had great programming and design skill like yourself ;-)
    Are you sure you want to  Yes  No
    Your message goes here
  • Andreas: I addressed this in greater detail in the talk. In Prototype, 'document' acts as the 'event bus' for all events, whether DOM-related or not. This is an opinionated choice, but one that (in my opinion) pays dividends in simplicity. One is free to write a separate event bus for non-DOM events; nearly all of the material covered in the slides will still be applicable.
    Are you sure you want to  Yes  No
    Your message goes here
  • I think this is a needless coupling of view and presentation layer, that makes it hard to reuse your code in another situation, cause you have to pay attention about the DOM all the time.
    In mootools (not sure about other frameworks) every 'Class' object that implements Events can listen events or fire events to another 'Class' object . None of them needs to know parts of the DOM that has nothing to with them. Every object just need to know the one DOM object its related to (a button, a select ...) and the eventBus object. So when you use the widget in another situation or something in the html page has changed there is only one 'Class' to change and not every part that use this dom object as an event observer.
    There is a nice talk by Nicholas Zakas ( and a talk at googles io conference ( about this topic. Also the book 'Pro JavaScript Design Patterns' ( described how to build the observer pattern by yourself.
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

No notes for slide


  • 1. How CUSTOM EVENTS will save the universe
  • 2. Law of Demeter
  • 3. “Each unit should have only limited knowledge about other units.”
  • 4. (we break this rule all the time)
  • 5. the Law of Demeter is about removing unnecessary coupling
  • 6. custom events can help decouple your code
  • 7. Broadcaster and receiver don’t have to know about one another…
  • 8. … so there’s far less to mock in your unit tests
  • 10. How do custom events work?
  • 11. $(document).observe('custom:event', function(event) { var customData = event.memo; // stuff }); $('troz').fire('custom:event', { foo: "bar" });
  • 12. $(document).bind('customevent', function(event, customData) { // stuff }); $('#troz').trigger('customevent', [{ foo: "bar" }]);
  • 13. $(document).addEvent('customevent', function(event, customData) { // stuff }); $('troz').fireEvent('customevent', { foo: "bar" });
  • 14. BUT WHY?
  • 15. Why? Makes testing easier (maybe you’ll do it now)
  • 16. Why? Rapid prototyping
  • 17. Why? More versatile than callbacks
  • 18. Why? Can be bubbled/canceled
  • 19. Why? Can handle exceptions properly (in theory)
  • 20. (quoth Dean Edwards)
  • 21. In Prototype, exceptions raised in one handler won’t affect another handler
  • 22. (is this a big deal? smart people disagree)
  • 24. Case Studies # 1
  • 25. Case Studies ( 2.0)
  • 26. scripty2 uses custom events… …as a “metronome” for effects
  • 27. window.setTimeout(function() {'effect:heartbeat'); }, 0);
  • 28. document.observe('effect:heartbeat', advanceEffectByOneFrame);
  • 29. Seems pointless… …until you need to debug
  • 30. Step through an animation frame by frame document.observe('keydown', function(event) { if (event.keyCode === Event.KEY_RIGHT) {'effect:heartbeat'); } });
  • 31. scripty2 uses custom events… …to pass messages between UI widgets
  • 32. S2.UI.Menu (used by other S2.UI components)
  • 33. var menu = new S2.UI.Menu(); menu.addChoice("Foo"); menu.addChoice("Bar"); someElement.insert(menu);;
  • 34. S2.UI widgets act like elements when needed, so... menu.observe('ui:menu:selected', function(event) { console.log('user clicked on:', event.memo.element); });
  • 35. Easy to use in any context
  • 36. Button with menu
  • 37. ASIDE: Custom events are cancelable
  • 38. var event = $('troz').fire('custom:event'); if (!event.stopped) performSomeDefaultAction();
  • 39. (prevent all menus from appearing) document.observe('ui:menu:before:open', function(event) { event.stop(); });
  • 40. scripty2 uses custom events… …as hooks for debugging
  • 41. “Why aren’t these effects queueing like I expect?”
  • 42. document.observe('effect:dequeued', function(event) { var queue = event.memo; console.log("Effects in queue:", queue.size()); });
  • 43. You get debugging FOR FREE
  • 44. Case Studies # 2
  • 45. Case Studies Mouse wheel
  • 46. window.addEventListener('DOMMouseScroll', handler); window.onmousewheel = handler; function handler(event) { var delta; if (event.wheelDelta) { delta = event.wheelDelta / 120; if (window.opera) delta = -delta; // (not a joke) } else if (event.detail) { delta = -event.detail / 3; } // Do stuff with your stupid delta }
  • 47. Instead, do this:
  • 48. window.addEventListener('DOMMouseScroll', handler); window.onmousewheel = handler; function handler(event) { var delta; if (event.wheelDelta) { delta = event.wheelDelta / 120; if (window.opera) delta = -delta; // (not a joke) } else if (event.detail) { delta = -event.detail / 3; } // Fire a custom event with the normalized delta. var result ='mouse:wheel', { delta: delta }); if (result.stopped) event.preventDefault(); }
  • 49. See also: hashchange
  • 50. Case Studies # 3
  • 51. Case Studies User idle state
  • 52. credit: kangax document.observe('state:idle', function() { turnOffBackgroundAjaxRequests(); }); document.observe('state:active', function() { turnOnBackgroundAjaxRequests(); });
  • 53. Case Studies # 4
  • 54. Case Studies Keyboard events
  • 55. (function() { var KEYS = {}; KEYS[Event.KEY_ESC] = "esc"; KEYS[Event.KEY_UP] = "up"; KEYS[Event.KEY_DOWN] = "down"; KEYS[Event.KEY_LEFT] = "left"; KEYS[Event.KEY_RIGHT] = "right"; // ... and so on function handler(event) { if (event.keyCode && KEYS[event.keyCode]) { event.element().fire("key:" + KEYS[event.keyCode], event); } } document.observe("keydown", handler); })();
  • 56. Then you’d be able to do something like this: document.observe('key:left', function() { moveSlide(-1); }); document.observe('key:right', function() { moveSlide( 1); });
  • 57. Case Studies # 5
  • 58. Data broadcasting
  • 59. Server-sent events are awesome… …but not universally supported
  • 60. for browsers that support server-sent events var eventSource = $('event_source'); eventSource.observe('server-sent-event-name', function(event) {'data:received',; });
  • 61. for browsers that don’t new Ajax.Request('/legacy/polling', { onComplete: function(request) {'data:received', request.responseJSON); } });
  • 62. observer works with either approach $(document).observe('data:received', function(event) { doStuffWithYourData(event.memo); });
  • 63. …and your unit tests can fire dummy data function testThatSomethingHappened() {'data:received', FIXTURE_DATA); assertSomething(); }
  • 64. FAQ
  • 65. FAQ “What if my events aren’t DOM-related?”
  • 66. (meh)
  • 67. Use the DOM anyway, I say
  • 68. FAQ “Isn’t this overkill?”
  • 69. Yes, sometimes
  • 70. FAQ “Aren’t events slow?”
  • 71. NO
  • 72. Events aren’t slow; they’re synchronous
  • 73. Events are only as slow as the handlers attached to them
  • 74. If performance is a concern, defer window.setTimeout(function() {'costly:custom:event'); }, 0);
  • 75. QUESTIONS? Andrew Dupont