1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22#include "config.h"
23#include "HTMLMapElement.h"
24
25#include "Attribute.h"
26#include "Document.h"
27#include "ElementIterator.h"
28#include "GenericCachedHTMLCollection.h"
29#include "HTMLAreaElement.h"
30#include "HTMLImageElement.h"
31#include "HitTestResult.h"
32#include "IntSize.h"
33#include "NodeRareData.h"
34#include <wtf/IsoMallocInlines.h>
35
36namespace WebCore {
37
38WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLMapElement);
39
40using namespace HTMLNames;
41
42HTMLMapElement::HTMLMapElement(const QualifiedName& tagName, Document& document)
43 : HTMLElement(tagName, document)
44{
45 ASSERT(hasTagName(mapTag));
46}
47
48Ref<HTMLMapElement> HTMLMapElement::create(Document& document)
49{
50 return adoptRef(*new HTMLMapElement(mapTag, document));
51}
52
53Ref<HTMLMapElement> HTMLMapElement::create(const QualifiedName& tagName, Document& document)
54{
55 return adoptRef(*new HTMLMapElement(tagName, document));
56}
57
58HTMLMapElement::~HTMLMapElement() = default;
59
60bool HTMLMapElement::mapMouseEvent(LayoutPoint location, const LayoutSize& size, HitTestResult& result)
61{
62 RefPtr<HTMLAreaElement> defaultArea;
63
64 for (auto& area : descendantsOfType<HTMLAreaElement>(*this)) {
65 if (area.isDefault()) {
66 if (!defaultArea)
67 defaultArea = &area;
68 } else if (area.mapMouseEvent(location, size, result))
69 return true;
70 }
71
72 if (defaultArea) {
73 result.setInnerNode(defaultArea.get());
74 result.setURLElement(defaultArea.get());
75 }
76 return defaultArea;
77}
78
79HTMLImageElement* HTMLMapElement::imageElement()
80{
81 if (m_name.isEmpty())
82 return nullptr;
83 return treeScope().imageElementByUsemap(*m_name.impl());
84}
85
86void HTMLMapElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
87{
88 // FIXME: This logic seems wrong for XML documents.
89 // Either the id or name will be used depending on the order the attributes are parsed.
90
91 if (name == HTMLNames::idAttr || name == HTMLNames::nameAttr) {
92 if (name == HTMLNames::idAttr) {
93 // Call base class so that hasID bit gets set.
94 HTMLElement::parseAttribute(name, value);
95 if (document().isHTMLDocument())
96 return;
97 }
98 if (isConnected())
99 treeScope().removeImageMap(*this);
100 String mapName = value;
101 if (mapName[0] == '#')
102 mapName = mapName.substring(1);
103 m_name = mapName;
104 if (isConnected())
105 treeScope().addImageMap(*this);
106
107 return;
108 }
109
110 HTMLElement::parseAttribute(name, value);
111}
112
113Ref<HTMLCollection> HTMLMapElement::areas()
114{
115 return ensureRareData().ensureNodeLists().addCachedCollection<GenericCachedHTMLCollection<CollectionTypeTraits<MapAreas>::traversalType>>(*this, MapAreas);
116}
117
118Node::InsertedIntoAncestorResult HTMLMapElement::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree)
119{
120 Node::InsertedIntoAncestorResult request = HTMLElement::insertedIntoAncestor(insertionType, parentOfInsertedTree);
121 if (insertionType.treeScopeChanged)
122 treeScope().addImageMap(*this);
123 return request;
124}
125
126void HTMLMapElement::removedFromAncestor(RemovalType removalType, ContainerNode& oldParentOfRemovedTree)
127{
128 if (removalType.treeScopeChanged)
129 oldParentOfRemovedTree.treeScope().removeImageMap(*this);
130 HTMLElement::removedFromAncestor(removalType, oldParentOfRemovedTree);
131}
132
133}
134