From 504e2c4e914344d681849485231b22972c114c50 Mon Sep 17 00:00:00 2001 From: Curtis Cummings Date: Mon, 27 Mar 2017 23:27:06 -0400 Subject: [PATCH 1/3] limit disabled dispatching fix to inserted and removed events --- dom/dispatch/dispatch-test.js | 13 ------------- dom/events/events.js | 8 +++++++- dom/events/inserted/inserted-test.js | 1 + 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/dom/dispatch/dispatch-test.js b/dom/dispatch/dispatch-test.js index a90ea980..72d82c24 100644 --- a/dom/dispatch/dispatch-test.js +++ b/dom/dispatch/dispatch-test.js @@ -17,19 +17,6 @@ test("basic synthetic events", function () { }); -test("synthetic events on disabled element", function () { - expect(1); - var input = document.createElement("input"); - input.disabled = true; - - domEvents.addEventListener.call(input, "foo", function(){ - ok(true, "called back"); - }); - - document.getElementById("qunit-fixture").appendChild(input); - domDispatch.call(input, "foo", [], false); -}); - test("more complex synthetic events", function () { var div = document.createElement("div"); var arr = []; diff --git a/dom/events/events.js b/dom/events/events.js index a8046238..bae42f54 100644 --- a/dom/events/events.js +++ b/dom/events/events.js @@ -1,6 +1,12 @@ var assign = require("../../js/assign/assign"); var _document = require("../document/document"); +var isPlainObject = require("../../js/is-plain-object/is-plain-object"); +function isDispatchingOnDisabled(element, ev) { + var isInsertedOrRemoved = isPlainObject(ev) ? (ev.type === 'inserted' || ev.type === 'removed') : (ev === 'inserted' || ev === 'removed'); + var isDisabled = !!element.disabled; + return isInsertedOrRemoved && isDisabled; +} /** * @module {{}} can-util/dom/events/events events * @parent can-util/dom @@ -23,7 +29,7 @@ module.exports = { dispatch: function(event, args, bubbles){ var doc = _document(); var ret; - var dispatchingOnDisabled = this.disabled; + var dispatchingOnDisabled = isDispatchingOnDisabled(this, event); var ev = doc.createEvent('HTMLEvents'); var isString = typeof event === "string"; diff --git a/dom/events/inserted/inserted-test.js b/dom/events/inserted/inserted-test.js index cf113e9b..0af57df3 100644 --- a/dom/events/inserted/inserted-test.js +++ b/dom/events/inserted/inserted-test.js @@ -39,6 +39,7 @@ function runTest(name, MUT_OBS) { }); // With no mutation observer this test will not pass without a setTimeout + // There is a setTimeout, 0 in the non-mutation observer code path setTimeout(function(){ domMutate.appendChild.call(document.getElementById("qunit-fixture"), input); }, 20); From cd6d40a1aa7228be3acb7dbf5960b51a4d926074 Mon Sep 17 00:00:00 2001 From: Curtis Cummings Date: Tue, 28 Mar 2017 10:59:42 -0400 Subject: [PATCH 2/3] Adding feature detection --- dom/events/events.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/dom/events/events.js b/dom/events/events.js index bae42f54..7ea518c2 100644 --- a/dom/events/events.js +++ b/dom/events/events.js @@ -1,6 +1,7 @@ var assign = require("../../js/assign/assign"); var _document = require("../document/document"); var isPlainObject = require("../../js/is-plain-object/is-plain-object"); +var fixSyntheticEventsOnDisabled = false; function isDispatchingOnDisabled(element, ev) { var isInsertedOrRemoved = isPlainObject(ev) ? (ev.type === 'inserted' || ev.type === 'removed') : (ev === 'inserted' || ev === 'removed'); @@ -29,7 +30,7 @@ module.exports = { dispatch: function(event, args, bubbles){ var doc = _document(); var ret; - var dispatchingOnDisabled = isDispatchingOnDisabled(this, event); + var dispatchingOnDisabled = fixSyntheticEventsOnDisabled && isDispatchingOnDisabled(this, event); var ev = doc.createEvent('HTMLEvents'); var isString = typeof event === "string"; @@ -41,9 +42,6 @@ module.exports = { assign(ev, event); } ev.args = args; - // In FireFox, dispatching an event on a disabled element throws an error. - // So ensure the mutatedNode is not disabled. - // https://bugzilla.mozilla.org/show_bug.cgi?id=329509 if(dispatchingOnDisabled) { this.disabled = false; } @@ -54,3 +52,16 @@ module.exports = { return ret; } }; + +// In FireFox, dispatching a synthetic event on a disabled element throws an error. +// This determines if we have to work around that when dispatching events. +// https://bugzilla.mozilla.org/show_bug.cgi?id=329509 +(function() { + var input = document.createElement("input"); + input.disabled = true; + try { + module.exports.dispatch.call(input, 'foo', [], false); + } catch(e) { + fixSyntheticEventsOnDisabled = true; + } +})(); From b061ba203ac0bda9fbdfdd56d342510c24ba5c7c Mon Sep 17 00:00:00 2001 From: Curtis Cummings Date: Tue, 28 Mar 2017 11:40:19 -0400 Subject: [PATCH 3/3] Update feature detection to account for browsers that do not fire synthetic events on disabled elements --- dom/events/events.js | 8 ++++++++ dom/events/inserted/inserted-test.js | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dom/events/events.js b/dom/events/events.js index 7ea518c2..7e3c9561 100644 --- a/dom/events/events.js +++ b/dom/events/events.js @@ -54,14 +54,22 @@ module.exports = { }; // In FireFox, dispatching a synthetic event on a disabled element throws an error. +// Other browsers, like IE 10 do not dispatch synthetic events on disabled elements at all. // This determines if we have to work around that when dispatching events. // https://bugzilla.mozilla.org/show_bug.cgi?id=329509 (function() { var input = document.createElement("input"); input.disabled = true; + var timer = setTimeout(function() { + fixSyntheticEventsOnDisabled = true; + }, 50); + module.exports.addEventListener.call(input, 'foo', function(){ + clearTimeout(timer); + }); try { module.exports.dispatch.call(input, 'foo', [], false); } catch(e) { + clearTimeout(timer); fixSyntheticEventsOnDisabled = true; } })(); diff --git a/dom/events/inserted/inserted-test.js b/dom/events/inserted/inserted-test.js index 0af57df3..f675a427 100644 --- a/dom/events/inserted/inserted-test.js +++ b/dom/events/inserted/inserted-test.js @@ -42,7 +42,7 @@ function runTest(name, MUT_OBS) { // There is a setTimeout, 0 in the non-mutation observer code path setTimeout(function(){ domMutate.appendChild.call(document.getElementById("qunit-fixture"), input); - }, 20); + }, 50); }); asyncTest("parent then child inserted - appendChild", function () { expect(1);