Skip to content

Commit

Permalink
Add support for event.path. Declarative events should now be processe…
Browse files Browse the repository at this point in the history
…d correctly when event travels through different shadowRoots.

Add test for event path.
  • Loading branch information
sorvell committed May 20, 2013
1 parent bcdd3b4 commit 3772119
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 10 deletions.
44 changes: 34 additions & 10 deletions src/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,29 +157,53 @@
};


// TODO(sorvell): Note that findController will not return the expected
// controller when when the event target is a distributed node.
// This because we cannot traverse from a composed node to a node
// in shadowRoot.
// This will be addressed via an event path api
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=21066
function listenLocal(inEvent) {
if (inEvent.cancelBubble) {
return;
}
inEvent.on = prefix + inEvent.type;
log.events && console.group("[%s]: listenLocal [%s]", this.localName, inEvent.on);
var t = inEvent.target;
log.events && console.group("[%s]: listenLocal [%s]", this.localName,
inEvent.on);
var path = inEvent.path();
if (!path || window.ShadowDOMPolyfill) {
listenLocalPolyfill(inEvent);
} else {
var c = null;
Array.prototype.some.call(path, function(t) {
if (t === this) {
return true;
}
c = c === this ? c : findController(t);
if (c) {
if (handleEvent.call(c, t, inEvent)) {
return true;
}
}
}, this);
}
log.events && console.groupEnd();
}


// TODO(sorvell): remove when ShadowDOM polyfill supports event path.
// Note that findController will not return the expected
// controller when when the event target is a distributed node.
// This because we cannot traverse from a composed node to a node
// in shadowRoot.
// This will be addressed via an event path api
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=21066
function listenLocalPolyfill(inEvent) {
log.events && console.log('event.path() not supported for', inEvent.type);
var t = inEvent.target, c = null;
while (t && t != this) {
var c = findController(t);
c = c === this ? c : findController(t);
if (c) {
if (handleEvent.call(c, t, inEvent)) {
return;
}
}
t = t.parentNode;
}
log.events && console.groupEnd();
}

function listenHost(inEvent) {
Expand Down
133 changes: 133 additions & 0 deletions test/html/event-path-declarative.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html>
<head>
<script src="../../polymer.js"></script>
<script src="../../tools/test/htmltest.js"></script>
<script src="../../node_modules/chai/chai.js"></script>
</head>
<body>
<x-bar><div id="target">Test</div></x-bar>

<element name="x-zug" on-test-event="testEventHandler">
<template>
x-zug:
<div id="xZugDiv" on-test-event="divTestEventHandler">
<content id="xZugContent" on-test-event="contentTestEventHandler"></content>
</div>
</template>
<script>
Polymer.register(this, {
contentTestEventHandler: function(e, detail, sender) {
console.log('%s on %s in %s, (4)', e.type, sender.id, this.localName);
testEvent(sender);
},
divTestEventHandler: function(e, detail, sender) {
console.log('%s on %s in %s, (5)', e.type, sender.id, this.localName);
testEvent(sender);
},
testEventHandler: function(e, detail, sender) {
console.log('%s on %s host event (6)', e.type, this.localName);
testEvent(sender);
}
});
</script>
</element>


<element name="x-foo" on-test-event="testEventHandler">
<template>
<style>
@host {
display: block;
border: 1px solid green;
padding: 10px;
}
</style>
x-foo:
<div id="xFooDiv" on-test-event="divTestEventHandler">
<x-zug><content id="xFooContent" on-test-event="contentTestEventHandler"></content></x-zug>
</div>
</template>
<script>
Polymer.register(this, {
contentTestEventHandler: function(e, detail, sender) {
console.log('%s on %s in %s, (3)', e.type, sender.id, this.localName);
testEvent(sender);
},
divTestEventHandler: function(e, detail, sender) {
console.log('%s on %s in %s, (7)', e.type, sender.id, this.localName);
testEvent(sender);
},
testEventHandler: function(e, detail, sender) {
console.log('%s on %s host event (8)', e.type, this.localName);
testEvent(sender);
}
});
</script>
</element>


<element name="x-bar" on-test-event="testEventHandler">
<template>
<style>
@host {
display: block;
border: 1px solid red;
padding: 10px;
}

.clicky {
border: 1px solid black;
}

</style>
x-bar:
<x-foo>
<div class="clicky" id="xBarDiv" on-test-event="divTestEventHandler"><content id="xBarContent" on-test-event="contentTestEventHandler"></content></div>
</x-foo>
</template>
<script>
Polymer.register(this, {
contentTestEventHandler: function(e, detail, sender) {
window.eventPath = Array.prototype.slice.call(e.path() || [], 0);
eventPath.shift();
testEvent(sender);
console.log('%s on %s in %s, (1)', e.type, sender.id, this.localName);
},
divTestEventHandler: function(e, detail, sender) {
console.log('%s on %s in %s, (2)', e.type, sender.id, this.localName);
testEvent(sender);
},
testEventHandler: function(e, detail, sender) {
console.log('%s on %s host event (9)', e.type, this.localName);
testEvent(sender);
}
});
</script>
</element>
<script>
eventPath = [];
testEvent = function(node) {
chai.assert.equal(node, eventPath[0], 'Event fired in expected order');
eventPath.shift();
// remove shadowRoots since not part of test.
while (!eventPath[0].localName) {
eventPath.shift();
}
}

document.addEventListener('WebComponentsReady', function() {
var target = document.querySelector('#target');
target.dispatchEvent(new CustomEvent('test-event', {bubbles: true}));
done();
});

</script>


</body>
</html>

0 comments on commit 3772119

Please sign in to comment.