Patch for 55595. r=joki, a=brendan

This commit is contained in:
hyatt%netscape.com 2000-11-27 07:55:20 +00:00
Родитель daa5773e5c
Коммит 56d558b610
69 изменённых файлов: 2501 добавлений и 1884 удалений

Просмотреть файл

@ -33,6 +33,9 @@
#include "nsISelectionPrivate.h"
#include "nsIEnumerator.h"
#include "nsReadableUtils.h"
#include "nsMutationEvent.h"
#include "nsEventListenerManager.h"
#include "nsPIDOMWindow.h"
#include "nsCRT.h"
#include "nsIEventStateManager.h"
@ -909,6 +912,73 @@ nsGenericDOMDataNode::CopyText(nsAWritableString& aResult)
return NS_OK;
}
static PRBool HasMutationListeners(nsIContent* aContent, PRUint32 aType)
{
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (!doc)
return PR_FALSE;
nsCOMPtr<nsIScriptGlobalObject> global;
doc->GetScriptGlobalObject(getter_AddRefs(global));
if (!global)
return PR_FALSE;
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(global));
if (!window)
return PR_FALSE;
PRBool set;
window->HasMutationListeners(aType, &set);
if (!set)
return PR_FALSE;
// We know a mutation listener is registered, but it might not
// be in our chain. Check quickly to see.
nsCOMPtr<nsIContent> curr = aContent;
nsCOMPtr<nsIEventListenerManager> manager;
while (curr) {
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(curr));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
nsCOMPtr<nsIContent> prev = curr;
prev->GetParent(*getter_AddRefs(curr));
}
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
rec = do_QueryInterface(window);
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
return PR_FALSE;
}
nsresult
nsGenericDOMDataNode::SetText(nsIContent *aOuterContent,
const PRUnichar* aBuffer,
@ -927,6 +997,22 @@ nsGenericDOMDataNode::SetText(nsIContent *aOuterContent,
}
mText.SetTo(aBuffer, aLength);
if (mDocument && HasMutationListeners(aOuterContent, NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aOuterContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_CHARACTERDATAMODIFIED;
mutation.mTarget = node;
// XXX Handle the setting of prevValue!
nsAutoString newVal(aBuffer);
if (!newVal.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(newVal));
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
// Trigger a reflow
if (aNotify && (nsnull != mDocument)) {
mDocument->ContentChanged(aOuterContent, nsnull);
@ -951,6 +1037,22 @@ nsGenericDOMDataNode::SetText(nsIContent *aOuterContent, const char* aBuffer,
}
mText.SetTo(aBuffer, aLength);
if (mDocument && HasMutationListeners(aOuterContent, NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aOuterContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_CHARACTERDATAMODIFIED;
mutation.mTarget = node;
// XXX Handle the setting of prevValue!
nsAutoString newVal; newVal.AssignWithConversion(aBuffer);
if (!newVal.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(newVal));
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
// Trigger a reflow
if (aNotify && (nsnull != mDocument)) {
mDocument->ContentChanged(aOuterContent, nsnull);

Просмотреть файл

@ -61,12 +61,16 @@
#include "prmem.h"
#include "nsDOMError.h"
#include "nsScriptSecurityManager.h"
#include "nsIDOMMutationEvent.h"
#include "nsMutationEvent.h"
#include "nsIBindingManager.h"
#include "nsIXBLBinding.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsIDOMViewCSS.h"
#include "nsIXBLService.h"
#include "nsPIDOMWindow.h"
#include "nsEventListenerManager.h"
#include "nsLayoutAtoms.h"
#include "nsHTMLAtoms.h"
@ -2718,6 +2722,73 @@ nsGenericContainerElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
return SetAttribute(ni, aValue, aNotify);
}
static PRBool HasMutationListeners(nsIContent* aContent, PRUint32 aType)
{
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (!doc)
return PR_FALSE;
nsCOMPtr<nsIScriptGlobalObject> global;
doc->GetScriptGlobalObject(getter_AddRefs(global));
if (!global)
return PR_FALSE;
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(global));
if (!window)
return PR_FALSE;
PRBool set;
window->HasMutationListeners(aType, &set);
if (!set)
return PR_FALSE;
// We know a mutation listener is registered, but it might not
// be in our chain. Check quickly to see.
nsCOMPtr<nsIContent> curr = aContent;
nsCOMPtr<nsIEventListenerManager> manager;
while (curr) {
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(curr));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
nsCOMPtr<nsIContent> prev = curr;
prev->GetParent(*getter_AddRefs(curr));
}
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
rec = do_QueryInterface(window);
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
return PR_FALSE;
}
nsresult
nsGenericContainerElement::SetAttribute(nsINodeInfo* aNodeInfo,
const nsAReadableString& aValue,
@ -2725,6 +2796,9 @@ nsGenericContainerElement::SetAttribute(nsINodeInfo* aNodeInfo,
{
NS_ENSURE_ARG_POINTER(aNodeInfo);
PRBool modification = PR_FALSE;
nsAutoString oldValue;
nsresult rv = NS_ERROR_OUT_OF_MEMORY;
if (!mAttributes) {
@ -2742,6 +2816,8 @@ nsGenericContainerElement::SetAttribute(nsINodeInfo* aNodeInfo,
for (index = 0; index < count; index++) {
attr = (nsGenericAttribute*)mAttributes->ElementAt(index);
if (attr->mNodeInfo == aNodeInfo) {
oldValue = attr->mValue;
modification = PR_TRUE;
attr->mValue = aValue;
rv = NS_OK;
break;
@ -2770,6 +2846,31 @@ nsGenericContainerElement::SetAttribute(nsINodeInfo* aNodeInfo,
if (binding)
binding->AttributeChanged(name, nameSpaceID, PR_FALSE);
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(mContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName;
name->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = name;
if (!oldValue.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(oldValue));
if (!aValue.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(aValue));
mutation.mAttrChange = modification ? nsIDOMMutationEvent::MODIFICATION :
nsIDOMMutationEvent::ADDITION;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
mDocument->AttributeChanged(mContent, nameSpaceID, name, NS_STYLE_HINT_UNKNOWN);
mDocument->EndUpdate();
@ -2854,6 +2955,30 @@ nsGenericContainerElement::UnsetAttribute(PRInt32 aNameSpaceID,
if (aNotify && (nsnull != mDocument)) {
mDocument->BeginUpdate();
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(mContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName;
aName->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aName;
if (!attr->mValue.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(attr->mValue));
mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
mAttributes->RemoveElementAt(index);
delete attr;
found = PR_TRUE;
@ -3036,6 +3161,21 @@ nsGenericContainerElement::InsertChildAt(nsIContent* aKid,
if (aNotify) {
doc->ContentInserted(mContent, aKid, aIndex);
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
}
}
if (aNotify && (nsnull != doc)) {
@ -3094,6 +3234,21 @@ nsGenericContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
if (aNotify) {
doc->ContentAppended(mContent, mChildren.Count() - 1);
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
}
}
if (aNotify && (nsnull != doc)) {
@ -3111,6 +3266,22 @@ nsGenericContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
if (aNotify && (nsnull != doc)) {
doc->BeginUpdate();
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(oldKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEREMOVED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
oldKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
nsRange::OwnerChildRemoved(mContent, aIndex, oldKid);
mChildren.RemoveElementAt(aIndex);
if (aNotify) {

Просмотреть файл

@ -1,9 +0,0 @@
#
# This is a list of local files which get copied to the mozilla:dist:layout directory
#
nsIEventListenerManager.h
nsIEventStateManager.h
nsIPrivateDOMEvent.h
nsIPrivateTextEvent.h
nsIPrivateTextRange.h
nsIPrivateCompositionEvent.h

Просмотреть файл

@ -29,6 +29,7 @@ include $(DEPTH)/config/autoconf.mk
MODULE = layout
EXPORTS = \
nsMutationEvent.h \
nsIEventListenerManager.h \
nsIEventStateManager.h \
nsIPrivateDOMEvent.h \

Просмотреть файл

@ -29,6 +29,7 @@ EXPORTS = \
nsIPrivateTextEvent.h \
nsIPrivateTextRange.h \
nsIPrivateCompositionEvent.h \
nsMutationEvent.h \
$(NULL)
MODULE=raptor

Просмотреть файл

@ -142,6 +142,11 @@ public:
* manager.
*/
virtual nsresult SetListenerTarget(nsISupports* aTarget) = 0;
/**
* Allows us to quickly determine if we have mutation listeners registered.
*/
virtual nsresult HasMutationListeners(PRBool* aListener) = 0;
};
extern NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult);

Просмотреть файл

@ -58,5 +58,7 @@ extern nsresult NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult,
nsIPresContext* aPresContext,
const nsAReadableString& aEventType,
nsEvent *aEvent);
extern nsresult NS_NewDOMMutationEvent(nsIDOMEvent** aResult, nsIPresContext* aPresContext,
nsEvent* aEvent);
#endif // nsIPrivateDOMEvent_h__

Просмотреть файл

@ -0,0 +1,38 @@
#include "nsGUIEvent.h"
#include "nsIDOMNode.h"
#include "nsIAtom.h"
#include "nsIDOMEventTarget.h"
struct nsMutationEvent : public nsEvent
{
nsCOMPtr<nsIDOMNode> mRelatedNode;
nsCOMPtr<nsIDOMEventTarget> mTarget;
nsCOMPtr<nsIAtom> mAttrName;
nsCOMPtr<nsIAtom> mPrevAttrValue;
nsCOMPtr<nsIAtom> mNewAttrValue;
unsigned short mAttrChange;
};
#define NS_MUTATION_EVENT 20
#define NS_MUTATION_START 1800
#define NS_MUTATION_SUBTREEMODIFIED (NS_MUTATION_START)
#define NS_MUTATION_NODEINSERTED (NS_MUTATION_START+1)
#define NS_MUTATION_NODEREMOVED (NS_MUTATION_START+2)
#define NS_MUTATION_NODEREMOVEDFROMDOCUMENT (NS_MUTATION_START+3)
#define NS_MUTATION_NODEINSERTEDINTODOCUMENT (NS_MUTATION_START+4)
#define NS_MUTATION_ATTRMODIFIED (NS_MUTATION_START+5)
#define NS_MUTATION_CHARACTERDATAMODIFIED (NS_MUTATION_START+6)
// Bits are actually checked to optimize mutation event firing.
// That's why I don't number from 0x00. The first event should
// always be 0x01.
#define NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED 0x01
#define NS_EVENT_BITS_MUTATION_NODEINSERTED 0x02
#define NS_EVENT_BITS_MUTATION_NODEREMOVED 0x04
#define NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT 0x08
#define NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT 0x10
#define NS_EVENT_BITS_MUTATION_ATTRMODIFIED 0x20
#define NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED 0x40

Просмотреть файл

@ -34,6 +34,7 @@ CPPSRCS = \
nsEventListenerManager.cpp \
nsEventStateManager.cpp \
nsDOMEvent.cpp \
nsDOMMutationEvent.cpp \
nsDOMEventsIIDs.cpp \
nsPrivateTextRange.cpp \
$(NULL)

Просмотреть файл

@ -32,6 +32,7 @@ DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN
CPPSRCS= nsEventListenerManager.cpp \
nsEventStateManager.cpp \
nsDOMEvent.cpp \
nsDOMMutationEvent.cpp \
nsDOMEventsIIDs.cpp \
nsPrivateTextRange.cpp \
$(NULL)
@ -39,6 +40,7 @@ CPPSRCS= nsEventListenerManager.cpp \
CPP_OBJS= .\$(OBJDIR)\nsEventListenerManager.obj \
.\$(OBJDIR)\nsEventStateManager.obj \
.\$(OBJDIR)\nsDOMEvent.obj \
.\$(OBJDIR)\nsDOMMutationEvent.obj \
.\$(OBJDIR)\nsDOMEventsIIDs.obj \
.\$(OBJDIR)\nsPrivateTextRange.obj \
$(NULL)

Просмотреть файл

@ -40,6 +40,7 @@
#include "nsIDOMAbstractView.h"
#include "prmem.h"
#include "nsLayoutAtoms.h"
#include "nsMutationEvent.h"
static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID);
@ -50,7 +51,10 @@ static char* mEventNames[] = {
"submit", "reset", "change", "select", "input", "paint" ,"text",
"create", "close", "destroy", "command", "broadcast", "commandupdate",
"dragenter", "dragover", "dragexit", "dragdrop", "draggesture", "resize",
"scroll","overflow", "underflow", "overflowchanged"
"scroll","overflow", "underflow", "overflowchanged",
"DOMSubtreeModified", "DOMNodeInserted", "DOMNodeRemoved",
"DOMNodeRemovedFromDocument", "DOMNodeInsertedIntoDocument",
"DOMAttrModified", "DOMCharacterDataModified"
};
nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAReadableString& aEventType) {
@ -76,6 +80,10 @@ nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAR
mEvent = PR_NEWZAP(nsEvent);
mEvent->eventStructType = NS_EVENT;
}
else if (eventType.EqualsIgnoreCase("MutationEvent")) {
mEvent = PR_NEWZAP(nsMutationEvent);
mEvent->eventStructType = NS_MUTATION_EVENT;
}
else {
mEvent = PR_NEWZAP(nsEvent);
mEvent->eventStructType = NS_EVENT;
@ -1013,7 +1021,6 @@ nsDOMEvent::InitKeyEvent(const nsAReadableString& aTypeArg, PRBool aCanBubbleArg
return NS_OK;
}
NS_METHOD nsDOMEvent::DuplicatePrivateData()
{
//XXX Write me!
@ -1183,6 +1190,20 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return mEventNames[eDOMEvents_underflow];
case NS_SCROLLPORT_OVERFLOWCHANGED:
return mEventNames[eDOMEvents_overflowchanged];
case NS_MUTATION_SUBTREEMODIFIED:
return mEventNames[eDOMEvents_subtreemodified];
case NS_MUTATION_NODEINSERTED:
return mEventNames[eDOMEvents_nodeinserted];
case NS_MUTATION_NODEREMOVED:
return mEventNames[eDOMEvents_noderemoved];
case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
return mEventNames[eDOMEvents_noderemovedfromdocument];
case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
return mEventNames[eDOMEvents_nodeinsertedintodocument];
case NS_MUTATION_ATTRMODIFIED:
return mEventNames[eDOMEvents_attrmodified];
case NS_MUTATION_CHARACTERDATAMODIFIED:
return mEventNames[eDOMEvents_characterdatamodified];
default:
break;
}

Просмотреть файл

@ -87,7 +87,14 @@ public:
eDOMEvents_scroll,
eDOMEvents_overflow,
eDOMEvents_underflow,
eDOMEvents_overflowchanged
eDOMEvents_overflowchanged,
eDOMEvents_subtreemodified,
eDOMEvents_nodeinserted,
eDOMEvents_noderemoved,
eDOMEvents_noderemovedfromdocument,
eDOMEvents_nodeinsertedintodocument,
eDOMEvents_attrmodified,
eDOMEvents_characterdatamodified
};
nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAReadableString& aEventType);

Просмотреть файл

@ -32,6 +32,7 @@
#include "nsIDOMCompositionListener.h"
#include "nsIDOMMenuListener.h"
#include "nsIDOMScrollListener.h"
#include "nsIDOMMutationListener.h"
NS_DEFINE_IID(kIDOMMouseListenerIID, NS_IDOMMOUSELISTENER_IID);
NS_DEFINE_IID(kIDOMKeyListenerIID, NS_IDOMKEYLISTENER_IID);
@ -45,3 +46,4 @@ NS_DEFINE_IID(kIDOMTextListenerIID,NS_IDOMTEXTLISTENER_IID);
NS_DEFINE_IID(kIDOMCompositionListenerIID,NS_IDOMCOMPOSITIONLISTENER_IID);
NS_DEFINE_IID(kIDOMMenuListenerIID, NS_IDOMMENULISTENER_IID);
NS_DEFINE_IID(kIDOMScrollListenerIID, NS_IDOMSCROLLLISTENER_IID);
NS_DEFINE_IID(kIDOMMutationListenerIID, NS_IDOMMUTATIONLISTENER_IID);

Просмотреть файл

@ -36,5 +36,6 @@ extern const nsIID kIDOMTextListenerIID;
extern const nsIID kIDOMCompositionListenerIID;
extern const nsIID kIDOMMenuListenerIID;
extern const nsIID kIDOMScrollListenerIID;
extern const nsIID kIDOMMutationListenerIID;
#endif /* nsDOMEVENTSIIDs_h___ */

Просмотреть файл

@ -0,0 +1,162 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsCOMPtr.h"
#include "nsIDOMMutationEvent.h"
#include "nsDOMEvent.h"
#include "nsMutationEvent.h"
class nsIPresContext;
class nsDOMMutationEvent : public nsIDOMMutationEvent, public nsDOMEvent
{
NS_DECL_IDOMMUTATIONEVENT
NS_FORWARD_IDOMEVENT(nsDOMEvent::)
NS_DECL_ISUPPORTS_INHERITED
nsDOMMutationEvent(nsIPresContext* aPresContext,
nsEvent* aEvent);
~nsDOMMutationEvent();
};
nsDOMMutationEvent::nsDOMMutationEvent(nsIPresContext* aPresContext,
nsEvent* aEvent)
:nsDOMEvent(aPresContext, aEvent, NS_LITERAL_STRING("MutationEvent"))
{
nsMutationEvent* mutation = (nsMutationEvent*)aEvent;
SetTarget(mutation->mTarget);
}
nsDOMMutationEvent::~nsDOMMutationEvent() {
}
NS_IMPL_ADDREF_INHERITED(nsDOMMutationEvent, nsDOMEvent)
NS_IMPL_RELEASE_INHERITED(nsDOMMutationEvent, nsDOMEvent)
NS_INTERFACE_MAP_BEGIN(nsDOMMutationEvent)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEvent, nsIDOMMutationEvent)
NS_INTERFACE_MAP_ENTRY(nsIPrivateDOMEvent)
NS_INTERFACE_MAP_ENTRY(nsIDOMMutationEvent)
NS_INTERFACE_MAP_END
NS_IMETHODIMP
nsDOMMutationEvent::GetRelatedNode(nsIDOMNode** aRelatedNode)
{
*aRelatedNode = nsnull;
if (mEvent) {
nsMutationEvent* mutation = NS_STATIC_CAST(nsMutationEvent*, mEvent);
*aRelatedNode = mutation->mRelatedNode;
NS_IF_ADDREF(*aRelatedNode);
}
else *aRelatedNode = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsDOMMutationEvent::GetPrevValue(nsAWritableString& aPrevValue)
{
if (mEvent) {
nsMutationEvent* mutation = NS_STATIC_CAST(nsMutationEvent*, mEvent);
if (mutation && mutation->mPrevAttrValue)
mutation->mPrevAttrValue->ToString(aPrevValue);
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMMutationEvent::GetNewValue(nsAWritableString& aNewValue)
{
if (mEvent) {
nsMutationEvent* mutation = NS_STATIC_CAST(nsMutationEvent*, mEvent);
if (mutation && mutation->mNewAttrValue)
mutation->mNewAttrValue->ToString(aNewValue);
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMMutationEvent::GetAttrName(nsAWritableString& aAttrName)
{
if (mEvent) {
nsMutationEvent* mutation = NS_STATIC_CAST(nsMutationEvent*, mEvent);
if (mutation && mutation->mAttrName)
mutation->mAttrName->ToString(aAttrName);
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMMutationEvent::GetAttrChange(PRUint16* aAttrChange)
{
*aAttrChange = 0;
if (mEvent) {
nsMutationEvent* mutation = NS_STATIC_CAST(nsMutationEvent*, mEvent);
if (mutation && mutation->mAttrChange)
*aAttrChange = mutation->mAttrChange;
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMMutationEvent::InitMutationEvent(const nsAReadableString& aTypeArg, PRBool aCanBubbleArg,
PRBool aCancelableArg, nsIDOMNode* aRelatedNodeArg,
const nsAReadableString& aPrevValueArg,
const nsAReadableString& aNewValueArg,
const nsAReadableString& aAttrNameArg)
{
NS_ENSURE_SUCCESS(SetEventType(aTypeArg), NS_ERROR_FAILURE);
mEvent->flags |= aCanBubbleArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_BUBBLE;
mEvent->flags |= aCancelableArg ? NS_EVENT_FLAG_NONE : NS_EVENT_FLAG_CANT_CANCEL;
nsMutationEvent* mutation = NS_STATIC_CAST(nsMutationEvent*, mEvent);
if (mutation) {
mutation->mRelatedNode = aRelatedNodeArg;
if (!aPrevValueArg.IsEmpty())
mutation->mPrevAttrValue = getter_AddRefs(NS_NewAtom(aPrevValueArg));
if (!aNewValueArg.IsEmpty())
mutation->mNewAttrValue = getter_AddRefs(NS_NewAtom(aNewValueArg));
if (!aAttrNameArg.IsEmpty()) {
mutation->mAttrName = getter_AddRefs(NS_NewAtom(aAttrNameArg));
// I guess we assume modification. Weird that this isn't specifiable.
mutation->mAttrChange = nsIDOMMutationEvent::MODIFICATION;
}
}
return NS_OK;
};
nsresult NS_NewDOMMutationEvent(nsIDOMEvent** aInstancePtrResult,
nsIPresContext* aPresContext,
nsEvent *aEvent)
{
nsDOMMutationEvent* it = new nsDOMMutationEvent(aPresContext, aEvent);
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
return it->QueryInterface(NS_GET_IID(nsIDOMEvent), (void **) aInstancePtrResult);
}

Просмотреть файл

@ -37,7 +37,9 @@
#include "nsIDOMCompositionListener.h"
#include "nsIDOMMenuListener.h"
#include "nsIDOMScrollListener.h"
#include "nsIDOMMutationListener.h"
#include "nsIEventStateManager.h"
#include "nsPIDOMWindow.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIScriptObjectOwner.h"
#include "nsIScriptEventListener.h"
@ -56,6 +58,7 @@
#include "nsIJSContextStack.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
#include "nsMutationEvent.h"
static NS_DEFINE_IID(kIEventListenerManagerIID, NS_IEVENTLISTENERMANAGER_IID);
static NS_DEFINE_IID(kIDOMEventListenerIID, NS_IDOMEVENTLISTENER_IID);
@ -77,6 +80,7 @@ nsEventListenerManager::nsEventListenerManager()
mCompositionListeners = nsnull;
mMenuListeners = nsnull;
mScrollListeners = nsnull;
mMutationListeners = nsnull;
mDestroyed = PR_FALSE;
mTarget = nsnull;
NS_INIT_REFCNT();
@ -97,6 +101,7 @@ nsEventListenerManager::~nsEventListenerManager()
ReleaseListeners(&mCompositionListeners, PR_FALSE);
ReleaseListeners(&mMenuListeners, PR_FALSE);
ReleaseListeners(&mScrollListeners, PR_FALSE);
ReleaseListeners(&mMutationListeners, PR_FALSE);
}
NS_IMPL_ADDREF(nsEventListenerManager)
@ -184,6 +189,9 @@ nsVoidArray** nsEventListenerManager::GetListenersByIID(const nsIID& aIID)
else if (aIID.Equals(kIDOMScrollListenerIID)) {
return &mScrollListeners;
}
else if (aIID.Equals(kIDOMMutationListenerIID)) {
return &mMutationListeners;
}
return nsnull;
}
@ -245,6 +253,25 @@ nsresult nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener
return NS_ERROR_OUT_OF_MEMORY;
}
// For mutation listeners, we need to update the global bit on the DOM window.
// Otherwise we won't actually fire the mutation event.
if (aIID.Equals(NS_GET_IID(nsIDOMMutationListener))) {
// Go from our target to the nearest enclosing DOM window.
nsCOMPtr<nsIScriptGlobalObject> global;
nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIContent> content(do_QueryInterface(mTarget));
if (content)
content->GetDocument(*getter_AddRefs(document));
else document = do_QueryInterface(mTarget);
if (document)
document->GetScriptGlobalObject(getter_AddRefs(global));
else global = do_QueryInterface(mTarget);
if (global) {
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(global));
window->SetMutationListeners(aSubType);
}
}
PRBool found = PR_FALSE;
nsListenerStruct* ls;
nsresult rv;
@ -504,6 +531,34 @@ nsresult nsEventListenerManager::GetIdentifiersForType(nsIAtom* aType, nsIID& aI
aIID = NS_GET_IID(nsIDOMDragListener);
*aFlags = NS_EVENT_BITS_DRAG_GESTURE;
}
else if (aType == nsLayoutAtoms::onDOMSubtreeModified) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED;
}
else if (aType == nsLayoutAtoms::onDOMNodeInserted) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_NODEINSERTED;
}
else if (aType == nsLayoutAtoms::onDOMNodeRemoved) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_NODEREMOVED;
}
else if (aType == nsLayoutAtoms::onDOMNodeInsertedIntoDocument) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT;
}
else if (aType == nsLayoutAtoms::onDOMNodeRemovedFromDocument) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT;
}
else if (aType == nsLayoutAtoms::onDOMAttrModified) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_ATTRMODIFIED;
}
else if (aType == nsLayoutAtoms::onDOMCharacterDataModified) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED;
}
else {
return NS_ERROR_FAILURE;
}
@ -1676,6 +1731,112 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
}
break;
case NS_MUTATION_SUBTREEMODIFIED:
case NS_MUTATION_NODEINSERTED:
case NS_MUTATION_NODEREMOVED:
case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
case NS_MUTATION_ATTRMODIFIED:
case NS_MUTATION_CHARACTERDATAMODIFIED:
if (nsnull != mMutationListeners) {
if (nsnull == *aDOMEvent) {
ret = NS_NewDOMMutationEvent(aDOMEvent, aPresContext, aEvent);
}
if (NS_OK == ret) {
for (int i=0; mMutationListeners && i<mMutationListeners->Count(); i++) {
nsListenerStruct *ls;
nsCOMPtr<nsIDOMMutationListener> mutationListener;
ls = (nsListenerStruct*)mMutationListeners->ElementAt(i);
if (ls->mFlags & aFlags) {
mutationListener = do_QueryInterface(ls->mListener);
if (mutationListener) {
switch(aEvent->message) {
case NS_MUTATION_SUBTREEMODIFIED:
ret = mutationListener->SubtreeModified(*aDOMEvent);
break;
case NS_MUTATION_NODEINSERTED:
ret = mutationListener->NodeInserted(*aDOMEvent);
break;
case NS_MUTATION_NODEREMOVED:
ret = mutationListener->NodeRemoved(*aDOMEvent);
break;
case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
ret = mutationListener->NodeInsertedIntoDocument(*aDOMEvent);
break;
case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
ret = mutationListener->NodeRemovedFromDocument(*aDOMEvent);
break;
case NS_MUTATION_ATTRMODIFIED:
ret = mutationListener->AttrModified(*aDOMEvent);
break;
case NS_MUTATION_CHARACTERDATAMODIFIED:
ret = mutationListener->CharacterDataModified(*aDOMEvent);
break;
default:
break;
}
}
else {
PRBool correctSubType = PR_FALSE;
PRUint32 subType = 0;
switch(aEvent->message) {
case NS_MUTATION_SUBTREEMODIFIED:
subType = NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_NODEINSERTED:
subType = NS_EVENT_BITS_MUTATION_NODEINSERTED;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_NODEINSERTED) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_NODEREMOVED:
subType = NS_EVENT_BITS_MUTATION_NODEREMOVED;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_NODEREMOVED) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
subType = NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
subType = NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_ATTRMODIFIED:
subType = NS_EVENT_BITS_MUTATION_ATTRMODIFIED;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_ATTRMODIFIED) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_CHARACTERDATAMODIFIED:
subType = NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED) {
correctSubType = PR_TRUE;
}
break;
default:
break;
}
if (correctSubType || ls->mSubType == NS_EVENT_BITS_NONE) {
ret = HandleEventSubType(ls, *aDOMEvent, aCurrentTarget, subType, aFlags);
}
}
}
}
}
}
break;
default:
break;
}
@ -1701,10 +1862,12 @@ nsresult nsEventListenerManager::CreateEvent(nsIPresContext* aPresContext,
{
nsAutoString str(aEventType);
if (!aEvent && !str.EqualsIgnoreCase("MouseEvent") && !str.EqualsIgnoreCase("KeyEvent") &&
!str.EqualsIgnoreCase("HTMLEvent")) {
!str.EqualsIgnoreCase("HTMLEvent") && !str.EqualsIgnoreCase("MutationEvent")) {
return NS_ERROR_FAILURE;
}
if (str.EqualsIgnoreCase("MutationEvent"))
return NS_NewDOMMutationEvent(aDOMEvent, aPresContext, aEvent);
return NS_NewDOMUIEvent(aDOMEvent, aPresContext, aEventType, aEvent);
}
@ -1965,6 +2128,7 @@ nsresult nsEventListenerManager::RemoveAllListeners(PRBool aScriptOnly)
ReleaseListeners(&mPaintListeners, aScriptOnly);
ReleaseListeners(&mTextListeners, aScriptOnly);
ReleaseListeners(&mCompositionListeners, aScriptOnly);
ReleaseListeners(&mMutationListeners, aScriptOnly);
mDestroyed = PR_TRUE;
return NS_OK;
}

Просмотреть файл

@ -107,6 +107,8 @@ public:
virtual nsresult SetListenerTarget(nsISupports* aTarget);
virtual nsresult HasMutationListeners(PRBool* aListener) { *aListener = (mMutationListeners != nsnull); return NS_OK; };
static nsresult GetIdentifiersForType(nsIAtom* aType, nsIID& aIID, PRInt32* aSubType);
// nsIDOMEventTarget interface
@ -151,6 +153,8 @@ protected:
nsVoidArray* mCompositionListeners;
nsVoidArray* mMenuListeners;
nsVoidArray* mScrollListeners;
nsVoidArray* mMutationListeners;
nsCOMPtr<nsIPrincipal> mPrincipal;
PRBool mDestroyed;
@ -242,4 +246,7 @@ protected:
#define NS_EVENT_BITS_PAINT_RESIZE 0x02
#define NS_EVENT_BITS_PAINT_SCROLL 0x04
//nsIDOMMutationListener
// These bits are found in nsMutationEvent.h.
#endif // nsEventListenerManager_h__

Просмотреть файл

@ -42,6 +42,7 @@
#include "nsIHTMLContent.h"
#include "nsILink.h"
#include "nsILinkHandler.h"
#include "nsPIDOMWindow.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptObjectOwner.h"
#include "nsISizeOfHandler.h"
@ -86,6 +87,13 @@
#include "nsIDOMHTMLFormElement.h"
#include "nsILanguageAtomService.h"
#include "nsIDOMMutationEvent.h"
#include "nsMutationEvent.h"
#include "nsEventListenerManager.h"
#include "nsIBindingManager.h"
#include "nsIXBLBinding.h"
#include "nsIParser.h"
#include "nsParserCIID.h"
#include "nsIHTMLContentSink.h"
@ -1229,6 +1237,73 @@ nsGenericHTMLElement::NormalizeAttributeString(const nsAReadableString& aStr,
return nimgr->GetNodeInfo(lower, nsnull, kNameSpaceID_None, aNodeInfo);
}
static PRBool HasMutationListeners(nsIContent* aContent, PRUint32 aType)
{
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (!doc)
return PR_FALSE;
nsCOMPtr<nsIScriptGlobalObject> global;
doc->GetScriptGlobalObject(getter_AddRefs(global));
if (!global)
return PR_FALSE;
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(global));
if (!window)
return PR_FALSE;
PRBool set;
window->HasMutationListeners(aType, &set);
if (!set)
return PR_FALSE;
// We know a mutation listener is registered, but it might not
// be in our chain. Check quickly to see.
nsCOMPtr<nsIContent> curr = aContent;
nsCOMPtr<nsIEventListenerManager> manager;
while (curr) {
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(curr));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
nsCOMPtr<nsIContent> prev = curr;
prev->GetParent(*getter_AddRefs(curr));
}
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
rec = do_QueryInterface(window);
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
return PR_FALSE;
}
nsresult
nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
@ -1302,6 +1377,9 @@ nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
if (NS_OK != result) {
return result;
}
nsAutoString strValue;
PRBool modification = PR_TRUE;
if (NS_CONTENT_ATTR_NOT_THERE !=
htmlContent->StringToAttribute(aAttribute, aValue, val)) {
// string value was mapped to nsHTMLValue, set it that way
@ -1324,13 +1402,14 @@ nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
}
// don't do any update if old == new
nsAutoString strValue;
result = GetAttribute(aNameSpaceID, aAttribute, strValue);
if ((NS_CONTENT_ATTR_NOT_THERE != result) && aValue.Equals(strValue)) {
NS_RELEASE(htmlContent);
return NS_OK;
}
modification = (result != NS_CONTENT_ATTR_NOT_THERE);
if (aNotify && (nsnull != mDocument)) {
mDocument->BeginUpdate();
}
@ -1363,11 +1442,45 @@ nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
}
NS_RELEASE(htmlContent);
if (aNotify && (nsnull != mDocument)) {
result = mDocument->AttributeChanged(mContent, aNameSpaceID, aAttribute, NS_STYLE_HINT_UNKNOWN);
mDocument->EndUpdate();
}
if (mDocument) {
nsCOMPtr<nsIBindingManager> bindingManager;
mDocument->GetBindingManager(getter_AddRefs(bindingManager));
nsCOMPtr<nsIXBLBinding> binding;
bindingManager->GetBinding(mContent, getter_AddRefs(binding));
if (binding)
binding->AttributeChanged(aAttribute, aNameSpaceID, PR_FALSE);
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(mContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName;
aAttribute->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aAttribute;
if (!strValue.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(strValue));
if (!aValue.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(aValue));
mutation.mAttrChange = modification ? nsIDOMMutationEvent::MODIFICATION :
nsIDOMMutationEvent::ADDITION;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
mDocument->AttributeChanged(mContent, aNameSpaceID, aAttribute, NS_STYLE_HINT_UNKNOWN);
mDocument->EndUpdate();
}
}
return result;
}
@ -1447,6 +1560,41 @@ nsGenericHTMLElement::SetHTMLAttribute(nsIAtom* aAttribute,
htmlContent, mAttributes);
NS_RELEASE(sheet);
}
nsCOMPtr<nsIBindingManager> bindingManager;
mDocument->GetBindingManager(getter_AddRefs(bindingManager));
nsCOMPtr<nsIXBLBinding> binding;
bindingManager->GetBinding(mContent, getter_AddRefs(binding));
if (binding)
binding->AttributeChanged(aAttribute, kNameSpaceID_None, PR_TRUE);
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
// XXX Figure out how to get the old value, so I can fill in
// the prevValue field and so that I can correctly indicate
// MODIFICATIONs/ADDITIONs.
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(mContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName;
aAttribute->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aAttribute;
nsAutoString value;
aValue.ToString(value);
if (!value.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(value));
mutation.mAttrChange = nsIDOMMutationEvent::MODIFICATION;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
mDocument->AttributeChanged(mContent, kNameSpaceID_None, aAttribute, impact);
mDocument->EndUpdate();
@ -1504,11 +1652,48 @@ nsGenericHTMLElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
}
}
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(mContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName;
aAttribute->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aAttribute;
nsHTMLValue oldAttr;
GetHTMLAttribute(aAttribute, oldAttr);
nsAutoString attr;
oldAttr.ToString(attr);
if (!attr.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(attr));
mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
if (nsnull != sheet) {
result = sheet->UnsetAttributeFor(aAttribute, htmlContent, mAttributes);
NS_RELEASE(sheet);
}
nsCOMPtr<nsIBindingManager> bindingManager;
mDocument->GetBindingManager(getter_AddRefs(bindingManager));
nsCOMPtr<nsIXBLBinding> binding;
bindingManager->GetBinding(mContent, getter_AddRefs(binding));
if (binding)
binding->AttributeChanged(aAttribute, aNameSpaceID, PR_TRUE);
if (aNotify) {
mDocument->AttributeChanged(mContent, aNameSpaceID, aAttribute, impact);
mDocument->EndUpdate();
@ -3198,7 +3383,6 @@ nsGenericHTMLLeafElement::GetChildNodes(nsIDOMNodeList** aChildNodes)
return slots->mChildNodes->QueryInterface(NS_GET_IID(nsIDOMNodeList), (void **)aChildNodes);
}
//----------------------------------------------------------------------
nsGenericHTMLContainerElement::nsGenericHTMLContainerElement()
@ -3375,6 +3559,21 @@ nsGenericHTMLContainerElement::InsertChildAt(nsIContent* aKid,
if (aNotify) {
doc->ContentInserted(mContent, aKid, aIndex);
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
}
}
if (aNotify && (nsnull != doc)) {
@ -3433,6 +3632,21 @@ nsGenericHTMLContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
if (aNotify) {
doc->ContentAppended(mContent, mChildren.Count() - 1);
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
}
}
if (aNotify && (nsnull != doc)) {
@ -3450,6 +3664,22 @@ nsGenericHTMLContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
}
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
if (nsnull != oldKid ) {
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(oldKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEREMOVED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
oldKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
nsRange::OwnerChildRemoved(mContent, aIndex, oldKid);
mChildren.RemoveElementAt(aIndex);
if (aNotify) {

Просмотреть файл

@ -164,6 +164,15 @@ LAYOUT_ATOM(onoverflow, "onoverflow")
LAYOUT_ATOM(onunderflow, "onunderflow")
LAYOUT_ATOM(onoverflowchanged, "onoverflowchanged")
// mutation events
LAYOUT_ATOM(onDOMSubtreeModified, "onDOMSubtreeModified")
LAYOUT_ATOM(onDOMNodeInserted, "onDOMNodeInserted")
LAYOUT_ATOM(onDOMNodeRemoved, "onDOMNodeRemoved")
LAYOUT_ATOM(onDOMNodeRemovedFromDocument, "onDOMNodeRemovedFromDocument")
LAYOUT_ATOM(onDOMNodeInsertedIntoDocument, "onDOMNodeInsertedIntoDocument")
LAYOUT_ATOM(onDOMAttrModified, "onDOMAttrModified")
LAYOUT_ATOM(onDOMCharacterDataModified, "onDOMCharacterDataModified")
// Alphabetical list of languages for lang-specific transforms
LAYOUT_ATOM(Japanese, "ja")
LAYOUT_ATOM(Korean, "ko")

Просмотреть файл

@ -40,6 +40,7 @@ CPPSRCS = \
nsXBLDragHandler.cpp \
nsXBLMouseHandler.cpp \
nsXBLMouseMotionHandler.cpp \
nsXBLMutationHandler.cpp \
nsXBLKeyHandler.cpp \
nsXBLLoadHandler.cpp \
nsXBLXULHandler.cpp \

Просмотреть файл

@ -35,6 +35,7 @@ CPPSRCS= \
nsXBLKeyHandler.cpp \
nsXBLMouseHandler.cpp \
nsXBLMouseMotionHandler.cpp \
nsXBLMutationHandler.cpp \
nsXBLDragHandler.cpp \
nsXBLFocusHandler.cpp \
nsXBLXULHandler.cpp \
@ -53,6 +54,7 @@ CPP_OBJS= \
.\$(OBJDIR)\nsXBLKeyHandler.obj \
.\$(OBJDIR)\nsXBLMouseHandler.obj \
.\$(OBJDIR)\nsXBLMouseMotionHandler.obj \
.\$(OBJDIR)\nsXBLMutationHandler.obj \
.\$(OBJDIR)\nsXBLDragHandler.obj \
.\$(OBJDIR)\nsXBLFocusHandler.obj \
.\$(OBJDIR)\nsXBLXULHandler.obj \

Просмотреть файл

@ -63,6 +63,7 @@
#include "nsIDOMFormListener.h"
#include "nsIDOMMenuListener.h"
#include "nsIDOMDragListener.h"
#include "nsIDOMMutationListener.h"
#include "nsIDOMAttr.h"
#include "nsIDOMNamedNodeMap.h"
@ -73,6 +74,7 @@
#include "nsXBLFocusHandler.h"
#include "nsXBLMouseHandler.h"
#include "nsXBLMouseMotionHandler.h"
#include "nsXBLMutationHandler.h"
#include "nsXBLXULHandler.h"
#include "nsXBLScrollHandler.h"
#include "nsXBLFormHandler.h"
@ -211,6 +213,14 @@ nsXBLBinding::kEventHandlerMap[] = {
{ "dragdrop", nsnull, &NS_GET_IID(nsIDOMDragListener) },
{ "draggesture", nsnull, &NS_GET_IID(nsIDOMDragListener) },
{ "DOMSubtreeModified", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMAttrModified", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMCharacterDataModified", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMNodeInserted", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMNodeRemoved", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMNodeInsertedIntoDocument", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMNodeRemovedFromDocument", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ nsnull, nsnull, nsnull }
};
@ -654,6 +664,12 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB
receiver->AddEventListener(type, (nsIDOMLoadListener*)loadHandler, useCapture);
handler = loadHandler;
}
else if(iid.Equals(NS_GET_IID(nsIDOMMutationListener))) {
nsXBLMutationHandler* mutationHandler;
NS_NewXBLMutationHandler(receiver, curr, &mutationHandler);
receiver->AddEventListener(type, (nsIDOMMutationListener*)mutationHandler, useCapture);
handler = mutationHandler;
}
else {
NS_WARNING("***** Non-compliant XBL event listener attached! *****");
nsAutoString value;

Просмотреть файл

@ -0,0 +1,201 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
*/
#include "nsCOMPtr.h"
#include "nsIXBLPrototypeHandler.h"
#include "nsXBLMutationHandler.h"
#include "nsIContent.h"
#include "nsIAtom.h"
#include "nsINameSpaceManager.h"
#include "nsIScriptContext.h"
#include "nsIScriptObjectOwner.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIEventListenerManager.h"
#include "nsIDOMEventReceiver.h"
#include "nsXBLBinding.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMWindowInternal.h"
#include "nsIPref.h"
#include "nsIServiceManager.h"
#include "nsIURI.h"
#include "nsXPIDLString.h"
PRUint32 nsXBLMutationHandler::gRefCnt = 0;
nsIAtom* nsXBLMutationHandler::kSubtreeModifiedAtom = nsnull;
nsIAtom* nsXBLMutationHandler::kAttrModifiedAtom = nsnull;
nsIAtom* nsXBLMutationHandler::kCharacterDataModifiedAtom = nsnull;
nsIAtom* nsXBLMutationHandler::kNodeRemovedAtom = nsnull;
nsIAtom* nsXBLMutationHandler::kNodeInsertedAtom = nsnull;
nsIAtom* nsXBLMutationHandler::kNodeRemovedFromDocumentAtom = nsnull;
nsIAtom* nsXBLMutationHandler::kNodeInsertedIntoDocumentAtom = nsnull;
nsXBLMutationHandler::nsXBLMutationHandler(nsIDOMEventReceiver* aReceiver, nsIXBLPrototypeHandler* aHandler)
:nsXBLEventHandler(aReceiver,aHandler)
{
gRefCnt++;
if (gRefCnt == 1) {
kNodeRemovedAtom = NS_NewAtom("DOMNodeRemoved");
kNodeInsertedAtom = NS_NewAtom("DOMNodeInserted");
kNodeRemovedFromDocumentAtom = NS_NewAtom("DOMNodeRemovedFromDocument");
kNodeInsertedIntoDocumentAtom = NS_NewAtom("DOMNodeInsertedIntoDocument");
kSubtreeModifiedAtom = NS_NewAtom("DOMSubtreeModified");
kAttrModifiedAtom = NS_NewAtom("DOMAttrModified");
kCharacterDataModifiedAtom = NS_NewAtom("DOMCharacterDataModified");
}
}
nsXBLMutationHandler::~nsXBLMutationHandler()
{
gRefCnt--;
if (gRefCnt == 0) {
NS_RELEASE(kSubtreeModifiedAtom);
NS_RELEASE(kAttrModifiedAtom);
NS_RELEASE(kCharacterDataModifiedAtom);
NS_RELEASE(kNodeInsertedAtom);
NS_RELEASE(kNodeRemovedAtom);
NS_RELEASE(kNodeInsertedIntoDocumentAtom);
NS_RELEASE(kNodeRemovedFromDocumentAtom);
}
}
NS_IMPL_ISUPPORTS_INHERITED1(nsXBLMutationHandler, nsXBLEventHandler, nsIDOMMutationListener)
nsresult nsXBLMutationHandler::SubtreeModified(nsIDOMEvent* aEvent)
{
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
if (eventName.get() != kSubtreeModifiedAtom)
return NS_OK;
mProtoHandler->ExecuteHandler(mEventReceiver, aEvent);
return NS_OK;
}
nsresult nsXBLMutationHandler::AttrModified(nsIDOMEvent* aEvent)
{
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
if (eventName.get() != kAttrModifiedAtom)
return NS_OK;
mProtoHandler->ExecuteHandler(mEventReceiver, aEvent);
return NS_OK;
}
nsresult nsXBLMutationHandler::CharacterDataModified(nsIDOMEvent* aEvent)
{
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
if (eventName.get() != kCharacterDataModifiedAtom)
return NS_OK;
mProtoHandler->ExecuteHandler(mEventReceiver, aEvent);
return NS_OK;
}
nsresult nsXBLMutationHandler::NodeInserted(nsIDOMEvent* aEvent)
{
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
if (eventName.get() != kNodeInsertedAtom)
return NS_OK;
mProtoHandler->ExecuteHandler(mEventReceiver, aEvent);
return NS_OK;
}
nsresult nsXBLMutationHandler::NodeRemoved(nsIDOMEvent* aEvent)
{
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
if (eventName.get() != kNodeRemovedAtom)
return NS_OK;
mProtoHandler->ExecuteHandler(mEventReceiver, aEvent);
return NS_OK;
}
nsresult nsXBLMutationHandler::NodeInsertedIntoDocument(nsIDOMEvent* aEvent)
{
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
if (eventName.get() != kNodeInsertedAtom)
return NS_OK;
mProtoHandler->ExecuteHandler(mEventReceiver, aEvent);
return NS_OK;
}
nsresult nsXBLMutationHandler::NodeRemovedFromDocument(nsIDOMEvent* aEvent)
{
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIAtom> eventName;
mProtoHandler->GetEventName(getter_AddRefs(eventName));
if (eventName.get() != kNodeRemovedAtom)
return NS_OK;
mProtoHandler->ExecuteHandler(mEventReceiver, aEvent);
return NS_OK;
}
///////////////////////////////////////////////////////////////////////////////////
nsresult
NS_NewXBLMutationHandler(nsIDOMEventReceiver* aRec, nsIXBLPrototypeHandler* aHandler,
nsXBLMutationHandler** aResult)
{
*aResult = new nsXBLMutationHandler(aRec, aHandler);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
* Contributor(s):
*/
#ifndef nsXBLMutationHandler_h__
#define nsXBLMutationHandler_h__
#include "nsIDOMMutationListener.h"
#include "nsXBLEventHandler.h"
class nsIXBLBinding;
class nsIDOMEvent;
class nsIContent;
class nsIDOMUIEvent;
class nsIAtom;
class nsIController;
class nsIXBLPrototypeHandler;
class nsXBLMutationHandler : public nsIDOMMutationListener,
public nsXBLEventHandler
{
public:
nsXBLMutationHandler(nsIDOMEventReceiver* aReceiver, nsIXBLPrototypeHandler* aHandler);
virtual ~nsXBLMutationHandler();
// nsIDOMetc.
virtual nsresult HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; };
NS_IMETHOD SubtreeModified(nsIDOMEvent* aEvent);
NS_IMETHOD AttrModified(nsIDOMEvent* aEvent);
NS_IMETHOD CharacterDataModified(nsIDOMEvent* aEvent);
NS_IMETHOD NodeInserted(nsIDOMEvent* aEvent);
NS_IMETHOD NodeRemoved(nsIDOMEvent* aEvent);
NS_IMETHOD NodeInsertedIntoDocument(nsIDOMEvent* aEvent);
NS_IMETHOD NodeRemovedFromDocument(nsIDOMEvent* aEvent);
NS_DECL_ISUPPORTS_INHERITED
protected:
static PRUint32 gRefCnt;
static nsIAtom* kSubtreeModifiedAtom;
static nsIAtom* kAttrModifiedAtom;
static nsIAtom* kCharacterDataModifiedAtom;
static nsIAtom* kNodeInsertedAtom;
static nsIAtom* kNodeRemovedAtom;
static nsIAtom* kNodeInsertedIntoDocumentAtom;
static nsIAtom* kNodeRemovedFromDocumentAtom;
protected:
// Members
};
extern nsresult
NS_NewXBLMutationHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandlerElement,
nsXBLMutationHandler** aResult);
#endif

Просмотреть файл

@ -116,6 +116,10 @@
#include "nsXULAtoms.h"
#include "nsITreeBoxObject.h"
#include "nsMutationEvent.h"
#include "nsIDOMMutationEvent.h"
#include "nsPIDOMWindow.h"
#include "prlog.h"
#include "rdf.h"
#include "rdfutil.h"
@ -297,6 +301,75 @@ struct XULBroadcastListener
//----------------------------------------------------------------------
static PRBool HasMutationListeners(nsIContent* aContent, PRUint32 aType)
{
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (!doc)
return PR_FALSE;
nsCOMPtr<nsIScriptGlobalObject> global;
doc->GetScriptGlobalObject(getter_AddRefs(global));
if (!global)
return PR_FALSE;
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(global));
if (!window)
return PR_FALSE;
PRBool set;
window->HasMutationListeners(aType, &set);
if (!set)
return PR_FALSE;
// We know a mutation listener is registered, but it might not
// be in our chain. Check quickly to see.
nsCOMPtr<nsIContent> curr = aContent;
nsCOMPtr<nsIEventListenerManager> manager;
while (curr) {
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(curr));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
nsCOMPtr<nsIContent> prev = curr;
prev->GetParent(*getter_AddRefs(curr));
}
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
rec = do_QueryInterface(window);
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
return PR_FALSE;
}
//----------------------------------------------------------------------
nsrefcnt nsXULElement::gRefCnt;
nsIRDFService* nsXULElement::gRDFService;
nsINameSpaceManager* nsXULElement::gNameSpaceManager;
@ -2353,6 +2426,22 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify)
// N.B. that this is "shallow"!
aKid->SetDocument(mDocument, PR_FALSE, PR_TRUE);
if (mDocument && HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this),
NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this)));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify && mDocument) {
mDocument->ContentInserted(NS_STATIC_CAST(nsIStyledContent*, this), aKid, aIndex);
}
@ -2422,6 +2511,22 @@ nsXULElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
// N.B. that this is only "shallow". Callers beware!
aKid->SetDocument(mDocument, PR_FALSE, PR_TRUE);
if (mDocument && HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this),
NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this)));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify && mDocument) {
mDocument->ContentAppended(NS_STATIC_CAST(nsIStyledContent*, this), mChildren.Count() - 1);
}
@ -2440,6 +2545,21 @@ nsXULElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
if (! oldKid)
return NS_ERROR_FAILURE;
if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this), NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(oldKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEREMOVED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this)));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
oldKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
// On the removal of a <treeitem>, <treechildren>, or <treecell> element,
// the possibility exists that some of the items in the removed subtree
// are selected (and therefore need to be deselected). We need to account for this.
@ -2706,12 +2826,16 @@ nsXULElement::SetAttribute(nsINodeInfo* aNodeInfo,
i++;
}
PRBool modification = PR_TRUE;
nsAutoString oldValue;
if (i < count) {
attr->GetValue(oldValue);
attr->SetValueInternal(aValue);
}
else {
// didn't find it
modification = PR_FALSE;
rv = nsXULAttribute::Create(NS_STATIC_CAST(nsIStyledContent*, this),
aNodeInfo, aValue, &attr);
if (NS_FAILED(rv)) return rv;
@ -2767,6 +2891,31 @@ nsXULElement::SetAttribute(nsINodeInfo* aNodeInfo,
if (binding)
binding->AttributeChanged(attrName, attrns, PR_FALSE);
if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*, this), NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName2;
attrName->ToString(attrName2);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName2, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = attrName;
if (!oldValue.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(oldValue));
if (!aValue.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(aValue));
mutation.mAttrChange = modification ? nsIDOMMutationEvent::MODIFICATION :
nsIDOMMutationEvent::ADDITION;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
nsCOMPtr<nsIAtom> tagName;
NodeInfo()->GetNameAtom(*getter_AddRefs(tagName));
@ -2938,6 +3087,29 @@ nsXULElement::UnsetAttribute(PRInt32 aNameSpaceID,
nsXULAttribute* attr = NS_REINTERPRET_CAST(nsXULAttribute*, Attributes()->ElementAt(i));
if (attr->GetNodeInfo()->Equals(aName, aNameSpaceID)) {
attr->GetValue(oldValue);
if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*, this), NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName2;
aName->ToString(attrName2);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName2, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aName;
if (!oldValue.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(oldValue));
mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
Attributes()->RemoveElementAt(i);
NS_RELEASE(attr);
successful = PR_TRUE;

Просмотреть файл

@ -40,7 +40,6 @@ class nsIFocusController;
#define NS_PIDOMWINDOW_IID \
{ 0x3aa80781, 0x7e6a, 0x11d3, { 0xbf, 0x87, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 } }
class nsPIDOMWindow : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_PIDOMWINDOW_IID; return iid; }
@ -59,6 +58,9 @@ public:
NS_IMETHOD GetChromeEventHandler(nsIChromeEventHandler** aHandler)=0;
NS_IMETHOD HasMutationListeners(PRUint32 aMutationEventType, PRBool* aResult)=0;
NS_IMETHOD SetMutationListeners(PRUint32 aType)=0;
NS_IMETHOD GetRootFocusController(nsIFocusController** aResult)=0;
/* from nsIBaseWindow */

Просмотреть файл

@ -6,6 +6,7 @@ nsIDOMEvent.h
nsIDOMUIEvent.h
nsIDOMKeyEvent.h
nsIDOMMouseEvent.h
nsIDOMMutationEvent.h
nsIDOMNSUIEvent.h
nsIDOMEventListener.h
nsIDOMEventCapturer.h
@ -16,6 +17,7 @@ nsIDOMKeyListener.h
nsIDOMLoadListener.h
nsIDOMMouseListener.h
nsIDOMMouseMotionListener.h
nsIDOMMutationListener.h
nsIDOMDragListener.h
nsIDOMPaintListener.h
nsIDOMEventTarget.h
@ -24,3 +26,4 @@ nsIDOMCompositionListener.h
nsIDOMMenuListener.h
nsIDOMScrollListener.h

Просмотреть файл

@ -33,6 +33,7 @@ EXPORTS = \
nsIDOMUIEvent.h \
nsIDOMKeyEvent.h \
nsIDOMMouseEvent.h \
nsIDOMMutationEvent.h \
nsIDOMEventListener.h \
nsIDOMEventCapturer.h \
nsIDOMEventReceiver.h \
@ -42,6 +43,7 @@ EXPORTS = \
nsIDOMLoadListener.h \
nsIDOMMouseListener.h \
nsIDOMMouseMotionListener.h \
nsIDOMMutationListener.h \
nsIDOMPaintListener.h \
nsIDOMDragListener.h \
nsIDOMNSUIEvent.h \

Просмотреть файл

@ -29,6 +29,7 @@ EXPORTS = \
nsIDOMUIEvent.h \
nsIDOMKeyEvent.h \
nsIDOMMouseEvent.h \
nsIDOMMutationEvent.h \
nsIDOMEventListener.h \
nsIDOMEventCapturer.h \
nsIDOMEventReceiver.h \
@ -38,6 +39,7 @@ EXPORTS = \
nsIDOMLoadListener.h \
nsIDOMMouseListener.h \
nsIDOMMouseMotionListener.h \
nsIDOMMutationListener.h \
nsIDOMPaintListener.h \
nsIDOMDragListener.h \
nsIDOMNSUIEvent.h \

Просмотреть файл

@ -0,0 +1,83 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* AUTO-GENERATED. DO NOT EDIT!!! */
#ifndef nsIDOMMutationEvent_h__
#define nsIDOMMutationEvent_h__
#include "nsISupports.h"
#include "nsString.h"
#include "nsIScriptContext.h"
#include "nsIDOMEvent.h"
class nsIDOMNode;
#define NS_IDOMMUTATIONEVENT_IID \
{ 0x8e440d86, 0x886a, 0x4e76, { 0x9e, 0x59, 0xc1, 0x3b, 0x93, 0x9c, 0x9a, 0x4b } }
class nsIDOMMutationEvent : public nsIDOMEvent {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IDOMMUTATIONEVENT_IID; return iid; }
enum {
MODIFICATION = 1,
ADDITION = 2,
REMOVAL = 3
};
NS_IMETHOD GetRelatedNode(nsIDOMNode** aRelatedNode)=0;
NS_IMETHOD GetPrevValue(nsAWritableString& aPrevValue)=0;
NS_IMETHOD GetNewValue(nsAWritableString& aNewValue)=0;
NS_IMETHOD GetAttrName(nsAWritableString& aAttrName)=0;
NS_IMETHOD GetAttrChange(PRUint16* aAttrChange)=0;
NS_IMETHOD InitMutationEvent(const nsAReadableString& aTypeArg, PRBool aCanBubbleArg, PRBool aCancelableArg, nsIDOMNode* aRelatedNodeArg, const nsAReadableString& aPrevValueArg, const nsAReadableString& aNewValueArg, const nsAReadableString& aAttrNameArg)=0;
};
#define NS_DECL_IDOMMUTATIONEVENT \
NS_IMETHOD GetRelatedNode(nsIDOMNode** aRelatedNode); \
NS_IMETHOD GetPrevValue(nsAWritableString& aPrevValue); \
NS_IMETHOD GetNewValue(nsAWritableString& aNewValue); \
NS_IMETHOD GetAttrName(nsAWritableString& aAttrName); \
NS_IMETHOD GetAttrChange(PRUint16* aAttrChange); \
NS_IMETHOD InitMutationEvent(const nsAReadableString& aTypeArg, PRBool aCanBubbleArg, PRBool aCancelableArg, nsIDOMNode* aRelatedNodeArg, const nsAReadableString& aPrevValueArg, const nsAReadableString& aNewValueArg, const nsAReadableString& aAttrNameArg); \
#define NS_FORWARD_IDOMMUTATIONEVENT(_to) \
NS_IMETHOD GetRelatedNode(nsIDOMNode** aRelatedNode) { return _to GetRelatedNode(aRelatedNode); } \
NS_IMETHOD GetPrevValue(nsAWritableString& aPrevValue) { return _to GetPrevValue(aPrevValue); } \
NS_IMETHOD GetNewValue(nsAWritableString& aNewValue) { return _to GetNewValue(aNewValue); } \
NS_IMETHOD GetAttrName(nsAWritableString& aAttrName) { return _to GetAttrName(aAttrName); } \
NS_IMETHOD GetAttrChange(PRUint16* aAttrChange) { return _to GetAttrChange(aAttrChange); } \
NS_IMETHOD InitMutationEvent(const nsAReadableString& aTypeArg, PRBool aCanBubbleArg, PRBool aCancelableArg, nsIDOMNode* aRelatedNodeArg, const nsAReadableString& aPrevValueArg, const nsAReadableString& aNewValueArg, const nsAReadableString& aAttrNameArg) { return _to InitMutationEvent(aTypeArg, aCanBubbleArg, aCancelableArg, aRelatedNodeArg, aPrevValueArg, aNewValueArg, aAttrNameArg); } \
extern "C" NS_DOM nsresult NS_InitMutationEventClass(nsIScriptContext *aContext, void **aPrototype);
extern "C" NS_DOM nsresult NS_NewScriptMutationEvent(nsIScriptContext *aContext, nsISupports *aSupports, nsISupports *aParent, void **aReturn);
#endif // nsIDOMMutationEvent_h__

