michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsIMutationObserver_h michael@0: #define nsIMutationObserver_h michael@0: michael@0: #include "nsISupports.h" michael@0: michael@0: class nsIAtom; michael@0: class nsIContent; michael@0: class nsIDocument; michael@0: class nsINode; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: class Element; michael@0: } // namespace dom michael@0: } // namespace mozilla michael@0: michael@0: #define NS_IMUTATION_OBSERVER_IID \ michael@0: { 0x16fe5e3e, 0xeadc, 0x4312, \ michael@0: { 0x9d, 0x44, 0xb6, 0xbe, 0xdd, 0x6b, 0x54, 0x74 } } michael@0: michael@0: /** michael@0: * Information details about a characterdata change. Basically, we michael@0: * view all changes as replacements of a length of text at some offset michael@0: * with some other text (of possibly some other length). michael@0: */ michael@0: struct CharacterDataChangeInfo michael@0: { michael@0: /** michael@0: * True if this character data change is just an append. michael@0: */ michael@0: bool mAppend; michael@0: michael@0: /** michael@0: * The offset in the text where the change occurred. michael@0: */ michael@0: uint32_t mChangeStart; michael@0: michael@0: /** michael@0: * The offset such that mChangeEnd - mChangeStart is equal to the length of michael@0: * the text we removed. If this was a pure insert or append, this is equal to michael@0: * mChangeStart. michael@0: */ michael@0: uint32_t mChangeEnd; michael@0: michael@0: /** michael@0: * The length of the text that was inserted in place of the removed text. If michael@0: * this was a pure text removal, this is 0. michael@0: */ michael@0: uint32_t mReplaceLength; michael@0: michael@0: /** michael@0: * The net result is that mChangeStart characters at the beginning of the michael@0: * text remained as they were. The next mChangeEnd - mChangeStart characters michael@0: * were removed, and mReplaceLength characters were inserted in their place. michael@0: * The text that used to begin at mChangeEnd now begins at michael@0: * mChangeStart + mReplaceLength. michael@0: */ michael@0: michael@0: struct Details { michael@0: enum { michael@0: eMerge, // two text nodes are merged as a result of normalize() michael@0: eSplit // a text node is split as a result of splitText() michael@0: } mType; michael@0: /** michael@0: * For eMerge it's the text node that will be removed, for eSplit it's the michael@0: * new text node. michael@0: */ michael@0: nsIContent* mNextSibling; michael@0: }; michael@0: michael@0: /** michael@0: * Used for splitText() and normalize(), otherwise null. michael@0: */ michael@0: Details* mDetails; michael@0: }; michael@0: michael@0: /** michael@0: * Mutation observer interface michael@0: * michael@0: * See nsINode::AddMutationObserver, nsINode::RemoveMutationObserver for how to michael@0: * attach or remove your observers. michael@0: * michael@0: * WARNING: During these notifications, you are not allowed to perform michael@0: * any mutations to the current or any other document, or start a michael@0: * network load. If you need to perform such operations do that michael@0: * during the _last_ nsIDocumentObserver::EndUpdate notification. The michael@0: * expection for this is ParentChainChanged, where mutations should be michael@0: * done from an async event, as the notification might not be michael@0: * surrounded by BeginUpdate/EndUpdate calls. michael@0: */ michael@0: class nsIMutationObserver : public nsISupports michael@0: { michael@0: public: michael@0: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMUTATION_OBSERVER_IID) michael@0: michael@0: /** michael@0: * Notification that the node value of a data node (text, cdata, pi, comment) michael@0: * will be changed. michael@0: * michael@0: * This notification is not sent when a piece of content is michael@0: * added/removed from the document (the other notifications are used michael@0: * for that). michael@0: * michael@0: * @param aDocument The owner-document of aContent. Can be null. michael@0: * @param aContent The piece of content that changed. Is never null. michael@0: * @param aInfo The structure with information details about the change. michael@0: * michael@0: * @note Callers of this method might not hold a strong reference to the michael@0: * observer. The observer is responsible for making sure it stays michael@0: * alive for the duration of the call as needed. The observer may michael@0: * assume that this call will happen when there are script blockers on michael@0: * the stack. michael@0: */ michael@0: virtual void CharacterDataWillChange(nsIDocument *aDocument, michael@0: nsIContent* aContent, michael@0: CharacterDataChangeInfo* aInfo) = 0; michael@0: michael@0: /** michael@0: * Notification that the node value of a data node (text, cdata, pi, comment) michael@0: * has changed. michael@0: * michael@0: * This notification is not sent when a piece of content is michael@0: * added/removed from the document (the other notifications are used michael@0: * for that). michael@0: * michael@0: * @param aDocument The owner-document of aContent. Can be null. michael@0: * @param aContent The piece of content that changed. Is never null. michael@0: * @param aInfo The structure with information details about the change. michael@0: * michael@0: * @note Callers of this method might not hold a strong reference to the michael@0: * observer. The observer is responsible for making sure it stays michael@0: * alive for the duration of the call as needed. The observer may michael@0: * assume that this call will happen when there are script blockers on michael@0: * the stack. michael@0: */ michael@0: virtual void CharacterDataChanged(nsIDocument *aDocument, michael@0: nsIContent* aContent, michael@0: CharacterDataChangeInfo* aInfo) = 0; michael@0: michael@0: /** michael@0: * Notification that an attribute of an element will change. This michael@0: * can happen before the BeginUpdate for the change and may not michael@0: * always be followed by an AttributeChanged (in particular, if the michael@0: * attribute doesn't actually change there will be no corresponding michael@0: * AttributeChanged). michael@0: * michael@0: * @param aDocument The owner-document of aContent. Can be null. michael@0: * @param aContent The element whose attribute will change michael@0: * @param aNameSpaceID The namespace id of the changing attribute michael@0: * @param aAttribute The name of the changing attribute michael@0: * @param aModType Whether or not the attribute will be added, changed, or michael@0: * removed. The constants are defined in michael@0: * nsIDOMMutationEvent.h. michael@0: * michael@0: * @note Callers of this method might not hold a strong reference to the michael@0: * observer. The observer is responsible for making sure it stays michael@0: * alive for the duration of the call as needed. The observer may michael@0: * assume that this call will happen when there are script blockers on michael@0: * the stack. michael@0: */ michael@0: virtual void AttributeWillChange(nsIDocument* aDocument, michael@0: mozilla::dom::Element* aElement, michael@0: int32_t aNameSpaceID, michael@0: nsIAtom* aAttribute, michael@0: int32_t aModType) = 0; michael@0: michael@0: /** michael@0: * Notification that an attribute of an element has changed. michael@0: * michael@0: * @param aDocument The owner-document of aContent. Can be null. michael@0: * @param aElement The element whose attribute changed michael@0: * @param aNameSpaceID The namespace id of the changed attribute michael@0: * @param aAttribute The name of the changed attribute michael@0: * @param aModType Whether or not the attribute was added, changed, or michael@0: * removed. The constants are defined in michael@0: * nsIDOMMutationEvent.h. michael@0: * michael@0: * @note Callers of this method might not hold a strong reference to the michael@0: * observer. The observer is responsible for making sure it stays michael@0: * alive for the duration of the call as needed. The observer may michael@0: * assume that this call will happen when there are script blockers on michael@0: * the stack. michael@0: */ michael@0: virtual void AttributeChanged(nsIDocument* aDocument, michael@0: mozilla::dom::Element* aElement, michael@0: int32_t aNameSpaceID, michael@0: nsIAtom* aAttribute, michael@0: int32_t aModType) = 0; michael@0: michael@0: /** michael@0: * Notification that an attribute of an element has been michael@0: * set to the value it already had. michael@0: * michael@0: * @param aDocument The owner-document of aContent. michael@0: * @param aElement The element whose attribute changed michael@0: * @param aNameSpaceID The namespace id of the changed attribute michael@0: * @param aAttribute The name of the changed attribute michael@0: */ michael@0: virtual void AttributeSetToCurrentValue(nsIDocument* aDocument, michael@0: mozilla::dom::Element* aElement, michael@0: int32_t aNameSpaceID, michael@0: nsIAtom* aAttribute) {} michael@0: michael@0: /** michael@0: * Notification that one or more content nodes have been appended to the michael@0: * child list of another node in the tree. michael@0: * michael@0: * @param aDocument The owner-document of aContent. Can be null. michael@0: * @param aContainer The container that had new children appended. Is never michael@0: * null. michael@0: * @param aFirstNewContent the node at aIndexInContainer in aContainer. michael@0: * @param aNewIndexInContainer the index in the container of the first michael@0: * new child michael@0: * michael@0: * @note Callers of this method might not hold a strong reference to the michael@0: * observer. The observer is responsible for making sure it stays michael@0: * alive for the duration of the call as needed. The observer may michael@0: * assume that this call will happen when there are script blockers on michael@0: * the stack. michael@0: */ michael@0: virtual void ContentAppended(nsIDocument *aDocument, michael@0: nsIContent* aContainer, michael@0: nsIContent* aFirstNewContent, michael@0: int32_t aNewIndexInContainer) = 0; michael@0: michael@0: /** michael@0: * Notification that a content node has been inserted as child to another michael@0: * node in the tree. michael@0: * michael@0: * @param aDocument The owner-document of aContent, or, when aContainer michael@0: * is null, the container that had the child inserted. michael@0: * Can be null. michael@0: * @param aContainer The container that had new a child inserted. Can be michael@0: * null to indicate that the child was inserted into michael@0: * aDocument michael@0: * @param aChild The newly inserted child. michael@0: * @param aIndexInContainer The index in the container of the new child. michael@0: * michael@0: * @note Callers of this method might not hold a strong reference to the michael@0: * observer. The observer is responsible for making sure it stays michael@0: * alive for the duration of the call as needed. The observer may michael@0: * assume that this call will happen when there are script blockers on michael@0: * the stack. michael@0: */ michael@0: virtual void ContentInserted(nsIDocument *aDocument, michael@0: nsIContent* aContainer, michael@0: nsIContent* aChild, michael@0: int32_t aIndexInContainer) = 0; michael@0: michael@0: /** michael@0: * Notification that a content node has been removed from the child list of michael@0: * another node in the tree. michael@0: * michael@0: * @param aDocument The owner-document of aContent, or, when aContainer michael@0: * is null, the container that had the child removed. michael@0: * Can be null. michael@0: * @param aContainer The container that had new a child removed. Can be michael@0: * null to indicate that the child was removed from michael@0: * aDocument. michael@0: * @param aChild The child that was removed. michael@0: * @param aIndexInContainer The index in the container which the child used michael@0: * to have. michael@0: * @param aPreviousSibling The previous sibling to the child that was removed. michael@0: * Can be null if there was no previous sibling. michael@0: * michael@0: * @note Callers of this method might not hold a strong reference to the michael@0: * observer. The observer is responsible for making sure it stays michael@0: * alive for the duration of the call as needed. The observer may michael@0: * assume that this call will happen when there are script blockers on michael@0: * the stack. michael@0: */ michael@0: virtual void ContentRemoved(nsIDocument *aDocument, michael@0: nsIContent* aContainer, michael@0: nsIContent* aChild, michael@0: int32_t aIndexInContainer, michael@0: nsIContent* aPreviousSibling) = 0; michael@0: michael@0: /** michael@0: * The node is in the process of being destroyed. Calling QI on the node is michael@0: * not supported, however it is possible to get children and flags through michael@0: * nsINode as well as calling IsNodeOfType(eCONTENT) and casting to michael@0: * nsIContent to get attributes. michael@0: * michael@0: * NOTE: This notification is only called on observers registered directly michael@0: * on the node. This is because when the node is destroyed it can not have michael@0: * any ancestors. If you want to know when a descendant node is being michael@0: * removed from the observed node, use the ContentRemoved notification. michael@0: * michael@0: * @param aNode The node being destroyed. michael@0: * michael@0: * @note Callers of this method might not hold a strong reference to michael@0: * the observer. The observer is responsible for making sure it michael@0: * stays alive for the duration of the call as needed. michael@0: */ michael@0: virtual void NodeWillBeDestroyed(const nsINode *aNode) = 0; michael@0: michael@0: /** michael@0: * Notification that the node's parent chain has changed. This michael@0: * happens when either the node or one of its ancestors is inserted michael@0: * or removed as a child of another node. michael@0: * michael@0: * Note that when a node is inserted this notification is sent to michael@0: * all descendants of that node, since all such nodes have their michael@0: * parent chain changed. michael@0: * michael@0: * @param aContent The piece of content that had its parent changed. michael@0: * michael@0: * @note Callers of this method might not hold a strong reference to michael@0: * the observer. The observer is responsible for making sure it michael@0: * stays alive for the duration of the call as needed. michael@0: */ michael@0: michael@0: virtual void ParentChainChanged(nsIContent *aContent) = 0; michael@0: }; michael@0: michael@0: NS_DEFINE_STATIC_IID_ACCESSOR(nsIMutationObserver, NS_IMUTATION_OBSERVER_IID) michael@0: michael@0: #define NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE \ michael@0: virtual void CharacterDataWillChange(nsIDocument* aDocument, \ michael@0: nsIContent* aContent, \ michael@0: CharacterDataChangeInfo* aInfo); michael@0: michael@0: #define NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED \ michael@0: virtual void CharacterDataChanged(nsIDocument* aDocument, \ michael@0: nsIContent* aContent, \ michael@0: CharacterDataChangeInfo* aInfo); michael@0: michael@0: #define NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE \ michael@0: virtual void AttributeWillChange(nsIDocument* aDocument, \ michael@0: mozilla::dom::Element* aElement, \ michael@0: int32_t aNameSpaceID, \ michael@0: nsIAtom* aAttribute, \ michael@0: int32_t aModType); michael@0: michael@0: #define NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED \ michael@0: virtual void AttributeChanged(nsIDocument* aDocument, \ michael@0: mozilla::dom::Element* aElement, \ michael@0: int32_t aNameSpaceID, \ michael@0: nsIAtom* aAttribute, \ michael@0: int32_t aModType); michael@0: michael@0: #define NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED \ michael@0: virtual void ContentAppended(nsIDocument* aDocument, \ michael@0: nsIContent* aContainer, \ michael@0: nsIContent* aFirstNewContent, \ michael@0: int32_t aNewIndexInContainer); michael@0: michael@0: #define NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED \ michael@0: virtual void ContentInserted(nsIDocument* aDocument, \ michael@0: nsIContent* aContainer, \ michael@0: nsIContent* aChild, \ michael@0: int32_t aIndexInContainer); michael@0: michael@0: #define NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED \ michael@0: virtual void ContentRemoved(nsIDocument* aDocument, \ michael@0: nsIContent* aContainer, \ michael@0: nsIContent* aChild, \ michael@0: int32_t aIndexInContainer, \ michael@0: nsIContent* aPreviousSibling); michael@0: michael@0: #define NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED \ michael@0: virtual void NodeWillBeDestroyed(const nsINode* aNode); michael@0: michael@0: #define NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED \ michael@0: virtual void ParentChainChanged(nsIContent *aContent); michael@0: michael@0: #define NS_DECL_NSIMUTATIONOBSERVER \ michael@0: NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE \ michael@0: NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED \ michael@0: NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE \ michael@0: NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED \ michael@0: NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED \ michael@0: NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED \ michael@0: NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED \ michael@0: NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED \ michael@0: NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED michael@0: michael@0: #define NS_IMPL_NSIMUTATIONOBSERVER_CORE_STUB(_class) \ michael@0: void \ michael@0: _class::NodeWillBeDestroyed(const nsINode* aNode) \ michael@0: { \ michael@0: } michael@0: michael@0: #define NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(_class) \ michael@0: void \ michael@0: _class::CharacterDataWillChange(nsIDocument* aDocument, \ michael@0: nsIContent* aContent, \ michael@0: CharacterDataChangeInfo* aInfo) \ michael@0: { \ michael@0: } \ michael@0: void \ michael@0: _class::CharacterDataChanged(nsIDocument* aDocument, \ michael@0: nsIContent* aContent, \ michael@0: CharacterDataChangeInfo* aInfo) \ michael@0: { \ michael@0: } \ michael@0: void \ michael@0: _class::AttributeWillChange(nsIDocument* aDocument, \ michael@0: mozilla::dom::Element* aElement, \ michael@0: int32_t aNameSpaceID, \ michael@0: nsIAtom* aAttribute, \ michael@0: int32_t aModType) \ michael@0: { \ michael@0: } \ michael@0: void \ michael@0: _class::AttributeChanged(nsIDocument* aDocument, \ michael@0: mozilla::dom::Element* aElement, \ michael@0: int32_t aNameSpaceID, \ michael@0: nsIAtom* aAttribute, \ michael@0: int32_t aModType) \ michael@0: { \ michael@0: } \ michael@0: void \ michael@0: _class::ContentAppended(nsIDocument* aDocument, \ michael@0: nsIContent* aContainer, \ michael@0: nsIContent* aFirstNewContent, \ michael@0: int32_t aNewIndexInContainer) \ michael@0: { \ michael@0: } \ michael@0: void \ michael@0: _class::ContentInserted(nsIDocument* aDocument, \ michael@0: nsIContent* aContainer, \ michael@0: nsIContent* aChild, \ michael@0: int32_t aIndexInContainer) \ michael@0: { \ michael@0: } \ michael@0: void \ michael@0: _class::ContentRemoved(nsIDocument* aDocument, \ michael@0: nsIContent* aContainer, \ michael@0: nsIContent* aChild, \ michael@0: int32_t aIndexInContainer, \ michael@0: nsIContent* aPreviousSibling) \ michael@0: { \ michael@0: } \ michael@0: void \ michael@0: _class::ParentChainChanged(nsIContent *aContent) \ michael@0: { \ michael@0: } michael@0: michael@0: michael@0: #endif /* nsIMutationObserver_h */