diff --git a/lib/legacy/legacy-element-mixin.html b/lib/legacy/legacy-element-mixin.html
index 1a671a7274..3ce281c363 100644
--- a/lib/legacy/legacy-element-mixin.html
+++ b/lib/legacy/legacy-element-mixin.html
@@ -81,6 +81,11 @@
/** @type {Object} */
this._debouncers;
this.created();
+ // Ensure listeners are applied immediately so that they are
+ // added before declarative event listeners. This allows an element to
+ // decorate itself via an event prior to any declarative listeners
+ // seeing the event. Note, this ensures compatibility with 1.x ordering.
+ this._applyListeners();
}
/**
@@ -180,7 +185,6 @@
*/
ready() {
this._ensureAttributes();
- this._applyListeners();
super.ready();
}
diff --git a/lib/utils/gestures.html b/lib/utils/gestures.html
index 8bdff53952..dacc404a63 100644
--- a/lib/utils/gestures.html
+++ b/lib/utils/gestures.html
@@ -579,7 +579,13 @@
*/
setTouchAction: function(node, value) {
if (HAS_NATIVE_TA) {
- node.style.touchAction = value;
+ // NOTE: add touchAction async so that events can be added in
+ // custom element constructors. Otherwise we run afoul of custom
+ // elements restriction against settings attributes (style) in the
+ // constructor.
+ Polymer.Async.microTask.run(() => {
+ node.style.touchAction = value;
+ });
}
node[TOUCH_ACTION] = value;
},
diff --git a/test/unit/events-elements.html b/test/unit/events-elements.html
index c5209f35e2..6df0e550c1 100644
--- a/test/unit/events-elements.html
+++ b/test/unit/events-elements.html
@@ -17,6 +17,8 @@
this._removed = [];
},
handle: function(e) {
+ const order = e._handleOrder = e._handleOrder || [];
+ order.push(this.localName);
this._handled[e.currentTarget.localName] = e.type;
},
unlisten: function(node, eventName, handler) {
@@ -51,6 +53,18 @@
+
+
+
+
+
+
+
diff --git a/test/unit/events.html b/test/unit/events.html
index c6d9c81cfb..7b896ca9c3 100644
--- a/test/unit/events.html
+++ b/test/unit/events.html
@@ -78,6 +78,23 @@
});
+ suite('listeners + on-*', function() {
+ suiteSetup(function() {
+ el = document.createElement('x-order');
+ document.body.appendChild(el);
+ });
+
+ suiteTeardown(function() {
+ document.body.removeChild(el);
+ });
+
+ test('listeners handled before on-* events', function() {
+ const e = el.$.inner.fire('foo', {});
+ assert.deepEqual(e._handleOrder, ['x-listeners', 'x-order']);
+ });
+
+ });
+
suite('dynamic', function() {
var options;