Просмотреть файл

@ -0,0 +1,48 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsIDOMMutationListener_h__
#define nsIDOMMutationListener_h__
#include "nsIDOMEvent.h"
#include "nsIDOMEventListener.h"
/*
* Mutation event listener interface.
*/
// {0666EC94-3C54-4e16-8511-E8CC865F236C}
#define NS_IDOMMUTATIONLISTENER_IID \
{ 0x666ec94, 0x3c54, 0x4e16, { 0x85, 0x11, 0xe8, 0xcc, 0x86, 0x5f, 0x23, 0x6c } }
class nsIDOMMutationListener : public nsIDOMEventListener {
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDOMMUTATIONLISTENER_IID)
NS_IMETHOD SubtreeModified(nsIDOMEvent* aMutationEvent)=0;
NS_IMETHOD NodeInserted(nsIDOMEvent* aMutationEvent)=0;
NS_IMETHOD NodeRemoved(nsIDOMEvent* aMutationEvent)=0;
NS_IMETHOD NodeRemovedFromDocument(nsIDOMEvent* aMutationEvent)=0;
NS_IMETHOD NodeInsertedIntoDocument(nsIDOMEvent* aMutationEvent)=0;
NS_IMETHOD AttrModified(nsIDOMEvent* aMutationEvent)=0;
NS_IMETHOD CharacterDataModified(nsIDOMEvent* aMutationEvent)=0;
};
#endif // nsIDOMMutationListener_h__

