SlideShare a Scribd company logo
How
CUSTOM EVENTS
 will save the universe
Law of Demeter
“Each unit should have
only limited knowledge
  about other units.”
(we break this rule
   all the time)
the Law of Demeter is about removing
unnecessary coupling
custom events can help
  decouple your code
Broadcaster and receiver
   don’t have to know
  about one another…
… so there’s far less to mock
      in your unit tests
YOU DO HAVE
UNIT TESTS, RIGHT?
How do custom events work?
How Custom Events Will Save the Universe
$(document).observe('custom:event', function(event) {
  var customData = event.memo;
  // stuff
});
$('troz').fire('custom:event', { foo: "bar" });
How Custom Events Will Save the Universe
$(document).bind('customevent', function(event, customData) {
  // stuff
});
$('#troz').trigger('customevent', [{ foo: "bar" }]);
How Custom Events Will Save the Universe
$(document).addEvent('customevent', function(event, customData) {
  // stuff
});
$('troz').fireEvent('customevent', { foo: "bar" });
BUT WHY?
Why?




       Makes testing easier
        (maybe you’ll do it now)
Why?




       Rapid prototyping
Why?




       More versatile than callbacks
Why?




       Can be bubbled/canceled
Why?




       Can handle exceptions properly
                  (in theory)
(quoth Dean Edwards)
In Prototype,
exceptions raised in one handler
  won’t affect another handler
(is this a big deal? smart people disagree)
CASE
STUDIES
Case Studies




               #
                   1
Case Studies




               (script.aculo.us 2.0)
scripty2 uses custom events…




                …as a “metronome” for effects
window.setTimeout(function() {
  document.fire('effect:heartbeat');
}, 0);
document.observe('effect:heartbeat', advanceEffectByOneFrame);
Seems pointless…
 …until you need to debug
Step through an animation
                         frame by frame

document.observe('keydown', function(event) {
  if (event.keyCode === Event.KEY_RIGHT) {
    document.fire('effect:heartbeat');
  }
});
scripty2 uses custom events…




                         …to pass messages
                        between UI widgets
How Custom Events Will Save the Universe
How Custom Events Will Save the Universe
S2.UI.Menu
(used by other S2.UI components)
var menu = new S2.UI.Menu();
menu.addChoice("Foo");
menu.addChoice("Bar");
someElement.insert(menu);
menu.open();
S2.UI widgets act like elements when needed, so...




    menu.observe('ui:menu:selected', function(event) {
      console.log('user clicked on:', event.memo.element);
    });
Easy to use
in any context
Button with menu
ASIDE:
Custom events are cancelable
var event = $('troz').fire('custom:event');
if (!event.stopped) performSomeDefaultAction();
(prevent all menus from appearing)




    document.observe('ui:menu:before:open', function(event) {
      event.stop();
    });
scripty2 uses custom events…




                    …as hooks for debugging
“Why aren’t these
 effects queueing
  like I expect?”
document.observe('effect:dequeued', function(event) {
  var queue = event.memo;
  console.log("Effects in queue:", queue.size());
});
You get debugging
   FOR FREE
Case Studies




               #
                   2
Case Studies




               Mouse wheel
http://adomas.org/javascript-mouse-wheel/




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
}
Instead, do this:
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 = event.target.fire('mouse:wheel', { delta: delta });
    if (result.stopped) event.preventDefault();
}
See also:


hashchange
Case Studies




               #
                   3
Case Studies




               User idle state
http://perfectionkills.com/detect-idle-state-with-custom-events/




                             credit: kangax

document.observe('state:idle', function() {
  turnOffBackgroundAjaxRequests();
});

document.observe('state:active', function() {
  turnOnBackgroundAjaxRequests();
});
Case Studies




               #
                   4
Case Studies




               Keyboard events
(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);
})();
Then you’d be able to do
                  something like this:
document.observe('key:left', function() { moveSlide(-1); });
document.observe('key:right', function() { moveSlide( 1); });
Case Studies




               #
                   5
Data broadcasting
Server-sent events are awesome…
     …but not universally supported
for browsers that support server-sent events

var eventSource = $('event_source');
eventSource.observe('server-sent-event-name', function(event) {
  document.fire('data:received', event.data);
});
for browsers that don’t

new Ajax.Request('/legacy/polling', {
  onComplete: function(request) {
    document.fire('data:received', request.responseJSON);
  }
});
observer works with either approach

$(document).observe('data:received', function(event) {
  doStuffWithYourData(event.memo);
});
…and your unit tests can fire dummy data

function testThatSomethingHappened() {
  document.fire('data:received', FIXTURE_DATA);
  assertSomething();
}
FAQ
FAQ




       “What if my events
      aren’t DOM-related?”
(meh)
Use the DOM anyway, I say
FAQ




      “Isn’t this overkill?”
Yes, sometimes
FAQ




      “Aren’t events slow?”
NO
Events aren’t slow;
they’re synchronous
Events are only
as slow as the handlers
   attached to them
If performance is a concern, defer
window.setTimeout(function() {
  document.fire('costly:custom:event');
}, 0);
QUESTIONS?
    Andrew Dupont
http://andrewdupont.net

More Related Content

PDF
Khan Academy Computer Science
PDF
Geração Automática de Ontologias Probabilíticas a partir de um modelo UMP-ST
PDF
Learning new words
PDF
How to Argue about Code
PDF
How to Argue about JavaScript
PDF
Writing Maintainable JavaScript
PDF
Everything is Permitted: Extending Built-ins
PDF
Open Government: An Overview
Khan Academy Computer Science
Geração Automática de Ontologias Probabilíticas a partir de um modelo UMP-ST
Learning new words
How to Argue about Code
How to Argue about JavaScript
Writing Maintainable JavaScript
Everything is Permitted: Extending Built-ins
Open Government: An Overview

Recently uploaded (20)

PDF
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
PDF
Getting Started with Data Integration: FME Form 101
PPTX
TLE Review Electricity (Electricity).pptx
PDF
A novel scalable deep ensemble learning framework for big data classification...
PDF
Univ-Connecticut-ChatGPT-Presentaion.pdf
PPTX
OMC Textile Division Presentation 2021.pptx
PPTX
Tartificialntelligence_presentation.pptx
PDF
Zenith AI: Advanced Artificial Intelligence
PDF
August Patch Tuesday
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
A contest of sentiment analysis: k-nearest neighbor versus neural network
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
PPTX
cloud_computing_Infrastucture_as_cloud_p
PPTX
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
PDF
A comparative study of natural language inference in Swahili using monolingua...
PPTX
1. Introduction to Computer Programming.pptx
PPTX
The various Industrial Revolutions .pptx
PDF
From MVP to Full-Scale Product A Startup’s Software Journey.pdf
PDF
Developing a website for English-speaking practice to English as a foreign la...
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
Getting Started with Data Integration: FME Form 101
TLE Review Electricity (Electricity).pptx
A novel scalable deep ensemble learning framework for big data classification...
Univ-Connecticut-ChatGPT-Presentaion.pdf
OMC Textile Division Presentation 2021.pptx
Tartificialntelligence_presentation.pptx
Zenith AI: Advanced Artificial Intelligence
August Patch Tuesday
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
A contest of sentiment analysis: k-nearest neighbor versus neural network
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
cloud_computing_Infrastucture_as_cloud_p
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
A comparative study of natural language inference in Swahili using monolingua...
1. Introduction to Computer Programming.pptx
The various Industrial Revolutions .pptx
From MVP to Full-Scale Product A Startup’s Software Journey.pdf
Developing a website for English-speaking practice to English as a foreign la...

How Custom Events Will Save the Universe