diff options
Diffstat (limited to 'dom/html/HTMLAreaElement.cpp')
-rw-r--r-- | dom/html/HTMLAreaElement.cpp | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/dom/html/HTMLAreaElement.cpp b/dom/html/HTMLAreaElement.cpp new file mode 100644 index 000000000..098081b8b --- /dev/null +++ b/dom/html/HTMLAreaElement.cpp @@ -0,0 +1,263 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/HTMLAreaElement.h" + +#include "mozilla/Attributes.h" +#include "mozilla/dom/HTMLAnchorElement.h" +#include "mozilla/dom/HTMLAreaElementBinding.h" +#include "mozilla/EventDispatcher.h" +#include "mozilla/EventStates.h" +#include "mozilla/MemoryReporting.h" + +NS_IMPL_NS_NEW_HTML_ELEMENT(Area) + +namespace mozilla { +namespace dom { + +HTMLAreaElement::HTMLAreaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) + : nsGenericHTMLElement(aNodeInfo) + , Link(this) +{ +} + +HTMLAreaElement::~HTMLAreaElement() +{ +} + +NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLAreaElement) + NS_INTERFACE_TABLE_INHERITED(HTMLAreaElement, + nsIDOMHTMLAreaElement, + Link) +NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLElement) + +NS_IMPL_ADDREF_INHERITED(HTMLAreaElement, Element) +NS_IMPL_RELEASE_INHERITED(HTMLAreaElement, Element) + +NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLAreaElement) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLAreaElement, + nsGenericHTMLElement) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRelList) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLAreaElement, + nsGenericHTMLElement) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mRelList) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_ELEMENT_CLONE(HTMLAreaElement) + + +NS_IMPL_STRING_ATTR(HTMLAreaElement, Alt, alt) +NS_IMPL_STRING_ATTR(HTMLAreaElement, Coords, coords) +NS_IMPL_URI_ATTR(HTMLAreaElement, Href, href) +NS_IMPL_BOOL_ATTR(HTMLAreaElement, NoHref, nohref) +NS_IMPL_STRING_ATTR(HTMLAreaElement, Shape, shape) +NS_IMPL_STRING_ATTR(HTMLAreaElement, Download, download) + +int32_t +HTMLAreaElement::TabIndexDefault() +{ + return 0; +} + +NS_IMETHODIMP +HTMLAreaElement::GetTarget(nsAString& aValue) +{ + if (!GetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue)) { + GetBaseTarget(aValue); + } + return NS_OK; +} + +NS_IMETHODIMP +HTMLAreaElement::SetTarget(const nsAString& aValue) +{ + return SetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue, true); +} + +nsresult +HTMLAreaElement::PreHandleEvent(EventChainPreVisitor& aVisitor) +{ + return PreHandleEventForAnchors(aVisitor); +} + +nsresult +HTMLAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor) +{ + return PostHandleEventForAnchors(aVisitor); +} + +bool +HTMLAreaElement::IsLink(nsIURI** aURI) const +{ + return IsHTMLLink(aURI); +} + +void +HTMLAreaElement::GetLinkTarget(nsAString& aTarget) +{ + GetAttr(kNameSpaceID_None, nsGkAtoms::target, aTarget); + if (aTarget.IsEmpty()) { + GetBaseTarget(aTarget); + } +} + +nsDOMTokenList* +HTMLAreaElement::RelList() +{ + if (!mRelList) { + mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, + HTMLAnchorElement::sSupportedRelValues); + } + return mRelList; +} + +nsresult +HTMLAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, + nsIContent* aBindingParent, + bool aCompileEventHandlers) +{ + Link::ResetLinkState(false, Link::ElementHasHref()); + nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent, + aBindingParent, + aCompileEventHandlers); + NS_ENSURE_SUCCESS(rv, rv); + + nsIDocument* doc = GetComposedDoc(); + if (doc) { + doc->RegisterPendingLinkUpdate(this); + } + return rv; +} + +void +HTMLAreaElement::UnbindFromTree(bool aDeep, bool aNullParent) +{ + // If this link is ever reinserted into a document, it might + // be under a different xml:base, so forget the cached state now. + Link::ResetLinkState(false, Link::ElementHasHref()); + + // Note, we need to use OwnerDoc() here, since GetComposedDoc() might + // return null. + nsIDocument* doc = OwnerDoc(); + if (doc) { + doc->UnregisterPendingLinkUpdate(this); + } + + nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); +} + +nsresult +HTMLAreaElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + bool aNotify) +{ + nsresult rv = + nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, aNotify); + + // The ordering of the parent class's SetAttr call and Link::ResetLinkState + // is important here! The attribute is not set until SetAttr returns, and + // we will need the updated attribute value because notifying the document + // that content states have changed will call IntrinsicState, which will try + // to get updated information about the visitedness from Link. + if (aName == nsGkAtoms::href && aNameSpaceID == kNameSpaceID_None) { + Link::ResetLinkState(!!aNotify, true); + } + + return rv; +} + +nsresult +HTMLAreaElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, + bool aNotify) +{ + nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, + aNotify); + + // The ordering of the parent class's UnsetAttr call and Link::ResetLinkState + // is important here! The attribute is not unset until UnsetAttr returns, and + // we will need the updated attribute value because notifying the document + // that content states have changed will call IntrinsicState, which will try + // to get updated information about the visitedness from Link. + if (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) { + Link::ResetLinkState(!!aNotify, false); + } + + return rv; +} + +#define IMPL_URI_PART(_part) \ + NS_IMETHODIMP \ + HTMLAreaElement::Get##_part(nsAString& a##_part) \ + { \ + Link::Get##_part(a##_part); \ + return NS_OK; \ + } \ + NS_IMETHODIMP \ + HTMLAreaElement::Set##_part(const nsAString& a##_part) \ + { \ + Link::Set##_part(a##_part); \ + return NS_OK; \ + } + +IMPL_URI_PART(Protocol) +IMPL_URI_PART(Host) +IMPL_URI_PART(Hostname) +IMPL_URI_PART(Pathname) +IMPL_URI_PART(Search) +IMPL_URI_PART(Port) +IMPL_URI_PART(Hash) + +#undef IMPL_URI_PART + +NS_IMETHODIMP +HTMLAreaElement::ToString(nsAString& aSource) +{ + return GetHref(aSource); +} + +NS_IMETHODIMP +HTMLAreaElement::GetPing(nsAString& aValue) +{ + GetAttr(kNameSpaceID_None, nsGkAtoms::ping, aValue); + return NS_OK; +} + +NS_IMETHODIMP +HTMLAreaElement::SetPing(const nsAString& aValue) +{ + return SetAttr(kNameSpaceID_None, nsGkAtoms::ping, aValue, true); +} + +already_AddRefed<nsIURI> +HTMLAreaElement::GetHrefURI() const +{ + return GetHrefURIForAnchors(); +} + +EventStates +HTMLAreaElement::IntrinsicState() const +{ + return Link::LinkState() | nsGenericHTMLElement::IntrinsicState(); +} + +size_t +HTMLAreaElement::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const +{ + return nsGenericHTMLElement::SizeOfExcludingThis(aMallocSizeOf) + + Link::SizeOfExcludingThis(aMallocSizeOf); +} + +JSObject* +HTMLAreaElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) +{ + return HTMLAreaElementBinding::Wrap(aCx, this, aGivenProto); +} + +} // namespace dom +} // namespace mozilla |