Просмотреть файл

@ -30,6 +30,8 @@ MODULE = layout
IDLSRCS = \
Event.idl \
MutationEvent.idl \
MouseKeyEvent.idl \
UIEvent.idl \
$(NULL)

Просмотреть файл

Просмотреть файл

@ -28,6 +28,7 @@ IDLSRCS = \
Event.idl \
UIEvent.idl \
MouseKeyEvent.idl \
MutationEvent.idl \
XPCOM_DESTDIR=$(DEPTH)\dom\public\coreEvents
JSSTUB_DESTDIR=$(DEPTH)\dom\src\events

Просмотреть файл

@ -706,6 +706,12 @@ enum nsDOMProp {
NS_DOM_PROP_MOUSEEVENT_RELATEDTARGET,
NS_DOM_PROP_MOUSEEVENT_SCREENX,
NS_DOM_PROP_MOUSEEVENT_SCREENY,
NS_DOM_PROP_MUTATIONEVENT_ATTRCHANGE,
NS_DOM_PROP_MUTATIONEVENT_ATTRNAME,
NS_DOM_PROP_MUTATIONEVENT_INITMUTATIONEVENT,
NS_DOM_PROP_MUTATIONEVENT_NEWVALUE,
NS_DOM_PROP_MUTATIONEVENT_PREVVALUE,
NS_DOM_PROP_MUTATIONEVENT_RELATEDNODE,
NS_DOM_PROP_NAMEDNODEMAP_GETNAMEDITEM,
NS_DOM_PROP_NAMEDNODEMAP_GETNAMEDITEMNS,
NS_DOM_PROP_NAMEDNODEMAP_ITEM,

Просмотреть файл

@ -704,6 +704,12 @@
"mouseevent.relatedtarget", \
"mouseevent.screenx", \
"mouseevent.screeny", \
"mutationevent.attrchange", \
"mutationevent.attrname", \
"mutationevent.initmutationevent", \
"mutationevent.newvalue", \
"mutationevent.prevvalue", \
"mutationevent.relatednode", \
"namednodemap.getnameditem", \
"namednodemap.getnameditemns", \
"namednodemap.item", \

Просмотреть файл

@ -141,7 +141,7 @@ GlobalWindowImpl::GlobalWindowImpl() :
mTimeouts(nsnull), mTimeoutInsertionPoint(&mTimeouts), mRunningTimeout(nsnull),
mTimeoutPublicIdCounter(1), mTimeoutFiringDepth(0),
mFirstDocumentLoad(PR_TRUE), mGlobalObjectOwner(nsnull), mDocShell(nsnull),
mChromeEventHandler(nsnull)
mChromeEventHandler(nsnull), mMutationBits(0)
{
NS_INIT_REFCNT();
if (gRefCnt++ == 0) {
@ -386,6 +386,9 @@ NS_IMETHODIMP GlobalWindowImpl::SetNewDocument(nsIDOMDocument* aDocument)
if (mDocument && mContext)
mContext->InitContext(this);
// Clear our mutation bitfield.
mMutationBits = 0;
return NS_OK;
}
@ -2826,7 +2829,20 @@ GlobalWindowImpl::GetRootFocusController(nsIFocusController** aController)
}
}
}
return NS_OK;
}
NS_IMETHODIMP
GlobalWindowImpl::HasMutationListeners(PRUint32 aMutationEventType, PRBool* aResult)
{
*aResult = (mMutationBits & aMutationEventType) != 0;
return NS_OK;
}
NS_IMETHODIMP
GlobalWindowImpl::SetMutationListeners(PRUint32 aType)
{
mMutationBits |= aType;
return NS_OK;
}

