Combine various SetAttr implementations so that we just have

nsGenericElement::SetAttr.  Bug 308270, r=sicking, sr=jst
This commit is contained in:
bzbarsky%mit.edu 2005-10-28 02:59:38 +00:00
Родитель cd8d0700c3
Коммит e22e482952
11 изменённых файлов: 669 добавлений и 877 удалений

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

@ -3789,43 +3789,24 @@ nsGenericElement::TriggerLink(nsPresContext* aPresContext,
}
nsresult
nsGenericElement::AddScriptEventListener(nsIAtom* aAttribute,
nsGenericElement::AddScriptEventListener(nsIAtom* aEventName,
const nsAString& aValue)
{
nsresult rv = NS_OK;
nsISupports *target = NS_STATIC_CAST(nsIContent *, this);
NS_PRECONDITION(aEventName, "Must have event name!");
nsCOMPtr<nsISupports> target;
PRBool defer = PR_TRUE;
nsCOMPtr<nsIEventListenerManager> manager;
// Attributes on the body and frameset tags get set on the global object
if (mNodeInfo->Equals(nsHTMLAtoms::body) ||
mNodeInfo->Equals(nsHTMLAtoms::frameset)) {
nsIScriptGlobalObject *sgo;
// If we have a document, and it has a script global, add the
// event listener on the global. If not, proceed as normal.
// XXXbz should we instead use GetCurrentDoc() here, override
// BindToTree for those classes and munge event listeners there?
nsIDocument *document = GetOwnerDoc();
if (document && (sgo = document->GetScriptGlobalObject())) {
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(sgo));
NS_ENSURE_TRUE(receiver, NS_ERROR_FAILURE);
receiver->GetListenerManager(getter_AddRefs(manager));
target = sgo;
defer = PR_FALSE;
}
} else {
GetListenerManager(getter_AddRefs(manager));
}
nsresult rv = GetEventListenerManagerForAttr(getter_AddRefs(manager),
getter_AddRefs(target),
&defer);
NS_ENSURE_SUCCESS(rv, rv);
if (manager) {
nsIDocument *ownerDoc = GetOwnerDoc();
rv =
manager->AddScriptEventListener(target, aAttribute, aValue, defer,
manager->AddScriptEventListener(target, aEventName, aValue, defer,
!nsContentUtils::IsChromeDoc(ownerDoc));
}
@ -4001,47 +3982,82 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
}
}
PRBool modification = PR_FALSE;
nsAutoString oldValue;
PRBool hasListeners = PR_FALSE;
PRBool modification = PR_FALSE;
PRInt32 index = mAttrsAndChildren.IndexOfAttr(aName, aNamespaceID);
if (index >= 0) {
modification = PR_TRUE;
// Get old value and see if it's the same as new one
const nsAttrName* attrName = mAttrsAndChildren.GetSafeAttrNameAt(index);
const nsAttrValue* val = mAttrsAndChildren.AttrAt(index);
NS_ASSERTION(attrName && val, "attribute is supposed to be there");
val->ToString(oldValue);
if (oldValue.Equals(aValue) &&
aPrefix == attrName->GetPrefix()) {
// Nothing to do
return NS_OK;
if (IsInDoc()) {
hasListeners =
HasMutationListeners(this, NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
}
// If we have no listeners and aNotify is false, we are almost certainly
// coming from the content sink and will almost certainly have no previous
// value. Even if we do, setting the value is cheap when we have no
// listeners and don't plan to notify. The check for aNotify here is an
// optimization, the check for haveListeners is a correctness issue.
if (hasListeners || aNotify) {
nsAttrInfo info(GetAttrInfo(aNamespaceID, aName));
if (info.mValue) {
// Check whether the old value is the same as the new one. Note that we
// only need to actually _get_ the old value if we have listeners.
PRBool valueMatches;
if (hasListeners) {
// Need to store the old value
info.mValue->ToString(oldValue);
valueMatches = aValue.Equals(oldValue);
} else if (aNotify) {
valueMatches = info.mValue->Equals(aValue, eCaseMatters);
}
if (valueMatches && aPrefix == info.mName->GetPrefix()) {
return NS_OK;
}
}
}
// Begin the update _before_ changing the attr value
nsIDocument *document = GetCurrentDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
nsresult rv = BeforeSetAttr(aNamespaceID, aName, &aValue, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
nsAttrValue attrValue;
if (aNamespaceID != kNameSpaceID_None ||
!ParseAttribute(aName, aValue, attrValue)) {
attrValue.SetTo(aValue);
}
rv = SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
attrValue, modification, hasListeners, aNotify);
NS_ENSURE_SUCCESS(rv, rv);
return AfterSetAttr(aNamespaceID, aName, &aValue, aNotify);
}
nsresult
nsGenericElement::SetAttrAndNotify(PRInt32 aNamespaceID,
nsIAtom* aName,
nsIAtom* aPrefix,
const nsAString& aOldValue,
nsAttrValue& aParsedValue,
PRBool aModification,
PRBool aFireMutation,
PRBool aNotify)
{
nsresult rv;
PRUint8 modType = aModification ?
NS_STATIC_CAST(PRUint8, nsIDOMMutationEvent::MODIFICATION) :
NS_STATIC_CAST(PRUint8, nsIDOMMutationEvent::ADDITION);
nsIDocument* document = GetCurrentDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
if (aNotify && document) {
document->AttributeWillChange(this, aNamespaceID, aName);
}
nsresult rv;
if (aNamespaceID == kNameSpaceID_None) {
if (aName == GetIDAttributeName() && !aValue.IsEmpty()) {
// Store id as atom. id="" means that the element has no id, not that it has
// an emptystring as the id.
nsAttrValue attrValue;
attrValue.ParseAtom(aValue);
rv = mAttrsAndChildren.SetAndTakeAttr(aName, attrValue);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
rv = mAttrsAndChildren.SetAttr(aName, aValue);
NS_ENSURE_SUCCESS(rv, rv);
// XXXbz Perhaps we should push up the attribute mapping function
// stuff to nsGenericElement?
if (!IsAttributeMapped(aName) ||
!SetMappedAttribute(document, aName, aParsedValue, &rv)) {
rv = mAttrsAndChildren.SetAndTakeAttr(aName, aParsedValue);
}
}
else {
@ -4051,17 +4067,17 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
getter_AddRefs(ni));
NS_ENSURE_SUCCESS(rv, rv);
nsAttrValue attrVal(aValue);
rv = mAttrsAndChildren.SetAndTakeAttr(ni, attrVal);
NS_ENSURE_SUCCESS(rv, rv);
rv = mAttrsAndChildren.SetAndTakeAttr(ni, aParsedValue);
}
NS_ENSURE_SUCCESS(rv, rv);
if (document) {
nsXBLBinding *binding = document->BindingManager()->GetBinding(this);
if (binding)
if (binding) {
binding->AttributeChanged(aName, aNamespaceID, PR_FALSE, aNotify);
}
if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) {
if (aFireMutation) {
nsCOMPtr<nsIDOMEventTarget> node =
do_QueryInterface(NS_STATIC_CAST(nsIContent *, this));
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_ATTRMODIFIED, node);
@ -4073,40 +4089,88 @@ nsGenericElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aName;
if (!oldValue.IsEmpty()) {
mutation.mPrevAttrValue = do_GetAtom(oldValue);
nsAutoString newValue;
aParsedValue.ToString(newValue);
if (!newValue.IsEmpty()) {
mutation.mNewAttrValue = do_GetAtom(newValue);
}
if (!aValue.IsEmpty()) {
mutation.mNewAttrValue = do_GetAtom(aValue);
if (!aOldValue.IsEmpty()) {
mutation.mPrevAttrValue = do_GetAtom(aOldValue);
}
if (modification) {
mutation.mAttrChange = nsIDOMMutationEvent::MODIFICATION;
} else {
mutation.mAttrChange = nsIDOMMutationEvent::ADDITION;
}
mutation.mAttrChange = modType;
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
PRInt32 modHint = modification ? PRInt32(nsIDOMMutationEvent::MODIFICATION)
: PRInt32(nsIDOMMutationEvent::ADDITION);
document->AttributeChanged(this, aNamespaceID, aName, modHint);
document->AttributeChanged(this, aNamespaceID, aName, modType);
}
}
if (aNamespaceID == kNameSpaceID_XMLEvents && aName == nsHTMLAtoms::_event &&
mNodeInfo->GetDocument()) {
if (aNamespaceID == kNameSpaceID_XMLEvents &&
aName == nsHTMLAtoms::_event && mNodeInfo->GetDocument()) {
mNodeInfo->GetDocument()->AddXMLEventsContent(this);
}
return NS_OK;
}
PRBool
nsGenericElement::ParseAttribute(nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aAttribute == GetIDAttributeName() && !aValue.IsEmpty()) {
// Store id as an atom. id="" means that the element has no id,
// not that it has an emptystring as the id.
aResult.ParseAtom(aValue);
return PR_TRUE;
}
return PR_FALSE;
}
PRBool
nsGenericElement::SetMappedAttribute(nsIDocument* aDocument,
nsIAtom* aName,
nsAttrValue& aValue,
nsresult* aRetval)
{
*aRetval = NS_OK;
return PR_FALSE;
}
nsresult
nsGenericElement::GetEventListenerManagerForAttr(nsIEventListenerManager** aManager,
nsISupports** aTarget,
PRBool* aDefer)
{
nsresult rv = GetListenerManager(aManager);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(*aTarget = NS_STATIC_CAST(nsIContent*, this));
}
*aDefer = PR_TRUE;
return rv;
}
nsGenericElement::nsAttrInfo
nsGenericElement::GetAttrInfo(PRInt32 aNamespaceID, nsIAtom* aName) const
{
NS_ASSERTION(nsnull != aName, "must have attribute name");
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
"must have a real namespace ID!");
PRInt32 index = mAttrsAndChildren.IndexOfAttr(aName, aNamespaceID);
if (index >= 0) {
return nsAttrInfo(mAttrsAndChildren.GetSafeAttrNameAt(index),
mAttrsAndChildren.AttrAt(index));
}
return nsAttrInfo(nsnull, nsnull);
}
nsresult
nsGenericElement::GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsAString& aResult) const

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

