2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Simon Hausmann (hausmann@kde.org)
5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * Copyright (C) 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
25 #include "HTMLBodyElement.h"
27 #include "CSSStyleSelector.h"
28 #include "CSSStyleSheet.h"
29 #include "CSSValueKeywords.h"
30 #include "EventNames.h"
32 #include "FrameView.h"
33 #include "HTMLFrameElementBase.h"
34 #include "HTMLNames.h"
35 #include "MappedAttribute.h"
36 #include "ScriptEventListener.h"
40 using namespace HTMLNames
;
42 HTMLBodyElement::HTMLBodyElement(const QualifiedName
& tagName
, Document
* document
)
43 : HTMLElement(tagName
, document
)
45 ASSERT(hasTagName(bodyTag
));
48 HTMLBodyElement::~HTMLBodyElement()
51 m_linkDecl
->setNode(0);
52 m_linkDecl
->setParent(0);
56 void HTMLBodyElement::createLinkDecl()
58 m_linkDecl
= CSSMutableStyleDeclaration::create();
59 m_linkDecl
->setParent(document()->elementSheet());
60 m_linkDecl
->setNode(this);
61 m_linkDecl
->setStrictParsing(!document()->inCompatMode());
64 bool HTMLBodyElement::mapToEntry(const QualifiedName
& attrName
, MappedAttributeEntry
& result
) const
66 if (attrName
== backgroundAttr
) {
67 result
= (MappedAttributeEntry
)(eLastEntry
+ document()->docID());
71 if (attrName
== bgcolorAttr
||
72 attrName
== textAttr
||
73 attrName
== marginwidthAttr
||
74 attrName
== leftmarginAttr
||
75 attrName
== marginheightAttr
||
76 attrName
== topmarginAttr
||
77 attrName
== bgpropertiesAttr
) {
82 return HTMLElement::mapToEntry(attrName
, result
);
85 void HTMLBodyElement::parseMappedAttribute(MappedAttribute
*attr
)
87 if (attr
->name() == backgroundAttr
) {
88 String url
= deprecatedParseURL(attr
->value());
90 addCSSImageProperty(attr
, CSSPropertyBackgroundImage
, document()->completeURL(url
).string());
91 } else if (attr
->name() == marginwidthAttr
|| attr
->name() == leftmarginAttr
) {
92 addCSSLength(attr
, CSSPropertyMarginRight
, attr
->value());
93 addCSSLength(attr
, CSSPropertyMarginLeft
, attr
->value());
94 } else if (attr
->name() == marginheightAttr
|| attr
->name() == topmarginAttr
) {
95 addCSSLength(attr
, CSSPropertyMarginBottom
, attr
->value());
96 addCSSLength(attr
, CSSPropertyMarginTop
, attr
->value());
97 } else if (attr
->name() == bgcolorAttr
) {
98 addCSSColor(attr
, CSSPropertyBackgroundColor
, attr
->value());
99 } else if (attr
->name() == textAttr
) {
100 addCSSColor(attr
, CSSPropertyColor
, attr
->value());
101 } else if (attr
->name() == bgpropertiesAttr
) {
102 if (equalIgnoringCase(attr
->value(), "fixed"))
103 addCSSProperty(attr
, CSSPropertyBackgroundAttachment
, CSSValueFixed
);
104 } else if (attr
->name() == vlinkAttr
||
105 attr
->name() == alinkAttr
||
106 attr
->name() == linkAttr
) {
107 if (attr
->isNull()) {
108 if (attr
->name() == linkAttr
)
109 document()->resetLinkColor();
110 else if (attr
->name() == vlinkAttr
)
111 document()->resetVisitedLinkColor();
113 document()->resetActiveLinkColor();
117 m_linkDecl
->setProperty(CSSPropertyColor
, attr
->value(), false, false);
118 RefPtr
<CSSValue
> val
= m_linkDecl
->getPropertyCSSValue(CSSPropertyColor
);
119 if (val
&& val
->isPrimitiveValue()) {
120 Color col
= document()->styleSelector()->getColorFromPrimitiveValue(static_cast<CSSPrimitiveValue
*>(val
.get()));
121 if (attr
->name() == linkAttr
)
122 document()->setLinkColor(col
);
123 else if (attr
->name() == vlinkAttr
)
124 document()->setVisitedLinkColor(col
);
126 document()->setActiveLinkColor(col
);
131 document()->recalcStyle(Force
);
132 } else if (attr
->name() == onloadAttr
)
133 document()->setWindowAttributeEventListener(eventNames().loadEvent
, createAttributeEventListener(document()->frame(), attr
));
134 else if (attr
->name() == onbeforeunloadAttr
)
135 document()->setWindowAttributeEventListener(eventNames().beforeunloadEvent
, createAttributeEventListener(document()->frame(), attr
));
136 else if (attr
->name() == onunloadAttr
)
137 document()->setWindowAttributeEventListener(eventNames().unloadEvent
, createAttributeEventListener(document()->frame(), attr
));
138 else if (attr
->name() == onpagehideAttr
)
139 document()->setWindowAttributeEventListener(eventNames().pagehideEvent
, createAttributeEventListener(document()->frame(), attr
));
140 else if (attr
->name() == onpageshowAttr
)
141 document()->setWindowAttributeEventListener(eventNames().pageshowEvent
, createAttributeEventListener(document()->frame(), attr
));
142 else if (attr
->name() == onpopstateAttr
)
143 document()->setWindowAttributeEventListener(eventNames().popstateEvent
, createAttributeEventListener(document()->frame(), attr
));
144 else if (attr
->name() == onblurAttr
)
145 document()->setWindowAttributeEventListener(eventNames().blurEvent
, createAttributeEventListener(document()->frame(), attr
));
146 else if (attr
->name() == onfocusAttr
)
147 document()->setWindowAttributeEventListener(eventNames().focusEvent
, createAttributeEventListener(document()->frame(), attr
));
148 #if ENABLE(ORIENTATION_EVENTS)
149 else if (attr
->name() == onorientationchangeAttr
)
150 document()->setWindowAttributeEventListener(eventNames().orientationchangeEvent
, createAttributeEventListener(document()->frame(), attr
));
152 else if (attr
->name() == onhashchangeAttr
)
153 document()->setWindowAttributeEventListener(eventNames().hashchangeEvent
, createAttributeEventListener(document()->frame(), attr
));
154 else if (attr
->name() == onresizeAttr
)
155 document()->setWindowAttributeEventListener(eventNames().resizeEvent
, createAttributeEventListener(document()->frame(), attr
));
156 else if (attr
->name() == onscrollAttr
)
157 document()->setWindowAttributeEventListener(eventNames().scrollEvent
, createAttributeEventListener(document()->frame(), attr
));
158 else if (attr
->name() == onstorageAttr
)
159 document()->setWindowAttributeEventListener(eventNames().storageEvent
, createAttributeEventListener(document()->frame(), attr
));
160 else if (attr
->name() == ononlineAttr
)
161 document()->setWindowAttributeEventListener(eventNames().onlineEvent
, createAttributeEventListener(document()->frame(), attr
));
162 else if (attr
->name() == onofflineAttr
)
163 document()->setWindowAttributeEventListener(eventNames().offlineEvent
, createAttributeEventListener(document()->frame(), attr
));
165 HTMLElement::parseMappedAttribute(attr
);
168 void HTMLBodyElement::insertedIntoDocument()
170 HTMLElement::insertedIntoDocument();
172 // FIXME: Perhaps this code should be in attach() instead of here.
173 Element
* ownerElement
= document()->ownerElement();
174 if (ownerElement
&& (ownerElement
->hasTagName(frameTag
) || ownerElement
->hasTagName(iframeTag
))) {
175 HTMLFrameElementBase
* ownerFrameElement
= static_cast<HTMLFrameElementBase
*>(ownerElement
);
176 int marginWidth
= ownerFrameElement
->getMarginWidth();
177 if (marginWidth
!= -1)
178 setAttribute(marginwidthAttr
, String::number(marginWidth
));
179 int marginHeight
= ownerFrameElement
->getMarginHeight();
180 if (marginHeight
!= -1)
181 setAttribute(marginheightAttr
, String::number(marginHeight
));
184 // FIXME: This call to scheduleRelayout should not be needed here.
185 // But without it we hang during WebKit tests; need to fix that and remove this.
186 if (FrameView
* view
= document()->view())
187 view
->scheduleRelayout();
190 bool HTMLBodyElement::isURLAttribute(Attribute
*attr
) const
192 return attr
->name() == backgroundAttr
;
195 String
HTMLBodyElement::aLink() const
197 return getAttribute(alinkAttr
);
200 void HTMLBodyElement::setALink(const String
& value
)
202 setAttribute(alinkAttr
, value
);
205 String
HTMLBodyElement::bgColor() const
207 return getAttribute(bgcolorAttr
);
210 void HTMLBodyElement::setBgColor(const String
& value
)
212 setAttribute(bgcolorAttr
, value
);
215 String
HTMLBodyElement::link() const
217 return getAttribute(linkAttr
);
220 void HTMLBodyElement::setLink(const String
& value
)
222 setAttribute(linkAttr
, value
);
225 String
HTMLBodyElement::text() const
227 return getAttribute(textAttr
);
230 void HTMLBodyElement::setText(const String
& value
)
232 setAttribute(textAttr
, value
);
235 String
HTMLBodyElement::vLink() const
237 return getAttribute(vlinkAttr
);
240 void HTMLBodyElement::setVLink(const String
& value
)
242 setAttribute(vlinkAttr
, value
);
245 static int adjustForZoom(int value
, FrameView
* frameView
)
247 float zoomFactor
= frameView
->frame()->zoomFactor();
250 // Needed because of truncation (rather than rounding) when scaling up.
253 return static_cast<int>(value
/ zoomFactor
);
256 int HTMLBodyElement::scrollLeft() const
258 // Update the document's layout.
259 Document
* doc
= document();
260 doc
->updateLayoutIgnorePendingStylesheets();
261 FrameView
* view
= doc
->view();
262 return view
? adjustForZoom(view
->scrollX(), view
) : 0;
265 void HTMLBodyElement::setScrollLeft(int scrollLeft
)
267 FrameView
* sview
= ownerDocument()->view();
269 // Update the document's layout
270 document()->updateLayoutIgnorePendingStylesheets();
271 sview
->setScrollPosition(IntPoint(static_cast<int>(scrollLeft
* sview
->frame()->zoomFactor()), sview
->scrollY()));
275 int HTMLBodyElement::scrollTop() const
277 // Update the document's layout.
278 Document
* doc
= document();
279 doc
->updateLayoutIgnorePendingStylesheets();
280 FrameView
* view
= doc
->view();
281 return view
? adjustForZoom(view
->scrollY(), view
) : 0;
284 void HTMLBodyElement::setScrollTop(int scrollTop
)
286 FrameView
* sview
= ownerDocument()->view();
288 // Update the document's layout
289 document()->updateLayoutIgnorePendingStylesheets();
290 sview
->setScrollPosition(IntPoint(sview
->scrollX(), static_cast<int>(scrollTop
* sview
->frame()->zoomFactor())));
294 int HTMLBodyElement::scrollHeight() const
296 // Update the document's layout.
297 Document
* doc
= document();
298 doc
->updateLayoutIgnorePendingStylesheets();
299 FrameView
* view
= doc
->view();
300 return view
? adjustForZoom(view
->contentsHeight(), view
) : 0;
303 int HTMLBodyElement::scrollWidth() const
305 // Update the document's layout.
306 Document
* doc
= document();
307 doc
->updateLayoutIgnorePendingStylesheets();
308 FrameView
* view
= doc
->view();
309 return view
? adjustForZoom(view
->contentsWidth(), view
) : 0;
312 void HTMLBodyElement::addSubresourceAttributeURLs(ListHashSet
<KURL
>& urls
) const
314 HTMLElement::addSubresourceAttributeURLs(urls
);
316 addSubresourceURL(urls
, document()->completeURL(getAttribute(backgroundAttr
)));
319 void HTMLBodyElement::didMoveToNewOwnerDocument()
321 // When moving body elements between documents, we should have to reset the parent sheet for any
322 // link style declarations. If we don't we might crash later.
323 // In practice I can't reproduce this theoretical problem.
324 // webarchive/adopt-attribute-styled-body-webarchive.html tries to make sure this crash won't surface.
326 m_linkDecl
->setParent(document()->elementSheet());
328 HTMLElement::didMoveToNewOwnerDocument();
331 } // namespace WebCore