Просмотреть файл

@ -161,9 +161,11 @@ public:
NS_IMETHOD GetChromeEventHandler(nsIChromeEventHandler** aHandler);
NS_IMETHOD HasMutationListeners(PRUint32 aMutationEventType, PRBool* aResult);
NS_IMETHOD SetMutationListeners(PRUint32 aEventType);
NS_IMETHOD GetRootFocusController(nsIFocusController** aResult);
NS_IMETHOD SetPositionAndSize(PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy, PRBool fRepaint);
NS_IMETHOD GetPositionAndSize(PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy);
@ -254,6 +256,7 @@ protected:
nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // Weak Reference
nsIDocShell* mDocShell; // Weak Reference
PRUint32 mMutationBits;
nsCOMPtr<nsIChromeEventHandler> mChromeEventHandler; // [Strong] We break it when we get torn down.
nsCOMPtr<nsIDOMCrypto> mCrypto;
nsCOMPtr<nsIDOMPkcs11> mPkcs11;

Просмотреть файл

@ -36,6 +36,7 @@ CPPSRCS = \
nsJSEvent.cpp \
nsJSUIEvent.cpp \
nsJSKeyEvent.cpp \
nsJSMutationEvent.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.

Просмотреть файл

@ -33,10 +33,11 @@ CPPSRCS = \
nsJSEvent.cpp \
nsJSUIEvent.cpp \
nsJSKeyEvent.cpp \
nsJSMutationEvent.cpp \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsJSEventListener.obj .\$(OBJDIR)\nsJSDOMEventListener.obj .\$(OBJDIR)\nsJSEvent.obj .\$(OBJDIR)\nsJSUIEvent.obj .\$(OBJDIR)\nsJSKeyEvent.obj
.\$(OBJDIR)\nsJSEventListener.obj .\$(OBJDIR)\nsJSMutationEvent.obj .\$(OBJDIR)\nsJSDOMEventListener.obj .\$(OBJDIR)\nsJSEvent.obj .\$(OBJDIR)\nsJSUIEvent.obj .\$(OBJDIR)\nsJSKeyEvent.obj
LINCS=-I$(XPDIST)\public\xpcom -I$(XPDIST)\public\raptor -I$(XPDIST)\public\dom -I$(XPDIST)\public\js