@ -546,12 +546,12 @@ public:
//----------------------------------------
/**
* Add a script event listener with the given attr name (like onclick)
* and with the value as JS
* @param aAttribute the event listener name
* Add a script event listener with the given event handler name
* (like onclick) and with the value as JS
* @param aEventName the event listener name
* @param aValue the JS to attach
*/
nsresult AddScriptEventListener(nsIAtom* aAttribute,
nsresult AddScriptEventListener(nsIAtom* aEventName,
const nsAString& aValue);
/**
@ -685,6 +685,138 @@ public:
static PLDHashTable sRangeListsHash;
protected:
/**
* Struct that stores info on an attribute. The name and value must
* either both be null or both be non-null.
*/
struct nsAttrInfo {
nsAttrInfo(const nsAttrName* aName, const nsAttrValue* aValue) :
mName(aName), mValue(aValue) {}
nsAttrInfo(const nsAttrInfo& aOther) :
mName(aOther.mName), mValue(aOther.mValue) {}
const nsAttrName* mName;
const nsAttrValue* mValue;
};
/**
* Set attribute and (if needed) notify documentobservers and fire off
* mutation events.
*
* @param aNamespaceID namespace of attribute
* @param aAttribute local-name of attribute
* @param aPrefix aPrefix of attribute
* @param aOldValue previous value of attribute. Only needed if
* aFireMutation is true.
* @param aParsedValue parsed new value of attribute
* @param aModification is this a attribute-modification or addition. Only
* needed if aFireMutation or aNotify is true.
* @param aFireMutation should mutation-events be fired?
* @param aNotify should we notify document-observers?
*/
nsresult SetAttrAndNotify(PRInt32 aNamespaceID,
nsIAtom* aName,
nsIAtom* aPrefix,
const nsAString& aOldValue,
nsAttrValue& aParsedValue,
PRBool aModification,
PRBool aFireMutation,
PRBool aNotify);
/**
* Convert an attribute string value to attribute type based on the type of
* attribute. Called by SetAttr(). Note that at the moment we only do this
* for attributes in the null namespace (kNameSpaceID_None).
*
* @param aAttribute the attribute to convert
* @param aValue the string value to convert
* @param aResult the nsAttrValue [OUT]
* @return PR_TRUE if the parsing was successful, PR_FALSE otherwise
*/
virtual PRBool ParseAttribute(nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
/**
* Try to set the attribute as a mapped attribute, if applicable. This will
* only be called for attributes that are in the null namespace and only on
* attributes that returned true when passed to IsAttributeMapped. The
* caller will not try to set the attr in any other way if this method
* returns PR_TRUE (the value of aRetval does not matter for that purpose).
*
* @param aDocument the current document of this node (an optimization)
* @param aName the name of the attribute
* @param aValue the nsAttrValue to set
* @param [out] aRetval the nsresult status of the operation, if any.
* @return PR_TRUE if the setting was attempted, PR_FALSE otherwise.
*/
virtual PRBool SetMappedAttribute(nsIDocument* aDocument,
nsIAtom* aName,
nsAttrValue& aValue,
nsresult* aRetval);
/**
* Hook that is called by nsGenericElement::SetAttr to allow subclasses to
* deal with attribute sets. This will only be called after we verify that
* we're actually doing an attr set and will be called before ParseAttribute
* and hence before we've set the new value.
*
* @param aNamespaceID the namespace of the attr being set
* @param aName the localname of the attribute being set
* @param aValue the value it's being set to. If null, the attr is being
* removed.
* // XXXbz we don't actually call this method when we're removing attrs yet.
* But we will eventually.
* @param aNotify Whether we plan to notify document observers.
*/
// Note that this is inlined so that when subclasses call it it gets
// inlined. Those calls don't go through a vtable.
virtual nsresult BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
return NS_OK;
}
/**
* Hook that is called by nsGenericElement::SetAttr to allow subclasses to
* deal with attribute sets. This will only be called after we have called
* SetAndTakeAttr (that is, after we have actually set the attr).
*
* @param aNamespaceID the namespace of the attr being set
* @param aName the localname of the attribute being set
* @param aValue the value it's being set to. If null, the attr is being
* removed.
* // XXXbz we don't actually call this method when we're removing attrs yet.
* But we will eventually.
* @param aNotify Whether we plan to notify document observers.
*/
// Note that this is inlined so that when subclasses call it it gets
// inlined. Those calls don't go through a vtable.
virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
return NS_OK;
}
/**
* Hook to allow subclasses to produce a different nsIEventListenerManager if
* needed for attachment of attribute-defined handlers
*/
virtual nsresult
GetEventListenerManagerForAttr(nsIEventListenerManager** aManager,
nsISupports** aTarget,
PRBool* aDefer);
/**
* Get the attr info for the given namespace ID and attribute name. The
* namespace ID must not be kNameSpaceID_Unknown and the name must not be
* null. Note that this can only return info on attributes that actually
* live on this element (and is only virtual to handle XUL prototypes). That
* is, this should only be called from methods that only care about attrs
* that effectively live in mAttrsAndChildren.
*/
virtual nsAttrInfo GetAttrInfo(PRInt32 aNamespaceID, nsIAtom* aName) const;
/**
* Duplicate children by calling importNode and append them to another
* element.

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

@ -1664,152 +1664,6 @@ nsGenericHTMLElement::GetHrefURIForAnchors(nsIURI** aURI)
return NS_OK;
}
nsresult
nsGenericHTMLElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aAttribute,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify)
{
NS_ASSERTION(aNamespaceID != kNameSpaceID_XHTML,
"Error, attribute on [X]HTML element set with XHTML namespace, "
"this is wrong, trust me! Lose the prefix on the attribute!");
nsresult rv;
nsAutoString oldValue;
PRBool hasListeners = PR_FALSE;
PRBool modification = PR_FALSE;
if (IsInDoc()) {
hasListeners = nsGenericElement::HasMutationListeners(this,
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
// If we have no listeners and aNotify is false, we are almost certainly
// coming from the content sink and will almost certainly have no previous
// value. Even if we do, setting the value is cheap when we have no
// listeners and don't plan to notify. The check for aNotify here is an
// optimization, the check for haveListeners is a correctness issue.
if (hasListeners || aNotify) {
// don't do any update if old == new.
// It would be nice to not have to call GetAttr here but to rather just
// grab the nsAttrValue from mAttrsAndChildren and compare that to
// aValue. However not all nsAttrValues can currently be converted to
// strings (specifically enums and nsISupports can't) so we have to take
// the detour through GetAttr for now.
rv = GetAttr(aNamespaceID, aAttribute, oldValue);
modification = rv != NS_CONTENT_ATTR_NOT_THERE;
if (modification && aValue.Equals(oldValue)) {
return NS_OK;
}
}
}
// Parse into a nsAttrValue
nsAttrValue attrValue;
if (aNamespaceID == kNameSpaceID_None) {
if (!ParseAttribute(aAttribute, aValue, attrValue)) {
attrValue.SetTo(aValue);
}
if (IsEventName(aAttribute)) {
AddScriptEventListener(aAttribute, aValue);
}
}
else {
attrValue.SetTo(aValue);
}
return SetAttrAndNotify(aNamespaceID, aAttribute, aPrefix, oldValue,
attrValue, modification, hasListeners, aNotify);
}
nsresult
nsGenericHTMLElement::SetAttrAndNotify(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
nsIAtom* aPrefix,
const nsAString& aOldValue,
nsAttrValue& aParsedValue,
PRBool aModification,
PRBool aFireMutation,
PRBool aNotify)
{
nsresult rv;
PRUint8 modType = aModification ?
NS_STATIC_CAST(PRUint8, nsIDOMMutationEvent::MODIFICATION) :
NS_STATIC_CAST(PRUint8, nsIDOMMutationEvent::ADDITION);
nsIDocument* document = GetCurrentDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
if (aNotify && document) {
document->AttributeWillChange(this, aNamespaceID, aAttribute);
}
if (aNamespaceID == kNameSpaceID_None) {
if (IsAttributeMapped(aAttribute)) {
nsHTMLStyleSheet* sheet = document ?
document->GetAttributeStyleSheet() : nsnull;
rv = mAttrsAndChildren.SetAndTakeMappedAttr(aAttribute, aParsedValue,
this, sheet);
}
else {
rv = mAttrsAndChildren.SetAndTakeAttr(aAttribute, aParsedValue);
}
NS_ENSURE_SUCCESS(rv, rv);
}
else {
nsCOMPtr<nsINodeInfo> ni;
rv = mNodeInfo->NodeInfoManager()->GetNodeInfo(aAttribute, aPrefix,
aNamespaceID,
getter_AddRefs(ni));
NS_ENSURE_SUCCESS(rv, rv);
rv = mAttrsAndChildren.SetAndTakeAttr(ni, aParsedValue);
NS_ENSURE_SUCCESS(rv, rv);
}
if (document) {
nsXBLBinding *binding = document->BindingManager()->GetBinding(this);
if (binding) {
binding->AttributeChanged(aAttribute, aNamespaceID, PR_FALSE, aNotify);
}
if (aFireMutation) {
nsCOMPtr<nsIDOMEventTarget> node =
do_QueryInterface(NS_STATIC_CAST(nsIContent *, this));
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_ATTRMODIFIED, node);
nsAutoString attrName;
aAttribute->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aAttribute;
nsAutoString newValue;
aParsedValue.ToString(newValue);
if (!newValue.IsEmpty()) {
mutation.mNewAttrValue = do_GetAtom(newValue);
}
if (!aOldValue.IsEmpty()) {
mutation.mPrevAttrValue = do_GetAtom(aOldValue);
}
mutation.mAttrChange = modType;
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
document->AttributeChanged(this, aNamespaceID, aAttribute, modType);
}
}
if (aNamespaceID == kNameSpaceID_XMLEvents &&
aAttribute == nsHTMLAtoms::_event && mNodeInfo->GetDocument()) {
mNodeInfo->GetDocument()->AddXMLEventsContent(this);
}
return NS_OK;
}
PRBool nsGenericHTMLElement::IsEventName(nsIAtom* aName)
{
const char* name;
@ -1859,6 +1713,58 @@ PRBool nsGenericHTMLElement::IsEventName(nsIAtom* aName)
aName == nsLayoutAtoms::onDOMFocusOut);
}
nsresult
nsGenericHTMLElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
if (aNamespaceID == kNameSpaceID_None && IsEventName(aName) && aValue) {
nsresult rv = AddScriptEventListener(aName, *aValue);
NS_ENSURE_SUCCESS(rv, rv);
}
return nsGenericElement::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify);
}
nsresult
nsGenericHTMLElement::GetEventListenerManagerForAttr(nsIEventListenerManager** aManager,
nsISupports** aTarget,
PRBool* aDefer)
{
// Attributes on the body and frameset tags get set on the global object
if (mNodeInfo->Equals(nsHTMLAtoms::body) ||
mNodeInfo->Equals(nsHTMLAtoms::frameset)) {
nsIScriptGlobalObject *sgo;
// If we have a document, and it has a script global, add the
// event listener on the global. If not, proceed as normal.
// XXXbz sXBL/XBL2 issue: should we instead use GetCurrentDoc() here,
// override BindToTree for those classes and munge event listeners there?
nsIDocument *document = GetOwnerDoc();
nsresult rv = NS_OK;
if (document && (sgo = document->GetScriptGlobalObject())) {
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(sgo));
NS_ENSURE_TRUE(receiver, NS_ERROR_FAILURE);
rv = receiver->GetListenerManager(aManager);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(*aTarget = sgo);
}
*aDefer = PR_FALSE;
} else {
*aManager = nsnull;
*aTarget = nsnull;
*aDefer = PR_FALSE;
}
return rv;
}
return nsGenericElement::GetEventListenerManagerForAttr(aManager, aTarget,
aDefer);
}
nsresult
nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify)
@ -1960,6 +1866,8 @@ nsGenericHTMLElement::SetInlineStyleRule(nsICSSStyleRule* aStyleRule,
// and thus will be the same.
if (hasListeners) {
// save the old attribute so we can set up the mutation event properly
// XXXbz if the old rule points to the same declaration as the new one,
// this is getting the new attr value, not the old one....
modification = GetAttr(kNameSpaceID_None, nsHTMLAtoms::style,
oldValueStr) != NS_CONTENT_ATTR_NOT_THERE;
}
@ -2148,11 +2056,6 @@ nsGenericHTMLElement::ParseAttribute(nsIAtom* aAttribute,
aValue, aResult);
return PR_TRUE;
}
if (aAttribute == nsHTMLAtoms::id && !aValue.IsEmpty()) {
aResult.ParseAtom(aValue);
return PR_TRUE;
}
if (aAttribute == nsHTMLAtoms::kClass) {
aResult.ParseAtomArray(aValue);
@ -2163,7 +2066,7 @@ nsGenericHTMLElement::ParseAttribute(nsIAtom* aAttribute,
return aResult.ParseIntWithBounds(aValue, -32768, 32767);
}
return PR_FALSE;
return nsGenericElement::ParseAttribute(aAttribute, aValue, aResult);
}
PRBool
@ -2176,6 +2079,22 @@ nsGenericHTMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
return FindAttributeDependence(aAttribute, map, NS_ARRAY_LENGTH(map));
}
PRBool
nsGenericHTMLElement::SetMappedAttribute(nsIDocument* aDocument,
nsIAtom* aName,
nsAttrValue& aValue,
nsresult* aRetval)
{
NS_PRECONDITION(aDocument == GetCurrentDoc(), "Unexpected document");
nsHTMLStyleSheet* sheet = aDocument ?
aDocument->GetAttributeStyleSheet() : nsnull;
*aRetval = mAttrsAndChildren.SetAndTakeMappedAttr(aName, aValue,
this, sheet);
return PR_TRUE;
}
nsMapRuleToAttributesFunc
nsGenericHTMLElement::GetAttributeMappingFunction() const
{
@ -3268,22 +3187,17 @@ nsGenericHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
}
nsresult
nsGenericHTMLFormElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify)
nsGenericHTMLFormElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
nsresult rv = NS_OK;
if (aNameSpaceID != kNameSpaceID_None) {
rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
aNotify);
} else {
if (aNameSpaceID == kNameSpaceID_None) {
nsCOMPtr<nsIFormControl> thisControl;
nsAutoString tmp;
QueryInterface(NS_GET_IID(nsIFormControl), getter_AddRefs(thisControl));
// Add & remove the control to and/or from the hash table
// remove the control from the hashtable as needed
if (mForm && (aName == nsHTMLAtoms::name || aName == nsHTMLAtoms::id)) {
GetAttr(kNameSpaceID_None, aName, tmp);
@ -3307,19 +3221,32 @@ nsGenericHTMLFormElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
mForm->RemoveElement(thisControl);
}
}
rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
aNotify);
return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName,
aValue, aNotify);
}
if (mForm && (aName == nsHTMLAtoms::name || aName == nsHTMLAtoms::id)) {
GetAttr(kNameSpaceID_None, aName, tmp);
nsresult
nsGenericHTMLFormElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
if (aNameSpaceID == kNameSpaceID_None) {
nsCOMPtr<nsIFormControl> thisControl =
do_QueryInterface(NS_STATIC_CAST(nsIContent, this));
if (!tmp.IsEmpty()) {
mForm->AddElementToTable(thisControl, tmp);
// add the control to the hashtable as needed
if (mForm && (aName == nsHTMLAtoms::name || aName == nsHTMLAtoms::id) &&
aValue) {
if (!aValue->IsEmpty()) {
mForm->AddElementToTable(thisControl, *aValue);
}
}
if (mForm && aName == nsHTMLAtoms::type) {
nsAutoString tmp;
GetAttr(kNameSpaceID_None, nsHTMLAtoms::name, tmp);
if (!tmp.IsEmpty()) {
@ -3334,17 +3261,29 @@ nsGenericHTMLFormElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
mForm->AddElement(thisControl);
}
// And notify on content state changes, if any
if (aNotify && aName == nsHTMLAtoms::disabled && CanBeDisabled()) {
nsIDocument* document = GetCurrentDoc();
if (document) {
mozAutoDocUpdate(document, UPDATE_CONTENT_STATE, PR_TRUE);
document->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_DISABLED |
NS_EVENT_STATE_ENABLED);
}
}
}
AfterSetAttr(aNameSpaceID, aName, &aValue, aNotify);
return rv;
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify);
}
nsresult
nsGenericHTMLFormElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
PRBool aNotify)
{
BeforeSetAttr(aNameSpaceID, aName, nsnull, aNotify);
nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aName, aNotify);
AfterSetAttr(aNameSpaceID, aName, nsnull, aNotify);
@ -3364,21 +3303,6 @@ nsGenericHTMLFormElement::CanBeDisabled() const
type != NS_FORM_OBJECT;
}
void
nsGenericHTMLFormElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
if (aNotify && aNameSpaceID == kNameSpaceID_None &&
aName == nsHTMLAtoms::disabled && CanBeDisabled()) {
nsIDocument* document = GetCurrentDoc();
if (document) {
mozAutoDocUpdate(document, UPDATE_CONTENT_STATE, PR_TRUE);
document->ContentStatesChanged(this, nsnull, NS_EVENT_STATE_DISABLED |
NS_EVENT_STATE_ENABLED);
}
}
}
void
nsGenericHTMLFormElement::FindAndSetForm()
{

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

@ -185,14 +185,6 @@ public:
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue,
PRBool aNotify);
virtual nsresult GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsAString& aResult) const;
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
@ -272,6 +264,10 @@ public:
nsAttrValue& aResult);
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual PRBool SetMappedAttribute(nsIDocument* aDocument,
nsIAtom* aName,
nsAttrValue& aValue,
nsresult* aRetval);
/**
* Get the base target for any links within this piece
@ -615,30 +611,6 @@ public:
*/
static PRBool InNavQuirksMode(nsIDocument* aDoc);
/**
* Set attribute and (if needed) notify documentobservers and fire off
* mutation events.
*
* @param aNamespaceID namespace of attribute
* @param aAttribute local-name of attribute
* @param aPrefix aPrefix of attribute
* @param aOldValue previous value of attribute. Only needed if
* aFireMutation is true.
* @param aParsedValue parsed new value of attribute
* @param aModification is this a attribute-modification or addition. Only
* needed if aFireMutation or aNotify is true.
* @param aFireMutation should mutation-events be fired?
* @param aNotify should we notify document-observers?
*/
nsresult SetAttrAndNotify(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
nsIAtom* aPrefix,
const nsAString& aOldValue,
nsAttrValue& aParsedValue,
PRBool aModification,
PRBool aFireMutation,
PRBool aNotify);
// Helper functions for <a> and <area>
static nsresult SetProtocolInHrefString(const nsAString &aHref,
const nsAString &aProtocol,
@ -711,6 +683,14 @@ protected:
*/
PRBool IsEventName(nsIAtom* aName);
virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual nsresult
GetEventListenerManagerForAttr(nsIEventListenerManager** aManager,
nsISupports** aTarget,
PRBool* aDefer);
virtual const nsAttrName* InternalGetExistingAttrNameFromQName(const nsAString& aStr) const;
/**
@ -865,15 +845,6 @@ public:
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
PRBool aNotify);
@ -886,18 +857,11 @@ protected:
*/
void FindAndSetForm();
/**
* Called when an attribute has just been changed.
*
* Note that this function is also called if the attribute change fails.
*
* @param aNameSpaceID The namespace ID of the attribute
* @param aName The attribute name (atom)
* @param aValue The new value (nsnull if it being removed)
* @param aNotify Notify about changes?
*/
virtual void AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
/**
* Returns true if the control can be disabled

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

@ -198,32 +198,6 @@ public:
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify)
{
BeforeSetAttr(aNameSpaceID, aName, &aValue, aNotify);
nsresult rv = nsGenericHTMLFormElement::SetAttr(aNameSpaceID, aName,
aPrefix, aValue, aNotify);
return rv;
}
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify)
{
BeforeSetAttr(aNameSpaceID, aAttribute, nsnull, aNotify);
nsresult rv = nsGenericHTMLFormElement::UnsetAttr(aNameSpaceID, aAttribute,
aNotify);
return rv;
}
virtual void DoneCreatingElement();
virtual PRInt32 IntrinsicState() const;
@ -271,13 +245,13 @@ protected:
/**
* Called when an attribute is about to be changed
*/
void BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
/**
* Called when an attribute has just been changed
*/
virtual void AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
void SelectAll(nsPresContext* aPresContext);
PRBool IsImage() const
@ -438,126 +412,128 @@ nsHTMLInputElement::CloneNode(PRBool aDeep, nsIDOMNode **aResult)
return nsGenericElement::CloneNode(aDeep, this, aResult);
}
void
nsresult
nsHTMLInputElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue,
PRBool aNotify)
{
if (aNameSpaceID != kNameSpaceID_None) {
return;
if (aNameSpaceID == kNameSpaceID_None) {
//
// When name or type changes, radio should be removed from radio group.
// (type changes are handled in the form itself currently)
// If the parser is not done creating the radio, we also should not do it.
//
if ((aName == nsHTMLAtoms::name ||
(aName == nsHTMLAtoms::type && !mForm)) &&
mType == NS_FORM_INPUT_RADIO &&
(mForm || !(GET_BOOLBIT(mBitField, BF_PARSER_CREATING)))) {
WillRemoveFromRadioGroup();
} else if (aNotify && aName == nsHTMLAtoms::src &&
aValue && mType == NS_FORM_INPUT_IMAGE) {
// Null value means the attr got unset; don't trigger on that
ImageURIChanged(*aValue, PR_TRUE, aNotify);
} else if (aNotify && aName == nsHTMLAtoms::disabled) {
SET_BOOLBIT(mBitField, BF_DISABLED_CHANGED, PR_TRUE);
}
}
//
// When name or type changes, radio should be removed from radio group.
// (type changes are handled in the form itself currently)
// If the parser is not done creating the radio, we also should not do it.
//
if ((aName == nsHTMLAtoms::name || (aName == nsHTMLAtoms::type && !mForm)) &&
mType == NS_FORM_INPUT_RADIO &&
(mForm || !(GET_BOOLBIT(mBitField, BF_PARSER_CREATING)))) {
WillRemoveFromRadioGroup();
} else if (aNotify && aName == nsHTMLAtoms::src &&
aValue && mType == NS_FORM_INPUT_IMAGE) {
// Null value means the attr got unset; don't trigger on that
ImageURIChanged(*aValue, PR_TRUE, aNotify);
} else if (aNotify && aName == nsHTMLAtoms::disabled) {
SET_BOOLBIT(mBitField, BF_DISABLED_CHANGED, PR_TRUE);
}
return nsGenericHTMLFormElement::BeforeSetAttr(aNameSpaceID, aName,
aValue, aNotify);
}
void
nsresult
nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue,
PRBool aNotify)
{
nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify);
if (aNameSpaceID != kNameSpaceID_None) {
return;
}
//
// When name or type changes, radio should be added to radio group.
// (type changes are handled in the form itself currently)
// If the parser is not done creating the radio, we also should not do it.
//
if ((aName == nsHTMLAtoms::name || (aName == nsHTMLAtoms::type && !mForm)) &&
mType == NS_FORM_INPUT_RADIO &&
(mForm || !(GET_BOOLBIT(mBitField, BF_PARSER_CREATING)))) {
AddedToRadioGroup();
}
//
// Some elements have to change their value when the value and checked
// attributes change (but they only do so when ValueChanged() and
// CheckedChanged() are false--i.e. the value has not been changed by the
// user or by JS)
//
// We only really need to call reset for the value so that the text control
// knows the new value. No other reason.
//
if (aName == nsHTMLAtoms::value &&
!GET_BOOLBIT(mBitField, BF_VALUE_CHANGED) &&
(mType == NS_FORM_INPUT_TEXT ||
mType == NS_FORM_INPUT_PASSWORD ||
mType == NS_FORM_INPUT_FILE)) {
Reset();
}
//
// Checked must be set no matter what type of control it is, since
// GetChecked() must reflect the new value
//
if (aName == nsHTMLAtoms::checked &&
!GET_BOOLBIT(mBitField, BF_CHECKED_CHANGED)) {
// Delay setting checked if the parser is creating this element (wait until
// everything is set)
if (GET_BOOLBIT(mBitField, BF_PARSER_CREATING)) {
SET_BOOLBIT(mBitField, BF_SHOULD_INIT_CHECKED, PR_TRUE);
} else {
PRBool defaultChecked;
GetDefaultChecked(&defaultChecked);
DoSetChecked(defaultChecked);
SetCheckedChanged(PR_FALSE);
if (aNameSpaceID == kNameSpaceID_None) {
//
// When name or type changes, radio should be added to radio group.
// (type changes are handled in the form itself currently)
// If the parser is not done creating the radio, we also should not do it.
//
if ((aName == nsHTMLAtoms::name ||
(aName == nsHTMLAtoms::type && !mForm)) &&
mType == NS_FORM_INPUT_RADIO &&
(mForm || !(GET_BOOLBIT(mBitField, BF_PARSER_CREATING)))) {
AddedToRadioGroup();
}
}
if (aName == nsHTMLAtoms::type) {
if (!aValue) {
// We're now a text input. Note that we have to handle this manually,
// since removing an attribute (which is what happened, since aValue is
// null) doesn't call ParseAttribute.
mType = NS_FORM_INPUT_TEXT;
//
// Some elements have to change their value when the value and checked
// attributes change (but they only do so when ValueChanged() and
// CheckedChanged() are false--i.e. the value has not been changed by the
// user or by JS)
//
// We only really need to call reset for the value so that the text control
// knows the new value. No other reason.
//
if (aName == nsHTMLAtoms::value &&
!GET_BOOLBIT(mBitField, BF_VALUE_CHANGED) &&
(mType == NS_FORM_INPUT_TEXT ||
mType == NS_FORM_INPUT_PASSWORD ||
mType == NS_FORM_INPUT_FILE)) {
Reset();
}
//
// Checked must be set no matter what type of control it is, since
// GetChecked() must reflect the new value
//
if (aName == nsHTMLAtoms::checked &&
!GET_BOOLBIT(mBitField, BF_CHECKED_CHANGED)) {
// Delay setting checked if the parser is creating this element
// (wait until everything is set)
if (GET_BOOLBIT(mBitField, BF_PARSER_CREATING)) {
SET_BOOLBIT(mBitField, BF_SHOULD_INIT_CHECKED, PR_TRUE);
} else {
PRBool defaultChecked;
GetDefaultChecked(&defaultChecked);
DoSetChecked(defaultChecked);
SetCheckedChanged(PR_FALSE);
}
}
if (aName == nsHTMLAtoms::type) {
if (!aValue) {
// We're now a text input. Note that we have to handle this manually,
// since removing an attribute (which is what happened, since aValue is
// null) doesn't call ParseAttribute.
mType = NS_FORM_INPUT_TEXT;
}
// If we are changing type from File/Text/Passwd to other input types
// we need save the mValue into value attribute
if (mValue &&
mType != NS_FORM_INPUT_TEXT &&
mType != NS_FORM_INPUT_PASSWORD &&
mType != NS_FORM_INPUT_FILE) {
SetAttr(kNameSpaceID_None, nsHTMLAtoms::value,
NS_ConvertUTF8toUCS2(mValue), PR_FALSE);
if (mValue) {
nsMemory::Free(mValue);
mValue = nsnull;
// If we are changing type from File/Text/Passwd to other input types
// we need save the mValue into value attribute
if (mValue &&
mType != NS_FORM_INPUT_TEXT &&
mType != NS_FORM_INPUT_PASSWORD &&
mType != NS_FORM_INPUT_FILE) {
SetAttr(kNameSpaceID_None, nsHTMLAtoms::value,
NS_ConvertUTF8toUCS2(mValue), PR_FALSE);
if (mValue) {
nsMemory::Free(mValue);
mValue = nsnull;
}
}
}
if (mType != NS_FORM_INPUT_IMAGE) {
// We're no longer an image input. Cancel our image requests, if we have
// any. Note that doing this when we already weren't an image is ok --
// just does nothing.
CancelImageRequests(aNotify);
} else if (aNotify) {
// We just got switched to be an image input; we should see
// whether we have an image to load;
nsAutoString src;
nsresult rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::src, src);
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
ImageURIChanged(src, PR_FALSE, aNotify);
if (mType != NS_FORM_INPUT_IMAGE) {
// We're no longer an image input. Cancel our image requests, if we have
// any. Note that doing this when we already weren't an image is ok --
// just does nothing.
CancelImageRequests(aNotify);
} else if (aNotify) {
// We just got switched to be an image input; we should see
// whether we have an image to load;
nsAutoString src;
nsresult rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::src, src);
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
ImageURIChanged(src, PR_FALSE, aNotify);
}
}
}
}
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
aValue, aNotify);
}
// nsIDOMHTMLInputElement

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

