Skip to content

Commit

Permalink
Use documentElement when matching delegated event targets
Browse files Browse the repository at this point in the history
The document object does not implement `Element.matches()` which is used
to tell when a selector matches an event delegated to a parent element;
using `document.documentElement` fixes the issue.

Closes #41
  • Loading branch information
m-mujica committed Feb 26, 2018
1 parent 6df719a commit 3c2f245
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 5 deletions.
14 changes: 12 additions & 2 deletions can-dom-events-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ unit.test('domEvents.addDelegateListener works', function (assert) {
var grandparent = document.createElement('div');
var parent = document.createElement('div');
var child = document.createElement('input');

grandparent.appendChild(parent);
parent.appendChild(child);

Expand All @@ -88,7 +88,7 @@ unit.test('domEvents.removeDelegateListener works', function (assert) {
var grandparent = document.createElement('div');
var parent = document.createElement('div');
var child = document.createElement('input');

grandparent.appendChild(parent);
parent.appendChild(child);

Expand Down Expand Up @@ -150,6 +150,16 @@ unit.test("delegate events: blur should work using capture phase", function (ass
domEvents.dispatch(child, "blur", false);
});

unit.test('domEvents.addDelegateListener handles document correctly', function (assert) {
var html = document.querySelector('html');
var handler = function handler() {};

domEvents.addDelegateListener(html, 'click', 'input', handler);
domEvents.dispatch(html, 'click');
domEvents.removeDelegateListener(html, 'click', 'input', handler);
assert.ok(true, 'works');
});

require('./helpers/make-event-registry-test');
require('./helpers/add-event-compat-test');
require('./helpers/add-event-jquery-test');
Expand Down
11 changes: 8 additions & 3 deletions helpers/-make-delegate-event-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,23 @@ function makeDelegator (domEvents) {
this.events = {}; // {[eventType: string]: Array<(event) -> void>}
this.delegated = {}; // {[eventType: string]: (event) -> void}
};

canReflect.assignSymbols( Delegator.prototype, {
"can.setKeyValue": function(eventType, handlersBySelector){
var handler = this.delegated[eventType] = function(ev){
canReflect.each(handlersBySelector, function(handlers, selector){
var cur = ev.target;
do {
if (cur.matches(selector)) {
// document does not implement `.matches` but documentElement does
var el = cur === document ? document.documentElement : cur;
if (el.matches(selector)) {
handlers.forEach(function(handler){
handler.call(cur, ev);
handler.call(el, ev);
});
}
// since `el` points to `documentElement` when `cur` === document,
// we need to continue using `cur` as the loop pointer, otherwhise
// it will never end as documentElement.parentNode === document
cur = cur.parentNode;
} while (cur && cur !== ev.currentTarget);
});
Expand Down

0 comments on commit 3c2f245

Please sign in to comment.