Checking in fix for 164482 (Patch by smaug@welho.com). Adding support for XML Events. r=bryner@brianryner.com, sr=jst@mozilla.org

This commit is contained in:
jst%mozilla.jstenback.com 2004-07-15 05:24:40 +00:00
Родитель e5c08f1f29
Коммит e3726ac002
15 изменённых файлов: 729 добавлений и 2 удалений

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

@ -93,4 +93,7 @@ nsresult
NS_NewGenConImageContent(nsIContent** aResult, nsINodeInfo* aNodeInfo, NS_NewGenConImageContent(nsIContent** aResult, nsINodeInfo* aNodeInfo,
imgIRequest* aImageRequest); imgIRequest* aImageRequest);
nsresult
NS_NewXMLEventsElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
#endif // nsContentCreatorFunctions_h__ #endif // nsContentCreatorFunctions_h__

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

@ -594,6 +594,8 @@ public:
virtual PRBool IsScriptEnabled() = 0; virtual PRBool IsScriptEnabled() = 0;
virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement) = 0;
/** /**
* Create an element with the specified name, prefix and namespace ID. * Create an element with the specified name, prefix and namespace ID.
* If aDocumentDefaultType is true we create an element of the default type * If aDocumentDefaultType is true we create an element of the default type

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

@ -57,6 +57,7 @@ class nsINameSpace;
#define kNameSpaceID_RDF 8 #define kNameSpaceID_RDF 8
#define kNameSpaceID_XUL 9 #define kNameSpaceID_XUL 9
#define kNameSpaceID_SVG 10 #define kNameSpaceID_SVG 10
#define kNameSpaceID_XMLEvents 11
#define NS_NAMESPACEMANAGER_CONTRACTID "@mozilla.org/content/namespacemanager;1" #define NS_NAMESPACEMANAGER_CONTRACTID "@mozilla.org/content/namespacemanager;1"

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

@ -104,6 +104,8 @@
#include "nsIRadioVisitor.h" #include "nsIRadioVisitor.h"
#include "nsIFormControl.h" #include "nsIFormControl.h"
#include "nsXMLEventsManager.h"
#include "nsBidiUtils.h" #include "nsBidiUtils.h"
static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID); static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
@ -675,6 +677,18 @@ nsDocument::Init()
return mNodeInfoManager->Init(this); return mNodeInfoManager->Init(this);
} }
nsresult
nsDocument::AddXMLEventsContent(nsIContent *aXMLEventsElement)
{
if (!mXMLEventsManager) {
mXMLEventsManager = new nsXMLEventsManager();
NS_ENSURE_TRUE(mXMLEventsManager, NS_ERROR_OUT_OF_MEMORY);
AddObserver(mXMLEventsManager);
}
mXMLEventsManager->AddXMLEventsContent(aXMLEventsElement);
return NS_OK;
}
void void
nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
{ {

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

@ -102,6 +102,7 @@ class nsIDTD;
class nsXPathDocumentTearoff; class nsXPathDocumentTearoff;
class nsIRadioVisitor; class nsIRadioVisitor;
class nsIFormControl; class nsIFormControl;
class nsXMLEventsManager;
struct nsRadioGroupStruct; struct nsRadioGroupStruct;
@ -493,6 +494,8 @@ public:
// Already declared in nsIDocument // Already declared in nsIDocument
virtual nsresult Init(); virtual nsresult Init();
virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement);
virtual nsresult CreateElem(nsIAtom *aName, nsIAtom *aPrefix, virtual nsresult CreateElem(nsIAtom *aName, nsIAtom *aPrefix,
PRInt32 aNamespaceID, PRInt32 aNamespaceID,
@ -582,6 +585,7 @@ protected:
nsCOMPtr<nsICSSLoader> mCSSLoader; nsCOMPtr<nsICSSLoader> mCSSLoader;
nsRefPtr<nsHTMLStyleSheet> mAttrStyleSheet; nsRefPtr<nsHTMLStyleSheet> mAttrStyleSheet;
nsCOMPtr<nsIHTMLCSSStyleSheet> mStyleAttrStyleSheet; nsCOMPtr<nsIHTMLCSSStyleSheet> mStyleAttrStyleSheet;
nsRefPtr<nsXMLEventsManager> mXMLEventsManager;
nsCOMPtr<nsIScriptEventManager> mScriptEventManager; nsCOMPtr<nsIScriptEventManager> mScriptEventManager;

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

@ -3344,6 +3344,11 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
} }
} }
if (aNamespaceID == kNameSpaceID_XMLEvents && aName == nsHTMLAtoms::_event &&
mNodeInfo->GetDocument()) {
mNodeInfo->GetDocument()->AddXMLEventsContent(this);
}
return NS_OK; return NS_OK;
} }

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

@ -54,6 +54,7 @@
#define kRDFNameSpaceURI "http://www.w3.org/1999/02/22-rdf-syntax-ns#" #define kRDFNameSpaceURI "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
#define kXULNameSpaceURI "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" #define kXULNameSpaceURI "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
#define kSVGNameSpaceURI "http://www.w3.org/2000/svg" #define kSVGNameSpaceURI "http://www.w3.org/2000/svg"
#define kXMLEventsNameSpaceURI "http://www.w3.org/2001/xml-events"
//----------------------------------------------------------- //-----------------------------------------------------------
// Name Space // Name Space
@ -354,6 +355,7 @@ nsresult NameSpaceManagerImpl::Init()
AddNameSpace(NS_LITERAL_STRING(kRDFNameSpaceURI), kNameSpaceID_RDF); AddNameSpace(NS_LITERAL_STRING(kRDFNameSpaceURI), kNameSpaceID_RDF);
AddNameSpace(NS_LITERAL_STRING(kXULNameSpaceURI), kNameSpaceID_XUL); AddNameSpace(NS_LITERAL_STRING(kXULNameSpaceURI), kNameSpaceID_XUL);
AddNameSpace(NS_LITERAL_STRING(kSVGNameSpaceURI), kNameSpaceID_SVG); AddNameSpace(NS_LITERAL_STRING(kSVGNameSpaceURI), kNameSpaceID_SVG);
AddNameSpace(NS_LITERAL_STRING(kXMLEventsNameSpaceURI), kNameSpaceID_XMLEvents);
return NS_OK; return NS_OK;
} }
@ -462,6 +464,9 @@ NS_NewElement(nsIContent** aResult, PRInt32 aElementType,
return NS_NewSVGElement(aResult, aNodeInfo); return NS_NewSVGElement(aResult, aNodeInfo);
} }
#endif #endif
if (aElementType == kNameSpaceID_XMLEvents) {
return NS_NewXMLEventsElement(aResult, aNodeInfo);
}
return NS_NewXMLElement(aResult, aNodeInfo); return NS_NewXMLElement(aResult, aNodeInfo);
} }
@ -478,6 +483,7 @@ NameSpaceManagerImpl::HasElementCreator(PRInt32 aNameSpaceID)
#ifdef MOZ_SVG #ifdef MOZ_SVG
aNameSpaceID == kNameSpaceID_SVG || aNameSpaceID == kNameSpaceID_SVG ||
#endif #endif
aNameSpaceID == kNameSpaceID_XMLEvents ||
PR_FALSE; PR_FALSE;
} }

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

@ -54,7 +54,9 @@ REQUIRES = xpcom \
widget \ widget \
caps \ caps \
xpconnect \ xpconnect \
webshell \
docshell \ docshell \
htmlparser \
pref \ pref \
view \ view \
necko \ necko \
@ -68,6 +70,8 @@ CPPSRCS = \
nsDOMMutationEvent.cpp \ nsDOMMutationEvent.cpp \
nsPrivateTextRange.cpp \ nsPrivateTextRange.cpp \
nsDOMEventGroup.cpp \ nsDOMEventGroup.cpp \
nsXMLEventsManager.cpp \
nsXMLEventsElement.cpp \
$(NULL) $(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib. # we don't want the shared lib, but we want to force the creation of a static lib.
@ -75,8 +79,11 @@ FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = -I$(srcdir)/../../html/base/src \ LOCAL_INCLUDES = \
-I$(srcdir)/../../base/src \
-I$(srcdir)/../../html/base/src \
-I$(srcdir)/../../xul/content/src \ -I$(srcdir)/../../xul/content/src \
-I$(srcdir)/../../xml/content/src \
-I$(srcdir)/../../../dom/src/base \ -I$(srcdir)/../../../dom/src/base \
$(NULL) $(NULL)

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

@ -0,0 +1,109 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* Olli Pettay.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXMLElement.h"
#include "nsHTMLAtoms.h"
class nsXMLEventsElement : public nsXMLElement {
public:
nsXMLEventsElement(nsINodeInfo *aNodeInfo);
virtual ~nsXMLEventsElement();
NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsXMLElement::)
virtual nsIAtom *GetIDAttributeName() const;
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
};
nsXMLEventsElement::nsXMLEventsElement(nsINodeInfo *aNodeInfo)
: nsXMLElement(aNodeInfo)
{
}
nsXMLEventsElement::~nsXMLEventsElement()
{
}
nsIAtom *
nsXMLEventsElement::GetIDAttributeName() const
{
if (mNodeInfo->Equals(nsHTMLAtoms::listener))
return nsHTMLAtoms::id;
return nsXMLElement::GetIDAttributeName();
}
nsresult
nsXMLEventsElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue, PRBool aNotify)
{
if (mNodeInfo->Equals(nsHTMLAtoms::listener) &&
mNodeInfo->GetDocument() && aNameSpaceID == kNameSpaceID_None &&
aName == nsHTMLAtoms::_event)
mNodeInfo->GetDocument()->AddXMLEventsContent(this);
return nsXMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
aNotify);
}
NS_IMETHODIMP
nsXMLEventsElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
*aReturn = nsnull;
nsXMLEventsElement* it = new nsXMLEventsElement(mNodeInfo);
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIDOMNode> kungFuDeathGrip(it);
CopyInnerTo(it, aDeep);
kungFuDeathGrip.swap(*aReturn);
return NS_OK;
}
nsresult
NS_NewXMLEventsElement(nsIContent** aInstancePtrResult, nsINodeInfo *aNodeInfo)
{
nsXMLEventsElement* it = new nsXMLEventsElement(aNodeInfo);
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aInstancePtrResult = it);
return NS_OK;
}

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

@ -0,0 +1,450 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* Olli Pettay.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIDOMMutationEvent.h"
#include "nsXMLEventsManager.h"
#include "nsHTMLAtoms.h"
#include "nsIDOMElement.h"
#include "nsIDOMDocument.h"
#include "nsIDOMEventReceiver.h"
#include "nsIStyledContent.h"
#include "nsNetUtil.h"
#include "nsIURL.h"
#include "nsIDOMEventListener.h"
#include "nsINameSpaceManager.h"
#include "nsINodeInfo.h"
PRBool nsXMLEventsListener::InitXMLEventsListener(nsIDocument * aDocument,
nsXMLEventsManager * aManager,
nsIContent * aContent)
{
PRInt32 nameSpaceID;
if (aContent->GetDocument() != aDocument)
return PR_FALSE;
if (aContent->GetNodeInfo()->Equals(nsHTMLAtoms::listener, kNameSpaceID_XMLEvents))
nameSpaceID = kNameSpaceID_None;
else
nameSpaceID = kNameSpaceID_XMLEvents;
nsAutoString eventType;
nsresult rv = aContent->GetAttr(nameSpaceID, nsHTMLAtoms::_event, eventType);
if (rv != NS_CONTENT_ATTR_HAS_VALUE)
return PR_FALSE;
nsAutoString handlerURIStr;
PRBool hasHandlerURI = PR_FALSE;
nsCOMPtr<nsIContent> handler;
nsAutoString observerID;
nsAutoString targetIdref;
if (aContent->GetAttr(nameSpaceID, nsHTMLAtoms::handler, handlerURIStr) !=
NS_CONTENT_ATTR_NOT_THERE) {
hasHandlerURI = PR_TRUE;
nsCAutoString handlerRef;
nsCOMPtr<nsIURI> handlerURI;
PRBool equals = PR_FALSE;
nsIURI *docURI = aDocument->GetDocumentURI();
nsIURI *baseURI = aDocument->GetBaseURI();
rv = NS_NewURI( getter_AddRefs(handlerURI), handlerURIStr, nsnull, baseURI);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIURL> handlerURL(do_QueryInterface(handlerURI));
if (handlerURL) {
handlerURL->GetRef(handlerRef);
handlerURL->SetRef(EmptyCString());
//We support only XML Events Basic.
docURI->Equals(handlerURL, &equals);
if (equals) {
nsCOMPtr<nsIDOMDocument> doc(do_QueryInterface(aDocument));
if (doc) {
nsCOMPtr<nsIDOMElement> domhandler;
doc->GetElementById(NS_ConvertUTF8toUTF16(handlerRef),
getter_AddRefs(domhandler));
handler = do_QueryInterface(domhandler);
}
}
}
}
}
else
handler = aContent;
if (!handler)
return PR_FALSE;
aContent->GetAttr(nameSpaceID, nsHTMLAtoms::target, targetIdref);
PRBool hasObserver =
aContent->GetAttr(nameSpaceID, nsHTMLAtoms::observer, observerID) !=
NS_CONTENT_ATTR_NOT_THERE;
nsAutoString phase;
PRBool capture =
aContent->GetAttr(nameSpaceID, nsHTMLAtoms::phase, phase) !=
NS_CONTENT_ATTR_NOT_THERE && phase.Equals(NS_LITERAL_STRING("capture"));
nsAutoString prop;
PRBool stopPropagation =
aContent->GetAttr(nameSpaceID, nsHTMLAtoms::propagate, prop) !=
NS_CONTENT_ATTR_NOT_THERE && prop.Equals(NS_LITERAL_STRING("stop"));
nsAutoString cancel;
PRBool cancelDefault =
aContent->GetAttr(nameSpaceID, nsHTMLAtoms::defaultAction, cancel) !=
NS_CONTENT_ATTR_NOT_THERE && cancel.Equals(NS_LITERAL_STRING("cancel"));
nsCOMPtr<nsIContent> observer;
if (!hasObserver) {
if (!hasHandlerURI) //Parent should be the observer
observer = aContent->GetParent();
else //We have the handler, so this is the observer
observer = aContent;
}
else if (!observerID.IsEmpty()) {
nsCOMPtr<nsIDOMDocument> doc(do_QueryInterface(aDocument));
if (doc) {
nsCOMPtr<nsIDOMElement> el;
doc->GetElementById(observerID, getter_AddRefs(el));
observer = do_QueryInterface(el);
}
}
nsCOMPtr<nsIDOMEventTarget> eventObserver;
if (observer)
eventObserver = do_QueryInterface(observer);
if (eventObserver) {
nsXMLEventsListener * eli = new nsXMLEventsListener(aManager,
aContent,
observer,
handler,
eventType,
capture,
stopPropagation,
cancelDefault,
targetIdref);
if (eli) {
nsresult rv = eventObserver->AddEventListener(eventType, eli, capture);
if (NS_SUCCEEDED(rv)) {
aManager->RemoveXMLEventsContent(aContent);
aManager->RemoveListener(aContent);
aManager->AddListener(aContent, eli);
return PR_TRUE;
}
else
delete eli;
}
}
return PR_FALSE;
}
nsXMLEventsListener::nsXMLEventsListener(nsXMLEventsManager * aManager,
nsIContent * aElement,
nsIContent * aObserver,
nsIContent * aHandler,
const nsAString& aEvent,
PRBool aPhase,
PRBool aStopPropagation,
PRBool aCancelDefault,
const nsAString& aTarget)
: mManager(aManager),
mElement(aElement),
mObserver(aObserver),
mHandler(aHandler),
mEvent(aEvent),
mPhase(aPhase),
mStopPropagation(aStopPropagation),
mCancelDefault(aCancelDefault)
{
if (!aTarget.IsEmpty())
mTarget = do_GetAtom(aTarget);
}
nsXMLEventsListener::~nsXMLEventsListener()
{
}
void nsXMLEventsListener::Unregister()
{
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mObserver);
if (target) {
target->RemoveEventListener(mEvent, this, mPhase);
}
mObserver = nsnull;
mHandler = nsnull;
}
void nsXMLEventsListener::SetIncomplete()
{
Unregister();
mManager->AddXMLEventsContent(mElement);
mElement = nsnull;
}
PRBool nsXMLEventsListener::ObserverEquals(nsIContent * aTarget)
{
return aTarget == mObserver;
}
PRBool nsXMLEventsListener::HandlerEquals(nsIContent * aTarget)
{
return aTarget == mHandler;
}
NS_IMPL_ISUPPORTS1(nsXMLEventsListener, nsIDOMEventListener)
NS_IMETHODIMP
nsXMLEventsListener::HandleEvent(nsIDOMEvent* aEvent)
{
if (!aEvent)
return NS_ERROR_INVALID_ARG;
PRBool targetMatched = PR_TRUE;
nsCOMPtr<nsIDOMEvent> event(aEvent);
if (mTarget) {
targetMatched = PR_FALSE;
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIStyledContent> targetEl(do_QueryInterface(target));
if (targetEl) {
nsCOMPtr<nsIAtom> id;
targetEl->GetID(getter_AddRefs(id));
if (id == mTarget)
targetMatched = PR_TRUE;
}
}
if (!targetMatched)
return NS_OK;
nsCOMPtr<nsIDOMEventListener> handler(do_QueryInterface(mHandler));
if (handler) {
nsresult rv = handler->HandleEvent(event);
if (NS_SUCCEEDED(rv)) {
if (mStopPropagation)
event->StopPropagation();
if (mCancelDefault)
event->PreventDefault();
}
return rv;
}
return NS_OK;
}
//XMLEventsManager / DocumentObserver
PR_STATIC_CALLBACK(PLDHashOperator) EnumAndUnregisterListener(nsISupports * aContent,
nsCOMPtr<nsXMLEventsListener> & aListener,
void * aData)
{
if (aListener)
aListener->Unregister();
return PL_DHASH_NEXT;
}
PR_STATIC_CALLBACK(PLDHashOperator) EnumAndSetIncomplete(nsISupports * aContent,
nsCOMPtr<nsXMLEventsListener> & aListener,
void * aData)
{
if (aListener && aData) {
nsCOMPtr<nsIContent> content = NS_STATIC_CAST(nsIContent *, aData);
if (content) {
if (aListener->ObserverEquals(content) || aListener->HandlerEquals(content)) {
aListener->SetIncomplete();
return PL_DHASH_REMOVE;
}
}
}
return PL_DHASH_NEXT;
}
nsXMLEventsManager::nsXMLEventsManager()
{
mListeners.Init();
}
nsXMLEventsManager::~nsXMLEventsManager()
{
}
NS_IMPL_ISUPPORTS1(nsXMLEventsManager, nsIDocumentObserver)
void nsXMLEventsManager::AddXMLEventsContent(nsIContent * aContent)
{
mIncomplete.RemoveObject(aContent);
mIncomplete.AppendObject(aContent);
}
void nsXMLEventsManager::RemoveXMLEventsContent(nsIContent * aContent)
{
mIncomplete.RemoveObject(aContent);
}
void nsXMLEventsManager::AddListener(nsIContent * aContent,
nsXMLEventsListener * aListener)
{
mListeners.Put(aContent, aListener);
}
PRBool nsXMLEventsManager::RemoveListener(nsIContent * aContent)
{
nsCOMPtr<nsXMLEventsListener> listener;
mListeners.Get(aContent, getter_AddRefs(listener));
if (listener) {
listener->Unregister();
mListeners.Remove(aContent);
return PR_TRUE;
}
return PR_FALSE;
}
void nsXMLEventsManager::AddListeners(nsIDocument* aDocument)
{
nsIContent *cur;
for (int i = 0; i < mIncomplete.Count(); ++i) {
cur = mIncomplete[i];
//If this succeeds, the object will be removed from mIncomplete
if (nsXMLEventsListener::InitXMLEventsListener(aDocument, this, cur) == PR_TRUE)
--i;
}
}
void
nsXMLEventsManager::BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) {}
void
nsXMLEventsManager::EndUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) {}
void
nsXMLEventsManager::DocumentWillBeDestroyed(nsIDocument* aDocument){
mIncomplete.Clear();
mListeners.Enumerate(EnumAndUnregisterListener, this);
mListeners.Clear();
aDocument->RemoveObserver(this);
}
void
nsXMLEventsManager::BeginLoad(nsIDocument* aDocument) {}
void
nsXMLEventsManager::EndLoad(nsIDocument* aDocument)
{
AddListeners(aDocument);
}
NS_IMPL_NSIDOCUMENTOBSERVER_REFLOW_STUB(nsXMLEventsManager)
NS_IMPL_NSIDOCUMENTOBSERVER_STATE_STUB(nsXMLEventsManager)
void
nsXMLEventsManager::CharacterDataChanged(nsIDocument* aDocument,
nsIContent* aContent,
PRBool aAppend) {}
void
nsXMLEventsManager::AttributeChanged(nsIDocument* aDocument,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType)
{
if (aNameSpaceID == kNameSpaceID_XMLEvents &&
(aAttribute == nsHTMLAtoms::_event ||
aAttribute == nsHTMLAtoms::handler ||
aAttribute == nsHTMLAtoms::target ||
aAttribute == nsHTMLAtoms::observer ||
aAttribute == nsHTMLAtoms::phase ||
aAttribute == nsHTMLAtoms::propagate)) {
RemoveListener(aContent);
AddXMLEventsContent(aContent);
nsXMLEventsListener::InitXMLEventsListener(aDocument, this, aContent);
}
else {
if (aContent->GetNodeInfo()->Equals(nsHTMLAtoms::listener, kNameSpaceID_XMLEvents)) {
RemoveListener(aContent);
AddXMLEventsContent(aContent);
nsXMLEventsListener::InitXMLEventsListener(aDocument, this, aContent);
}
else if (aContent->GetIDAttributeName() == aAttribute) {
if (aModType == nsIDOMMutationEvent::REMOVAL)
mListeners.Enumerate(EnumAndSetIncomplete, aContent);
else if (aModType == nsIDOMMutationEvent::MODIFICATION) {
//Remove possible listener
mListeners.Enumerate(EnumAndSetIncomplete, aContent);
//Add new listeners
AddListeners(aDocument);
}
else {
//If we are adding the ID attribute, we must check whether we can
//add new listeners
AddListeners(aDocument);
}
}
}
}
void
nsXMLEventsManager::ContentAppended(nsIDocument* aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
AddListeners(aDocument);
}
void
nsXMLEventsManager::ContentInserted(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
AddListeners(aDocument);
}
void
nsXMLEventsManager::ContentRemoved(nsIDocument* aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
if (!aChild || !aChild->IsContentOfType(nsIContent::eELEMENT))
return;
//Note, we can't use IDs here, the observer may not always have an ID.
//And to remember: the same observer can be referenced by many
//XMLEventsListeners
//If the content was an XML Events observer or handler
mListeners.Enumerate(EnumAndSetIncomplete, aChild);
//If the content was an XML Events attributes container
if (RemoveListener(aChild)) {
//for aContainer.appendChild(aContainer.removeChild(aChild));
AddXMLEventsContent(aChild);
}
PRUint32 count = aChild->GetChildCount();
for (PRUint32 i = 0; i < count; ++i) {
ContentRemoved(aDocument, aChild, aChild->GetChildAt(i), i);
}
}
NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(nsXMLEventsManager)

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

@ -0,0 +1,110 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* Olli Pettay.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsXMLEventsManager_h___
#define nsXMLEventsManager_h___
#include "nsCOMPtr.h"
#include "nsIDocument.h"
#include "nsIContent.h"
#include "nsCOMArray.h"
#include "nsIDOMEventListener.h"
#include "nsInterfaceHashtable.h"
#include "nsIAtom.h"
/*
* The implementation of the XML Events Basic profile
*/
class nsXMLEventsManager;
class nsXMLEventsListener : public nsIDOMEventListener {
public:
static PRBool InitXMLEventsListener(nsIDocument * aDocument,
nsXMLEventsManager * aManager,
nsIContent * aContent);
nsXMLEventsListener(nsXMLEventsManager * aManager,
nsIContent * aElement,
nsIContent* aObserver,
nsIContent * aHandler,
const nsAString& aEvent,
PRBool aPhase,
PRBool aStopPropagation,
PRBool aCancelDefault,
const nsAString& aTarget);
~nsXMLEventsListener();
void Unregister();
//Removes this event listener from observer and adds the element back to the
//list of incomplete XML Events declarations in XMLEventsManager
void SetIncomplete();
PRBool ObserverEquals(nsIContent * aTarget);
PRBool HandlerEquals(nsIContent * aTarget);
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
private:
nsXMLEventsManager * mManager;
nsCOMPtr<nsIContent> mElement;
nsCOMPtr<nsIContent> mObserver;
nsCOMPtr<nsIContent> mHandler;
nsString mEvent;
nsCOMPtr<nsIAtom> mTarget;
PRPackedBool mPhase;
PRPackedBool mStopPropagation;
PRPackedBool mCancelDefault;
};
class nsXMLEventsManager : public nsIDocumentObserver {
public:
nsXMLEventsManager();
~nsXMLEventsManager();
NS_DECL_ISUPPORTS
NS_DECL_NSIDOCUMENTOBSERVER
void AddXMLEventsContent(nsIContent * aContent);
void RemoveXMLEventsContent(nsIContent * aContent);
void AddListener(nsIContent * aContent, nsXMLEventsListener * aListener);
//Returns PR_TRUE if a listener was removed.
PRBool RemoveListener(nsIContent * aXMLElement);
private:
void AddListeners(nsIDocument* aDocument);
nsInterfaceHashtable<nsISupportsHashKey,nsXMLEventsListener> mListeners;
nsCOMArray<nsIContent> mIncomplete;
};
#endif /* nsXMLEventsManager_h___ */

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

@ -1746,6 +1746,11 @@ nsGenericHTMLElement::SetAttrAndNotify(PRInt32 aNamespaceID,
} }
} }
if (aNamespaceID == kNameSpaceID_XMLEvents &&
aAttribute == nsHTMLAtoms::_event && mNodeInfo->GetDocument()) {
mNodeInfo->GetDocument()->AddXMLEventsContent(this);
}
return NS_OK; return NS_OK;
} }

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

@ -115,6 +115,7 @@ HTML_ATOM(content, "content")
HTML_ATOM(contentLocation, "content-location") HTML_ATOM(contentLocation, "content-location")
HTML_ATOM(coords, "coords") HTML_ATOM(coords, "coords")
HTML_ATOM(dd, "dd") HTML_ATOM(dd, "dd")
HTML_ATOM(defaultAction, "defaultAction") //XML Events
HTML_ATOM(defaultchecked, "defaultchecked") HTML_ATOM(defaultchecked, "defaultchecked")
HTML_ATOM(defaultselected, "defaultselected") HTML_ATOM(defaultselected, "defaultselected")
HTML_ATOM(defaultvalue, "defaultvalue") HTML_ATOM(defaultvalue, "defaultvalue")
@ -150,6 +151,7 @@ HTML_ATOM(h3, "h3")
HTML_ATOM(h4, "h4") HTML_ATOM(h4, "h4")
HTML_ATOM(h5, "h5") HTML_ATOM(h5, "h5")
HTML_ATOM(h6, "h6") HTML_ATOM(h6, "h6")
HTML_ATOM(handler, "handler") //XML Events
HTML_ATOM(head, "head") HTML_ATOM(head, "head")
HTML_ATOM(headerContentLanguage, "content-language") HTML_ATOM(headerContentLanguage, "content-language")
HTML_ATOM(headerContentScriptType, "content-script-type") HTML_ATOM(headerContentScriptType, "content-script-type")
@ -182,6 +184,7 @@ HTML_ATOM(layer, "layer")
HTML_ATOM(layout, "layout") HTML_ATOM(layout, "layout")
HTML_ATOM(li, "li") HTML_ATOM(li, "li")
HTML_ATOM(link, "link") HTML_ATOM(link, "link")
HTML_ATOM(listener, "listener") //XML Events
HTML_ATOM(left, "left") HTML_ATOM(left, "left")
HTML_ATOM(leftmargin, "leftmargin") HTML_ATOM(leftmargin, "leftmargin")
HTML_ATOM(leftpadding, "leftpadding") HTML_ATOM(leftpadding, "leftpadding")
@ -211,6 +214,7 @@ HTML_ATOM(noscript, "noscript")
HTML_ATOM(noshade, "noshade") HTML_ATOM(noshade, "noshade")
HTML_ATOM(nowrap, "nowrap") HTML_ATOM(nowrap, "nowrap")
HTML_ATOM(object, "object") HTML_ATOM(object, "object")
HTML_ATOM(observer, "observer") //XML Events
HTML_ATOM(ol, "ol") HTML_ATOM(ol, "ol")
HTML_ATOM(optgroup, "optgroup") HTML_ATOM(optgroup, "optgroup")
HTML_ATOM(option, "option") HTML_ATOM(option, "option")
@ -219,11 +223,13 @@ HTML_ATOM(p, "p")
HTML_ATOM(pagex, "pagex") HTML_ATOM(pagex, "pagex")
HTML_ATOM(pagey, "pagey") HTML_ATOM(pagey, "pagey")
HTML_ATOM(param, "param") HTML_ATOM(param, "param")
HTML_ATOM(phase, "phase") //XML Events
HTML_ATOM(plaintext, "plaintext") HTML_ATOM(plaintext, "plaintext")
HTML_ATOM(pointSize, "point-size") HTML_ATOM(pointSize, "point-size")
HTML_ATOM(pre, "pre") HTML_ATOM(pre, "pre")
HTML_ATOM(profile, "profile") HTML_ATOM(profile, "profile")
HTML_ATOM(prompt, "prompt") HTML_ATOM(prompt, "prompt")
HTML_ATOM(propagate, "propagate") //XML Events
HTML_ATOM(q, "q") HTML_ATOM(q, "q")
HTML_ATOM(readonly, "readonly") HTML_ATOM(readonly, "readonly")
HTML_ATOM(refresh, "refresh") HTML_ATOM(refresh, "refresh")

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

@ -115,6 +115,7 @@ HTML_ATOM(content, "content")
HTML_ATOM(contentLocation, "content-location") HTML_ATOM(contentLocation, "content-location")
HTML_ATOM(coords, "coords") HTML_ATOM(coords, "coords")
HTML_ATOM(dd, "dd") HTML_ATOM(dd, "dd")
HTML_ATOM(defaultAction, "defaultAction") //XML Events
HTML_ATOM(defaultchecked, "defaultchecked") HTML_ATOM(defaultchecked, "defaultchecked")
HTML_ATOM(defaultselected, "defaultselected") HTML_ATOM(defaultselected, "defaultselected")
HTML_ATOM(defaultvalue, "defaultvalue") HTML_ATOM(defaultvalue, "defaultvalue")
@ -150,6 +151,7 @@ HTML_ATOM(h3, "h3")
HTML_ATOM(h4, "h4") HTML_ATOM(h4, "h4")
HTML_ATOM(h5, "h5") HTML_ATOM(h5, "h5")
HTML_ATOM(h6, "h6") HTML_ATOM(h6, "h6")
HTML_ATOM(handler, "handler") //XML Events
HTML_ATOM(head, "head") HTML_ATOM(head, "head")
HTML_ATOM(headerContentLanguage, "content-language") HTML_ATOM(headerContentLanguage, "content-language")
HTML_ATOM(headerContentScriptType, "content-script-type") HTML_ATOM(headerContentScriptType, "content-script-type")
@ -182,6 +184,7 @@ HTML_ATOM(layer, "layer")
HTML_ATOM(layout, "layout") HTML_ATOM(layout, "layout")
HTML_ATOM(li, "li") HTML_ATOM(li, "li")
HTML_ATOM(link, "link") HTML_ATOM(link, "link")
HTML_ATOM(listener, "listener") //XML Events
HTML_ATOM(left, "left") HTML_ATOM(left, "left")
HTML_ATOM(leftmargin, "leftmargin") HTML_ATOM(leftmargin, "leftmargin")
HTML_ATOM(leftpadding, "leftpadding") HTML_ATOM(leftpadding, "leftpadding")
@ -211,6 +214,7 @@ HTML_ATOM(noscript, "noscript")
HTML_ATOM(noshade, "noshade") HTML_ATOM(noshade, "noshade")
HTML_ATOM(nowrap, "nowrap") HTML_ATOM(nowrap, "nowrap")
HTML_ATOM(object, "object") HTML_ATOM(object, "object")
HTML_ATOM(observer, "observer") //XML Events
HTML_ATOM(ol, "ol") HTML_ATOM(ol, "ol")
HTML_ATOM(optgroup, "optgroup") HTML_ATOM(optgroup, "optgroup")
HTML_ATOM(option, "option") HTML_ATOM(option, "option")
@ -219,11 +223,13 @@ HTML_ATOM(p, "p")
HTML_ATOM(pagex, "pagex") HTML_ATOM(pagex, "pagex")
HTML_ATOM(pagey, "pagey") HTML_ATOM(pagey, "pagey")
HTML_ATOM(param, "param") HTML_ATOM(param, "param")
HTML_ATOM(phase, "phase") //XML Events
HTML_ATOM(plaintext, "plaintext") HTML_ATOM(plaintext, "plaintext")
HTML_ATOM(pointSize, "point-size") HTML_ATOM(pointSize, "point-size")
HTML_ATOM(pre, "pre") HTML_ATOM(pre, "pre")
HTML_ATOM(profile, "profile") HTML_ATOM(profile, "profile")
HTML_ATOM(prompt, "prompt") HTML_ATOM(prompt, "prompt")
HTML_ATOM(propagate, "propagate") //XML Events
HTML_ATOM(q, "q") HTML_ATOM(q, "q")
HTML_ATOM(readonly, "readonly") HTML_ATOM(readonly, "readonly")
HTML_ATOM(refresh, "refresh") HTML_ATOM(refresh, "refresh")

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

@ -130,7 +130,6 @@ nsXMLElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_IMPL_ADDREF_INHERITED(nsXMLElement, nsGenericElement) NS_IMPL_ADDREF_INHERITED(nsXMLElement, nsGenericElement)
NS_IMPL_RELEASE_INHERITED(nsXMLElement, nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsXMLElement, nsGenericElement)
nsresult nsresult
nsXMLElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix, nsXMLElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue, PRBool aNotify) const nsAString& aValue, PRBool aNotify)