Skip to content

Commit d70e0d4

Browse files
author
Gonzalo Ruiz de Villa
committed
test(browserTrigger): allow event bubbling
In some browsers, events don't bubble when they are dispatched on node inside a detached tree. When this is the case, the bubbling is made manually. This may be convenient when unit testing directives, for example.
1 parent 2f0d4fb commit d70e0d4

File tree

1 file changed

+54
-1
lines changed

1 file changed

+54
-1
lines changed

Diff for: src/ngScenario/browserTrigger.js

+54-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,12 @@
118118
return originalPreventDefault.apply(evnt, arguments);
119119
};
120120

121-
element.dispatchEvent(evnt);
121+
if (!eventData.bubbles || supportsEventBubblingInDetachedTree() || isAttachedToDocument(element)) {
122+
element.dispatchEvent(evnt);
123+
} else {
124+
triggerForPath(element, evnt);
125+
}
126+
122127
finalProcessDefault = !(angular['ff-684208-preventDefault'] || !fakeProcessDefault);
123128

124129
delete angular['ff-684208-preventDefault'];
@@ -156,4 +161,52 @@
156161

157162
return evnt;
158163
}
164+
165+
function supportsEventBubblingInDetachedTree() {
166+
if ('_cached' in supportsEventBubblingInDetachedTree) {
167+
return supportsEventBubblingInDetachedTree._cached;
168+
}
169+
supportsEventBubblingInDetachedTree._cached = false;
170+
var doc = window.document;
171+
if (doc) {
172+
var parent = doc.createElement('div'),
173+
child = parent.cloneNode();
174+
parent.appendChild(child);
175+
parent.addEventListener('e', function() {
176+
supportsEventBubblingInDetachedTree._cached = true;
177+
});
178+
var evnt = document.createEvent('Events');
179+
evnt.initEvent('e', true, true);
180+
child.dispatchEvent(evnt);
181+
}
182+
return supportsEventBubblingInDetachedTree._cached;
183+
}
184+
185+
function triggerForPath(element, evnt) {
186+
var stop = false;
187+
188+
var _stopPropagation = evnt.stopPropagation;
189+
evnt.stopPropagation = function() {
190+
stop = true;
191+
_stopPropagation.apply(event, arguments);
192+
};
193+
patchEventTargetForBubbling(evnt, element);
194+
do {
195+
element.dispatchEvent(evnt);
196+
} while (!stop && (element = element.parentNode));
197+
}
198+
199+
function patchEventTargetForBubbling(event, target) {
200+
event._target = target;
201+
Object.defineProperty(event, "target", {get: function() { return this._target;}});
202+
}
203+
204+
function isAttachedToDocument(element) {
205+
while (element = element.parentNode) {
206+
if (element === window) {
207+
return true;
208+
}
209+
}
210+
return false;
211+
}
159212
}());

0 commit comments

Comments
 (0)