/// <summary> /// Checks if the component has the listener or any of component's ancestors /// have listeners for the supplied event type /// </summary> /// <param name="eventType"></param> /// <param name="target"></param> /// <returns></returns> internal static bool HasBubblingEventListener(string eventType, DisplayListMember target) { /** * 0) Get parent chain * */ List <DisplayListMember> parentChain = ComponentUtil.GetParentChain(target, true); parentChain.Add(target); // add myself /** * 1) Look for at least one subscribed component * */ foreach (DisplayListMember component in parentChain) { if (component.HasEventListener(eventType)) { return(true); } } return(false); // no subscribed components }
/// <summary> /// Bubbles event through 3 phases /// <see cref="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture"/> /// </summary> /// <param name="e"></param> internal static void BubbleEvent(Event e) { if (e.Canceled) { return; } /** * 0) Get parent chain * */ List <DisplayListMember> parentChain = ComponentUtil.GetParentChain((DisplayListMember)e.Target, true); // true for reversing /** * 1) Capture phase * */ e.Phase = EventPhase.Capture; foreach (DisplayListMember d in parentChain) { // set current target e.CurrentTarget = d; // execute listeners on current target // any of the listeners my cancel the event, that's handled by ExecuteListeners method internally d.ExecuteListeners(e); // all the listeners (or part of the listeners, in the case of cancelation) // on current target have been executed. // if event canceled or propagation stopped, go no further if (!e.Bubbles || e.Canceled) { return; } } /** * 2) Target phase * */ e.Phase = EventPhase.Target; e.CurrentTarget = e.Target; ((EventDispatcher)e.Target).ExecuteListeners(e); //, EventPhase.Target); // executing target listeners // if event canceled or propagation stopped, go no further if (!e.Bubbles || e.Canceled) { return; } /** * 3) Bubbling phase * */ e.Phase = EventPhase.Bubbling; parentChain.Reverse(); // reversing the parent chain & starting to bubble foreach (DisplayListMember d in parentChain) { // set current target e.CurrentTarget = d; // execute listeners on current target // any of the listeners my cancel the event, that's handled by ExecuteListeners method internally d.ExecuteListeners(e); // all the listeners (or part of the listeners, in the case of cancelation) // on current target have been executed. // if event canceled or propagation stopped, go no further if (!e.Bubbles || e.Canceled) { return; } } /** * Cleanup * */ if (e is IDisposable) { ((IDisposable)e).Dispose(); } }