@ -87,22 +87,6 @@ public:
virtual PRInt32 IntrinsicState() const;
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify)
{
nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
aValue, aNotify);
AfterSetAttr(aNameSpaceID, aName, &aValue, aNotify);
return rv;
}
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify)
{
@ -124,8 +108,8 @@ protected:
/**
* Called when an attribute has just been changed
*/
void AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
};
@ -200,7 +184,7 @@ nsHTMLOptGroupElement::GetSelect(nsISelectElement **aSelectElement)
}
}
void
nsresult
nsHTMLOptGroupElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
@ -213,6 +197,9 @@ nsHTMLOptGroupElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
NS_EVENT_STATE_ENABLED);
}
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify);
}
nsresult

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

@ -114,22 +114,6 @@ public:
// nsIContent
virtual PRInt32 IntrinsicState() const;
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify)
{
nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
aValue, aNotify);
AfterSetAttr(aNameSpaceID, aName, &aValue, aNotify);
return rv;
}
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify)
{
@ -158,8 +142,8 @@ protected:
/**
* Called when an attribute has just been changed
*/
void AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
PRPackedBool mIsInitialized;
PRPackedBool mIsSelected;
};
@ -511,7 +495,7 @@ nsHTMLOptionElement::GetSelect(nsIDOMHTMLSelectElement **aSelectElement) const
}
}
void
nsresult
nsHTMLOptionElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
@ -524,6 +508,9 @@ nsHTMLOptionElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
NS_EVENT_STATE_ENABLED);
}
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify);
}
NS_IMETHODIMP

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