Просмотреть файл

@ -22,6 +22,7 @@
#include "nsJSDOMEventListener.h"
#include "nsString.h"
#include "nsIServiceManager.h"
#include "nsIDOMMutationEvent.h"
#include "nsIScriptSecurityManager.h"
#include "nsIScriptGlobalObject.h"
#include "nsJSUtils.h"
@ -79,8 +80,10 @@ NS_IMPL_RELEASE(nsJSDOMEventListener)
nsresult nsJSDOMEventListener::HandleEvent(nsIDOMEvent* aEvent)
{
JSObject *eventObj;
if (NS_OK != NS_NewScriptKeyEvent(mContext, aEvent, nsnull, (void**)&eventObj))
return NS_ERROR_FAILURE;
if (NS_OK != NS_NewScriptKeyEvent(mContext, aEvent, nsnull, (void**)&eventObj)) {
if (NS_OK != NS_NewScriptMutationEvent(mContext, aEvent, nsnull, (void**)&eventObj))
return NS_ERROR_FAILURE;
}
jsval argv[1];
argv[0] = OBJECT_TO_JSVAL(eventObj);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

Просмотреть файл

@ -164,6 +164,15 @@ LAYOUT_ATOM(onoverflow, "onoverflow")
LAYOUT_ATOM(onunderflow, "onunderflow")
LAYOUT_ATOM(onoverflowchanged, "onoverflowchanged")
// mutation events
LAYOUT_ATOM(onDOMSubtreeModified, "onDOMSubtreeModified")
LAYOUT_ATOM(onDOMNodeInserted, "onDOMNodeInserted")
LAYOUT_ATOM(onDOMNodeRemoved, "onDOMNodeRemoved")
LAYOUT_ATOM(onDOMNodeRemovedFromDocument, "onDOMNodeRemovedFromDocument")
LAYOUT_ATOM(onDOMNodeInsertedIntoDocument, "onDOMNodeInsertedIntoDocument")
LAYOUT_ATOM(onDOMAttrModified, "onDOMAttrModified")
LAYOUT_ATOM(onDOMCharacterDataModified, "onDOMCharacterDataModified")
// Alphabetical list of languages for lang-specific transforms
LAYOUT_ATOM(Japanese, "ja")
LAYOUT_ATOM(Korean, "ko")

Просмотреть файл

@ -1,190 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/******
This file contains the list of all layout nsIAtoms and their values
It is designed to be used as inline input to nsLayoutAtoms.cpp *only*
through the magic of C preprocessing.
All entires must be enclosed in the macro LAYOUT_ATOM which will have cruel
and unusual things done to it
It is recommended (but not strictly necessary) to keep all entries
in alphabetical order
The first argument to LAYOUT_ATOM is the C++ identifier of the atom
The second argument is the string value of the atom
******/
// Alphabetical list of media type atoms
LAYOUT_ATOM(all, "all") // Media atoms must be lower case
LAYOUT_ATOM(aural, "aural")
LAYOUT_ATOM(braille, "braille")
LAYOUT_ATOM(embossed, "embossed")
LAYOUT_ATOM(handheld, "handheld")
LAYOUT_ATOM(print, "print")
LAYOUT_ATOM(projection, "projection")
LAYOUT_ATOM(screen, "screen")
LAYOUT_ATOM(tty, "tty")
LAYOUT_ATOM(tv, "tv")
// Alphabetical list of standard name space prefixes
LAYOUT_ATOM(htmlNameSpace, "html")
LAYOUT_ATOM(xmlNameSpace, "xml")
LAYOUT_ATOM(xmlnsNameSpace, "xmlns")
// Alphabetical list of frame additional child list names
LAYOUT_ATOM(absoluteList, "Absolute-list")
LAYOUT_ATOM(bulletList, "Bullet-list")
LAYOUT_ATOM(captionList, "Caption-list")
LAYOUT_ATOM(colGroupList, "ColGroup-list")
LAYOUT_ATOM(editorDisplayList, "EditorDisplay-List")
LAYOUT_ATOM(fixedList, "Fixed-list")
LAYOUT_ATOM(floaterList, "Floater-list")
LAYOUT_ATOM(overflowList, "Overflow-list")
LAYOUT_ATOM(popupList, "Popup-list")
// Alphabetical list of pseudo tag names for non-element content
LAYOUT_ATOM(canvasPseudo, ":canvas")
LAYOUT_ATOM(commentTagName, "__moz_comment")
LAYOUT_ATOM(dummyOptionPseudo, ":-moz-dummy-option")
LAYOUT_ATOM(optionSelectedPseudo, "-moz-option-selected")
LAYOUT_ATOM(textTagName, "__moz_text")
LAYOUT_ATOM(pagePseudo, ":-moz-page")
LAYOUT_ATOM(pageSequencePseudo, ":-moz-page-sequence")
LAYOUT_ATOM(processingInstructionTagName, "__moz_pi")
LAYOUT_ATOM(scrolledContentPseudo, ":scrolled-content")
LAYOUT_ATOM(viewportPseudo, ":viewport")
LAYOUT_ATOM(viewportScrollPseudo, ":viewport-scroll")
LAYOUT_ATOM(selectScrolledContentPseudo, ":-moz-select-scrolled-content")
// Alphabetical list of frame types
LAYOUT_ATOM(areaFrame, "AreaFrame")
LAYOUT_ATOM(blockFrame, "BlockFrame")
LAYOUT_ATOM(brFrame, "BRFrame")
LAYOUT_ATOM(bulletFrame, "BulletFrame")
LAYOUT_ATOM(hrFrame, "HRFrame")
LAYOUT_ATOM(htmlFrameInnerFrame, "htmlFrameInnerFrame")
LAYOUT_ATOM(htmlFrameOuterFrame, "htmlFrameOuterFrame")
LAYOUT_ATOM(imageFrame, "ImageFrame")
LAYOUT_ATOM(inlineFrame, "InlineFrame")
LAYOUT_ATOM(letterFrame, "LetterFrame")
LAYOUT_ATOM(lineFrame, "LineFrame")
LAYOUT_ATOM(objectFrame, "ObjectFrame")
LAYOUT_ATOM(pageFrame, "PageFrame")
LAYOUT_ATOM(placeholderFrame, "PlaceholderFrame")
LAYOUT_ATOM(positionedInlineFrame, "PositionedInlineFrame")
LAYOUT_ATOM(canvasFrame, "CanvasFrame")
LAYOUT_ATOM(rootFrame, "RootFrame")
LAYOUT_ATOM(scrollFrame, "ScrollFrame")
LAYOUT_ATOM(tableCaptionFrame, "TableCaptionFrame")
LAYOUT_ATOM(tableCellFrame, "TableCellFrame")
LAYOUT_ATOM(tableColFrame, "TableColFrame")
LAYOUT_ATOM(tableColGroupFrame, "TableColGroupFrame")
LAYOUT_ATOM(tableFrame, "TableFrame")
LAYOUT_ATOM(tableOuterFrame, "TableOuterFrame")
LAYOUT_ATOM(tableRowGroupFrame, "TableRowGroupFrame")
LAYOUT_ATOM(tableRowFrame, "TableRowFrame")
LAYOUT_ATOM(textInputFrame,"TextInputFrame")
LAYOUT_ATOM(textFrame, "TextFrame")
LAYOUT_ATOM(viewportFrame, "ViewportFrame")
// Alphabetical list of frame property names
LAYOUT_ATOM(collapseOffsetProperty, "CollapseOffsetProperty") // nsPoint*
LAYOUT_ATOM(inlineFrameAnnotation, "InlineFrameAnnotation") // BOOL
LAYOUT_ATOM(maxElementSizeProperty, "MaxElementSizeProperty") // nsSize*
LAYOUT_ATOM(overflowAreaProperty, "OverflowArea") // nsRect*
LAYOUT_ATOM(overflowProperty, "OverflowProperty") // list of nsIFrame*
LAYOUT_ATOM(overflowLinesProperty, "OverflowLinesProperty") // list of nsLineBox*
LAYOUT_ATOM(spaceManagerProperty, "SpaceManagerProperty") // the space manager for a block
LAYOUT_ATOM(viewProperty, "ViewProperty") // nsView*
// Alphabetical list of event handler names
LAYOUT_ATOM(onabort, "onabort")
LAYOUT_ATOM(onblur, "onblur")
LAYOUT_ATOM(onbroadcast, "onbroadcast")
LAYOUT_ATOM(onchange, "onchange")
LAYOUT_ATOM(onclick, "onclick")
LAYOUT_ATOM(onclose, "onclose")
LAYOUT_ATOM(oncommand, "oncommand")
LAYOUT_ATOM(oncommandupdate, "oncommandupdate")
LAYOUT_ATOM(oncreate, "oncreate")
LAYOUT_ATOM(ondblclick, "ondblclick")
LAYOUT_ATOM(ondestroy, "ondestroy")
LAYOUT_ATOM(ondragdrop, "ondragdrop")
LAYOUT_ATOM(ondragenter, "ondragenter")
LAYOUT_ATOM(ondragexit, "ondragexit")
LAYOUT_ATOM(ondraggesture, "ondraggesture")
LAYOUT_ATOM(ondragover, "ondragover")
LAYOUT_ATOM(onerror, "onerror")
LAYOUT_ATOM(onfocus, "onfocus")
LAYOUT_ATOM(oninput, "oninput")
LAYOUT_ATOM(onkeydown, "onkeydown")
LAYOUT_ATOM(onkeypress, "onkeypress")
LAYOUT_ATOM(onkeyup, "onkeyup")
LAYOUT_ATOM(onload, "onload")
LAYOUT_ATOM(onmousedown, "onmousedown")
LAYOUT_ATOM(onmousemove, "onmousemove")
LAYOUT_ATOM(onmouseover, "onmouseover")
LAYOUT_ATOM(onmouseout, "onmouseout")
LAYOUT_ATOM(onmouseup, "onmouseup")
LAYOUT_ATOM(onpaint, "onpaint")
LAYOUT_ATOM(onreset, "onreset")
LAYOUT_ATOM(onresize, "onresize")
LAYOUT_ATOM(onscroll, "onscroll")
LAYOUT_ATOM(onselect, "onselect")
LAYOUT_ATOM(onsubmit, "onsubmit")
LAYOUT_ATOM(onunload, "onunload")
// scrolling
LAYOUT_ATOM(onoverflow, "onoverflow")
LAYOUT_ATOM(onunderflow, "onunderflow")
LAYOUT_ATOM(onoverflowchanged, "onoverflowchanged")
// Alphabetical list of languages for lang-specific transforms
LAYOUT_ATOM(Japanese, "ja")
LAYOUT_ATOM(Korean, "ko")
// other
LAYOUT_ATOM(wildcard, "*")
LAYOUT_ATOM(mozdirty, "_moz_dirty")
#ifdef DEBUG
// Alphabetical list of atoms used by debugging code
LAYOUT_ATOM(cellMap, "TableCellMap")
LAYOUT_ATOM(imageMap, "ImageMap")
LAYOUT_ATOM(lineBoxBig, "LineBox:inline,big")
LAYOUT_ATOM(lineBoxBlockBig, "LineBox:block,big")
LAYOUT_ATOM(lineBoxBlockSmall, "LineBox:block,small")
LAYOUT_ATOM(lineBoxFloaters, "LineBoxFloaters")
LAYOUT_ATOM(lineBoxSmall, "LineBox:inline,small")
LAYOUT_ATOM(spaceManager, "SpaceManager")
LAYOUT_ATOM(tableColCache, "TableColumnCache")
LAYOUT_ATOM(tableStrategy, "TableLayoutStrategy")
LAYOUT_ATOM(textRun, "TextRun")
LAYOUT_ATOM(xml_document_entities, "XMLDocumentEntities")
LAYOUT_ATOM(xml_document_notations, "XMLDocumentNotations")
#endif

Просмотреть файл

@ -33,6 +33,9 @@
#include "nsISelectionPrivate.h"
#include "nsIEnumerator.h"
#include "nsReadableUtils.h"
#include "nsMutationEvent.h"
#include "nsEventListenerManager.h"
#include "nsPIDOMWindow.h"
#include "nsCRT.h"
#include "nsIEventStateManager.h"
@ -909,6 +912,73 @@ nsGenericDOMDataNode::CopyText(nsAWritableString& aResult)
return NS_OK;
}
static PRBool HasMutationListeners(nsIContent* aContent, PRUint32 aType)
{
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (!doc)
return PR_FALSE;
nsCOMPtr<nsIScriptGlobalObject> global;
doc->GetScriptGlobalObject(getter_AddRefs(global));
if (!global)
return PR_FALSE;
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(global));
if (!window)
return PR_FALSE;
PRBool set;
window->HasMutationListeners(aType, &set);
if (!set)
return PR_FALSE;
// We know a mutation listener is registered, but it might not
// be in our chain. Check quickly to see.
nsCOMPtr<nsIContent> curr = aContent;
nsCOMPtr<nsIEventListenerManager> manager;
while (curr) {
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(curr));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
nsCOMPtr<nsIContent> prev = curr;
prev->GetParent(*getter_AddRefs(curr));
}
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
rec = do_QueryInterface(window);
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
return PR_FALSE;
}
nsresult
nsGenericDOMDataNode::SetText(nsIContent *aOuterContent,
const PRUnichar* aBuffer,
@ -927,6 +997,22 @@ nsGenericDOMDataNode::SetText(nsIContent *aOuterContent,
}
mText.SetTo(aBuffer, aLength);
if (mDocument && HasMutationListeners(aOuterContent, NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aOuterContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_CHARACTERDATAMODIFIED;
mutation.mTarget = node;
// XXX Handle the setting of prevValue!
nsAutoString newVal(aBuffer);
if (!newVal.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(newVal));
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
// Trigger a reflow
if (aNotify && (nsnull != mDocument)) {
mDocument->ContentChanged(aOuterContent, nsnull);
@ -951,6 +1037,22 @@ nsGenericDOMDataNode::SetText(nsIContent *aOuterContent, const char* aBuffer,
}
mText.SetTo(aBuffer, aLength);
if (mDocument && HasMutationListeners(aOuterContent, NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aOuterContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_CHARACTERDATAMODIFIED;
mutation.mTarget = node;
// XXX Handle the setting of prevValue!
nsAutoString newVal; newVal.AssignWithConversion(aBuffer);
if (!newVal.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(newVal));
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
// Trigger a reflow
if (aNotify && (nsnull != mDocument)) {
mDocument->ContentChanged(aOuterContent, nsnull);

Просмотреть файл

@ -61,12 +61,16 @@
#include "prmem.h"
#include "nsDOMError.h"
#include "nsScriptSecurityManager.h"
#include "nsIDOMMutationEvent.h"
#include "nsMutationEvent.h"
#include "nsIBindingManager.h"
#include "nsIXBLBinding.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsIDOMViewCSS.h"
#include "nsIXBLService.h"
#include "nsPIDOMWindow.h"
#include "nsEventListenerManager.h"
#include "nsLayoutAtoms.h"
#include "nsHTMLAtoms.h"
@ -2718,6 +2722,73 @@ nsGenericContainerElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
return SetAttribute(ni, aValue, aNotify);
}
static PRBool HasMutationListeners(nsIContent* aContent, PRUint32 aType)
{
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (!doc)
return PR_FALSE;
nsCOMPtr<nsIScriptGlobalObject> global;
doc->GetScriptGlobalObject(getter_AddRefs(global));
if (!global)
return PR_FALSE;
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(global));
if (!window)
return PR_FALSE;
PRBool set;
window->HasMutationListeners(aType, &set);
if (!set)
return PR_FALSE;
// We know a mutation listener is registered, but it might not
// be in our chain. Check quickly to see.
nsCOMPtr<nsIContent> curr = aContent;
nsCOMPtr<nsIEventListenerManager> manager;
while (curr) {
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(curr));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
nsCOMPtr<nsIContent> prev = curr;
prev->GetParent(*getter_AddRefs(curr));
}
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
rec = do_QueryInterface(window);
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
return PR_FALSE;
}
nsresult
nsGenericContainerElement::SetAttribute(nsINodeInfo* aNodeInfo,
const nsAReadableString& aValue,
@ -2725,6 +2796,9 @@ nsGenericContainerElement::SetAttribute(nsINodeInfo* aNodeInfo,
{
NS_ENSURE_ARG_POINTER(aNodeInfo);
PRBool modification = PR_FALSE;
nsAutoString oldValue;
nsresult rv = NS_ERROR_OUT_OF_MEMORY;
if (!mAttributes) {
@ -2742,6 +2816,8 @@ nsGenericContainerElement::SetAttribute(nsINodeInfo* aNodeInfo,
for (index = 0; index < count; index++) {
attr = (nsGenericAttribute*)mAttributes->ElementAt(index);
if (attr->mNodeInfo == aNodeInfo) {
oldValue = attr->mValue;
modification = PR_TRUE;
attr->mValue = aValue;
rv = NS_OK;
break;
@ -2770,6 +2846,31 @@ nsGenericContainerElement::SetAttribute(nsINodeInfo* aNodeInfo,
if (binding)
binding->AttributeChanged(name, nameSpaceID, PR_FALSE);
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(mContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName;
name->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = name;
if (!oldValue.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(oldValue));
if (!aValue.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(aValue));
mutation.mAttrChange = modification ? nsIDOMMutationEvent::MODIFICATION :
nsIDOMMutationEvent::ADDITION;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
mDocument->AttributeChanged(mContent, nameSpaceID, name, NS_STYLE_HINT_UNKNOWN);
mDocument->EndUpdate();
@ -2854,6 +2955,30 @@ nsGenericContainerElement::UnsetAttribute(PRInt32 aNameSpaceID,
if (aNotify && (nsnull != mDocument)) {
mDocument->BeginUpdate();
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(mContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName;
aName->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aName;
if (!attr->mValue.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(attr->mValue));
mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
mAttributes->RemoveElementAt(index);
delete attr;
found = PR_TRUE;
@ -3036,6 +3161,21 @@ nsGenericContainerElement::InsertChildAt(nsIContent* aKid,
if (aNotify) {
doc->ContentInserted(mContent, aKid, aIndex);
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
}
}
if (aNotify && (nsnull != doc)) {
@ -3094,6 +3234,21 @@ nsGenericContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
if (aNotify) {
doc->ContentAppended(mContent, mChildren.Count() - 1);
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
}
}
if (aNotify && (nsnull != doc)) {
@ -3111,6 +3266,22 @@ nsGenericContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
if (aNotify && (nsnull != doc)) {
doc->BeginUpdate();
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(oldKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEREMOVED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
oldKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
nsRange::OwnerChildRemoved(mContent, aIndex, oldKid);
mChildren.RemoveElementAt(aIndex);
if (aNotify) {

Просмотреть файл

@ -1,9 +0,0 @@
#
# This is a list of local files which get copied to the mozilla:dist:layout directory
#
nsIEventListenerManager.h
nsIEventStateManager.h
nsIPrivateDOMEvent.h
nsIPrivateTextEvent.h
nsIPrivateTextRange.h
nsIPrivateCompositionEvent.h

Просмотреть файл

@ -1,43 +0,0 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = layout
EXPORTS = \
nsIEventListenerManager.h \
nsIEventStateManager.h \
nsIPrivateDOMEvent.h \
nsIPrivateTextEvent.h \
nsIPrivateTextRange.h \
nsIPrivateCompositionEvent.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -1,37 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..
EXPORTS = \
nsIEventListenerManager.h \
nsIEventStateManager.h \
nsIPrivateDOMEvent.h \
nsIPrivateTextEvent.h \
nsIPrivateTextRange.h \
nsIPrivateCompositionEvent.h \
$(NULL)
MODULE=raptor
include <$(DEPTH)\config\rules.mak>

Просмотреть файл

@ -1,149 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsIEventListenerManager_h__
#define nsIEventListenerManager_h__
#include "nsGUIEvent.h"
#include "nsISupports.h"
#include "nsVoidArray.h"
class nsIPresContext;
class nsIDOMEventListener;
class nsIScriptObjectOwner;
class nsIDOMEventTarget;
/*
* Event listener manager interface.
*/
#define NS_IEVENTLISTENERMANAGER_IID \
{ /* cd91bcf0-ded9-11d1-bd85-00805f8ae3f4 */ \
0xcd91bcf0, 0xded9, 0x11d1, \
{0xbd, 0x85, 0x00, 0x80, 0x5f, 0x8a, 0xe3, 0xf4} }
class nsIEventListenerManager : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IEVENTLISTENERMANAGER_IID; return iid; }
/**
* Retrieves events listeners of all types.
* @param
*/
virtual nsresult GetEventListeners(nsVoidArray **aListeners, const nsIID& aIID) = 0;
/**
* Sets events listeners of all types.
* @param an event listener
*/
virtual nsresult AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 flags) = 0;
/**
* Removes events listeners of all types.
* @param an event listener
*/
virtual nsresult RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 flags) = 0;
/**
* Sets events listeners of all types.
* @param an event listener
*/
virtual nsresult AddEventListenerByType(nsIDOMEventListener *aListener, const nsAReadableString& type, PRInt32 flags) = 0;
/**
* Removes events listeners of all types.
* @param an event listener
*/
virtual nsresult RemoveEventListenerByType(nsIDOMEventListener *aListener, const nsAReadableString& type, PRInt32 flags) = 0;
/**
* Creates a script event listener for the given script object with name mName and function
* body mFunc.
* @param an event listener
*/
virtual nsresult AddScriptEventListener(nsIScriptContext*aContext,
nsIScriptObjectOwner *aScriptObjectOwner,
nsIAtom *aName,
const nsAReadableString& aFunc,
REFNSIID aIID,
PRBool aDeferCompilation) = 0;
/**
* Registers an event listener that already exists on the given script object with the event
* listener manager.
* @param an event listener
*/
virtual nsresult RegisterScriptEventListener(nsIScriptContext *aContext,
nsIScriptObjectOwner *aScriptObjectOwner,
nsIAtom* aName,
REFNSIID aIID) = 0;
/**
* Causes a check for event listeners and processing by them if they exist.
* Event flags live in nsGUIEvent.h
* @param an event listener
*/
virtual nsresult HandleEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
nsIDOMEventTarget* aCurrentTarget,
PRUint32 aFlags,
nsEventStatus* aEventStatus) = 0;
/**
* Creates a DOM event that can subsequently be passed into HandleEvent.
* (used rarely in the situation where methods on the event need to be
* invoked prior to the processing of the event).
*/
virtual nsresult CreateEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
const nsAReadableString& aEventType,
nsIDOMEvent** aDOMEvent) = 0;
/**
* Changes script listener of specified event types from bubbling listeners to capturing listeners.
* @param event types
*/
virtual nsresult CaptureEvent(PRInt32 aEventTypes) = 0;
/**
* Changes script listener of specified event types from capturing listeners to bubbling listeners.
* @param event types
*/
virtual nsresult ReleaseEvent(PRInt32 aEventTypes) = 0;
/**
* Removes all event listeners registered by this instance of the listener
* manager.
*/
virtual nsresult RemoveAllListeners(PRBool aScriptOnly) = 0;
/**
* Removes all event listeners registered by this instance of the listener
* manager.
*/
virtual nsresult SetListenerTarget(nsISupports* aTarget) = 0;
};
extern NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult);
#endif // nsIEventListenerManager_h__

Просмотреть файл

@ -1,62 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsIPrivateDOMEvent_h__
#define nsIPrivateDOMEvent_h__
#include "nsGUIEvent.h"
#include "nsISupports.h"
class nsIPresContext;
/*
* Event listener manager interface.
*/
#define NS_IPRIVATEDOMEVENT_IID \
{ /* 80a98c80-2036-11d2-bd89-00805f8ae3f4 */ \
0x80a98c80, 0x2036, 0x11d2, \
{0xbd, 0x89, 0x00, 0x80, 0x5f, 0x8a, 0xe3, 0xf4} }
class nsIDOMEventTarget;
class nsIDOMEvent;
class nsIPrivateDOMEvent : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IPRIVATEDOMEVENT_IID; return iid; }
NS_IMETHOD DuplicatePrivateData() = 0;
NS_IMETHOD SetTarget(nsIDOMEventTarget* aTarget) = 0;
NS_IMETHOD SetCurrentTarget(nsIDOMEventTarget* aTarget) = 0;
NS_IMETHOD SetOriginalTarget(nsIDOMEventTarget* aTarget) = 0;
NS_IMETHOD IsDispatchStopped(PRBool* aIsDispatchPrevented) = 0;
NS_IMETHOD GetInternalNSEvent(nsEvent** aNSEvent) = 0;
NS_IMETHOD HasOriginalTarget(PRBool* aResult)=0;
};
extern nsresult NS_NewDOMEvent(nsIDOMEvent** aInstancePtrResult, nsIPresContext* aPresContext, nsEvent *aEvent);
extern nsresult NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult,
nsIPresContext* aPresContext,
const nsAReadableString& aEventType,
nsEvent *aEvent);
#endif // nsIPrivateDOMEvent_h__

Просмотреть файл

Просмотреть файл

@ -34,6 +34,7 @@ CPPSRCS = \
nsEventListenerManager.cpp \
nsEventStateManager.cpp \
nsDOMEvent.cpp \
nsDOMMutationEvent.cpp \
nsDOMEventsIIDs.cpp \
nsPrivateTextRange.cpp \
$(NULL)

Просмотреть файл

@ -32,6 +32,7 @@ DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN
CPPSRCS= nsEventListenerManager.cpp \
nsEventStateManager.cpp \
nsDOMEvent.cpp \
nsDOMMutationEvent.cpp \
nsDOMEventsIIDs.cpp \
nsPrivateTextRange.cpp \
$(NULL)
@ -39,6 +40,7 @@ CPPSRCS= nsEventListenerManager.cpp \
CPP_OBJS= .\$(OBJDIR)\nsEventListenerManager.obj \
.\$(OBJDIR)\nsEventStateManager.obj \
.\$(OBJDIR)\nsDOMEvent.obj \
.\$(OBJDIR)\nsDOMMutationEvent.obj \
.\$(OBJDIR)\nsDOMEventsIIDs.obj \
.\$(OBJDIR)\nsPrivateTextRange.obj \
$(NULL)

Просмотреть файл

@ -40,6 +40,7 @@
#include "nsIDOMAbstractView.h"
#include "prmem.h"
#include "nsLayoutAtoms.h"
#include "nsMutationEvent.h"
static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID);
@ -50,7 +51,10 @@ static char* mEventNames[] = {
"submit", "reset", "change", "select", "input", "paint" ,"text",
"create", "close", "destroy", "command", "broadcast", "commandupdate",
"dragenter", "dragover", "dragexit", "dragdrop", "draggesture", "resize",
"scroll","overflow", "underflow", "overflowchanged"
"scroll","overflow", "underflow", "overflowchanged",
"DOMSubtreeModified", "DOMNodeInserted", "DOMNodeRemoved",
"DOMNodeRemovedFromDocument", "DOMNodeInsertedIntoDocument",
"DOMAttrModified", "DOMCharacterDataModified"
};
nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAReadableString& aEventType) {
@ -76,6 +80,10 @@ nsDOMEvent::nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAR
mEvent = PR_NEWZAP(nsEvent);
mEvent->eventStructType = NS_EVENT;
}
else if (eventType.EqualsIgnoreCase("MutationEvent")) {
mEvent = PR_NEWZAP(nsMutationEvent);
mEvent->eventStructType = NS_MUTATION_EVENT;
}
else {
mEvent = PR_NEWZAP(nsEvent);
mEvent->eventStructType = NS_EVENT;
@ -1013,7 +1021,6 @@ nsDOMEvent::InitKeyEvent(const nsAReadableString& aTypeArg, PRBool aCanBubbleArg
return NS_OK;
}
NS_METHOD nsDOMEvent::DuplicatePrivateData()
{
//XXX Write me!
@ -1183,6 +1190,20 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return mEventNames[eDOMEvents_underflow];
case NS_SCROLLPORT_OVERFLOWCHANGED:
return mEventNames[eDOMEvents_overflowchanged];
case NS_MUTATION_SUBTREEMODIFIED:
return mEventNames[eDOMEvents_subtreemodified];
case NS_MUTATION_NODEINSERTED:
return mEventNames[eDOMEvents_nodeinserted];
case NS_MUTATION_NODEREMOVED:
return mEventNames[eDOMEvents_noderemoved];
case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
return mEventNames[eDOMEvents_noderemovedfromdocument];
case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
return mEventNames[eDOMEvents_nodeinsertedintodocument];
case NS_MUTATION_ATTRMODIFIED:
return mEventNames[eDOMEvents_attrmodified];
case NS_MUTATION_CHARACTERDATAMODIFIED:
return mEventNames[eDOMEvents_characterdatamodified];
default:
break;
}

Просмотреть файл

@ -87,7 +87,14 @@ public:
eDOMEvents_scroll,
eDOMEvents_overflow,
eDOMEvents_underflow,
eDOMEvents_overflowchanged
eDOMEvents_overflowchanged,
eDOMEvents_subtreemodified,
eDOMEvents_nodeinserted,
eDOMEvents_noderemoved,
eDOMEvents_noderemovedfromdocument,
eDOMEvents_nodeinsertedintodocument,
eDOMEvents_attrmodified,
eDOMEvents_characterdatamodified
};
nsDOMEvent(nsIPresContext* aPresContext, nsEvent* aEvent, const nsAReadableString& aEventType);

Просмотреть файл

@ -1,47 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsDOMEventsIIDs.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMMouseMotionListener.h"
#include "nsIDOMFocusListener.h"
#include "nsIDOMFormListener.h"
#include "nsIDOMLoadListener.h"
#include "nsIDOMDragListener.h"
#include "nsIDOMPaintListener.h"
#include "nsIDOMTextListener.h"
#include "nsIDOMCompositionListener.h"
#include "nsIDOMMenuListener.h"
#include "nsIDOMScrollListener.h"
NS_DEFINE_IID(kIDOMMouseListenerIID, NS_IDOMMOUSELISTENER_IID);
NS_DEFINE_IID(kIDOMKeyListenerIID, NS_IDOMKEYLISTENER_IID);
NS_DEFINE_IID(kIDOMMouseMotionListenerIID, NS_IDOMMOUSEMOTIONLISTENER_IID);
NS_DEFINE_IID(kIDOMFocusListenerIID, NS_IDOMFOCUSLISTENER_IID);
NS_DEFINE_IID(kIDOMFormListenerIID, NS_IDOMFORMLISTENER_IID);
NS_DEFINE_IID(kIDOMLoadListenerIID, NS_IDOMLOADLISTENER_IID);
NS_DEFINE_IID(kIDOMDragListenerIID, NS_IDOMDRAGLISTENER_IID);
NS_DEFINE_IID(kIDOMPaintListenerIID, NS_IDOMPAINTLISTENER_IID);
NS_DEFINE_IID(kIDOMTextListenerIID,NS_IDOMTEXTLISTENER_IID);
NS_DEFINE_IID(kIDOMCompositionListenerIID,NS_IDOMCOMPOSITIONLISTENER_IID);
NS_DEFINE_IID(kIDOMMenuListenerIID, NS_IDOMMENULISTENER_IID);
NS_DEFINE_IID(kIDOMScrollListenerIID, NS_IDOMSCROLLLISTENER_IID);

Просмотреть файл

@ -1,40 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsDOMEVENTSIIDs_h___
#define nsDOMEVENTSIIDs_h___
#include "nsISupports.h"
extern const nsIID kIDOMMouseListenerIID;
extern const nsIID kIDOMKeyListenerIID;
extern const nsIID kIDOMMouseMotionListenerIID;
extern const nsIID kIDOMFocusListenerIID;
extern const nsIID kIDOMFormListenerIID;
extern const nsIID kIDOMLoadListenerIID;
extern const nsIID kIDOMDragListenerIID;
extern const nsIID kIDOMPaintListenerIID;
extern const nsIID kIDOMTextListenerIID;
extern const nsIID kIDOMCompositionListenerIID;
extern const nsIID kIDOMMenuListenerIID;
extern const nsIID kIDOMScrollListenerIID;
#endif /* nsDOMEVENTSIIDs_h___ */

Просмотреть файл

Просмотреть файл

@ -37,7 +37,9 @@
#include "nsIDOMCompositionListener.h"
#include "nsIDOMMenuListener.h"
#include "nsIDOMScrollListener.h"
#include "nsIDOMMutationListener.h"
#include "nsIEventStateManager.h"
#include "nsPIDOMWindow.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIScriptObjectOwner.h"
#include "nsIScriptEventListener.h"
@ -56,6 +58,7 @@
#include "nsIJSContextStack.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
#include "nsMutationEvent.h"
static NS_DEFINE_IID(kIEventListenerManagerIID, NS_IEVENTLISTENERMANAGER_IID);
static NS_DEFINE_IID(kIDOMEventListenerIID, NS_IDOMEVENTLISTENER_IID);
@ -77,6 +80,7 @@ nsEventListenerManager::nsEventListenerManager()
mCompositionListeners = nsnull;
mMenuListeners = nsnull;
mScrollListeners = nsnull;
mMutationListeners = nsnull;
mDestroyed = PR_FALSE;
mTarget = nsnull;
NS_INIT_REFCNT();
@ -97,6 +101,7 @@ nsEventListenerManager::~nsEventListenerManager()
ReleaseListeners(&mCompositionListeners, PR_FALSE);
ReleaseListeners(&mMenuListeners, PR_FALSE);
ReleaseListeners(&mScrollListeners, PR_FALSE);
ReleaseListeners(&mMutationListeners, PR_FALSE);
}
NS_IMPL_ADDREF(nsEventListenerManager)
@ -184,6 +189,9 @@ nsVoidArray** nsEventListenerManager::GetListenersByIID(const nsIID& aIID)
else if (aIID.Equals(kIDOMScrollListenerIID)) {
return &mScrollListeners;
}
else if (aIID.Equals(kIDOMMutationListenerIID)) {
return &mMutationListeners;
}
return nsnull;
}
@ -245,6 +253,25 @@ nsresult nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener
return NS_ERROR_OUT_OF_MEMORY;
}
// For mutation listeners, we need to update the global bit on the DOM window.
// Otherwise we won't actually fire the mutation event.
if (aIID.Equals(NS_GET_IID(nsIDOMMutationListener))) {
// Go from our target to the nearest enclosing DOM window.
nsCOMPtr<nsIScriptGlobalObject> global;
nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIContent> content(do_QueryInterface(mTarget));
if (content)
content->GetDocument(*getter_AddRefs(document));
else document = do_QueryInterface(mTarget);
if (document)
document->GetScriptGlobalObject(getter_AddRefs(global));
else global = do_QueryInterface(mTarget);
if (global) {
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(global));
window->SetMutationListeners(aSubType);
}
}
PRBool found = PR_FALSE;
nsListenerStruct* ls;
nsresult rv;
@ -504,6 +531,34 @@ nsresult nsEventListenerManager::GetIdentifiersForType(nsIAtom* aType, nsIID& aI
aIID = NS_GET_IID(nsIDOMDragListener);
*aFlags = NS_EVENT_BITS_DRAG_GESTURE;
}
else if (aType == nsLayoutAtoms::onDOMSubtreeModified) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED;
}
else if (aType == nsLayoutAtoms::onDOMNodeInserted) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_NODEINSERTED;
}
else if (aType == nsLayoutAtoms::onDOMNodeRemoved) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_NODEREMOVED;
}
else if (aType == nsLayoutAtoms::onDOMNodeInsertedIntoDocument) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT;
}
else if (aType == nsLayoutAtoms::onDOMNodeRemovedFromDocument) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT;
}
else if (aType == nsLayoutAtoms::onDOMAttrModified) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_ATTRMODIFIED;
}
else if (aType == nsLayoutAtoms::onDOMCharacterDataModified) {
aIID = NS_GET_IID(nsIDOMMutationListener);
*aFlags = NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED;
}
else {
return NS_ERROR_FAILURE;
}
@ -1676,6 +1731,112 @@ nsresult nsEventListenerManager::HandleEvent(nsIPresContext* aPresContext,
}
break;
case NS_MUTATION_SUBTREEMODIFIED:
case NS_MUTATION_NODEINSERTED:
case NS_MUTATION_NODEREMOVED:
case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
case NS_MUTATION_ATTRMODIFIED:
case NS_MUTATION_CHARACTERDATAMODIFIED:
if (nsnull != mMutationListeners) {
if (nsnull == *aDOMEvent) {
ret = NS_NewDOMMutationEvent(aDOMEvent, aPresContext, aEvent);
}
if (NS_OK == ret) {
for (int i=0; mMutationListeners && i<mMutationListeners->Count(); i++) {
nsListenerStruct *ls;
nsCOMPtr<nsIDOMMutationListener> mutationListener;
ls = (nsListenerStruct*)mMutationListeners->ElementAt(i);
if (ls->mFlags & aFlags) {
mutationListener = do_QueryInterface(ls->mListener);
if (mutationListener) {
switch(aEvent->message) {
case NS_MUTATION_SUBTREEMODIFIED:
ret = mutationListener->SubtreeModified(*aDOMEvent);
break;
case NS_MUTATION_NODEINSERTED:
ret = mutationListener->NodeInserted(*aDOMEvent);
break;
case NS_MUTATION_NODEREMOVED:
ret = mutationListener->NodeRemoved(*aDOMEvent);
break;
case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
ret = mutationListener->NodeInsertedIntoDocument(*aDOMEvent);
break;
case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
ret = mutationListener->NodeRemovedFromDocument(*aDOMEvent);
break;
case NS_MUTATION_ATTRMODIFIED:
ret = mutationListener->AttrModified(*aDOMEvent);
break;
case NS_MUTATION_CHARACTERDATAMODIFIED:
ret = mutationListener->CharacterDataModified(*aDOMEvent);
break;
default:
break;
}
}
else {
PRBool correctSubType = PR_FALSE;
PRUint32 subType = 0;
switch(aEvent->message) {
case NS_MUTATION_SUBTREEMODIFIED:
subType = NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_NODEINSERTED:
subType = NS_EVENT_BITS_MUTATION_NODEINSERTED;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_NODEINSERTED) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_NODEREMOVED:
subType = NS_EVENT_BITS_MUTATION_NODEREMOVED;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_NODEREMOVED) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_NODEINSERTEDINTODOCUMENT:
subType = NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_NODEINSERTEDINTODOCUMENT) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_NODEREMOVEDFROMDOCUMENT:
subType = NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_NODEREMOVEDFROMDOCUMENT) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_ATTRMODIFIED:
subType = NS_EVENT_BITS_MUTATION_ATTRMODIFIED;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_ATTRMODIFIED) {
correctSubType = PR_TRUE;
}
break;
case NS_MUTATION_CHARACTERDATAMODIFIED:
subType = NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED;
if (ls->mSubType & NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED) {
correctSubType = PR_TRUE;
}
break;
default:
break;
}
if (correctSubType || ls->mSubType == NS_EVENT_BITS_NONE) {
ret = HandleEventSubType(ls, *aDOMEvent, aCurrentTarget, subType, aFlags);
}
}
}
}
}
}
break;
default:
break;
}
@ -1701,10 +1862,12 @@ nsresult nsEventListenerManager::CreateEvent(nsIPresContext* aPresContext,
{
nsAutoString str(aEventType);
if (!aEvent && !str.EqualsIgnoreCase("MouseEvent") && !str.EqualsIgnoreCase("KeyEvent") &&
!str.EqualsIgnoreCase("HTMLEvent")) {
!str.EqualsIgnoreCase("HTMLEvent") && !str.EqualsIgnoreCase("MutationEvent")) {
return NS_ERROR_FAILURE;
}
if (str.EqualsIgnoreCase("MutationEvent"))
return NS_NewDOMMutationEvent(aDOMEvent, aPresContext, aEvent);
return NS_NewDOMUIEvent(aDOMEvent, aPresContext, aEventType, aEvent);
}
@ -1965,6 +2128,7 @@ nsresult nsEventListenerManager::RemoveAllListeners(PRBool aScriptOnly)
ReleaseListeners(&mPaintListeners, aScriptOnly);
ReleaseListeners(&mTextListeners, aScriptOnly);
ReleaseListeners(&mCompositionListeners, aScriptOnly);
ReleaseListeners(&mMutationListeners, aScriptOnly);
mDestroyed = PR_TRUE;
return NS_OK;
}

