diff --git a/src/wrappers/events.js b/src/wrappers/events.js
index c162aba..ea967af 100644
--- a/src/wrappers/events.js
+++ b/src/wrappers/events.js
@@ -656,10 +656,62 @@
}
},
dispatchEvent: function(event) {
- dispatchEvent(event, this);
+ // We want to use the native dispatchEvent because it triggers the default
+ // actions (like checking a checkbox). However, if there are no listeners
+ // in the composed tree then there are no events that will trigger and
+ // listeners in the non composed tree that are part of the event path are
+ // not notified.
+ //
+ // If we find out that there are no listeners in the composed tree we add
+ // a temporary listener to the target which makes us get called back even
+ // in that case.
+
+ var nativeEvent = unwrap(event);
+ var eventType = nativeEvent.type;
+
+ // Allow dispatching the same event again. This is safe because if user
+ // code calls this during an existing dispatch of the same event the
+ // native dispatchEvent throws (that is required by the spec).
+ handledEventsTable.set(nativeEvent, false);
+
+ // Force rendering since we prefer native dispatch and that works on the
+ // composed tree.
+ scope.renderAllPending();
+
+ var tempListener;
+ if (!hasListenerInAncestors(this, eventType)) {
+ tempListener = function() {};
+ this.addEventListener(eventType, tempListener, true);
+ }
+
+ try {
+ return unwrap(this).dispatchEvent_(nativeEvent);
+ } finally {
+ if (tempListener)
+ this.removeEventListener(eventType, tempListener, true);
+ }
}
};
+ function hasListener(node, type) {
+ var listeners = listenersTable.get(node);
+ if (listeners) {
+ for (var i = 0; i < listeners.length; i++) {
+ if (!listeners[i].removed && listeners[i].type === type)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ function hasListenerInAncestors(target, type) {
+ for (var node = unwrap(target); node; node = node.parentNode) {
+ if (hasListener(wrap(node), type))
+ return true;
+ }
+ return false;
+ }
+
if (OriginalEventTarget)
registerWrapper(OriginalEventTarget, EventTarget);
diff --git a/test/js/events.js b/test/js/events.js
index 966eee5..01e1e15 100644
--- a/test/js/events.js
+++ b/test/js/events.js
@@ -1361,4 +1361,28 @@ test('retarget order (multiple shadow roots)', function() {
assert.equal(data, 'b');
});
+ test('dispatch should trigger default actions', function() {
+ var div = document.createElement('div');
+ div.innerHTML = '';
+ var checkbox = div.firstChild;
+ assert.isFalse(checkbox.checked);
+ checkbox.dispatchEvent(new MouseEvent('click'));
+ assert.isTrue(checkbox.checked);
+ });
+
+ test('dispatch should trigger default actions 2', function() {
+ var div = document.createElement('div');
+ div.innerHTML = '';
+ var checkbox = div.firstChild;
+ var sr = div.createShadowRoot();
+
+ assert.isFalse(checkbox.checked);
+ checkbox.dispatchEvent(new MouseEvent('click'));
+ assert.isTrue(checkbox.checked);
+
+ div.offsetWidth;
+ checkbox.dispatchEvent(new MouseEvent('click'));
+ assert.isFalse(checkbox.checked);
+ });
+
});