@ -138,62 +138,50 @@ nsSVGElement::GetClassAttributeName() const
}
nsresult
nsSVGElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue,
PRBool aNotify)
nsSVGElement::BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
NS_ENSURE_ARG_POINTER(aName);
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
"Don't call SetAttr with unknown namespace");
nsresult rv;
nsAutoString oldValue;
PRBool hasListeners = PR_FALSE;
PRBool modification = PR_FALSE;
PRInt32 index = mAttrsAndChildren.IndexOfAttr(aName, aNamespaceID);
if (IsInDoc()) {
hasListeners = nsGenericElement::HasMutationListeners(this,
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
// If we have no listeners and aNotify is false, we are almost certainly
// coming from the content sink and will almost certainly have no previous
// value. Even if we do, setting the value is cheap when we have no
// listeners and don't plan to notify. The check for aNotify here is an
// optimization, the check for haveListeners is a correctness issue.
if (index >= 0 && (hasListeners || aNotify)) {
modification = PR_TRUE;
// don't do any update if old == new.
mAttrsAndChildren.AttrAt(index)->ToString(oldValue);
if (aValue.Equals(oldValue) &&
aPrefix == mAttrsAndChildren.GetSafeAttrNameAt(index)->GetPrefix()) {
return NS_OK;
}
}
}
// If this is an svg presentation attribute we need to map it into
// the content stylerule.
// XXX For some reason incremental mapping doesn't work, so for now
// just delete the style rule and lazily reconstruct it in
// GetContentStyleRule()
if(aNamespaceID == kNameSpaceID_None && IsAttributeMapped(aName))
if (aNamespaceID == kNameSpaceID_None && IsAttributeMapped(aName)) {
mContentStyleRule = nsnull;
}
return nsGenericElement::BeforeSetAttr(aNamespaceID, aName, aValue, aNotify);
}
nsresult
nsSVGElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
if (IsEventName(aName) && aValue) {
nsresult rv = AddScriptEventListener(GetEventNameForAttr(aName), *aValue);
NS_ENSURE_SUCCESS(rv, rv);
}
return nsGenericElement::AfterSetAttr(aNamespaceID, aName, aValue, aNotify);
}
PRBool
nsSVGElement::ParseAttribute(nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
// Parse value
nsAttrValue attrValue;
nsCOMPtr<nsISVGValue> svg_value;
if (index >= 0) {
const nsAttrValue* val = mAttrsAndChildren.GetAttr(aAttribute);
if (val) {
// Found the attr in the list.
const nsAttrValue* currVal = mAttrsAndChildren.AttrAt(index);
if (currVal->Type() == nsAttrValue::eSVGValue) {
svg_value = currVal->GetSVGValue();
if (val->Type() == nsAttrValue::eSVGValue) {
svg_value = val->GetSVGValue();
}
}
else {
// Could be a mapped attribute.
svg_value = GetMappedAttribute(aNamespaceID, aName);
svg_value = GetMappedAttribute(kNameSpaceID_None, aAttribute);
}
if (svg_value) {
@ -204,43 +192,29 @@ nsSVGElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName, nsIAtom* aPrefix,
// To accomodate this "erronous" value, we'll insert a proxy
// object between ourselves and the actual value object:
nsCOMPtr<nsISVGValue> proxy;
rv = NS_CreateSVGStringProxyValue(svg_value, getter_AddRefs(proxy));
NS_ENSURE_SUCCESS(rv, rv);
nsresult rv =
NS_CreateSVGStringProxyValue(svg_value, getter_AddRefs(proxy));
// Failure means we'll store this attr as a string, not an SVGValue, but
// that's the best we can do short of throwing outright.
NS_ENSURE_SUCCESS(rv, PR_FALSE);
svg_value->RemoveObserver(this);
proxy->SetValueString(aValue);
proxy->AddObserver(this);
attrValue.SetTo(proxy);
aResult.SetTo(proxy);
}
else {
attrValue.SetTo(svg_value);
aResult.SetTo(svg_value);
}
}
else if (aName == nsSVGAtoms::style && aNamespaceID == kNameSpaceID_None) {
nsGenericHTMLElement::ParseStyleAttribute(this, PR_TRUE, aValue, attrValue);
}
// We don't have an nsISVGValue attribute.
else if (aName == nsSVGAtoms::id && aNamespaceID == kNameSpaceID_None){
attrValue.ParseAtom(aValue);
}
else {
attrValue.SetTo(aValue);
return PR_TRUE;
}
if (aNamespaceID == kNameSpaceID_None && IsEventName(aName)) {
nsCOMPtr<nsIEventListenerManager> manager;
GetListenerManager(getter_AddRefs(manager));
if (manager) {
nsIAtom* eventName = GetEventNameForAttr(aName);
nsIDocument *ownerDoc = GetOwnerDoc();
manager->AddScriptEventListener(NS_STATIC_CAST(nsIContent*, this), eventName,
aValue, PR_TRUE,
!nsContentUtils::IsChromeDoc(ownerDoc));
}
if (aAttribute == nsSVGAtoms::style) {
nsGenericHTMLElement::ParseStyleAttribute(this, PR_TRUE, aValue, aResult);
return PR_TRUE;
}
return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue, attrValue,
modification, hasListeners, aNotify);
return nsGenericElement::ParseAttribute(aAttribute, aValue, aResult);
}
nsresult
@ -628,86 +602,6 @@ nsSVGElement::IsEventName(nsIAtom* aName)
return PR_FALSE;
}
nsresult
nsSVGElement::SetAttrAndNotify(PRInt32 aNamespaceID, nsIAtom* aAttribute,
nsIAtom* aPrefix, const nsAString& aOldValue,
nsAttrValue& aParsedValue, PRBool aModification,
PRBool aFireMutation, PRBool aNotify)
{
nsresult rv;
PRUint8 modType = aModification ?
NS_STATIC_CAST(PRUint8, nsIDOMMutationEvent::MODIFICATION) :
NS_STATIC_CAST(PRUint8, nsIDOMMutationEvent::ADDITION);
nsIDocument* document = GetCurrentDoc();
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
if (aNotify && document) {
document->AttributeWillChange(this, aNamespaceID, aAttribute);
}
if (aNamespaceID == kNameSpaceID_None) {
// XXX doesn't check IsAttributeMapped here.
rv = mAttrsAndChildren.SetAndTakeAttr(aAttribute, aParsedValue);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
nsCOMPtr<nsINodeInfo> ni;
rv = mNodeInfo->NodeInfoManager()->GetNodeInfo(aAttribute, aPrefix,
aNamespaceID,
getter_AddRefs(ni));
NS_ENSURE_SUCCESS(rv, rv);
rv = mAttrsAndChildren.SetAndTakeAttr(ni, aParsedValue);
NS_ENSURE_SUCCESS(rv, rv);
}
if (document) {
nsXBLBinding *binding = document->BindingManager()->GetBinding(this);
if (binding) {
binding->AttributeChanged(aAttribute, aNamespaceID, PR_FALSE, aNotify);
}
if (aFireMutation) {
nsCOMPtr<nsIDOMEventTarget> node = do_QueryInterface(NS_STATIC_CAST(nsIContent *, this));
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_ATTRMODIFIED, node);
nsAutoString attrName;
aAttribute->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aAttribute;
nsAutoString newValue;
// We don't really need to call GetAttr here, but lets try to keep this
// code as similar to nsGenericHTMLElement::SetAttrAndNotify as possible
// so that they can merge sometime in the future.
GetAttr(aNamespaceID, aAttribute, newValue);
if (!newValue.IsEmpty()) {
mutation.mNewAttrValue = do_GetAtom(newValue);
}
if (!aOldValue.IsEmpty()) {
mutation.mPrevAttrValue = do_GetAtom(aOldValue);
}
mutation.mAttrChange = modType;
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
document->AttributeChanged(this, aNamespaceID, aAttribute, modType);
}
}
if (aNamespaceID == kNameSpaceID_XMLEvents &&
aAttribute == nsHTMLAtoms::_event && GetOwnerDoc()) {
GetOwnerDoc()->AddXMLEventsContent(this);
}
return NS_OK;
}
void
nsSVGElement::UpdateContentStyleRule()
{

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

@ -76,14 +76,6 @@ public:
PRBool aNullParent = PR_TRUE);
virtual nsIAtom *GetIDAttributeName() const;
virtual nsIAtom *GetClassAttributeName() const;
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify);
@ -124,33 +116,17 @@ public:
virtual void ParentChainChanged();
protected:
virtual nsresult BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual PRBool ParseAttribute(nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
// Hooks for subclasses
virtual PRBool IsEventName(nsIAtom* aName);
/**
* Set attribute and (if needed) notify documentobservers and fire off
* mutation events.
*
* @param aNamespaceID namespace of attribute
* @param aAttribute local-name of attribute
* @param aPrefix aPrefix of attribute
* @param aOldValue previous value of attribute. Only needed if
* aFireMutation is true.
* @param aParsedValue parsed new value of attribute
* @param aModification is this a attribute-modification or addition. Only
* needed if aFireMutation or aNotify is true.
* @param aFireMutation should mutation-events be fired?
* @param aNotify should we notify document-observers?
*/
nsresult SetAttrAndNotify(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
nsIAtom* aPrefix,
const nsAString& aOldValue,
nsAttrValue& aParsedValue,
PRBool aModification,
PRBool aFireMutation,
PRBool aNotify);
void UpdateContentStyleRule();
nsISVGValue* GetMappedAttribute(PRInt32 aNamespaceID, nsIAtom* aName);
nsresult AddMappedSVGValue(nsIAtom* aName, nsISupports* aValue,

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

@ -552,44 +552,36 @@ nsXULElement::MaybeTriggerAutoLink(nsIDocShell *aShell)
}
nsresult
nsXULElement::AddScriptEventListener(nsIAtom* aName, const nsAString& aValue)
nsXULElement::GetEventListenerManagerForAttr(nsIEventListenerManager** aManager,
nsISupports** aTarget,
PRBool* aDefer)
{
// XXX sXBL/XBL2 issue! Owner or current document?
// Note that If it's current, then we need to hook up listeners on the root
// when we BindToTree...
// XXXbz sXBL/XBL2 issue: should we instead use GetCurrentDoc()
// here, override BindToTree for those classes and munge event
// listeners there?
nsIDocument* doc = GetOwnerDoc();
if (!doc)
return NS_OK; // XXX
nsresult rv;
nsISupports *target = NS_STATIC_CAST(nsIContent *, this);
PRBool defer = PR_TRUE;
nsCOMPtr<nsIEventListenerManager> manager;
return NS_ERROR_UNEXPECTED; // XXX
nsIContent *root = doc->GetRootContent();
nsCOMPtr<nsIContent> content(do_QueryInterface(NS_STATIC_CAST(nsIStyledContent*, this)));
if ((!root || root == content) && !mNodeInfo->Equals(nsXULAtoms::overlay)) {
if ((!root || root == this) && !mNodeInfo->Equals(nsXULAtoms::overlay)) {
nsIScriptGlobalObject *global = doc->GetScriptGlobalObject();
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(global);
if (! receiver)
return NS_ERROR_UNEXPECTED;
rv = receiver->GetListenerManager(getter_AddRefs(manager));
target = global;
defer = PR_FALSE;
}
else {
rv = GetListenerManager(getter_AddRefs(manager));
nsresult rv = receiver->GetListenerManager(aManager);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(*aTarget = global);
}
*aDefer = PR_FALSE;
return rv;
}
if (NS_FAILED(rv)) return rv;
return manager->AddScriptEventListener(target, aName, aValue, defer,
!nsContentUtils::IsChromeDoc(doc));
return nsGenericElement::GetEventListenerManagerForAttr(aManager,
aTarget,
aDefer);
}
nsresult
@ -1195,185 +1187,79 @@ nsXULElement::UnregisterAccessKey(const nsAString& aOldValue)
}
}
// XXX attribute code swiped from nsGenericContainerElement
// this class could probably just use nsGenericContainerElement
// needed to maintain attribute namespace ID as well as ordering
// NOTE: Changes to this function may need to be made in
// |SetInlineStyleRule| as well.
nsresult
nsXULElement::SetAttr(PRInt32 aNamespaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue, PRBool aNotify)
nsXULElement::BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
nsAutoString oldValue;
PRBool hasListeners = PR_FALSE;
PRBool modification = PR_FALSE;
if (IsInDoc()) {
PRBool isAccessKey = aName == nsXULAtoms::accesskey &&
aNamespaceID == kNameSpaceID_None;
hasListeners = nsGenericElement::HasMutationListeners(this,
NS_EVENT_BITS_MUTATION_ATTRMODIFIED);
// If we have no listeners and aNotify is false, we are almost
// certainly coming from the content sink and will almost certainly
// have no previous value. Even if we do, setting the value is cheap
// when we have no listeners and don't plan to notify. The check for
// aNotify here is an optimization, the check for haveListeners is a
// correctness issue.
// The check for isAccessKey is so that we get the old value and can
// unregister the old key.
if (hasListeners || aNotify || isAccessKey) {
// Don't do any update if old == new.
const nsAttrValue* attrVal =
mAttrsAndChildren.GetAttr(aName, aNamespaceID);
if (attrVal) {
modification = PR_TRUE;
attrVal->ToString(oldValue);
if (aValue.Equals(oldValue)) {
return NS_OK;
}
}
// If the accesskey attribute changes, unregister it here. It will
// be registered for the new value in the relevant frames. Also see
// nsAreaFrame, nsBoxFrame and nsTextBoxFrame's AttributeChanged
// If we want to merge with nsGenericElement then we could maybe
// do this in WillChangeAttr instead. That is only called when
// aNotify is true, but that might be enough.
if (isAccessKey) {
UnregisterAccessKey(oldValue);
}
if (aNamespaceID == kNameSpaceID_None && aName == nsXULAtoms::accesskey &&
IsInDoc()) {
const nsAttrValue* attrVal = FindLocalOrProtoAttr(aNamespaceID, aName);
if (attrVal) {
nsAutoString oldValue;
attrVal->ToString(oldValue);
UnregisterAccessKey(oldValue);
}
}
// XXX UnsetAttr handles more attributes then we do. See bug 233642.
return nsGenericElement::BeforeSetAttr(aNamespaceID, aName,
aValue, aNotify);
}
// Parse into a nsAttrValue
// WARNING!!
// This code is largely duplicated in nsXULPrototypeElement::SetAttrAt.
// Any changes should be made to both functions.
nsAttrValue attrValue;
nsresult
nsXULElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aName == nsXULAtoms::style) {
nsGenericHTMLElement::ParseStyleAttribute(this, PR_TRUE, aValue,
attrValue);
}
else if (aName == nsXULAtoms::id &&
!aValue.IsEmpty()) {
// Store id as atom.
// id="" means that the element has no id. Not that it has
// emptystring as id.
attrValue.ParseAtom(aValue);
}
else if (aName == nsXULAtoms::clazz) {
attrValue.ParseAtomArray(aValue);
}
else {
attrValue.ParseStringOrAtom(aValue);
}
// XXX UnsetAttr handles more attributes then we do. See bug 233642.
// Add popup and event listeners. We can't call AddListenerFor since
// the attribute isn't set yet.
MaybeAddPopupListener(aName);
if (IsEventHandler(aName)) {
AddScriptEventListener(aName, aValue);
if (IsEventHandler(aName) && aValue) {
AddScriptEventListener(aName, *aValue);
}
// Hide chrome if needed
if (aName == nsXULAtoms::hidechrome &&
mNodeInfo->Equals(nsXULAtoms::window)) {
HideWindowChrome(NS_LITERAL_STRING("true").Equals(aValue));
HideWindowChrome(aValue && NS_LITERAL_STRING("true").Equals(*aValue));
}
// XXX need to check if they're changing an event handler: if so, then we need
// to unhook the old one.
}
else {
attrValue.ParseStringOrAtom(aValue);
// XXX need to check if they're changing an event handler: if
// so, then we need to unhook the old one. Or something.
}
return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
attrValue, modification, hasListeners, aNotify);
return nsGenericElement::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify);
}
nsresult
nsXULElement::SetAttrAndNotify(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
nsIAtom* aPrefix,
const nsAString& aOldValue,
nsAttrValue& aParsedValue,
PRBool aModification,
PRBool aFireMutation,
PRBool aNotify)
PRBool
nsXULElement::ParseAttribute(nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
nsresult rv;
PRUint8 modType = aModification ?
NS_STATIC_CAST(PRUint8, nsIDOMMutationEvent::MODIFICATION) :
NS_STATIC_CAST(PRUint8, nsIDOMMutationEvent::ADDITION);
// Parse into a nsAttrValue
nsIDocument* doc = GetCurrentDoc();
mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify);
if (aNotify && doc) {
doc->AttributeWillChange(this, aNamespaceID, aAttribute);
// WARNING!!
// This code is largely duplicated in nsXULPrototypeElement::SetAttrAt.
// Any changes should be made to both functions.
if (aAttribute == nsXULAtoms::style) {
nsGenericHTMLElement::ParseStyleAttribute(this, PR_TRUE, aValue,
aResult);
return PR_TRUE;
}
if (aNamespaceID == kNameSpaceID_None) {
rv = mAttrsAndChildren.SetAndTakeAttr(aAttribute, aParsedValue);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
nsCOMPtr<nsINodeInfo> ni;
rv = mNodeInfo->NodeInfoManager()->GetNodeInfo(aAttribute, aPrefix,
aNamespaceID,
getter_AddRefs(ni));
NS_ENSURE_SUCCESS(rv, rv);
rv = mAttrsAndChildren.SetAndTakeAttr(ni, aParsedValue);
NS_ENSURE_SUCCESS(rv, rv);
if (aAttribute == nsXULAtoms::clazz) {
aResult.ParseAtomArray(aValue);
return PR_TRUE;
}
if (doc) {
nsXBLBinding *binding = doc->BindingManager()->GetBinding(this);
if (binding) {
binding->AttributeChanged(aAttribute, aNamespaceID, PR_FALSE, aNotify);
}
if (aFireMutation) {
nsCOMPtr<nsIDOMEventTarget> node =
do_QueryInterface(NS_STATIC_CAST(nsIContent *, this));
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_ATTRMODIFIED, node);
nsAutoString attrName;
aAttribute->ToString(attrName);
nsCOMPtr<nsIDOMAttr> attrNode;
GetAttributeNode(attrName, getter_AddRefs(attrNode));
mutation.mRelatedNode = attrNode;
mutation.mAttrName = aAttribute;
nsAutoString newValue;
// We don't really need to call GetAttr here, but lets do it
// anyway to ease future codeshare with nsGenericHTMLElement
// which has to call GetAttr here due to enums.
GetAttr(aNamespaceID, aAttribute, newValue);
if (!newValue.IsEmpty()) {
mutation.mNewAttrValue = do_GetAtom(newValue);
}
if (!aOldValue.IsEmpty()) {
mutation.mPrevAttrValue = do_GetAtom(aOldValue);
}
mutation.mAttrChange = modType;
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
}
if (aNotify) {
doc->AttributeChanged(this, aNamespaceID, aAttribute, modType);
}
if (!nsGenericElement::ParseAttribute(aAttribute, aValue, aResult)) {
// Fall back to parsing as atom for short values
aResult.ParseStringOrAtom(aValue);
}
return NS_OK;
return PR_TRUE;
}
const nsAttrName*
@ -2718,22 +2604,20 @@ NS_IMETHODIMP nsXULElement::HandleChromeEvent(nsPresContext* aPresContext,
//----------------------------------------------------------------------
const nsAttrValue*
nsXULElement::FindLocalOrProtoAttr(PRInt32 aNamespaceID, nsIAtom *aName) const
nsGenericElement::nsAttrInfo
nsXULElement::GetAttrInfo(PRInt32 aNamespaceID, nsIAtom *aName) const
{
const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNamespaceID);
if (val) {
return val;
nsAttrInfo info(nsGenericElement::GetAttrInfo(aNamespaceID, aName));
if (!info.mValue) {
nsXULPrototypeAttribute *protoattr =
FindPrototypeAttribute(aNamespaceID, aName);
if (protoattr) {
return nsAttrInfo(&protoattr->mName, &protoattr->mValue);
}
}
nsXULPrototypeAttribute *protoattr =
FindPrototypeAttribute(aNamespaceID, aName);
if (protoattr) {
return &protoattr->mValue;
}
return nsnull;
return info;
}

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

@ -478,13 +478,6 @@ public:
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual nsIAtom *GetIDAttributeName() const;
virtual nsIAtom *GetClassAttributeName() const;
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
}
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
const nsAString& aValue, PRBool aNotify);
virtual nsresult GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsAString& aResult) const;
virtual PRBool HasAttr(PRInt32 aNameSpaceID, nsIAtom* aName) const;
@ -548,8 +541,6 @@ public:
{ UnsetFlags(aFlags << XUL_ELEMENT_LAZY_STATE_OFFSET); }
PRBool GetLazyState(LazyState aFlag)
{ return GetFlags() & (aFlag << XUL_ELEMENT_LAZY_STATE_OFFSET); }
NS_HIDDEN_(nsresult) AddScriptEventListener(nsIAtom* aName,
const nsAString& aValue);
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsGenericElement::)
@ -611,8 +602,31 @@ protected:
*/
nsresult MakeHeavyweight();
/**
* Get the attr info for the given namespace ID and attribute name.
* The namespace ID must not be kNameSpaceID_Unknown and the name
* must not be null.
*/
virtual nsAttrInfo GetAttrInfo(PRInt32 aNamespaceID, nsIAtom* aName) const;
const nsAttrValue* FindLocalOrProtoAttr(PRInt32 aNameSpaceID,
nsIAtom *aName) const;
nsIAtom *aName) const {
return nsXULElement::GetAttrInfo(aNameSpaceID, aName).mValue;
}
virtual nsresult BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
virtual PRBool ParseAttribute(nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
virtual nsresult
GetEventListenerManagerForAttr(nsIEventListenerManager** aManager,
nsISupports** aTarget,
PRBool* aDefer);
/**
* Return our prototype's attribute, if one exists.
@ -629,16 +643,6 @@ protected:
nsresult HideWindowChrome(PRBool aShouldHide);
nsresult SetAttrAndNotify(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
nsIAtom* aPrefix,
const nsAString& aOldValue,
nsAttrValue& aParsedValue,
PRBool aModification,
PRBool aFireMutation,
PRBool aNotify);
const nsAttrName* InternalGetExistingAttrNameFromQName(const nsAString& aStr) const;
protected: