1

I'd like to understand how the CustomEvent system works, in Javascript.

[EDIT2]

The dream solution is here : http://www.html5rocks.com/en/tutorials/es7/observe/

[/EDIT2]

[EDIT]

This piece of codes illustrates pretty well the type of DOM-aware system I'm looking for, thx to @Jared Farrish, There is also the deferred method. But I'm still thinking it is a kind of javascript limitation and that the langage deserves to implement a clever way to do. Ideally, children would not have to execute orders given by parent or by any other element. Instead, a child node should takes its own decisions, by knowing in real-time the interesting parts of DOM activity.

var body = document.body,
    btn = document.getElementById('fire'),
    warn;

    warn = document.createEvent('CustomEvent');
    warn.initEvent('warning', true, true);

body.addEventListener('warning', function() {
    body.style.backgroundColor = 'blue';
});

btn.addEventListener('warning', function() {
    this.style.backgroundColor = 'green';
});

btn.addEventListener('click', function init() {
    body.dispatchEvent(warn);
    btn.dispatchEvent(warn);
});

source : http://jsfiddle.net/p6myjLza/2/

[/EDIT]

Saying I create this very basic event :

var warning = new CustomEvent('warning', { 
    'detail': 'This is a warning!' 
});

Now the object warning contains useful data. It is stored in the browser memory. Let's trigger it.

document.dispatchEvent(warning);

By doing above statement, I think I say to document : "hey dude, fire this specific event plz". And then, the event is triggered. And how far as I understand, I assume it also means that (somehow) the DOM is aware that the event has been triggered.

Now I would like another element, saying body, to change is style.backgroundColor from transparent to red each time the event warning is triggered. In other word, I want body to listen to this specific event and react consequently.

document.getElementsByTagName('body')[0].addEventListener('warning',
function(e){
    this.style.backgroundColor = 'red';
}, false);

But this works not.

Actually, it works if I switch the position of dispatchEvent() and addEventListener()by initializing the second before the first. But it is not what I am expecting from Javascript. What I want to achieve is the ability to trigger an event somewhere, and ordering some element elsewhere to catch it and react each time this event is triggered.

Is it something achievable?

Note : I discovered promises today and thought they were what I'm looking for, but they're not as they just capable to "chain" things without being able to delay them.

Guillaume Fe
  • 339
  • 1
  • 15
  • 1
    This is how you would organize it in a simplified example: http://jsfiddle.net/p6myjLza/1 Note that the custom event is simply a vehicle for working the event through the DOM; it needs to be dispatched against the element, which is `document.body` in your example. Here's another (slightly more complete) example: http://stackoverflow.com/a/12341715/451969 – Jared Farrish Apr 06 '15 at 00:02
  • 1
    events are not remembered, so you have to add the listener before the event is raised... – dandavis Apr 06 '15 at 00:08
  • 1
    Also, I think your confusion comes from the fact that you're creating and dispatching the event immediately (during page load, I assume), then (later in page load) adding a listener, which didn't exist when you called the custom event. This is a bit like calling "Wolf!" then buying sheep. Switching them around "works" because you're adding the event listener then immediately calling an event against it, so the order just happens to work. See in my example how I use an event handler on the `button.click` event, which means the event is created/dispatched after both events listeners exist. – Jared Farrish Apr 06 '15 at 00:08
  • Ty for your answers, @Jared Farrish I'm stil confused. In your first example, the background property is set by the init function, not because of the event. I might be wrong, but I'm looking for a system that make the button intelligent enough to "sniff" CustomEvents, detect (mostly alone) that "warning" has been triggered and adapt itself (by changing bkg color in this example). Instead of only listening at DOM events, like : var body = document.body, btn = document.getElementById('fire'); btn.addEventListener('click', function init() { body.style.backgroundColor = 'blue'; }); – Guillaume Fe Apr 06 '15 at 00:25
  • 1
    Put the desired effect (background color change) in the element's `warning` event handler? http://jsfiddle.net/p6myjLza/2/ – Jared Farrish Apr 06 '15 at 00:28
  • in other word, I want the click on a A button able to be detected by a B element, with nothing other link that the event itself (I would like to not have to write into the function something like "when click on A, change B". I want something like : "B, when A is clicked, change yourself" – Guillaume Fe Apr 06 '15 at 00:30
  • 1
    I think what you want is a form of [event delegation](https://learn.jquery.com/events/event-delegation/). ([Also.](http://stackoverflow.com/a/1688293/451969)) – Jared Farrish Apr 06 '15 at 00:34
  • About event delegation, I definitely avoid jquery in my core mechanism, but this kinda ressource looks indeed very good http://lists.evolt.org/archive/Week-of-Mon-20090209/127339.html – Guillaume Fe Apr 06 '15 at 00:41
  • Here's a simple example of event delegation (no jQuery): http://jsfiddle.net/p6myjLza/5/ – Jared Farrish Apr 06 '15 at 00:48
  • Here's a more complete example: http://jsfiddle.net/p6myjLza/6/ And your request for a more "clever" method (ie, as it currently works is somehow limited) would result in a very slow and probably buggy architecture. There's a reason why it was constructed like it is. The "alternative" that some use is to attach an event handler to the `document` node itself, which means the `document` processes all events that bubble or propagate to it. Note, `document.body` event delegation in most cases should be avoided at all costs (due to inefficiency, look up `jQuery.live()` for more info). – Jared Farrish Apr 06 '15 at 01:04
  • This is an example of using `document` to listen to an event: http://jsfiddle.net/p6myjLza/7/ (Note how similar it is to the previous, `parent` example.) – Jared Farrish Apr 06 '15 at 01:08
  • Forget about it ;) Thx for all the examples, it helps a lot! – Guillaume Fe Apr 06 '15 at 01:15
  • 1
    People new to Javascript always complain about how it's different; learn it first, use it, and when you've mastered it, then complain about it. It's much more powerful than it looks at first. (And I think what you're reaching for are [observables/binding](http://knockoutjs.com/documentation/observables.html), which are not low-level in Javascript (yet).) – Jared Farrish Apr 06 '15 at 01:17
  • 1
    And of course [`Object.observe()`](http://www.html5rocks.com/en/tutorials/es7/observe/). – Jared Farrish Apr 06 '15 at 01:23
  • Yes!!! that is exactly what I think we need to develop intelligent UI! u_u – Guillaume Fe Apr 06 '15 at 01:44

1 Answers1

1

You've almost got it! What happens, however, is that you are triggering the event on the document level and the body tag, where the event handler is, is lower - events bubble up when triggered.

If you simply dispatch the event from the body, you'd see it triggers the handler

document.getElementsByTagName('body')[0].dispatchEvent(warning);
VLAZ
  • 18,437
  • 8
  • 35
  • 54