Ticket #2530448 (closed defect)

Reporter


John McLaughlin
Opened: 06/19/11
Last modified: 08/18/11
Status: closed
Type: defect
Resolution: fixed

Owner


Luke Smith
Target Release: 3.4.0
Priority: P4 (low)
Summary: Document return false for event subscribers
Description:

Apparently if the return value is "false" from a handler that is defined before a "fireOnce" event is fired, subsequent handlers that are also defined before the "fire" are ignored. This doesn't seem
to be the case for handlers defined after the event is fired.

This is easy to work around, but tough to track down, especially since the behavior can be different depending on the timing of the event firing. I looked at the source code, and it appears that this
might be intentional behavior. Nevertheless it seems to be confusing, inconsistent, and undocumented.

Type: defect Observed in Version: 3.3.0
Component: Event Severity: S4 (low)
Assigned To: Luke Smith Target Release: 3.4.0
Location: API Documentation Priority: P4 (low)
Tags: fireOnce,custom,event Relates To:
Browsers: N/A
URL:
Test Information:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Custom Event Callback Return Value Example</title>

<link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/3.3.0/build/cssfonts/fonts-min.css" />
<script type="text/javascript" src="http://yui.yahooapis.com/3.3.0/build/yui/yui.js"></script>
</head>
<body class="yui3-skin-sam yui-skin-sam">
<div id="exampleContainer"></div>

<script type="text/javascript">

YUI({ filter: 'raw' }).use("base", "event", "widget", function(Y) {

var W = Y.Base.create('my-wiggie', Y.Widget, [], {
renderUI: function () {
var vp = this;
var vpcb = vp.get('contentBox');
vpcb.append('<div>Custom Event Test: See log for results.</div>');
},
bindUI: function () {
var w = this;

w.on('my-cevt', function (e) {
Y.log('First Pre Fire Callback');
return false;
});

w.on('my-cevt', function (e) {
// This won't execute because the previous callback returned false.
Y.log('Second Pre Fire Callback');
});

w.publish('my-cevt', {fireOnce: true}).fire();

w.on('my-cevt', function (e) {
Y.log('First Post Fire Callback');
return false;
});

w.on('my-cevt', function (e) {
Y.log('Second Post Fire Callback');
});
}
});

var myW = new W({
render: Y.one('#exampleContainer')
});
myW.render();

});

</script>
</body>
</html>

Change History

Luke Smith

YUI Contributor

Posted: 06/20/11
  • priority changed to P3 (normal)
  • status changed from new to infoneeded

fireOnce events immediately execute new subscription callbacks after they have been fired. Separately, returning false from an event subscriber (unfortunately) has been overloaded to be equivalent to e.preventDefault(); e.stopImmediatePropagation(). The latter call stops the processing of further subscribers. However, it doesn't stop further subscriptions from being made for a subsequent fire().


var handle = foo.on("notAFireOnce", function (e) {
e.stopImmediatePropagation();
});
foo.on("notAFireOnce", function (e) {
Y.log("this is not called the first time, but is after handle.detach() is called");
});

foo.fire("notAFireOnce"); // no log
foo.on("notAFireOnce", function (e) {
Y.log("subsequent subscriptions are A OK");
});

foo.fire("notAFireOnce"); // no log because the first sub calls stopImmediatePropagation

handle.detach();
foo.fire("notAFireOnce"); // calls both Y.log subscribers

The same is true for fireOnce events, but each call to on() or after() after the event is fired ignores previous subscriptions (they've already been notified) and is effectively a call to on()+fire().

So it sounds like what you're asking for is that if a fireOnce event is stopped with stopImmediatePropagation or return false, that post-fire() subscriptions don't execute.

Is this a fair summation?

John McLaughlin

YUI Contributor

Posted: 06/20/11
  • status changed from infoneeded to assigned

That sounds like it would be most consistent.

Fortunately it turns out that isn't as much of a problem as I had feared, since the preventDefault/stopPropagation behavior only occurs from an actual "false" return value, but no other falsey values including "undefined'. However it seems to me that the 'false' return value behavior (independent of the fireOnce issue) is worthy of a paragraph in the main Event documentation page, or at least the API docs. You can even label it as a "feature" ;)

Luke Smith

YUI Contributor

Posted: 06/27/11
  • location changed to API Documentation
  • milestone changed to 3.4.0
  • priority changed from P3 (normal) to P4 (low)
  • severity changed from S3 (normal) to S4 (low)
  • status changed from assigned to accepted
  • summary changed from Return value of handlers affects fireOnce custom event behavior to Document return false for event subscribers

I've created #2530477 to track the code related modification. I'll leave this ticket to track the documentation change. Docs I can probably do for 3.4.0, but not the code change.

Luke Smith

YUI Contributor

Posted: 06/27/11
  • estimated changed from 0 to .1
  • remaining changed from 0 to .1
  • sprint changed to sprint 3

Luke Smith

YUI Contributor

Posted: 07/27/11
  • sprint changed from sprint 3 to sprint 4

Luke Smith

YUI Contributor

Posted: 08/4/11
  • completed changed from 0 to 0.1
  • remaining changed from 0.1 to 0
  • status changed from accepted to checkedin

I've added verbiage in the Event user guide and EventTarget's on() method API docs for 3.4.0.

More EventTarget methods should have their docs updated to make sense in the context of Node, but it's a start.

Luke Smith

YUI Contributor

Posted: 08/4/11

Add API doc content for on + return falsennPartial solution, as the other methods neednto have language friendly for reading on thenNode API docs (inherited methods).nnFixes #2530448
View Commit: 389a9f8339d5c537895c22b7a6b55d96d9aa6639

George

YUI Developer

Posted: 08/18/11
  • resolution changed to fixed
  • status changed from checkedin to closed