Просмотреть файл

@ -1,245 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsEventListenerManager_h__
#define nsEventListenerManager_h__
#include "nsIEventListenerManager.h"
#include "jsapi.h"
#include "nsCOMPtr.h"
#include "nsIPrincipal.h"
#include "nsIDOMEventReceiver.h"
class nsIDOMEvent;
class nsIAtom;
typedef struct {
nsIDOMEventListener* mListener;
PRUint8 mFlags;
PRUint8 mSubType;
PRUint8 mHandlerIsString;
PRUint8 mSubTypeCapture;
} nsListenerStruct;
//Flag must live higher than all event flags in nsGUIEvent.h
#define NS_PRIV_EVENT_FLAG_SCRIPT 0x80
/*
* Event listener manager
*/
class nsEventListenerManager : public nsIEventListenerManager,
public nsIDOMEventReceiver
{
public:
nsEventListenerManager();
virtual ~nsEventListenerManager();
NS_DECL_ISUPPORTS
nsVoidArray** GetListenersByIID(const nsIID& aIID);
/**
* Retrieves events listeners of all types.
* @param
*/
virtual nsresult GetEventListeners(nsVoidArray **aListeners, const nsIID& aIID);
/**
* Sets events listeners of all types.
* @param an event listener
*/
virtual nsresult AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags);
virtual nsresult RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags);
virtual nsresult AddEventListenerByType(nsIDOMEventListener *aListener, const nsAReadableString& type, PRInt32 aFlags);
virtual nsresult RemoveEventListenerByType(nsIDOMEventListener *aListener, const nsAReadableString& type, PRInt32 aFlags) ;
virtual nsresult AddScriptEventListener(nsIScriptContext*aContext,
nsIScriptObjectOwner *aScriptObjectOwner,
nsIAtom *aName,
const nsAReadableString& aFunc,
REFNSIID aIID,
PRBool aDeferCompilation);
virtual nsresult RegisterScriptEventListener(nsIScriptContext *aContext,
nsIScriptObjectOwner *aScriptObjectOwner,
nsIAtom* aName,
const nsIID& aIID);
virtual nsresult CaptureEvent(PRInt32 aEventTypes);
virtual nsresult ReleaseEvent(PRInt32 aEventTypes);
virtual nsresult HandleEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent,
nsIDOMEventTarget* aCurrentTarget,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual nsresult CreateEvent(nsIPresContext* aPresContext,
nsEvent* aEvent,
const nsAReadableString& aEventType,
nsIDOMEvent** aDOMEvent);
virtual nsresult RemoveAllListeners(PRBool aScriptOnly);
virtual nsresult SetListenerTarget(nsISupports* aTarget);
static nsresult GetIdentifiersForType(nsIAtom* aType, nsIID& aIID, PRInt32* aSubType);
// nsIDOMEventTarget interface
NS_IMETHOD AddEventListener(const nsAReadableString& aType,
nsIDOMEventListener* aListener,
PRBool aUseCapture);
NS_IMETHOD RemoveEventListener(const nsAReadableString& aType,
nsIDOMEventListener* aListener,
PRBool aUseCapture);
NS_IMETHOD DispatchEvent(nsIDOMEvent* aEvent);
// nsIDOMEventReceiver interface
NS_IMETHOD AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID);
NS_IMETHOD RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID& aIID);
NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult);
NS_IMETHOD GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult);
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
protected:
nsresult HandleEventSubType(nsListenerStruct* aListenerStruct,
nsIDOMEvent* aDOMEvent,
nsIDOMEventTarget* aCurrentTarget,
PRUint32 aSubType,
PRUint32 aPhaseFlags);
nsListenerStruct* FindJSEventListener(REFNSIID aIID);
nsresult SetJSEventListener(nsIScriptContext *aContext, nsIScriptObjectOwner *aOwner, nsIAtom* aName, REFNSIID aIID, PRBool aIsString);
nsresult AddEventListener(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags, PRInt32 aSubType);
nsresult RemoveEventListener(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags, PRInt32 aSubType);
void ReleaseListeners(nsVoidArray** aListeners, PRBool aScriptOnly);
nsresult FlipCaptureBit(PRInt32 aEventTypes, PRBool aInitCapture);
nsVoidArray* mEventListeners;
nsVoidArray* mMouseListeners;
nsVoidArray* mMouseMotionListeners;
nsVoidArray* mKeyListeners;
nsVoidArray* mLoadListeners;
nsVoidArray* mFocusListeners;
nsVoidArray* mFormListeners;
nsVoidArray* mDragListeners;
nsVoidArray* mPaintListeners;
nsVoidArray* mTextListeners;
nsVoidArray* mCompositionListeners;
nsVoidArray* mMenuListeners;
nsVoidArray* mScrollListeners;
nsCOMPtr<nsIPrincipal> mPrincipal;
PRBool mDestroyed;
nsISupports* mTarget; //WEAK
};
//Set of defines for distinguishing event handlers within listener groupings
//XXX Current usage allows no more than 7 types per listener grouping
#define NS_EVENT_BITS_NONE 0x00
//nsIDOMMouseListener
#define NS_EVENT_BITS_MOUSE_NONE 0x00
#define NS_EVENT_BITS_MOUSE_MOUSEDOWN 0x01
#define NS_EVENT_BITS_MOUSE_MOUSEUP 0x02
#define NS_EVENT_BITS_MOUSE_CLICK 0x04
#define NS_EVENT_BITS_MOUSE_DBLCLICK 0x08
#define NS_EVENT_BITS_MOUSE_MOUSEOVER 0x10
#define NS_EVENT_BITS_MOUSE_MOUSEOUT 0x20
//nsIDOMMouseMotionListener
#define NS_EVENT_BITS_MOUSEMOTION_NONE 0x00
#define NS_EVENT_BITS_MOUSEMOTION_MOUSEMOVE 0x01
#define NS_EVENT_BITS_MOUSEMOTION_DRAGMOVE 0x02
//nsIDOMKeyListener
#define NS_EVENT_BITS_KEY_NONE 0x00
#define NS_EVENT_BITS_KEY_KEYDOWN 0x01
#define NS_EVENT_BITS_KEY_KEYUP 0x02
#define NS_EVENT_BITS_KEY_KEYPRESS 0x04
//nsIDOMTextListener
#define NS_EVENT_BITS_TEXT_NONE 0x00
#define NS_EVENT_BITS_TEXT_TEXT 0x01
//nsIDOMCompositionListener
#define NS_EVENT_BITS_COMPOSITION_NONE 0x00
#define NS_EVENT_BITS_COMPOSITION_START 0x01
#define NS_EVENT_BITS_COMPOSITION_END 0x02
#define NS_EVENT_BITS_COMPOSITION_QUERY 0x04
//nsIDOMFocusListener
#define NS_EVENT_BITS_FOCUS_NONE 0x00
#define NS_EVENT_BITS_FOCUS_FOCUS 0x01
#define NS_EVENT_BITS_FOCUS_BLUR 0x02
//nsIDOMFormListener
#define NS_EVENT_BITS_FORM_NONE 0x00
#define NS_EVENT_BITS_FORM_SUBMIT 0x01
#define NS_EVENT_BITS_FORM_RESET 0x02
#define NS_EVENT_BITS_FORM_CHANGE 0x04
#define NS_EVENT_BITS_FORM_SELECT 0x08
#define NS_EVENT_BITS_FORM_INPUT 0x10
//nsIDOMLoadListener
#define NS_EVENT_BITS_LOAD_NONE 0x00
#define NS_EVENT_BITS_LOAD_LOAD 0x01
#define NS_EVENT_BITS_LOAD_UNLOAD 0x02
#define NS_EVENT_BITS_LOAD_ABORT 0x04
#define NS_EVENT_BITS_LOAD_ERROR 0x08
//nsIDOMMenuListener
#define NS_EVENT_BITS_MENU_NONE 0x00
#define NS_EVENT_BITS_MENU_CREATE 0x01
#define NS_EVENT_BITS_XUL_CLOSE 0x02
#define NS_EVENT_BITS_MENU_DESTROY 0x04
#define NS_EVENT_BITS_MENU_ACTION 0x08
#define NS_EVENT_BITS_XUL_BROADCAST 0x10
#define NS_EVENT_BITS_XUL_COMMAND_UPDATE 0x20
//nsIScrollListener
#define NS_EVENT_BITS_SCROLLPORT_NONE 0x00
#define NS_EVENT_BITS_SCROLLPORT_OVERFLOW 0x01
#define NS_EVENT_BITS_SCROLLPORT_UNDERFLOW 0x02
#define NS_EVENT_BITS_SCROLLPORT_OVERFLOWCHANGED 0x04
//nsIDOMDragListener
#define NS_EVENT_BITS_DRAG_NONE 0x00
#define NS_EVENT_BITS_DRAG_ENTER 0x01
#define NS_EVENT_BITS_DRAG_OVER 0x02
#define NS_EVENT_BITS_DRAG_EXIT 0x04
#define NS_EVENT_BITS_DRAG_DROP 0x08
#define NS_EVENT_BITS_DRAG_GESTURE 0x10
//nsIDOMPaintListener
#define NS_EVENT_BITS_PAINT_NONE 0x00
#define NS_EVENT_BITS_PAINT_PAINT 0x01
#define NS_EVENT_BITS_PAINT_RESIZE 0x02
#define NS_EVENT_BITS_PAINT_SCROLL 0x04
#endif // nsEventListenerManager_h__

