Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit c8bfbfc

Browse files
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. Closes #5178
1 parent 3ba8bb7 commit c8bfbfc

File tree

1 file changed

+54
-1
lines changed

1 file changed

+54
-1
lines changed

src/ngScenario/browserTrigger.js

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,12 @@
119119
return originalPreventDefault.apply(evnt, arguments);
120120
};
121121

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

125130
delete angular['ff-684208-preventDefault'];
@@ -157,4 +162,52 @@
157162

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

0 commit comments

Comments
 (0)