Event delegation in 1.1.9's Zii scripts

Trying to deal with an issue this morning I ended up reading the new jquery.yiigridview.js.

I found that the problem may be in part related to the way 1.1.9 delegates events to document like this, for example:


line 87:  $(document).on('change', inputSelector, function () { ... });

Delegating to an element all the way up the DOM tree has consequences:

  • Every click anywhere on the page triggers jQuery event handling. The target event handler doesn’t trigger unless the click is on a selected target but jQuery must check on every click anywhere on the page if the click was on a matching target or not. And this work increases for every such handler delegated to document (CGridView attaches as many as four, I think).

  • Attaching the delegated handler to the root of the DOM tree means you can’t attach a user event handler to an ancestor of a selected target element, catch the event as it bubbles up and stop propagation.

As an example of the latter, say you put a FORM around a CGV. If the CGV has filters then pressing enter/return in one of those INPUTs will submit the enclosing FORM. Since the change event is delegated to an ancestor of the FORM, you can’t catch the event and prevent bubbling before it reaches the FORM.

I would have thought that as a general design principle one would delegate to an element as close to the targets as possible. The above example could be delegated instead to the THEAD enclosing the filter INPUTs. That would mitigate both issues.

Yes, you are right on that… the old live() method was working exactly like that…

I put this intentionaly so to not break any user code… as by delegating to a grid container would possibly break someone application… as there are many different usage of the grid from normal grid usage, to grid rendered on ajax calls to a full one page ajax application.

I understand the need to avoid introducing breaking changes.

But that style of delegation bit me again yesterday. I needed a selectionChanged handler on a class of CGVs. Some of its instances have, in one column, links that open a JUI dialog. The link click handler cannot, afaict, prevent the click event from reaching the selectionChanged handler.

To sort this out I put, in the selectionChanged handler, a test to see if the event target was one of those links. That’s nasty. It creates a tight coupling between functions in different parts of the project that should be independent. And because Zii doesn’t pass the event to the selectionChanged changed handler, I had to use globals to do the check.

Would it be possible to introduce an option allowing the user to configure the delegation of CGV’s event handlers? The default would retain current behavior.I know this would add complexity into the framework but not doing so adds complexity to our apps.

I often hang out on #yii on freenode and related questions come up repeatedly. Evidently many users find it hard to figure out what’s going on and what workarounds might exist.

did you try with the event.stoppropagation() or event.stopImmediatePropagation() on the link handler?