525
526 } // LEntry
527
528 /**
529 * Introduced in DOM Level 2. <p> Register an event listener with this
530 * Node. A listener may be independently registered as both Capturing and
531 * Bubbling, but may only be registered once per role; redundant
532 * registrations are ignored.
533 * @param node node to add listener to
534 * @param type Event name (NOT event group!) to listen for.
535 * @param listener Who gets called when event is dispatched
536 * @param useCapture True iff listener is registered on
537 * capturing phase rather than at-target or bubbling
538 */
539 @Override
540 protected void addEventListener(NodeImpl node, String type,
541 EventListener listener, boolean useCapture)
542 {
543 // We can't dispatch to blank type-name, and of course we need
544 // a listener to dispatch to
545 if (type == null || type.equals("") || listener == null)
546 return;
547
548 // Each listener may be registered only once per type per phase.
549 // Simplest way to code that is to zap the previous entry, if any.
550 removeEventListener(node, type, listener, useCapture);
551
552 List<LEntry> nodeListeners = getEventListeners(node);
553 if(nodeListeners == null) {
554 nodeListeners = new ArrayList<>();
555 setEventListeners(node, nodeListeners);
556 }
557 nodeListeners.add(new LEntry(type, listener, useCapture));
558
559 // Record active listener
560 LCount lc = LCount.lookup(type);
561 if (useCapture) {
562 ++lc.captures;
563 ++lc.total;
564 }
565 else {
569
570 } // addEventListener(NodeImpl,String,EventListener,boolean) :void
571
572 /**
573 * Introduced in DOM Level 2. <p> Deregister an event listener previously
574 * registered with this Node. A listener must be independently removed
575 * from the Capturing and Bubbling roles. Redundant removals (of listeners
576 * not currently registered for this role) are ignored.
577 * @param node node to remove listener from
578 * @param type Event name (NOT event group!) to listen for.
579 * @param listener Who gets called when event is dispatched
580 * @param useCapture True iff listener is registered on
581 * capturing phase rather than at-target or bubbling
582 */
583 @Override
584 protected void removeEventListener(NodeImpl node, String type,
585 EventListener listener,
586 boolean useCapture)
587 {
588 // If this couldn't be a valid listener registration, ignore request
589 if (type == null || type.equals("") || listener == null)
590 return;
591 List<LEntry> nodeListeners = getEventListeners(node);
592 if (nodeListeners == null)
593 return;
594
595 // Note that addListener has previously ensured that
596 // each listener may be registered only once per type per phase.
597 // count-down is OK for deletions!
598 for (int i = nodeListeners.size() - 1; i >= 0; --i) {
599 LEntry le = nodeListeners.get(i);
600 if (le.useCapture == useCapture && le.listener == listener &&
601 le.type.equals(type)) {
602 nodeListeners.remove(i);
603 // Storage management: Discard empty listener lists
604 if (nodeListeners.isEmpty())
605 setEventListeners(node, null);
606
607 // Remove active listener
608 LCount lc = LCount.lookup(type);
609 if (useCapture) {
673 * when dispatch begins.
674 * I believe the DOM's intent is that event objects be redispatchable,
675 * though it isn't stated in those terms.
676 * @param node node to dispatch to
677 * @param event the event object to be dispatched to
678 * registered EventListeners
679 * @return true if the event's <code>preventDefault()</code>
680 * method was invoked by an EventListener; otherwise false.
681 */
682 @Override
683 @SuppressWarnings({"rawtypes", "unchecked"})
684 protected boolean dispatchEvent(NodeImpl node, Event event) {
685 if (event == null) return false;
686
687 // Can't use anyone else's implementation, since there's no public
688 // API for setting the event's processing-state fields.
689 EventImpl evt = (EventImpl)event;
690
691 // VALIDATE -- must have been initialized at least once, must have
692 // a non-null non-blank name.
693 if(!evt.initialized || evt.type == null || evt.type.equals("")) {
694 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "UNSPECIFIED_EVENT_TYPE_ERR", null);
695 throw new EventException(EventException.UNSPECIFIED_EVENT_TYPE_ERR, msg);
696 }
697
698 // If nobody is listening for this event, discard immediately
699 LCount lc = LCount.lookup(evt.getType());
700 if (lc.total == 0)
701 return evt.preventDefault;
702
703 // INITIALIZE THE EVENT'S DISPATCH STATUS
704 // (Note that Event objects are reusable in our implementation;
705 // that doesn't seem to be explicitly guaranteed in the DOM, but
706 // I believe it is the intent.)
707 evt.target = node;
708 evt.stopPropagation = false;
709 evt.preventDefault = false;
710
711 // Capture pre-event parentage chain, not including target;
712 // use pre-event-dispatch ancestors even if event handlers mutate
713 // document and change the target's context.
|
525
526 } // LEntry
527
528 /**
529 * Introduced in DOM Level 2. <p> Register an event listener with this
530 * Node. A listener may be independently registered as both Capturing and
531 * Bubbling, but may only be registered once per role; redundant
532 * registrations are ignored.
533 * @param node node to add listener to
534 * @param type Event name (NOT event group!) to listen for.
535 * @param listener Who gets called when event is dispatched
536 * @param useCapture True iff listener is registered on
537 * capturing phase rather than at-target or bubbling
538 */
539 @Override
540 protected void addEventListener(NodeImpl node, String type,
541 EventListener listener, boolean useCapture)
542 {
543 // We can't dispatch to blank type-name, and of course we need
544 // a listener to dispatch to
545 if (type == null || type.isEmpty() || listener == null)
546 return;
547
548 // Each listener may be registered only once per type per phase.
549 // Simplest way to code that is to zap the previous entry, if any.
550 removeEventListener(node, type, listener, useCapture);
551
552 List<LEntry> nodeListeners = getEventListeners(node);
553 if(nodeListeners == null) {
554 nodeListeners = new ArrayList<>();
555 setEventListeners(node, nodeListeners);
556 }
557 nodeListeners.add(new LEntry(type, listener, useCapture));
558
559 // Record active listener
560 LCount lc = LCount.lookup(type);
561 if (useCapture) {
562 ++lc.captures;
563 ++lc.total;
564 }
565 else {
569
570 } // addEventListener(NodeImpl,String,EventListener,boolean) :void
571
572 /**
573 * Introduced in DOM Level 2. <p> Deregister an event listener previously
574 * registered with this Node. A listener must be independently removed
575 * from the Capturing and Bubbling roles. Redundant removals (of listeners
576 * not currently registered for this role) are ignored.
577 * @param node node to remove listener from
578 * @param type Event name (NOT event group!) to listen for.
579 * @param listener Who gets called when event is dispatched
580 * @param useCapture True iff listener is registered on
581 * capturing phase rather than at-target or bubbling
582 */
583 @Override
584 protected void removeEventListener(NodeImpl node, String type,
585 EventListener listener,
586 boolean useCapture)
587 {
588 // If this couldn't be a valid listener registration, ignore request
589 if (type == null || type.isEmpty() || listener == null)
590 return;
591 List<LEntry> nodeListeners = getEventListeners(node);
592 if (nodeListeners == null)
593 return;
594
595 // Note that addListener has previously ensured that
596 // each listener may be registered only once per type per phase.
597 // count-down is OK for deletions!
598 for (int i = nodeListeners.size() - 1; i >= 0; --i) {
599 LEntry le = nodeListeners.get(i);
600 if (le.useCapture == useCapture && le.listener == listener &&
601 le.type.equals(type)) {
602 nodeListeners.remove(i);
603 // Storage management: Discard empty listener lists
604 if (nodeListeners.isEmpty())
605 setEventListeners(node, null);
606
607 // Remove active listener
608 LCount lc = LCount.lookup(type);
609 if (useCapture) {
673 * when dispatch begins.
674 * I believe the DOM's intent is that event objects be redispatchable,
675 * though it isn't stated in those terms.
676 * @param node node to dispatch to
677 * @param event the event object to be dispatched to
678 * registered EventListeners
679 * @return true if the event's <code>preventDefault()</code>
680 * method was invoked by an EventListener; otherwise false.
681 */
682 @Override
683 @SuppressWarnings({"rawtypes", "unchecked"})
684 protected boolean dispatchEvent(NodeImpl node, Event event) {
685 if (event == null) return false;
686
687 // Can't use anyone else's implementation, since there's no public
688 // API for setting the event's processing-state fields.
689 EventImpl evt = (EventImpl)event;
690
691 // VALIDATE -- must have been initialized at least once, must have
692 // a non-null non-blank name.
693 if(!evt.initialized || evt.type == null || evt.type.isEmpty()) {
694 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "UNSPECIFIED_EVENT_TYPE_ERR", null);
695 throw new EventException(EventException.UNSPECIFIED_EVENT_TYPE_ERR, msg);
696 }
697
698 // If nobody is listening for this event, discard immediately
699 LCount lc = LCount.lookup(evt.getType());
700 if (lc.total == 0)
701 return evt.preventDefault;
702
703 // INITIALIZE THE EVENT'S DISPATCH STATUS
704 // (Note that Event objects are reusable in our implementation;
705 // that doesn't seem to be explicitly guaranteed in the DOM, but
706 // I believe it is the intent.)
707 evt.target = node;
708 evt.stopPropagation = false;
709 evt.preventDefault = false;
710
711 // Capture pre-event parentage chain, not including target;
712 // use pre-event-dispatch ancestors even if event handlers mutate
713 // document and change the target's context.
|