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, 2010 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 "Attribute.h"
28 #include "CSSParser.h"
29 #include "CSSValueKeywords.h"
30 #include "EventNames.h"
32 #include "FrameView.h"
33 #include "HTMLFrameElementBase.h"
34 #include "HTMLNames.h"
35 #include "HTMLParserIdioms.h"
37 #include "ScriptEventListener.h"
41 using namespace HTMLNames;
43 HTMLBodyElement::HTMLBodyElement(const QualifiedName& tagName, Document* document)
44 : HTMLElement(tagName, document)
46 ASSERT(hasTagName(bodyTag));
49 PassRefPtr<HTMLBodyElement> HTMLBodyElement::create(Document* document)
51 return adoptRef(new HTMLBodyElement(bodyTag, document));
54 PassRefPtr<HTMLBodyElement> HTMLBodyElement::create(const QualifiedName& tagName, Document* document)
56 return adoptRef(new HTMLBodyElement(tagName, document));
59 HTMLBodyElement::~HTMLBodyElement()
63 bool HTMLBodyElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
65 if (attrName == backgroundAttr) {
66 result = (MappedAttributeEntry)(eLastEntry + document()->docID());
70 if (attrName == bgcolorAttr ||
71 attrName == textAttr ||
72 attrName == marginwidthAttr ||
73 attrName == leftmarginAttr ||
74 attrName == marginheightAttr ||
75 attrName == topmarginAttr ||
76 attrName == bgpropertiesAttr) {
81 return HTMLElement::mapToEntry(attrName, result);
84 void HTMLBodyElement::parseMappedAttribute(Attribute* attr)
86 if (attr->name() == backgroundAttr) {
87 String url = stripLeadingAndTrailingHTMLSpaces(attr->value());
89 addCSSImageProperty(attr, CSSPropertyBackgroundImage, document()->completeURL(url).string());
90 } else if (attr->name() == marginwidthAttr || attr->name() == leftmarginAttr) {
91 addCSSLength(attr, CSSPropertyMarginRight, attr->value());
92 addCSSLength(attr, CSSPropertyMarginLeft, attr->value());
93 } else if (attr->name() == marginheightAttr || attr->name() == topmarginAttr) {
94 addCSSLength(attr, CSSPropertyMarginBottom, attr->value());
95 addCSSLength(attr, CSSPropertyMarginTop, attr->value());
96 } else if (attr->name() == bgcolorAttr) {
97 addCSSColor(attr, CSSPropertyBackgroundColor, attr->value());
98 } else if (attr->name() == textAttr) {
99 addCSSColor(attr, CSSPropertyColor, attr->value());
100 } else if (attr->name() == bgpropertiesAttr) {
101 if (equalIgnoringCase(attr->value(), "fixed"))
102 addCSSProperty(attr, CSSPropertyBackgroundAttachment, CSSValueFixed);
103 } else if (attr->name() == vlinkAttr ||
104 attr->name() == alinkAttr ||
105 attr->name() == linkAttr) {
106 if (attr->isNull()) {
107 if (attr->name() == linkAttr)
108 document()->resetLinkColor();
109 else if (attr->name() == vlinkAttr)
110 document()->resetVisitedLinkColor();
112 document()->resetActiveLinkColor();
115 if (CSSParser::parseColor(color, attr->value(), !document()->inQuirksMode())) {
116 if (attr->name() == linkAttr)
117 document()->setLinkColor(color);
118 else if (attr->name() == vlinkAttr)
119 document()->setVisitedLinkColor(color);
121 document()->setActiveLinkColor(color);
126 document()->recalcStyle(Force);
127 } else if (attr->name() == onloadAttr)
128 document()->setWindowAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(document()->frame(), attr));
129 else if (attr->name() == onbeforeunloadAttr)
130 document()->setWindowAttributeEventListener(eventNames().beforeunloadEvent, createAttributeEventListener(document()->frame(), attr));
131 else if (attr->name() == onunloadAttr)
132 document()->setWindowAttributeEventListener(eventNames().unloadEvent, createAttributeEventListener(document()->frame(), attr));
133 else if (attr->name() == onpagehideAttr)
134 document()->setWindowAttributeEventListener(eventNames().pagehideEvent, createAttributeEventListener(document()->frame(), attr));
135 else if (attr->name() == onpageshowAttr)
136 document()->setWindowAttributeEventListener(eventNames().pageshowEvent, createAttributeEventListener(document()->frame(), attr));
137 else if (attr->name() == onpopstateAttr)
138 document()->setWindowAttributeEventListener(eventNames().popstateEvent, createAttributeEventListener(document()->frame(), attr));
139 else if (attr->name() == onblurAttr)
140 document()->setWindowAttributeEventListener(eventNames().blurEvent, createAttributeEventListener(document()->frame(), attr));
141 else if (attr->name() == onfocusAttr)
142 document()->setWindowAttributeEventListener(eventNames().focusEvent, createAttributeEventListener(document()->frame(), attr));
143 #if ENABLE(ORIENTATION_EVENTS)
144 else if (attr->name() == onorientationchangeAttr)
145 document()->setWindowAttributeEventListener(eventNames().orientationchangeEvent, createAttributeEventListener(document()->frame(), attr));
147 else if (attr->name() == onhashchangeAttr)
148 document()->setWindowAttributeEventListener(eventNames().hashchangeEvent, createAttributeEventListener(document()->frame(), attr));
149 else if (attr->name() == onresizeAttr)
150 document()->setWindowAttributeEventListener(eventNames().resizeEvent, createAttributeEventListener(document()->frame(), attr));
151 else if (attr->name() == onscrollAttr)
152 document()->setWindowAttributeEventListener(eventNames().scrollEvent, createAttributeEventListener(document()->frame(), attr));
153 else if (attr->name() == onselectionchangeAttr)
154 document()->setAttributeEventListener(eventNames().selectionchangeEvent, createAttributeEventListener(document()->frame(), attr));
155 else if (attr->name() == onstorageAttr)
156 document()->setWindowAttributeEventListener(eventNames().storageEvent, createAttributeEventListener(document()->frame(), attr));
157 else if (attr->name() == ononlineAttr)
158 document()->setWindowAttributeEventListener(eventNames().onlineEvent, createAttributeEventListener(document()->frame(), attr));
159 else if (attr->name() == onofflineAttr)
160 document()->setWindowAttributeEventListener(eventNames().offlineEvent, createAttributeEventListener(document()->frame(), attr));
162 HTMLElement::parseMappedAttribute(attr);
165 void HTMLBodyElement::insertedIntoDocument()
167 HTMLElement::insertedIntoDocument();
169 // FIXME: Perhaps this code should be in attach() instead of here.
170 Element* ownerElement = document()->ownerElement();
171 if (ownerElement && (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))) {
172 HTMLFrameElementBase* ownerFrameElement = static_cast<HTMLFrameElementBase*>(ownerElement);
173 int marginWidth = ownerFrameElement->marginWidth();
174 if (marginWidth != -1)
175 setAttribute(marginwidthAttr, String::number(marginWidth));
176 int marginHeight = ownerFrameElement->marginHeight();
177 if (marginHeight != -1)
178 setAttribute(marginheightAttr, String::number(marginHeight));
181 // FIXME: This call to scheduleRelayout should not be needed here.
182 // But without it we hang during WebKit tests; need to fix that and remove this.
183 if (FrameView* view = document()->view())
184 view->scheduleRelayout();
186 if (document() && document()->page())
187 document()->page()->updateViewportArguments();
190 bool HTMLBodyElement::isURLAttribute(Attribute *attr) const
192 return attr->name() == backgroundAttr || HTMLElement::isURLAttribute(attr);
195 bool HTMLBodyElement::supportsFocus() const
197 return rendererIsEditable() || HTMLElement::supportsFocus();
200 String HTMLBodyElement::aLink() const
202 return getAttribute(alinkAttr);
205 void HTMLBodyElement::setALink(const String& value)
207 setAttribute(alinkAttr, value);
210 String HTMLBodyElement::bgColor() const
212 return getAttribute(bgcolorAttr);
215 void HTMLBodyElement::setBgColor(const String& value)
217 setAttribute(bgcolorAttr, value);
220 String HTMLBodyElement::link() const
222 return getAttribute(linkAttr);
225 void HTMLBodyElement::setLink(const String& value)
227 setAttribute(linkAttr, value);
230 String HTMLBodyElement::text() const
232 return getAttribute(textAttr);
235 void HTMLBodyElement::setText(const String& value)
237 setAttribute(textAttr, value);
240 String HTMLBodyElement::vLink() const
242 return getAttribute(vlinkAttr);
245 void HTMLBodyElement::setVLink(const String& value)
247 setAttribute(vlinkAttr, value);
250 static int adjustForZoom(int value, Document* document)
252 Frame* frame = document->frame();
253 float zoomFactor = frame->pageZoomFactor() * frame->frameScaleFactor();
256 // Needed because of truncation (rather than rounding) when scaling up.
259 return static_cast<int>(value / zoomFactor);
262 int HTMLBodyElement::scrollLeft()
264 // Update the document's layout.
265 Document* document = this->document();
266 document->updateLayoutIgnorePendingStylesheets();
267 FrameView* view = document->view();
268 return view ? adjustForZoom(view->scrollX(), document) : 0;
271 void HTMLBodyElement::setScrollLeft(int scrollLeft)
273 Document* document = this->document();
274 document->updateLayoutIgnorePendingStylesheets();
275 Frame* frame = document->frame();
278 FrameView* view = frame->view();
281 view->setScrollPosition(IntPoint(static_cast<int>(scrollLeft * frame->pageZoomFactor() * frame->frameScaleFactor()), view->scrollY()));
284 int HTMLBodyElement::scrollTop()
286 // Update the document's layout.
287 Document* document = this->document();
288 document->updateLayoutIgnorePendingStylesheets();
289 FrameView* view = document->view();
290 return view ? adjustForZoom(view->scrollY(), document) : 0;
293 void HTMLBodyElement::setScrollTop(int scrollTop)
295 Document* document = this->document();
296 document->updateLayoutIgnorePendingStylesheets();
297 Frame* frame = document->frame();
300 FrameView* view = frame->view();
303 view->setScrollPosition(IntPoint(view->scrollX(), static_cast<int>(scrollTop * frame->pageZoomFactor() * frame->frameScaleFactor())));
306 int HTMLBodyElement::scrollHeight()
308 // Update the document's layout.
309 Document* document = this->document();
310 document->updateLayoutIgnorePendingStylesheets();
311 FrameView* view = document->view();
312 return view ? adjustForZoom(view->contentsHeight(), document) : 0;
315 int HTMLBodyElement::scrollWidth()
317 // Update the document's layout.
318 Document* document = this->document();
319 document->updateLayoutIgnorePendingStylesheets();
320 FrameView* view = document->view();
321 return view ? adjustForZoom(view->contentsWidth(), document) : 0;
324 void HTMLBodyElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
326 HTMLElement::addSubresourceAttributeURLs(urls);
328 addSubresourceURL(urls, document()->completeURL(getAttribute(backgroundAttr)));
331 } // namespace WebCore