1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Copyright (C) 2012 Samsung Electronics. 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
23 #include "config.h"
24 #include "core/html/forms/ImageInputType.h"
25
26 #include "core/HTMLNames.h"
27 #include "core/InputTypeNames.h"
28 #include "core/events/MouseEvent.h"
29 #include "core/fetch/ImageResource.h"
30 #include "core/html/FormDataList.h"
31 #include "core/html/HTMLFormElement.h"
32 #include "core/html/HTMLImageLoader.h"
33 #include "core/html/HTMLInputElement.h"
34 #include "core/html/parser/HTMLParserIdioms.h"
35 #include "core/rendering/RenderImage.h"
36 #include "wtf/PassOwnPtr.h"
37 #include "wtf/text/StringBuilder.h"
38
39 namespace WebCore {
40
41 using namespace HTMLNames;
42
ImageInputType(HTMLInputElement & element)43 inline ImageInputType::ImageInputType(HTMLInputElement& element)
44 : BaseButtonInputType(element)
45 {
46 }
47
create(HTMLInputElement & element)48 PassRefPtrWillBeRawPtr<InputType> ImageInputType::create(HTMLInputElement& element)
49 {
50 return adoptRefWillBeNoop(new ImageInputType(element));
51 }
52
formControlType() const53 const AtomicString& ImageInputType::formControlType() const
54 {
55 return InputTypeNames::image;
56 }
57
isFormDataAppendable() const58 bool ImageInputType::isFormDataAppendable() const
59 {
60 return true;
61 }
62
appendFormData(FormDataList & encoding,bool) const63 bool ImageInputType::appendFormData(FormDataList& encoding, bool) const
64 {
65 if (!element().isActivatedSubmit())
66 return false;
67 const AtomicString& name = element().name();
68 if (name.isEmpty()) {
69 encoding.appendData("x", m_clickLocation.x());
70 encoding.appendData("y", m_clickLocation.y());
71 return true;
72 }
73
74 DEFINE_STATIC_LOCAL(String, dotXString, (".x"));
75 DEFINE_STATIC_LOCAL(String, dotYString, (".y"));
76 encoding.appendData(name + dotXString, m_clickLocation.x());
77 encoding.appendData(name + dotYString, m_clickLocation.y());
78
79 if (!element().value().isEmpty())
80 encoding.appendData(name, element().value());
81 return true;
82 }
83
resultForDialogSubmit() const84 String ImageInputType::resultForDialogSubmit() const
85 {
86 StringBuilder result;
87 result.appendNumber(m_clickLocation.x());
88 result.append(",");
89 result.appendNumber(m_clickLocation.y());
90 return result.toString();
91 }
92
supportsValidation() const93 bool ImageInputType::supportsValidation() const
94 {
95 return false;
96 }
97
extractClickLocation(Event * event)98 static IntPoint extractClickLocation(Event* event)
99 {
100 if (!event->underlyingEvent() || !event->underlyingEvent()->isMouseEvent())
101 return IntPoint();
102 MouseEvent* mouseEvent = toMouseEvent(event->underlyingEvent());
103 if (mouseEvent->isSimulated())
104 return IntPoint();
105 return IntPoint(mouseEvent->offsetX(), mouseEvent->offsetY());
106 }
107
handleDOMActivateEvent(Event * event)108 void ImageInputType::handleDOMActivateEvent(Event* event)
109 {
110 RefPtrWillBeRawPtr<HTMLInputElement> element(this->element());
111 if (element->isDisabledFormControl() || !element->form())
112 return;
113 element->setActivatedSubmit(true);
114 m_clickLocation = extractClickLocation(event);
115 element->form()->prepareForSubmission(event); // Event handlers can run.
116 element->setActivatedSubmit(false);
117 event->setDefaultHandled();
118 }
119
createRenderer(RenderStyle *) const120 RenderObject* ImageInputType::createRenderer(RenderStyle*) const
121 {
122 RenderImage* image = new RenderImage(&element());
123 image->setImageResource(RenderImageResource::create());
124 return image;
125 }
126
altAttributeChanged()127 void ImageInputType::altAttributeChanged()
128 {
129 RenderImage* image = toRenderImage(element().renderer());
130 if (!image)
131 return;
132 image->updateAltText();
133 }
134
srcAttributeChanged()135 void ImageInputType::srcAttributeChanged()
136 {
137 if (!element().renderer())
138 return;
139 element().imageLoader()->updateFromElementIgnoringPreviousError();
140 }
141
startResourceLoading()142 void ImageInputType::startResourceLoading()
143 {
144 BaseButtonInputType::startResourceLoading();
145
146 HTMLImageLoader* imageLoader = element().imageLoader();
147 imageLoader->updateFromElement();
148
149 RenderImage* renderer = toRenderImage(element().renderer());
150 if (!renderer)
151 return;
152
153 RenderImageResource* imageResource = renderer->imageResource();
154 imageResource->setImageResource(imageLoader->image());
155
156 // If we have no image at all because we have no src attribute, set
157 // image height and width for the alt text instead.
158 if (!imageLoader->image() && !imageResource->cachedImage())
159 renderer->setImageSizeForAltText();
160 }
161
shouldRespectAlignAttribute()162 bool ImageInputType::shouldRespectAlignAttribute()
163 {
164 return true;
165 }
166
canBeSuccessfulSubmitButton()167 bool ImageInputType::canBeSuccessfulSubmitButton()
168 {
169 return true;
170 }
171
isImageButton() const172 bool ImageInputType::isImageButton() const
173 {
174 return true;
175 }
176
isEnumeratable()177 bool ImageInputType::isEnumeratable()
178 {
179 return false;
180 }
181
shouldRespectHeightAndWidthAttributes()182 bool ImageInputType::shouldRespectHeightAndWidthAttributes()
183 {
184 return true;
185 }
186
height() const187 unsigned ImageInputType::height() const
188 {
189 RefPtrWillBeRawPtr<HTMLInputElement> element(this->element());
190
191 if (!element->renderer()) {
192 // Check the attribute first for an explicit pixel value.
193 unsigned height;
194 if (parseHTMLNonNegativeInteger(element->fastGetAttribute(heightAttr), height))
195 return height;
196
197 // If the image is available, use its height.
198 if (element->hasImageLoader()) {
199 HTMLImageLoader* imageLoader = element->imageLoader();
200 if (imageLoader->image())
201 return imageLoader->image()->imageSizeForRenderer(element->renderer(), 1).height();
202 }
203 }
204
205 element->document().updateLayout();
206
207 RenderBox* box = element->renderBox();
208 return box ? adjustForAbsoluteZoom(box->contentHeight(), box) : 0;
209 }
210
width() const211 unsigned ImageInputType::width() const
212 {
213 RefPtrWillBeRawPtr<HTMLInputElement> element(this->element());
214
215 if (!element->renderer()) {
216 // Check the attribute first for an explicit pixel value.
217 unsigned width;
218 if (parseHTMLNonNegativeInteger(element->fastGetAttribute(widthAttr), width))
219 return width;
220
221 // If the image is available, use its width.
222 if (element->hasImageLoader()) {
223 HTMLImageLoader* imageLoader = element->imageLoader();
224 if (imageLoader->image())
225 return imageLoader->image()->imageSizeForRenderer(element->renderer(), 1).width();
226 }
227 }
228
229 element->document().updateLayout();
230
231 RenderBox* box = element->renderBox();
232 return box ? adjustForAbsoluteZoom(box->contentWidth(), box) : 0;
233 }
234
hasLegalLinkAttribute(const QualifiedName & name) const235 bool ImageInputType::hasLegalLinkAttribute(const QualifiedName& name) const
236 {
237 return name == srcAttr || BaseButtonInputType::hasLegalLinkAttribute(name);
238 }
239
subResourceAttributeName() const240 const QualifiedName& ImageInputType::subResourceAttributeName() const
241 {
242 return srcAttr;
243 }
244
245 } // namespace WebCore
246