зеркало из https://github.com/mozilla/gecko-dev.git
Bug 275196, xml:id, r=sicking, sr=dbaron
This commit is contained in:
Родитель
e81335e2c5
Коммит
e8dba5a1b4
|
@ -63,8 +63,8 @@ class nsIDocShell;
|
|||
|
||||
// IID for the nsIContent interface
|
||||
#define NS_ICONTENT_IID \
|
||||
{ 0x36b375cb, 0xf01e, 0x4c18, \
|
||||
{ 0xbf, 0x9e, 0xba, 0xad, 0x77, 0x1d, 0xce, 0x22 } }
|
||||
{ 0x609baee8, 0x3c0a, 0x4122, \
|
||||
{ 0x9c, 0xc6, 0xe4, 0xc9, 0x83, 0x53, 0xff, 0x9c } }
|
||||
|
||||
// hack to make egcs / gcc 2.95.2 happy
|
||||
class nsIContent_base : public nsINode {
|
||||
|
@ -211,10 +211,21 @@ public:
|
|||
|
||||
/**
|
||||
* Returns an atom holding the name of the attribute of type ID on
|
||||
* this content node (if applicable). Returns null for non-element
|
||||
* content nodes.
|
||||
* this content node (if applicable).
|
||||
* Language specific ID attribute has the highest priority, then
|
||||
* ID attribute defined in DTD, and finally xml:id.
|
||||
* Returns null for non-element content nodes.
|
||||
*/
|
||||
virtual nsIAtom *GetIDAttributeName() const = 0;
|
||||
virtual nsIAtom* GetIDAttributeName(PRInt32& aNameSpaceID) const = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the attribute can be
|
||||
* used as an ID attribute of the element.
|
||||
* Note this may return true with many attributes, but only one
|
||||
* is used as an ID at a time.
|
||||
*/
|
||||
virtual PRBool IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const = 0;
|
||||
|
||||
/**
|
||||
* Normalizes an attribute name and returns it as a nodeinfo if an attribute
|
||||
|
@ -731,8 +742,8 @@ public:
|
|||
|
||||
/**
|
||||
* Get the ID of this content node (the atom corresponding to the
|
||||
* value of the null-namespace attribute whose name is given by
|
||||
* GetIDAttributeName(). This may be null if there is no ID.
|
||||
* value of the attribute whose name is given by GetIDAttributeName().
|
||||
* This may be null if there is no ID.
|
||||
*/
|
||||
virtual nsIAtom* GetID() const = 0;
|
||||
|
||||
|
|
|
@ -600,14 +600,15 @@ nsDOMAttribute::GetIsId(PRBool* aReturn)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIAtom* idAtom = content->GetIDAttributeName();
|
||||
PRInt32 namespaceID;
|
||||
nsIAtom* idAtom = content->GetIDAttributeName(namespaceID);
|
||||
if (!idAtom)
|
||||
{
|
||||
*aReturn = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aReturn = mNodeInfo->Equals(idAtom, kNameSpaceID_None);
|
||||
*aReturn = mNodeInfo->Equals(idAtom, namespaceID);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -631,11 +631,19 @@ nsGenericDOMDataNode::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
|||
}
|
||||
|
||||
nsIAtom *
|
||||
nsGenericDOMDataNode::GetIDAttributeName() const
|
||||
nsGenericDOMDataNode::GetIDAttributeName(PRInt32& aNameSpaceID) const
|
||||
{
|
||||
aNameSpaceID = kNameSpaceID_Unknown;
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsGenericDOMDataNode::IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
already_AddRefed<nsINodeInfo>
|
||||
nsGenericDOMDataNode::GetExistingAttrNameFromQName(const nsAString& aStr) const
|
||||
{
|
||||
|
|
|
@ -195,7 +195,9 @@ public:
|
|||
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
|
||||
PRBool aNullParent = PR_TRUE);
|
||||
|
||||
virtual nsIAtom *GetIDAttributeName() const;
|
||||
virtual nsIAtom *GetIDAttributeName(PRInt32& aNamespaceId) const;
|
||||
virtual PRBool IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const;
|
||||
virtual already_AddRefed<nsINodeInfo> GetExistingAttrNameFromQName(const nsAString& aStr) const;
|
||||
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString& aValue, PRBool aNotify)
|
||||
|
|
|
@ -2260,9 +2260,10 @@ nsGenericElement::DispatchDOMEvent(nsEvent* aEvent,
|
|||
nsIAtom*
|
||||
nsGenericElement::GetID() const
|
||||
{
|
||||
nsIAtom* IDName = GetIDAttributeName();
|
||||
PRInt32 namespaceID;
|
||||
nsIAtom* IDName = GetIDAttributeName(namespaceID);
|
||||
if (IDName) {
|
||||
const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(IDName);
|
||||
const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(IDName, namespaceID);
|
||||
if (attrVal){
|
||||
if (attrVal->Type() == nsAttrValue::eAtom) {
|
||||
return attrVal->GetAtomValue();
|
||||
|
@ -2325,9 +2326,26 @@ nsGenericElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
|
|||
}
|
||||
|
||||
nsIAtom *
|
||||
nsGenericElement::GetIDAttributeName() const
|
||||
nsGenericElement::GetIDAttributeName(PRInt32& aNameSpaceID) const
|
||||
{
|
||||
return mNodeInfo->GetIDAttributeAtom();
|
||||
aNameSpaceID = kNameSpaceID_None;
|
||||
nsIAtom* idAtom = mNodeInfo->GetIDAttributeAtom();
|
||||
if (idAtom && HasAttr(aNameSpaceID, idAtom)) {
|
||||
return idAtom;
|
||||
}
|
||||
|
||||
aNameSpaceID = kNameSpaceID_XML;
|
||||
return nsGkAtoms::id;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsGenericElement::IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const
|
||||
{
|
||||
return (aNameSpaceID == kNameSpaceID_None &&
|
||||
aAtom == mNodeInfo->GetIDAttributeAtom()) ||
|
||||
(aNameSpaceID == kNameSpaceID_XML &&
|
||||
aAtom == nsGkAtoms::id);
|
||||
}
|
||||
|
||||
nsIAtom *
|
||||
|
@ -3652,8 +3670,8 @@ nsGenericElement::ParseAttribute(PRInt32 aNamespaceID,
|
|||
const nsAString& aValue,
|
||||
nsAttrValue& aResult)
|
||||
{
|
||||
if (aNamespaceID == kNameSpaceID_None &&
|
||||
aAttribute == GetIDAttributeName() && !aValue.IsEmpty()) {
|
||||
if (IsPotentialIDAttributeName(aNamespaceID, aAttribute) &&
|
||||
!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);
|
||||
|
|
|
@ -383,7 +383,9 @@ public:
|
|||
PRBool aCompileEventHandlers);
|
||||
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
|
||||
PRBool aNullParent = PR_TRUE);
|
||||
virtual nsIAtom *GetIDAttributeName() const;
|
||||
virtual nsIAtom *GetIDAttributeName(PRInt32& aNameSpaceID) const;
|
||||
virtual PRBool IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const;
|
||||
virtual nsIAtom *GetClassAttributeName() const;
|
||||
virtual already_AddRefed<nsINodeInfo> GetExistingAttrNameFromQName(const nsAString& aStr) const;
|
||||
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
|
|
|
@ -46,7 +46,9 @@ public:
|
|||
virtual ~nsXMLEventsElement();
|
||||
NS_FORWARD_NSIDOMNODE(nsXMLElement::)
|
||||
|
||||
virtual nsIAtom *GetIDAttributeName() const;
|
||||
virtual nsIAtom *GetIDAttributeName(PRInt32& aNameSpaceID) const;
|
||||
virtual PRBool IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const;
|
||||
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
nsIAtom* aPrefix, const nsAString& aValue,
|
||||
PRBool aNotify);
|
||||
|
@ -63,11 +65,21 @@ nsXMLEventsElement::~nsXMLEventsElement()
|
|||
}
|
||||
|
||||
nsIAtom *
|
||||
nsXMLEventsElement::GetIDAttributeName() const
|
||||
nsXMLEventsElement::GetIDAttributeName(PRInt32& aNameSpaceID) const
|
||||
{
|
||||
if (mNodeInfo->Equals(nsGkAtoms::listener))
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::id)) {
|
||||
aNameSpaceID = kNameSpaceID_None;
|
||||
return nsGkAtoms::id;
|
||||
return nsXMLElement::GetIDAttributeName();
|
||||
}
|
||||
return nsGenericElement::GetIDAttributeName(aNameSpaceID);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXMLEventsElement::IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const
|
||||
{
|
||||
return (aNameSpaceID == kNameSpaceID_None && aAtom == nsGkAtoms::id) ||
|
||||
nsGenericElement::IsPotentialIDAttributeName(aNameSpaceID, aAtom);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -377,20 +377,11 @@ nsXMLEventsManager::AttributeChanged(nsIDocument* aDocument,
|
|||
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);
|
||||
}
|
||||
else if (aContent->IsPotentialIDAttributeName(aNameSpaceID, aAttribute)) {
|
||||
//Remove possible listener
|
||||
mListeners.Enumerate(EnumAndSetIncomplete, aContent);
|
||||
//Add new listeners
|
||||
AddListeners(aDocument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1493,9 +1493,21 @@ nsGenericHTMLElement::GetClasses() const
|
|||
}
|
||||
|
||||
nsIAtom *
|
||||
nsGenericHTMLElement::GetIDAttributeName() const
|
||||
nsGenericHTMLElement::GetIDAttributeName(PRInt32& aNameSpaceID) const
|
||||
{
|
||||
return nsGkAtoms::id;
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::id)) {
|
||||
aNameSpaceID = kNameSpaceID_None;
|
||||
return nsGkAtoms::id;
|
||||
}
|
||||
return nsGenericElement::GetIDAttributeName(aNameSpaceID);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsGenericHTMLElement::IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const
|
||||
{
|
||||
return (aNameSpaceID == kNameSpaceID_None && aAtom == nsGkAtoms::id) ||
|
||||
nsGenericElement::IsPotentialIDAttributeName(aNameSpaceID, aAtom);
|
||||
}
|
||||
|
||||
nsIAtom *
|
||||
|
|
|
@ -241,7 +241,9 @@ public:
|
|||
virtual void UpdateEditableState();
|
||||
|
||||
virtual const nsAttrValue* GetClasses() const;
|
||||
virtual nsIAtom *GetIDAttributeName() const;
|
||||
virtual nsIAtom *GetIDAttributeName(PRInt32& aNameSpaceID) const;
|
||||
virtual PRBool IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const;
|
||||
virtual nsIAtom *GetClassAttributeName() const;
|
||||
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
|
||||
virtual nsICSSStyleRule* GetInlineStyleRule();
|
||||
|
|
|
@ -1376,8 +1376,7 @@ nsHTMLDocument::AttributeWillChange(nsIContent* aContent, PRInt32 aNameSpaceID,
|
|||
return;
|
||||
}
|
||||
}
|
||||
} else if (aAttribute == aContent->GetIDAttributeName() &&
|
||||
aNameSpaceID == kNameSpaceID_None) {
|
||||
} else if (aContent->IsPotentialIDAttributeName(aNameSpaceID, aAttribute)) {
|
||||
nsresult rv = RemoveFromIdTable(aContent);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -1406,8 +1405,7 @@ nsHTMLDocument::AttributeChanged(nsIDocument* aDocument,
|
|||
if (name) {
|
||||
UpdateNameTableEntry(name, aContent);
|
||||
}
|
||||
} else if (aAttribute == aContent->GetIDAttributeName() &&
|
||||
aNameSpaceID == kNameSpaceID_None) {
|
||||
} else if (aContent->IsPotentialIDAttributeName(aNameSpaceID, aAttribute)) {
|
||||
nsIAtom* id = aContent->GetID();
|
||||
if (id) {
|
||||
UpdateIdTableEntry(id, aContent);
|
||||
|
|
|
@ -126,10 +126,22 @@ NS_INTERFACE_MAP_END_INHERITING(nsGenericElement)
|
|||
//----------------------------------------------------------------------
|
||||
// nsIContent methods
|
||||
|
||||
nsIAtom *
|
||||
nsSVGElement::GetIDAttributeName() const
|
||||
nsIAtom*
|
||||
nsSVGElement::GetIDAttributeName(PRInt32& aNameSpaceID) const
|
||||
{
|
||||
return nsGkAtoms::id;
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::id)) {
|
||||
aNameSpaceID = kNameSpaceID_None;
|
||||
return nsGkAtoms::id;
|
||||
}
|
||||
return nsGenericElement::GetIDAttributeName(aNameSpaceID);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSVGElement::IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const
|
||||
{
|
||||
return (aNameSpaceID == kNameSpaceID_None && aAtom == nsGkAtoms::id) ||
|
||||
nsGenericElement::IsPotentialIDAttributeName(aNameSpaceID, aAtom);
|
||||
}
|
||||
|
||||
nsIAtom *
|
||||
|
|
|
@ -71,7 +71,9 @@ public:
|
|||
|
||||
// nsIContent interface methods
|
||||
|
||||
virtual nsIAtom *GetIDAttributeName() const;
|
||||
virtual nsIAtom *GetIDAttributeName(PRInt32& aNameSpaceID) const;
|
||||
virtual PRBool IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const;
|
||||
virtual nsIAtom *GetClassAttributeName() const;
|
||||
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
||||
PRBool aNotify);
|
||||
|
|
|
@ -265,10 +265,21 @@ nsXTFElementWrapper::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
|
|||
}
|
||||
|
||||
nsIAtom *
|
||||
nsXTFElementWrapper::GetIDAttributeName() const
|
||||
nsXTFElementWrapper::GetIDAttributeName(PRInt32& aNameSpaceID) const
|
||||
{
|
||||
// XXX:
|
||||
return nsGkAtoms::id;
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::id)) {
|
||||
aNameSpaceID = kNameSpaceID_None;
|
||||
return nsGkAtoms::id;
|
||||
}
|
||||
return nsXTFElementWrapperBase::GetIDAttributeName(aNameSpaceID);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXTFElementWrapper::IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const
|
||||
{
|
||||
return (aNameSpaceID == kNameSpaceID_None && aAtom == nsGkAtoms::id) ||
|
||||
nsXTFElementWrapperBase::IsPotentialIDAttributeName(aNameSpaceID, aAtom);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -78,7 +78,9 @@ public:
|
|||
nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify);
|
||||
nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
|
||||
nsIAtom *GetIDAttributeName() const;
|
||||
virtual nsIAtom *GetIDAttributeName(PRInt32& aNameSpaceID) const;
|
||||
virtual PRBool IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const;
|
||||
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
nsIAtom* aPrefix, const nsAString& aValue,
|
||||
PRBool aNotify);
|
||||
|
|
|
@ -1633,7 +1633,9 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify)
|
|||
nsIAtom*
|
||||
nsXULElement::GetID() const
|
||||
{
|
||||
const nsAttrValue* attrVal = FindLocalOrProtoAttr(kNameSpaceID_None, nsGkAtoms::id);
|
||||
PRInt32 namespaceID;
|
||||
nsIAtom* IDName = GetIDAttributeName(namespaceID);
|
||||
const nsAttrValue* attrVal = FindLocalOrProtoAttr(namespaceID, IDName);
|
||||
|
||||
NS_ASSERTION(!attrVal ||
|
||||
attrVal->Type() == nsAttrValue::eAtom ||
|
||||
|
@ -1739,9 +1741,21 @@ nsXULElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
|||
}
|
||||
|
||||
nsIAtom *
|
||||
nsXULElement::GetIDAttributeName() const
|
||||
nsXULElement::GetIDAttributeName(PRInt32& aNameSpaceID) const
|
||||
{
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::id)) {
|
||||
aNameSpaceID = kNameSpaceID_None;
|
||||
return nsGkAtoms::id;
|
||||
}
|
||||
return nsGenericElement::GetIDAttributeName(aNameSpaceID);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXULElement::IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const
|
||||
{
|
||||
return (aNameSpaceID == kNameSpaceID_None && aAtom == nsGkAtoms::id) ||
|
||||
nsGenericElement::IsPotentialIDAttributeName(aNameSpaceID, aAtom);
|
||||
}
|
||||
|
||||
nsIAtom *
|
||||
|
|
|
@ -505,7 +505,9 @@ public:
|
|||
virtual void UnbindFromTree(PRBool aDeep, PRBool aNullParent);
|
||||
virtual void SetNativeAnonymous(PRBool aAnonymous);
|
||||
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
|
||||
virtual nsIAtom *GetIDAttributeName() const;
|
||||
virtual nsIAtom *GetIDAttributeName(PRInt32& aNameSpaceID) const;
|
||||
virtual PRBool IsPotentialIDAttributeName(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAtom) const;
|
||||
virtual nsIAtom *GetClassAttributeName() const;
|
||||
virtual PRBool GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
nsAString& aResult) const;
|
||||
|
|
|
@ -929,7 +929,8 @@ nsXULDocument::AttributeChanged(nsIDocument* aDocument,
|
|||
|
||||
// XXXbz check aNameSpaceID, dammit!
|
||||
// First see if we need to update our element map.
|
||||
if ((aAttribute == nsGkAtoms::id) || (aAttribute == nsGkAtoms::ref)) {
|
||||
if (aElement->IsPotentialIDAttributeName(aNameSpaceID, aAttribute) ||
|
||||
(aAttribute == nsGkAtoms::ref && aNameSpaceID == kNameSpaceID_None)) {
|
||||
|
||||
rv = mElementMap.Enumerate(RemoveElementsFromMapByContent, aElement);
|
||||
if (NS_FAILED(rv)) return;
|
||||
|
@ -1757,31 +1758,29 @@ nsXULDocument::GetTemplateBuilderFor(nsIContent* aContent,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Attributes that are used with getElementById() and the
|
||||
// resource-to-element map.
|
||||
nsIAtom** nsXULDocument::kIdentityAttrs[] =
|
||||
{
|
||||
&nsGkAtoms::id,
|
||||
&nsGkAtoms::ref,
|
||||
nsnull
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsXULDocument::AddElementToMap(nsIContent* aElement)
|
||||
{
|
||||
// Look at the element's 'id' and 'ref' attributes, and if set,
|
||||
// Look at the element's ID and 'ref' attributes, and if set,
|
||||
// add pointers in the resource-to-element map to the element.
|
||||
nsresult rv;
|
||||
|
||||
for (PRInt32 i = 0; kIdentityAttrs[i] != nsnull; ++i) {
|
||||
nsAutoString value;
|
||||
aElement->GetAttr(kNameSpaceID_None, *kIdentityAttrs[i], value);
|
||||
if (!value.IsEmpty()) {
|
||||
rv = mElementMap.Add(value, aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsIAtom* idAtom = aElement->GetID();
|
||||
if (idAtom) {
|
||||
nsAutoString idStr;
|
||||
idAtom->ToString(idStr);
|
||||
if (!idStr.IsEmpty()) {
|
||||
rv = mElementMap.Add(idStr, aElement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString refvalue;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::ref, refvalue);
|
||||
if (!refvalue.IsEmpty()) {
|
||||
rv = mElementMap.Add(refvalue, aElement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1791,16 +1790,23 @@ nsXULDocument::RemoveElementFromMap(nsIContent* aElement)
|
|||
{
|
||||
// Remove the element from the resource-to-element map.
|
||||
nsresult rv;
|
||||
|
||||
for (PRInt32 i = 0; kIdentityAttrs[i] != nsnull; ++i) {
|
||||
nsAutoString value;
|
||||
aElement->GetAttr(kNameSpaceID_None, *kIdentityAttrs[i], value);
|
||||
if (!value.IsEmpty()) {
|
||||
rv = mElementMap.Remove(value, aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsIAtom* idAtom = aElement->GetID();
|
||||
if (idAtom) {
|
||||
nsAutoString idStr;
|
||||
idAtom->ToString(idStr);
|
||||
if (!idStr.IsEmpty()) {
|
||||
rv = mElementMap.Remove(idStr, aElement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString refvalue;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::ref, refvalue);
|
||||
if (!refvalue.IsEmpty()) {
|
||||
rv = mElementMap.Remove(refvalue, aElement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -10128,7 +10128,8 @@ nsCSSFrameConstructor::AttributeChanged(nsIContent* aContent,
|
|||
#endif
|
||||
|
||||
// the style tag has its own interpretation based on aHint
|
||||
nsChangeHint hint = aContent->GetAttributeChangeHint(aAttribute, aModType);
|
||||
nsChangeHint hint = (aNameSpaceID == kNameSpaceID_None)
|
||||
? aContent->GetAttributeChangeHint(aAttribute, aModType) : nsChangeHint(0);
|
||||
|
||||
PRBool reframe = (hint & nsChangeHint_ReconstructFrame) != 0;
|
||||
|
||||
|
@ -10163,15 +10164,19 @@ nsCSSFrameConstructor::AttributeChanged(nsIContent* aContent,
|
|||
|
||||
if (primaryFrame) {
|
||||
// See if we have appearance information for a theme.
|
||||
const nsStyleDisplay* disp = primaryFrame->GetStyleDisplay();
|
||||
if (disp->mAppearance) {
|
||||
nsPresContext* presContext = mPresShell->GetPresContext();
|
||||
nsITheme *theme = presContext->GetTheme();
|
||||
if (theme && theme->ThemeSupportsWidget(presContext, primaryFrame, disp->mAppearance)) {
|
||||
PRBool repaint = PR_FALSE;
|
||||
theme->WidgetStateChanged(primaryFrame, disp->mAppearance, aAttribute, &repaint);
|
||||
if (repaint)
|
||||
NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
const nsStyleDisplay* disp = primaryFrame->GetStyleDisplay();
|
||||
if (disp->mAppearance) {
|
||||
nsPresContext* presContext = mPresShell->GetPresContext();
|
||||
nsITheme *theme = presContext->GetTheme();
|
||||
if (theme && theme->ThemeSupportsWidget(presContext, primaryFrame,
|
||||
disp->mAppearance)) {
|
||||
PRBool repaint = PR_FALSE;
|
||||
theme->WidgetStateChanged(primaryFrame, disp->mAppearance, aAttribute,
|
||||
&repaint);
|
||||
if (repaint)
|
||||
NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10188,6 +10193,7 @@ nsCSSFrameConstructor::AttributeChanged(nsIContent* aContent,
|
|||
// the frame's AttributeChanged() in case it does something that affects the style
|
||||
nsFrameManager *frameManager = shell->FrameManager();
|
||||
nsReStyleHint rshint = frameManager->HasAttributeDependentStyle(aContent,
|
||||
aNameSpaceID,
|
||||
aAttribute,
|
||||
aModType,
|
||||
aStateMask);
|
||||
|
|
|
@ -1445,12 +1445,14 @@ nsFrameManager::ComputeStyleChangeFor(nsIFrame *aFrame,
|
|||
|
||||
nsReStyleHint
|
||||
nsFrameManager::HasAttributeDependentStyle(nsIContent *aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom *aAttribute,
|
||||
PRInt32 aModType,
|
||||
PRUint32 aStateMask)
|
||||
{
|
||||
nsReStyleHint hint = mStyleSet->HasAttributeDependentStyle(GetPresContext(),
|
||||
aContent,
|
||||
aNameSpaceID,
|
||||
aAttribute,
|
||||
aModType,
|
||||
aStateMask);
|
||||
|
|
|
@ -191,6 +191,7 @@ public:
|
|||
|
||||
// Determine whether an attribute affects style
|
||||
NS_HIDDEN_(nsReStyleHint) HasAttributeDependentStyle(nsIContent *aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom *aAttribute,
|
||||
PRInt32 aModType,
|
||||
PRUint32 aStateMask);
|
||||
|
|
|
@ -1001,6 +1001,8 @@ static PRBool AttrMatchesValue(const nsAttrSelector* aAttrSelector,
|
|||
static PRBool SelectorMatches(RuleProcessorData &data,
|
||||
nsCSSSelector* aSelector,
|
||||
PRInt32 aStateMask, // states NOT to test
|
||||
PRInt32 aNameSpaceID, // the namespace of the
|
||||
// attribute NOT to test
|
||||
nsIAtom* aAttribute, // attribute NOT to test
|
||||
PRBool* const aDependence = nsnull)
|
||||
|
||||
|
@ -1322,9 +1324,9 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
|||
result = PR_TRUE;
|
||||
nsAttrSelector* attr = aSelector->mAttrList;
|
||||
do {
|
||||
if (attr->mAttr == aAttribute) {
|
||||
// XXX we should really have a namespace, not just an attr
|
||||
// name, in HasAttributeDependentStyle!
|
||||
if (attr->mAttr == aAttribute &&
|
||||
(attr->mNameSpace == aNameSpaceID ||
|
||||
attr->mNameSpace == kNameSpaceID_Unknown)) {
|
||||
result = PR_TRUE;
|
||||
if (aDependence)
|
||||
*aDependence = PR_TRUE;
|
||||
|
@ -1396,8 +1398,9 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
|||
if (result && IDList) {
|
||||
// test for ID match
|
||||
result = PR_FALSE;
|
||||
|
||||
if (aAttribute && aAttribute == data.mContent->GetIDAttributeName()) {
|
||||
PRInt32 namespaceID;
|
||||
if (aAttribute &&
|
||||
data.mContent->IsPotentialIDAttributeName(namespaceID, aAttribute)) {
|
||||
result = PR_TRUE;
|
||||
if (aDependence)
|
||||
*aDependence = PR_TRUE;
|
||||
|
@ -1435,7 +1438,8 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
|||
|
||||
if (result && aSelector->mClassList) {
|
||||
// test for class match
|
||||
if (aAttribute && aAttribute == data.mContent->GetClassAttributeName()) {
|
||||
if (aAttribute && aAttribute == data.mContent->GetClassAttributeName() &&
|
||||
aNameSpaceID == kNameSpaceID_None) {
|
||||
result = PR_TRUE;
|
||||
if (aDependence)
|
||||
*aDependence = PR_TRUE;
|
||||
|
@ -1462,7 +1466,7 @@ static PRBool SelectorMatches(RuleProcessorData &data,
|
|||
for (nsCSSSelector *negation = aSelector->mNegations;
|
||||
result && negation; negation = negation->mNegations) {
|
||||
PRBool dependence = PR_FALSE;
|
||||
result = !SelectorMatches(data, negation, aStateMask,
|
||||
result = !SelectorMatches(data, negation, aStateMask, aNameSpaceID,
|
||||
aAttribute, &dependence);
|
||||
// If the selector does match due to the dependence on aStateMask
|
||||
// or aAttribute, then we want to keep result true so that the
|
||||
|
@ -1536,7 +1540,7 @@ static PRBool SelectorMatchesTree(RuleProcessorData& aPrevData,
|
|||
if (! data) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (SelectorMatches(*data, selector, 0, nsnull)) {
|
||||
if (SelectorMatches(*data, selector, 0, kNameSpaceID_Unknown, nsnull)) {
|
||||
// to avoid greedy matching, we need to recur if this is a
|
||||
// descendant combinator and the next combinator is not
|
||||
if ((NS_IS_GREEDY_OPERATOR(selector->mOperator)) &&
|
||||
|
@ -1573,7 +1577,7 @@ static void ContentEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
|
|||
{
|
||||
ElementRuleProcessorData* data = (ElementRuleProcessorData*)aData;
|
||||
|
||||
if (SelectorMatches(*data, aSelector, 0, nsnull)) {
|
||||
if (SelectorMatches(*data, aSelector, 0, kNameSpaceID_Unknown, nsnull)) {
|
||||
nsCSSSelector *next = aSelector->mNext;
|
||||
if (!next || SelectorMatchesTree(*data, next)) {
|
||||
// for performance, require that every implementation of
|
||||
|
@ -1626,7 +1630,7 @@ static void PseudoEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
|
|||
if (PRUnichar('+') == selector->mOperator) {
|
||||
return; // not valid here, can't match
|
||||
}
|
||||
if (SelectorMatches(*data, selector, 0, nsnull)) {
|
||||
if (SelectorMatches(*data, selector, 0, kNameSpaceID_Unknown, nsnull)) {
|
||||
selector = selector->mNext;
|
||||
}
|
||||
else {
|
||||
|
@ -1697,7 +1701,8 @@ PR_STATIC_CALLBACK(PRBool) StateEnumFunc(void* aSelector, void* aData)
|
|||
// bother calling SelectorMatches, since even if it returns false
|
||||
// enumData->change won't change.
|
||||
if ((possibleChange & ~(enumData->change)) &&
|
||||
SelectorMatches(*data, selector, data->mStateMask, nsnull) &&
|
||||
SelectorMatches(*data, selector, data->mStateMask, kNameSpaceID_Unknown,
|
||||
nsnull) &&
|
||||
SelectorMatchesTree(*data, selector->mNext)) {
|
||||
enumData->change = nsReStyleHint(enumData->change | possibleChange);
|
||||
}
|
||||
|
@ -1751,7 +1756,8 @@ PR_STATIC_CALLBACK(PRBool) AttributeEnumFunc(void* aSelector, void* aData)
|
|||
// bother calling SelectorMatches, since even if it returns false
|
||||
// enumData->change won't change.
|
||||
if ((possibleChange & ~(enumData->change)) &&
|
||||
SelectorMatches(*data, selector, data->mStateMask, data->mAttribute) &&
|
||||
SelectorMatches(*data, selector, data->mStateMask, data->mNameSpaceID,
|
||||
data->mAttribute) &&
|
||||
SelectorMatchesTree(*data, selector->mNext)) {
|
||||
enumData->change = nsReStyleHint(enumData->change | possibleChange);
|
||||
}
|
||||
|
@ -1772,6 +1778,7 @@ nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData
|
|||
// and :visited rules from prefs), rather than hacking AddRule below
|
||||
// to add |href| to the hash, we'll just handle it here.
|
||||
if (aData->mAttribute == nsGkAtoms::href &&
|
||||
aData->mNameSpaceID == kNameSpaceID_None &&
|
||||
aData->mIsHTMLContent &&
|
||||
(aData->mContentTag == nsGkAtoms::a ||
|
||||
aData->mContentTag == nsGkAtoms::area ||
|
||||
|
@ -1789,11 +1796,13 @@ nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData
|
|||
// we have a hashtable with a per-attribute list.
|
||||
|
||||
if (cascade) {
|
||||
if (aData->mAttribute == aData->mContent->GetIDAttributeName()) {
|
||||
if (aData->mContent->IsPotentialIDAttributeName(aData->mNameSpaceID,
|
||||
aData->mAttribute)) {
|
||||
cascade->mIDSelectors.EnumerateForwards(AttributeEnumFunc, &data);
|
||||
}
|
||||
|
||||
if (aData->mAttribute == aData->mContent->GetClassAttributeName()) {
|
||||
if (aData->mNameSpaceID == kNameSpaceID_None &&
|
||||
aData->mAttribute == aData->mContent->GetClassAttributeName()) {
|
||||
cascade->mClassSelectors.EnumerateForwards(AttributeEnumFunc, &data);
|
||||
}
|
||||
|
||||
|
|
|
@ -153,19 +153,24 @@ struct StateRuleProcessorData : public RuleProcessorData {
|
|||
struct AttributeRuleProcessorData : public RuleProcessorData {
|
||||
AttributeRuleProcessorData(nsPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType,
|
||||
PRUint32 aStateMask)
|
||||
: RuleProcessorData(aPresContext, aContent, nsnull),
|
||||
mNameSpaceID(aNameSpaceID),
|
||||
mAttribute(aAttribute),
|
||||
mModType(aModType),
|
||||
mStateMask(aStateMask)
|
||||
{
|
||||
NS_PRECONDITION(aContent, "null pointer");
|
||||
}
|
||||
nsIAtom* mAttribute; // |HasAttributeDependentStyle| for which attribute?
|
||||
PRInt32 mModType; // The type of modification (see nsIDOMMutationEvent).
|
||||
PRUint32 mStateMask; // The states that changed with the attr change.
|
||||
// |HasAttributeDependentStyle| for which attribute?
|
||||
PRInt32 mNameSpaceID;
|
||||
nsIAtom* mAttribute;
|
||||
|
||||
PRInt32 mModType; // The type of modification (see nsIDOMMutationEvent).
|
||||
PRUint32 mStateMask; // The states that changed with the attr change.
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -959,10 +959,10 @@ nsStyleSet::HasStateDependentStyle(nsPresContext* aPresContext,
|
|||
|
||||
struct AttributeData : public AttributeRuleProcessorData {
|
||||
AttributeData(nsPresContext* aPresContext,
|
||||
nsIContent* aContent, nsIAtom* aAttribute, PRInt32 aModType,
|
||||
PRUint32 aStateMask)
|
||||
: AttributeRuleProcessorData(aPresContext, aContent, aAttribute, aModType,
|
||||
aStateMask),
|
||||
nsIContent* aContent, PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute, PRInt32 aModType, PRUint32 aStateMask)
|
||||
: AttributeRuleProcessorData(aPresContext, aContent, aNameSpaceID,
|
||||
aAttribute, aModType, aStateMask),
|
||||
mHint(nsReStyleHint(0))
|
||||
{}
|
||||
nsReStyleHint mHint;
|
||||
|
@ -982,6 +982,7 @@ SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData)
|
|||
nsReStyleHint
|
||||
nsStyleSet::HasAttributeDependentStyle(nsPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType,
|
||||
PRUint32 aStateMask)
|
||||
|
@ -996,8 +997,8 @@ nsStyleSet::HasAttributeDependentStyle(nsPresContext* aPresContext,
|
|||
mRuleProcessors[eDocSheet] ||
|
||||
mRuleProcessors[eStyleAttrSheet] ||
|
||||
mRuleProcessors[eOverrideSheet])) {
|
||||
AttributeData data(aPresContext, aContent, aAttribute, aModType,
|
||||
aStateMask);
|
||||
AttributeData data(aPresContext, aContent, aNameSpaceID, aAttribute,
|
||||
aModType, aStateMask);
|
||||
WalkRuleProcessors(SheetHasAttributeStyle, &data);
|
||||
result = data.mHint;
|
||||
}
|
||||
|
|
|
@ -139,6 +139,7 @@ class nsStyleSet
|
|||
// Test if style is dependent on the presence of an attribute.
|
||||
nsReStyleHint HasAttributeDependentStyle(nsPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aModType,
|
||||
PRUint32 aStateMask);
|
||||
|
|
|
@ -68,6 +68,7 @@ css_properties.js: host_ListCSSProperties$(HOST_BIN_SUFFIX) css_properties_like_
|
|||
|
||||
_TEST_FILES = test_bug74880.html \
|
||||
test_bug221428.html \
|
||||
test_bug275196.xhtml \
|
||||
test_bug302186.html \
|
||||
test_bug319381.html \
|
||||
test_bug357614.html \
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
<?xml version="1.0"?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:foo="http://example.org/2005/02/13/#foo"
|
||||
xml:id="start">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=275196
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 275196</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<style type="text/css">
|
||||
:root {
|
||||
background: red;
|
||||
}
|
||||
|
||||
:root#foo {
|
||||
background: rgb(0, 255, 0);
|
||||
}
|
||||
|
||||
:root#bar {
|
||||
background: rgb(0, 0, 255);
|
||||
}
|
||||
|
||||
*[*|green] {
|
||||
background: rgb(0, 255, 0);
|
||||
}
|
||||
|
||||
#xhtml3, #foo2 {
|
||||
background: rgb(0, 255, 0);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=275196">Mozilla Bug 275196</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<div id="xhtml1" green="true">Element in XHTML namespace, attribute in null namespace</div>
|
||||
<div id="xhtml2" foo:green="true">Element in XHTML namespace, attribute in foo namespace</div>
|
||||
<foo:foo xml:id="foo1" foo:green="true">Element in foo namespace, attribute in foo namespace</foo:foo>
|
||||
<div id="xhtml3">Element in XHTML namespace, id attribute</div>
|
||||
<foo:foo xml:id="foo2">Element in foo namespace, xml:id attribute</foo:foo>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
<![CDATA[
|
||||
|
||||
/** Test for Bug 275196 **/
|
||||
|
||||
// Test whether setting 'native' ID overrides xml:id
|
||||
function test_1() {
|
||||
try {
|
||||
document.getElementById('start').setAttribute('id', 'bar');
|
||||
} catch (e) {
|
||||
ok(false, "Couldn't find element 'start'");
|
||||
test_2();
|
||||
return;
|
||||
}
|
||||
ok(document.defaultView.getComputedStyle(document.documentElement, null).
|
||||
getPropertyValue('background-color') == "rgb(0, 0, 255)",
|
||||
"The background of the documentElement should be blue.");
|
||||
test_2();
|
||||
}
|
||||
|
||||
// Test if ID 'start' was removed from the document when the ID was set to 'bar'.
|
||||
function test_2() {
|
||||
ok(document.getElementById('bar') != document.getElementById('start'),
|
||||
"Element with ID 'bar' shouldn't be the same as 'start'");
|
||||
test_3();
|
||||
}
|
||||
|
||||
// Setting xml:id and removing 'native' ID
|
||||
function test_3() {
|
||||
var b = null;
|
||||
try {
|
||||
b = document.getElementById('bar');
|
||||
b.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:id", "foo");
|
||||
b.removeAttribute('id');
|
||||
} catch (e) {
|
||||
ok(false, e);
|
||||
test_4();
|
||||
return;
|
||||
}
|
||||
ok(document.defaultView.getComputedStyle(document.documentElement, null).
|
||||
getPropertyValue('background-color') == "rgb(0, 255, 0)",
|
||||
"The background of the documentElement should be green.");
|
||||
test_4();
|
||||
}
|
||||
|
||||
// Setting 'native' ID
|
||||
function test_4() {
|
||||
try {
|
||||
document.getElementById('foo').setAttribute('id', 'bar');
|
||||
} catch (e) {
|
||||
ok(false, e);
|
||||
test_5();
|
||||
return;
|
||||
}
|
||||
ok(document.defaultView.getComputedStyle(document.documentElement, null).
|
||||
getPropertyValue('background-color') == "rgb(0, 0, 255)",
|
||||
"The background of the documentElement should be blue.");
|
||||
test_5();
|
||||
}
|
||||
|
||||
function testElementBackground(elementId) {
|
||||
var el = document.getElementById(elementId);
|
||||
ok(document.defaultView.getComputedStyle(el, null).
|
||||
getPropertyValue('background-color') == "rgb(0, 255, 0)",
|
||||
"The background of the element should be green.");
|
||||
|
||||
el.removeAttribute("green");
|
||||
el.removeAttributeNS("http://example.org/2005/02/13/#foo", "green");
|
||||
ok(document.defaultView.getComputedStyle(el, null).
|
||||
getPropertyValue('background-color') == "transparent",
|
||||
"The element should have transparent background.");
|
||||
}
|
||||
|
||||
// Test *[*|green] style rule.
|
||||
function test_5() {
|
||||
testElementBackground("xhtml1");
|
||||
testElementBackground("xhtml2");
|
||||
testElementBackground("foo1");
|
||||
test_6();
|
||||
}
|
||||
|
||||
// Test #xhtml3, #foo2 style rule.
|
||||
function test_6() {
|
||||
var el = document.getElementById("xhtml3");
|
||||
ok(document.defaultView.getComputedStyle(el, null).
|
||||
getPropertyValue('background-color') == "rgb(0, 255, 0)",
|
||||
"The background of the element should be green.");
|
||||
|
||||
el = document.getElementById("foo2");
|
||||
ok(document.defaultView.getComputedStyle(el, null).
|
||||
getPropertyValue('background-color') == "rgb(0, 255, 0)",
|
||||
"The background of the element should be green.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(test_1);
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
Загрузка…
Ссылка в новой задаче