зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
e5c08f1f29
Коммит
e3726ac002
|
@ -93,4 +93,7 @@ nsresult
|
|||
NS_NewGenConImageContent(nsIContent** aResult, nsINodeInfo* aNodeInfo,
|
||||
imgIRequest* aImageRequest);
|
||||
|
||||
nsresult
|
||||
NS_NewXMLEventsElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
|
||||
|
||||
#endif // nsContentCreatorFunctions_h__
|
||||
|
|
|
@ -594,6 +594,8 @@ public:
|
|||
|
||||
virtual PRBool IsScriptEnabled() = 0;
|
||||
|
||||
virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement) = 0;
|
||||
|
||||
/**
|
||||
* Create an element with the specified name, prefix and namespace ID.
|
||||
* If aDocumentDefaultType is true we create an element of the default type
|
||||
|
|
|
@ -57,6 +57,7 @@ class nsINameSpace;
|
|||
#define kNameSpaceID_RDF 8
|
||||
#define kNameSpaceID_XUL 9
|
||||
#define kNameSpaceID_SVG 10
|
||||
#define kNameSpaceID_XMLEvents 11
|
||||
|
||||
#define NS_NAMESPACEMANAGER_CONTRACTID "@mozilla.org/content/namespacemanager;1"
|
||||
|
||||
|
|
|
@ -104,6 +104,8 @@
|
|||
#include "nsIRadioVisitor.h"
|
||||
#include "nsIFormControl.h"
|
||||
|
||||
#include "nsXMLEventsManager.h"
|
||||
|
||||
#include "nsBidiUtils.h"
|
||||
|
||||
static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
|
||||
|
@ -675,6 +677,18 @@ nsDocument::Init()
|
|||
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
|
||||
nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
|
|
|
@ -102,6 +102,7 @@ class nsIDTD;
|
|||
class nsXPathDocumentTearoff;
|
||||
class nsIRadioVisitor;
|
||||
class nsIFormControl;
|
||||
class nsXMLEventsManager;
|
||||
struct nsRadioGroupStruct;
|
||||
|
||||
|
||||
|
@ -493,6 +494,8 @@ public:
|
|||
// Already declared in nsIDocument
|
||||
|
||||
virtual nsresult Init();
|
||||
|
||||
virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement);
|
||||
|
||||
virtual nsresult CreateElem(nsIAtom *aName, nsIAtom *aPrefix,
|
||||
PRInt32 aNamespaceID,
|
||||
|
@ -582,6 +585,7 @@ protected:
|
|||
nsCOMPtr<nsICSSLoader> mCSSLoader;
|
||||
nsRefPtr<nsHTMLStyleSheet> mAttrStyleSheet;
|
||||
nsCOMPtr<nsIHTMLCSSStyleSheet> mStyleAttrStyleSheet;
|
||||
nsRefPtr<nsXMLEventsManager> mXMLEventsManager;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#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 kSVGNameSpaceURI "http://www.w3.org/2000/svg"
|
||||
#define kXMLEventsNameSpaceURI "http://www.w3.org/2001/xml-events"
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Name Space
|
||||
|
@ -354,6 +355,7 @@ nsresult NameSpaceManagerImpl::Init()
|
|||
AddNameSpace(NS_LITERAL_STRING(kRDFNameSpaceURI), kNameSpaceID_RDF);
|
||||
AddNameSpace(NS_LITERAL_STRING(kXULNameSpaceURI), kNameSpaceID_XUL);
|
||||
AddNameSpace(NS_LITERAL_STRING(kSVGNameSpaceURI), kNameSpaceID_SVG);
|
||||
AddNameSpace(NS_LITERAL_STRING(kXMLEventsNameSpaceURI), kNameSpaceID_XMLEvents);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -462,6 +464,9 @@ NS_NewElement(nsIContent** aResult, PRInt32 aElementType,
|
|||
return NS_NewSVGElement(aResult, aNodeInfo);
|
||||
}
|
||||
#endif
|
||||
if (aElementType == kNameSpaceID_XMLEvents) {
|
||||
return NS_NewXMLEventsElement(aResult, aNodeInfo);
|
||||
}
|
||||
return NS_NewXMLElement(aResult, aNodeInfo);
|
||||
}
|
||||
|
||||
|
@ -478,6 +483,7 @@ NameSpaceManagerImpl::HasElementCreator(PRInt32 aNameSpaceID)
|
|||
#ifdef MOZ_SVG
|
||||
aNameSpaceID == kNameSpaceID_SVG ||
|
||||
#endif
|
||||
aNameSpaceID == kNameSpaceID_XMLEvents ||
|
||||
PR_FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,9 @@ REQUIRES = xpcom \
|
|||
widget \
|
||||
caps \
|
||||
xpconnect \
|
||||
webshell \
|
||||
docshell \
|
||||
htmlparser \
|
||||
pref \
|
||||
view \
|
||||
necko \
|
||||
|
@ -68,6 +70,8 @@ CPPSRCS = \
|
|||
nsDOMMutationEvent.cpp \
|
||||
nsPrivateTextRange.cpp \
|
||||
nsDOMEventGroup.cpp \
|
||||
nsXMLEventsManager.cpp \
|
||||
nsXMLEventsElement.cpp \
|
||||
$(NULL)
|
||||
|
||||
# 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
|
||||
|
||||
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)/../../xml/content/src \
|
||||
-I$(srcdir)/../../../dom/src/base \
|
||||
$(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;
|
||||
}
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@ HTML_ATOM(content, "content")
|
|||
HTML_ATOM(contentLocation, "content-location")
|
||||
HTML_ATOM(coords, "coords")
|
||||
HTML_ATOM(dd, "dd")
|
||||
HTML_ATOM(defaultAction, "defaultAction") //XML Events
|
||||
HTML_ATOM(defaultchecked, "defaultchecked")
|
||||
HTML_ATOM(defaultselected, "defaultselected")
|
||||
HTML_ATOM(defaultvalue, "defaultvalue")
|
||||
|
@ -150,6 +151,7 @@ HTML_ATOM(h3, "h3")
|
|||
HTML_ATOM(h4, "h4")
|
||||
HTML_ATOM(h5, "h5")
|
||||
HTML_ATOM(h6, "h6")
|
||||
HTML_ATOM(handler, "handler") //XML Events
|
||||
HTML_ATOM(head, "head")
|
||||
HTML_ATOM(headerContentLanguage, "content-language")
|
||||
HTML_ATOM(headerContentScriptType, "content-script-type")
|
||||
|
@ -182,6 +184,7 @@ HTML_ATOM(layer, "layer")
|
|||
HTML_ATOM(layout, "layout")
|
||||
HTML_ATOM(li, "li")
|
||||
HTML_ATOM(link, "link")
|
||||
HTML_ATOM(listener, "listener") //XML Events
|
||||
HTML_ATOM(left, "left")
|
||||
HTML_ATOM(leftmargin, "leftmargin")
|
||||
HTML_ATOM(leftpadding, "leftpadding")
|
||||
|
@ -211,6 +214,7 @@ HTML_ATOM(noscript, "noscript")
|
|||
HTML_ATOM(noshade, "noshade")
|
||||
HTML_ATOM(nowrap, "nowrap")
|
||||
HTML_ATOM(object, "object")
|
||||
HTML_ATOM(observer, "observer") //XML Events
|
||||
HTML_ATOM(ol, "ol")
|
||||
HTML_ATOM(optgroup, "optgroup")
|
||||
HTML_ATOM(option, "option")
|
||||
|
@ -219,11 +223,13 @@ HTML_ATOM(p, "p")
|
|||
HTML_ATOM(pagex, "pagex")
|
||||
HTML_ATOM(pagey, "pagey")
|
||||
HTML_ATOM(param, "param")
|
||||
HTML_ATOM(phase, "phase") //XML Events
|
||||
HTML_ATOM(plaintext, "plaintext")
|
||||
HTML_ATOM(pointSize, "point-size")
|
||||
HTML_ATOM(pre, "pre")
|
||||
HTML_ATOM(profile, "profile")
|
||||
HTML_ATOM(prompt, "prompt")
|
||||
HTML_ATOM(propagate, "propagate") //XML Events
|
||||
HTML_ATOM(q, "q")
|
||||
HTML_ATOM(readonly, "readonly")
|
||||
HTML_ATOM(refresh, "refresh")
|
||||
|
|
|
@ -115,6 +115,7 @@ HTML_ATOM(content, "content")
|
|||
HTML_ATOM(contentLocation, "content-location")
|
||||
HTML_ATOM(coords, "coords")
|
||||
HTML_ATOM(dd, "dd")
|
||||
HTML_ATOM(defaultAction, "defaultAction") //XML Events
|
||||
HTML_ATOM(defaultchecked, "defaultchecked")
|
||||
HTML_ATOM(defaultselected, "defaultselected")
|
||||
HTML_ATOM(defaultvalue, "defaultvalue")
|
||||
|
@ -150,6 +151,7 @@ HTML_ATOM(h3, "h3")
|
|||
HTML_ATOM(h4, "h4")
|
||||
HTML_ATOM(h5, "h5")
|
||||
HTML_ATOM(h6, "h6")
|
||||
HTML_ATOM(handler, "handler") //XML Events
|
||||
HTML_ATOM(head, "head")
|
||||
HTML_ATOM(headerContentLanguage, "content-language")
|
||||
HTML_ATOM(headerContentScriptType, "content-script-type")
|
||||
|
@ -182,6 +184,7 @@ HTML_ATOM(layer, "layer")
|
|||
HTML_ATOM(layout, "layout")
|
||||
HTML_ATOM(li, "li")
|
||||
HTML_ATOM(link, "link")
|
||||
HTML_ATOM(listener, "listener") //XML Events
|
||||
HTML_ATOM(left, "left")
|
||||
HTML_ATOM(leftmargin, "leftmargin")
|
||||
HTML_ATOM(leftpadding, "leftpadding")
|
||||
|
@ -211,6 +214,7 @@ HTML_ATOM(noscript, "noscript")
|
|||
HTML_ATOM(noshade, "noshade")
|
||||
HTML_ATOM(nowrap, "nowrap")
|
||||
HTML_ATOM(object, "object")
|
||||
HTML_ATOM(observer, "observer") //XML Events
|
||||
HTML_ATOM(ol, "ol")
|
||||
HTML_ATOM(optgroup, "optgroup")
|
||||
HTML_ATOM(option, "option")
|
||||
|
@ -219,11 +223,13 @@ HTML_ATOM(p, "p")
|
|||
HTML_ATOM(pagex, "pagex")
|
||||
HTML_ATOM(pagey, "pagey")
|
||||
HTML_ATOM(param, "param")
|
||||
HTML_ATOM(phase, "phase") //XML Events
|
||||
HTML_ATOM(plaintext, "plaintext")
|
||||
HTML_ATOM(pointSize, "point-size")
|
||||
HTML_ATOM(pre, "pre")
|
||||
HTML_ATOM(profile, "profile")
|
||||
HTML_ATOM(prompt, "prompt")
|
||||
HTML_ATOM(propagate, "propagate") //XML Events
|
||||
HTML_ATOM(q, "q")
|
||||
HTML_ATOM(readonly, "readonly")
|
||||
HTML_ATOM(refresh, "refresh")
|
||||
|
|
|
@ -130,7 +130,6 @@ nsXMLElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|||
NS_IMPL_ADDREF_INHERITED(nsXMLElement, nsGenericElement)
|
||||
NS_IMPL_RELEASE_INHERITED(nsXMLElement, nsGenericElement)
|
||||
|
||||
|
||||
nsresult
|
||||
nsXMLElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
|
||||
const nsAString& aValue, PRBool aNotify)
|
||||
|
|
Загрузка…
Ссылка в новой задаче