documentimpl.java

来自「JAVA 所有包」· Java 代码 · 共 1,302 行 · 第 1/4 页

JAVA
1,302
字号
    */    protected boolean dispatchEvent(NodeImpl node, Event event) {        if (event == null) return false;                // Can't use anyone else's implementation, since there's no public        // API for setting the event's processing-state fields.        EventImpl evt = (EventImpl)event;        // VALIDATE -- must have been initialized at least once, must have        // a non-null non-blank name.        if(!evt.initialized || evt.type == null || evt.type.equals("")) {            String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "UNSPECIFIED_EVENT_TYPE_ERR", null);            throw new EventException(EventException.UNSPECIFIED_EVENT_TYPE_ERR, msg);        }                // If nobody is listening for this event, discard immediately        LCount lc = LCount.lookup(evt.getType());        if (lc.total == 0)            return evt.preventDefault;        // INITIALIZE THE EVENT'S DISPATCH STATUS        // (Note that Event objects are reusable in our implementation;        // that doesn't seem to be explicitly guaranteed in the DOM, but        // I believe it is the intent.)        evt.target = node;        evt.stopPropagation = false;        evt.preventDefault = false;                // Capture pre-event parentage chain, not including target;        // use pre-event-dispatch ancestors even if event handlers mutate        // document and change the target's context.        // Note that this is parents ONLY; events do not        // cross the Attr/Element "blood/brain barrier".         // DOMAttrModified. which looks like an exception,        // is issued to the Element rather than the Attr        // and causes a _second_ DOMSubtreeModified in the Element's        // tree.        Vector pv = new Vector(10,10);        Node p = node;        Node n = p.getParentNode();        while (n != null) {            pv.addElement(n);            p = n;            n = n.getParentNode();        }                // CAPTURING_PHASE:        if (lc.captures > 0) {            evt.eventPhase = Event.CAPTURING_PHASE;            // Ancestors are scanned, root to target, for             // Capturing listeners.            for (int j = pv.size() - 1; j >= 0; --j) {                if (evt.stopPropagation)                    break;  // Someone set the flag. Phase ends.                // Handle all capturing listeners on this node                NodeImpl nn = (NodeImpl) pv.elementAt(j);                evt.currentTarget = nn;                Vector nodeListeners = getEventListeners(nn);                if (nodeListeners != null) {                    Vector nl = (Vector) nodeListeners.clone();                    // call listeners in the order in which they got registered                    int nlsize = nl.size();                    for (int i = 0; i < nlsize; i++) {                        LEntry le = (LEntry) nl.elementAt(i);                        if (le.useCapture && le.type.equals(evt.type) &&                            nodeListeners.contains(le)) {                            try {                                le.listener.handleEvent(evt);                            }                            catch (Exception e) {                                // All exceptions are ignored.                            }                        }                    }                }            }        }                        // Both AT_TARGET and BUBBLE use non-capturing listeners.        if (lc.bubbles > 0) {            // AT_TARGET PHASE: Event is dispatched to NON-CAPTURING listeners            // on the target node. Note that capturing listeners on the target            // node are _not_ invoked, even during the capture phase.            evt.eventPhase = Event.AT_TARGET;            evt.currentTarget = node;            Vector nodeListeners = getEventListeners(node);            if (!evt.stopPropagation && nodeListeners != null) {                Vector nl = (Vector) nodeListeners.clone();                // call listeners in the order in which they got registered                int nlsize = nl.size();                for (int i = 0; i < nlsize; i++) {                    LEntry le = (LEntry) nl.elementAt(i);                    if (!le.useCapture && le.type.equals(evt.type) &&                        nodeListeners.contains(le)) {                        try {                            le.listener.handleEvent(evt);                        }                        catch (Exception e) {                            // All exceptions are ignored.                        }                    }                }            }            // BUBBLING_PHASE: Ancestors are scanned, target to root, for            // non-capturing listeners. If the event's preventBubbling flag            // has been set before processing of a node commences, we            // instead immediately advance to the default phase.            // Note that not all events bubble.            if (evt.bubbles) {                evt.eventPhase = Event.BUBBLING_PHASE;                int pvsize = pv.size();                for (int j = 0; j < pvsize; j++) {                    if (evt.stopPropagation)                        break;  // Someone set the flag. Phase ends.                    // Handle all bubbling listeners on this node                    NodeImpl nn = (NodeImpl) pv.elementAt(j);                    evt.currentTarget = nn;                    nodeListeners = getEventListeners(nn);                    if (nodeListeners != null) {                        Vector nl = (Vector) nodeListeners.clone();                        // call listeners in the order in which they got                        // registered                        int nlsize = nl.size();                        for (int i = 0; i < nlsize; i++) {                            LEntry le = (LEntry) nl.elementAt(i);                            if (!le.useCapture && le.type.equals(evt.type) &&                                nodeListeners.contains(le)) {                                try {                                    le.listener.handleEvent(evt);                                }                                catch (Exception e) {                                    // All exceptions are ignored.                                }                            }                        }                    }                }            }        }                // DEFAULT PHASE: Some DOMs have default behaviors bound to specific        // nodes. If this DOM does, and if the event's preventDefault flag has        // not been set, we now return to the target node and process its        // default handler for this event, if any.        // No specific phase value defined, since this is DOM-internal        if (lc.defaults > 0 && (!evt.cancelable || !evt.preventDefault)) {            // evt.eventPhase = Event.DEFAULT_PHASE;            // evt.currentTarget = node;            // DO_DEFAULT_OPERATION        }        return evt.preventDefault;            } // dispatchEvent(NodeImpl,Event) :boolean    /**     * NON-DOM INTERNAL: DOMNodeInsertedIntoDocument and ...RemovedFrom...     * are dispatched to an entire subtree. This is the distribution code     * therefor. They DO NOT bubble, thanks be, but may be captured.     * <p>     * Similar to code in dispatchingEventToSubtree however this method     * is only used on the target node and does not start a dispatching chain     * on the sibling of the target node as this is not part of the subtree      * ***** At the moment I'm being sloppy and using the normal     * capture dispatcher on every node. This could be optimized hugely     * by writing a capture engine that tracks our position in the tree to     * update the capture chain without repeated chases up to root.     * @param n target node (that was directly inserted or removed)     * @param e event to be sent to that node and its subtree     */    protected void dispatchEventToSubtree(Node n, Event e) {                ((NodeImpl) n).dispatchEvent(e);        if (n.getNodeType() == Node.ELEMENT_NODE) {            NamedNodeMap a = n.getAttributes();            for (int i = a.getLength() - 1; i >= 0; --i)                dispatchingEventToSubtree(a.item(i), e);        }        dispatchingEventToSubtree(n.getFirstChild(), e);            } // dispatchEventToSubtree(NodeImpl,Node,Event) :void    /**     * Dispatches event to the target node's descendents recursively     *      * @param n node to dispatch to     * @param e event to be sent to that node and its subtree     */    protected void dispatchingEventToSubtree(Node n, Event e) {    	if (n==null)     		return;    	    	// ***** Recursive implementation. This is excessively expensive,        // and should be replaced in conjunction with optimization        // mentioned above.    	((NodeImpl) n).dispatchEvent(e);        if (n.getNodeType() == Node.ELEMENT_NODE) {            NamedNodeMap a = n.getAttributes();            for (int i = a.getLength() - 1; i >= 0; --i)                dispatchingEventToSubtree(a.item(i), e);        }        dispatchingEventToSubtree(n.getFirstChild(), e);           dispatchingEventToSubtree(n.getNextSibling(), e);    }        /**     * NON-DOM INTERNAL: Return object for getEnclosingAttr. Carries     * (two values, the Attr node affected (if any) and its previous      * string value. Simple struct, no methods.     */    class EnclosingAttr implements Serializable {        private static final long serialVersionUID = 3257001077260759859L;        AttrImpl node;        String oldvalue;    }    EnclosingAttr savedEnclosingAttr;    /**     * NON-DOM INTERNAL: Convenience wrapper for calling     * dispatchAggregateEvents when the context was established     * by <code>savedEnclosingAttr</code>.     * @param node node to dispatch to     * @param ea description of Attr affected by current operation     */    protected void dispatchAggregateEvents(NodeImpl node, EnclosingAttr ea) {        if (ea != null)            dispatchAggregateEvents(node, ea.node, ea.oldvalue,                                    MutationEvent.MODIFICATION);        else            dispatchAggregateEvents(node, null, null, (short) 0);	            } // dispatchAggregateEvents(NodeImpl,EnclosingAttr) :void    /**     * NON-DOM INTERNAL: Generate the "aggregated" post-mutation events     * DOMAttrModified and DOMSubtreeModified.     * Both of these should be issued only once for each user-requested     * mutation operation, even if that involves multiple changes to     * the DOM.     * For example, if a DOM operation makes multiple changes to a single     * Attr before returning, it would be nice to generate only one      * DOMAttrModified, and multiple changes over larger scope but within     * a recognizable single subtree might want to generate only one      * DOMSubtreeModified, sent to their lowest common ancestor.      * <p>     * To manage this, use the "internal" versions of insert and remove     * with MUTATION_LOCAL, then make an explicit call to this routine     * at the higher level. Some examples now exist in our code.     *     * @param node The node to dispatch to     * @param enclosingAttr The Attr node (if any) whose value has been changed     * as a result of the DOM operation. Null if none such.     * @param oldValue The String value previously held by the     * enclosingAttr. Ignored if none such.     * @param change Type of modification to the attr. See     * MutationEvent.attrChange     */    protected void dispatchAggregateEvents(NodeImpl node,                                           AttrImpl enclosingAttr,                                           String oldvalue, short change) {        // We have to send DOMAttrModified.        NodeImpl owner = null;        if (enclosingAttr != null) {            LCount lc = LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);            owner = (NodeImpl) enclosingAttr.getOwnerElement();            if (lc.total > 0) {                if (owner != null) {                    MutationEventImpl me =  new MutationEventImpl();                    me.initMutationEvent(MutationEventImpl.DOM_ATTR_MODIFIED,                                         true, false, enclosingAttr,                                         oldvalue,                                         enclosingAttr.getNodeValue(),                                         enclosingAttr.getNodeName(),                                         change);                    owner.dispatchEvent(me);                }            }        }        // DOMSubtreeModified gets sent to the lowest common root of a        // set of changes.         // "This event is dispatched after all other events caused by the        // mutation have been fired."        LCount lc = LCount.lookup(MutationEventImpl.DOM_SUBTREE_MODIFIED);        if (lc.total > 0) {            MutationEvent me =  new MutationEventImpl();            me.initMutationEvent(MutationEventImpl.DOM_SUBTREE_MODIFIED,                                 true, false, null, null,                                 null, null, (short) 0);            // If we're within an Attr, DStM gets sent to the Attr            // and to its owningElement. Otherwise we dispatch it            // locally.            if (enclosingAttr != null) {                dispatchEvent(enclosingAttr, me);                if (owner != null)                    dispatchEvent(owner, me);            }            else                dispatchEvent(node, me);        }    } // dispatchAggregateEvents(NodeImpl, AttrImpl,String) :void    /**     * NON-DOM INTERNAL: Pre-mutation context check, in     * preparation for later generating DOMAttrModified events.     * Determines whether this node is within an Attr     * @param node node to get enclosing attribute for     * @return either a description of that Attr, or null if none such.      */    protected void saveEnclosingAttr(NodeImpl node) {        savedEnclosingAttr = null;        // MUTATION PREPROCESSING AND PRE-EVENTS:        // If we're within the scope of an Attr and DOMAttrModified         // was requested, we need to preserve its previous value for        // that event.        LCount lc = LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);        if (lc.total > 0) {            NodeImpl eventAncestor = node;            while (true) {                if (eventAncestor == null)                    return;                int type = eventAncestor.getNodeType();

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?