Просмотреть файл

@ -42,6 +42,7 @@
#include "nsIHTMLContent.h"
#include "nsILink.h"
#include "nsILinkHandler.h"
#include "nsPIDOMWindow.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptObjectOwner.h"
#include "nsISizeOfHandler.h"
@ -86,6 +87,13 @@
#include "nsIDOMHTMLFormElement.h"
#include "nsILanguageAtomService.h"
#include "nsIDOMMutationEvent.h"
#include "nsMutationEvent.h"
#include "nsEventListenerManager.h"
#include "nsIBindingManager.h"
#include "nsIXBLBinding.h"
#include "nsIParser.h"
#include "nsParserCIID.h"
#include "nsIHTMLContentSink.h"
@ -1229,6 +1237,73 @@ nsGenericHTMLElement::NormalizeAttributeString(const nsAReadableString& aStr,
return nimgr->GetNodeInfo(lower, nsnull, kNameSpaceID_None, aNodeInfo);
}
static PRBool HasMutationListeners(nsIContent* aContent, PRUint32 aType)
{
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (!doc)
return PR_FALSE;
nsCOMPtr<nsIScriptGlobalObject> global;
doc->GetScriptGlobalObject(getter_AddRefs(global));
if (!global)
return PR_FALSE;
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(global));
if (!window)
return PR_FALSE;
PRBool set;
window->HasMutationListeners(aType, &set);
if (!set)
return PR_FALSE;
// We know a mutation listener is registered, but it might not
// be in our chain. Check quickly to see.
nsCOMPtr<nsIContent> curr = aContent;
nsCOMPtr<nsIEventListenerManager> manager;
while (curr) {
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(curr));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
nsCOMPtr<nsIContent> prev = curr;
prev->GetParent(*getter_AddRefs(curr));
}
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
rec = do_QueryInterface(window);
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
return PR_FALSE;
}
nsresult
nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
@ -1302,6 +1377,9 @@ nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
if (NS_OK != result) {
return result;
}
nsAutoString strValue;
PRBool modification = PR_TRUE;
if (NS_CONTENT_ATTR_NOT_THERE !=
htmlContent->StringToAttribute(aAttribute, aValue, val)) {
// string value was mapped to nsHTMLValue, set it that way
@ -1324,13 +1402,14 @@ nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
}
// don't do any update if old == new
nsAutoString strValue;
result = GetAttribute(aNameSpaceID, aAttribute, strValue);
if ((NS_CONTENT_ATTR_NOT_THERE != result) && aValue.Equals(strValue)) {
NS_RELEASE(htmlContent);
return NS_OK;
}
modification = (result != NS_CONTENT_ATTR_NOT_THERE);
if (aNotify && (nsnull != mDocument)) {
mDocument->BeginUpdate();
}
@ -1363,11 +1442,45 @@ nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
}
NS_RELEASE(htmlContent);
if (aNotify && (nsnull != mDocument)) {
result = mDocument->AttributeChanged(mContent, aNameSpaceID, aAttribute, NS_STYLE_HINT_UNKNOWN);
mDocument->EndUpdate();
}
if (mDocument) {
nsCOMPtr<nsIBindingManager> bindingManager;
mDocument->GetBindingManager(getter_AddRefs(bindingManager));
nsCOMPtr<nsIXBLBinding> binding;
bindingManager->GetBinding(mContent, getter_AddRefs(binding));
if (binding)
binding->AttributeChanged(aAttribute, aNameSpaceID, PR_FALSE);
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(mContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName;
aAttribute->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aAttribute;
if (!strValue.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(strValue));
if (!aValue.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(aValue));
mutation.mAttrChange = modification ? nsIDOMMutationEvent::MODIFICATION :
nsIDOMMutationEvent::ADDITION;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
mDocument->AttributeChanged(mContent, aNameSpaceID, aAttribute, NS_STYLE_HINT_UNKNOWN);
mDocument->EndUpdate();
}
}
return result;
}
@ -1447,6 +1560,41 @@ nsGenericHTMLElement::SetHTMLAttribute(nsIAtom* aAttribute,
htmlContent, mAttributes);
NS_RELEASE(sheet);
}
nsCOMPtr<nsIBindingManager> bindingManager;
mDocument->GetBindingManager(getter_AddRefs(bindingManager));
nsCOMPtr<nsIXBLBinding> binding;
bindingManager->GetBinding(mContent, getter_AddRefs(binding));
if (binding)
binding->AttributeChanged(aAttribute, kNameSpaceID_None, PR_TRUE);
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
// XXX Figure out how to get the old value, so I can fill in
// the prevValue field and so that I can correctly indicate
// MODIFICATIONs/ADDITIONs.
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(mContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName;
aAttribute->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aAttribute;
nsAutoString value;
aValue.ToString(value);
if (!value.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(value));
mutation.mAttrChange = nsIDOMMutationEvent::MODIFICATION;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
mDocument->AttributeChanged(mContent, kNameSpaceID_None, aAttribute, impact);
mDocument->EndUpdate();
@ -1504,11 +1652,48 @@ nsGenericHTMLElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
}
}
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(mContent));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName;
aAttribute->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aAttribute;
nsHTMLValue oldAttr;
GetHTMLAttribute(aAttribute, oldAttr);
nsAutoString attr;
oldAttr.ToString(attr);
if (!attr.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(attr));
mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
if (nsnull != sheet) {
result = sheet->UnsetAttributeFor(aAttribute, htmlContent, mAttributes);
NS_RELEASE(sheet);
}
nsCOMPtr<nsIBindingManager> bindingManager;
mDocument->GetBindingManager(getter_AddRefs(bindingManager));
nsCOMPtr<nsIXBLBinding> binding;
bindingManager->GetBinding(mContent, getter_AddRefs(binding));
if (binding)
binding->AttributeChanged(aAttribute, aNameSpaceID, PR_TRUE);
if (aNotify) {
mDocument->AttributeChanged(mContent, aNameSpaceID, aAttribute, impact);
mDocument->EndUpdate();
@ -3198,7 +3383,6 @@ nsGenericHTMLLeafElement::GetChildNodes(nsIDOMNodeList** aChildNodes)
return slots->mChildNodes->QueryInterface(NS_GET_IID(nsIDOMNodeList), (void **)aChildNodes);
}
//----------------------------------------------------------------------
nsGenericHTMLContainerElement::nsGenericHTMLContainerElement()
@ -3375,6 +3559,21 @@ nsGenericHTMLContainerElement::InsertChildAt(nsIContent* aKid,
if (aNotify) {
doc->ContentInserted(mContent, aKid, aIndex);
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
}
}
if (aNotify && (nsnull != doc)) {
@ -3433,6 +3632,21 @@ nsGenericHTMLContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
if (aNotify) {
doc->ContentAppended(mContent, mChildren.Count() - 1);
}
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
}
}
if (aNotify && (nsnull != doc)) {
@ -3450,6 +3664,22 @@ nsGenericHTMLContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
}
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
if (nsnull != oldKid ) {
if (HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(oldKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEREMOVED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(mContent));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
oldKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
nsRange::OwnerChildRemoved(mContent, aIndex, oldKid);
mChildren.RemoveElementAt(aIndex);
if (aNotify) {

Просмотреть файл

@ -40,6 +40,7 @@ CPPSRCS = \
nsXBLDragHandler.cpp \
nsXBLMouseHandler.cpp \
nsXBLMouseMotionHandler.cpp \
nsXBLMutationHandler.cpp \
nsXBLKeyHandler.cpp \
nsXBLLoadHandler.cpp \
nsXBLXULHandler.cpp \

Просмотреть файл

@ -35,6 +35,7 @@ CPPSRCS= \
nsXBLKeyHandler.cpp \
nsXBLMouseHandler.cpp \
nsXBLMouseMotionHandler.cpp \
nsXBLMutationHandler.cpp \
nsXBLDragHandler.cpp \
nsXBLFocusHandler.cpp \
nsXBLXULHandler.cpp \
@ -53,6 +54,7 @@ CPP_OBJS= \
.\$(OBJDIR)\nsXBLKeyHandler.obj \
.\$(OBJDIR)\nsXBLMouseHandler.obj \
.\$(OBJDIR)\nsXBLMouseMotionHandler.obj \
.\$(OBJDIR)\nsXBLMutationHandler.obj \
.\$(OBJDIR)\nsXBLDragHandler.obj \
.\$(OBJDIR)\nsXBLFocusHandler.obj \
.\$(OBJDIR)\nsXBLXULHandler.obj \

Просмотреть файл

@ -63,6 +63,7 @@
#include "nsIDOMFormListener.h"
#include "nsIDOMMenuListener.h"
#include "nsIDOMDragListener.h"
#include "nsIDOMMutationListener.h"
#include "nsIDOMAttr.h"
#include "nsIDOMNamedNodeMap.h"
@ -73,6 +74,7 @@
#include "nsXBLFocusHandler.h"
#include "nsXBLMouseHandler.h"
#include "nsXBLMouseMotionHandler.h"
#include "nsXBLMutationHandler.h"
#include "nsXBLXULHandler.h"
#include "nsXBLScrollHandler.h"
#include "nsXBLFormHandler.h"
@ -211,6 +213,14 @@ nsXBLBinding::kEventHandlerMap[] = {
{ "dragdrop", nsnull, &NS_GET_IID(nsIDOMDragListener) },
{ "draggesture", nsnull, &NS_GET_IID(nsIDOMDragListener) },
{ "DOMSubtreeModified", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMAttrModified", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMCharacterDataModified", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMNodeInserted", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMNodeRemoved", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMNodeInsertedIntoDocument", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ "DOMNodeRemovedFromDocument", nsnull, &NS_GET_IID(nsIDOMMutationListener) },
{ nsnull, nsnull, nsnull }
};
@ -654,6 +664,12 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB
receiver->AddEventListener(type, (nsIDOMLoadListener*)loadHandler, useCapture);
handler = loadHandler;
}
else if(iid.Equals(NS_GET_IID(nsIDOMMutationListener))) {
nsXBLMutationHandler* mutationHandler;
NS_NewXBLMutationHandler(receiver, curr, &mutationHandler);
receiver->AddEventListener(type, (nsIDOMMutationListener*)mutationHandler, useCapture);
handler = mutationHandler;
}
else {
NS_WARNING("***** Non-compliant XBL event listener attached! *****");
nsAutoString value;

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -116,6 +116,10 @@
#include "nsXULAtoms.h"
#include "nsITreeBoxObject.h"
#include "nsMutationEvent.h"
#include "nsIDOMMutationEvent.h"
#include "nsPIDOMWindow.h"
#include "prlog.h"
#include "rdf.h"
#include "rdfutil.h"
@ -297,6 +301,75 @@ struct XULBroadcastListener
//----------------------------------------------------------------------
static PRBool HasMutationListeners(nsIContent* aContent, PRUint32 aType)
{
nsCOMPtr<nsIDocument> doc;
aContent->GetDocument(*getter_AddRefs(doc));
if (!doc)
return PR_FALSE;
nsCOMPtr<nsIScriptGlobalObject> global;
doc->GetScriptGlobalObject(getter_AddRefs(global));
if (!global)
return PR_FALSE;
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(global));
if (!window)
return PR_FALSE;
PRBool set;
window->HasMutationListeners(aType, &set);
if (!set)
return PR_FALSE;
// We know a mutation listener is registered, but it might not
// be in our chain. Check quickly to see.
nsCOMPtr<nsIContent> curr = aContent;
nsCOMPtr<nsIEventListenerManager> manager;
while (curr) {
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(curr));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
nsCOMPtr<nsIContent> prev = curr;
prev->GetParent(*getter_AddRefs(curr));
}
nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
rec = do_QueryInterface(window);
if (rec) {
rec->GetListenerManager(getter_AddRefs(manager));
if (manager) {
PRBool hasMutationListeners = PR_FALSE;
manager->HasMutationListeners(&hasMutationListeners);
if (hasMutationListeners)
return PR_TRUE;
}
}
return PR_FALSE;
}
//----------------------------------------------------------------------
nsrefcnt nsXULElement::gRefCnt;
nsIRDFService* nsXULElement::gRDFService;
nsINameSpaceManager* nsXULElement::gNameSpaceManager;
@ -2353,6 +2426,22 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify)
// N.B. that this is "shallow"!
aKid->SetDocument(mDocument, PR_FALSE, PR_TRUE);
if (mDocument && HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this),
NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this)));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify && mDocument) {
mDocument->ContentInserted(NS_STATIC_CAST(nsIStyledContent*, this), aKid, aIndex);
}
@ -2422,6 +2511,22 @@ nsXULElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
// N.B. that this is only "shallow". Callers beware!
aKid->SetDocument(mDocument, PR_FALSE, PR_TRUE);
if (mDocument && HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this),
NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(aKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEINSERTED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this)));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
aKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify && mDocument) {
mDocument->ContentAppended(NS_STATIC_CAST(nsIStyledContent*, this), mChildren.Count() - 1);
}
@ -2440,6 +2545,21 @@ nsXULElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
if (! oldKid)
return NS_ERROR_FAILURE;
if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this), NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(oldKid));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_NODEREMOVED;
mutation.mTarget = node;
nsCOMPtr<nsIDOMNode> relNode(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*,this)));
mutation.mRelatedNode = relNode;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
oldKid->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
// On the removal of a <treeitem>, <treechildren>, or <treecell> element,
// the possibility exists that some of the items in the removed subtree
// are selected (and therefore need to be deselected). We need to account for this.
@ -2706,12 +2826,16 @@ nsXULElement::SetAttribute(nsINodeInfo* aNodeInfo,
i++;
}
PRBool modification = PR_TRUE;
nsAutoString oldValue;
if (i < count) {
attr->GetValue(oldValue);
attr->SetValueInternal(aValue);
}
else {
// didn't find it
modification = PR_FALSE;
rv = nsXULAttribute::Create(NS_STATIC_CAST(nsIStyledContent*, this),
aNodeInfo, aValue, &attr);
if (NS_FAILED(rv)) return rv;
@ -2767,6 +2891,31 @@ nsXULElement::SetAttribute(nsINodeInfo* aNodeInfo,
if (binding)
binding->AttributeChanged(attrName, attrns, PR_FALSE);
if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*, this), NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName2;
attrName->ToString(attrName2);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName2, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = attrName;
if (!oldValue.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(oldValue));
if (!aValue.IsEmpty())
mutation.mNewAttrValue = getter_AddRefs(NS_NewAtom(aValue));
mutation.mAttrChange = modification ? nsIDOMMutationEvent::MODIFICATION :
nsIDOMMutationEvent::ADDITION;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
nsCOMPtr<nsIAtom> tagName;
NodeInfo()->GetNameAtom(*getter_AddRefs(tagName));
@ -2938,6 +3087,29 @@ nsXULElement::UnsetAttribute(PRInt32 aNameSpaceID,
nsXULAttribute* attr = NS_REINTERPRET_CAST(nsXULAttribute*, Attributes()->ElementAt(i));
if (attr->GetNodeInfo()->Equals(aName, aNameSpaceID)) {
attr->GetValue(oldValue);
if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*, this), NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
nsCOMPtr<nsIDOMEventTarget> node(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)));
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_ATTRMODIFIED;
mutation.mTarget = node;
nsAutoString attrName2;
aName->ToString(attrName2);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName2, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aName;
if (!oldValue.IsEmpty())
mutation.mPrevAttrValue = getter_AddRefs(NS_NewAtom(oldValue));
mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
nsEventStatus status = nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMEvent> domEvent;
HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), NS_EVENT_FLAG_INIT, &status);
}
Attributes()->RemoveElementAt(i);
NS_RELEASE(attr);
successful = PR_TRUE;