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 blink { 40 41 using namespace HTMLNames; 42 43 inline ImageInputType::ImageInputType(HTMLInputElement& element) 44 : BaseButtonInputType(element) 45 { 46 } 47 48 PassRefPtrWillBeRawPtr<InputType> ImageInputType::create(HTMLInputElement& element) 49 { 50 return adoptRefWillBeNoop(new ImageInputType(element)); 51 } 52 53 const AtomicString& ImageInputType::formControlType() const 54 { 55 return InputTypeNames::image; 56 } 57 58 bool ImageInputType::isFormDataAppendable() const 59 { 60 return true; 61 } 62 63 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 84 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 93 bool ImageInputType::supportsValidation() const 94 { 95 return false; 96 } 97 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 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 120 RenderObject* ImageInputType::createRenderer(RenderStyle*) const 121 { 122 RenderImage* image = new RenderImage(&element()); 123 image->setImageResource(RenderImageResource::create()); 124 return image; 125 } 126 127 void ImageInputType::altAttributeChanged() 128 { 129 RenderImage* image = toRenderImage(element().renderer()); 130 if (!image) 131 return; 132 image->updateAltText(); 133 } 134 135 void ImageInputType::srcAttributeChanged() 136 { 137 if (!element().renderer()) 138 return; 139 element().imageLoader()->updateFromElement(ImageLoader::UpdateIgnorePreviousError); 140 } 141 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 162 bool ImageInputType::shouldRespectAlignAttribute() 163 { 164 return true; 165 } 166 167 bool ImageInputType::canBeSuccessfulSubmitButton() 168 { 169 return true; 170 } 171 172 bool ImageInputType::isEnumeratable() 173 { 174 return false; 175 } 176 177 bool ImageInputType::shouldRespectHeightAndWidthAttributes() 178 { 179 return true; 180 } 181 182 unsigned ImageInputType::height() const 183 { 184 RefPtrWillBeRawPtr<HTMLInputElement> element(this->element()); 185 186 if (!element->renderer()) { 187 // Check the attribute first for an explicit pixel value. 188 unsigned height; 189 if (parseHTMLNonNegativeInteger(element->fastGetAttribute(heightAttr), height)) 190 return height; 191 192 // If the image is available, use its height. 193 if (element->hasImageLoader()) { 194 HTMLImageLoader* imageLoader = element->imageLoader(); 195 if (imageLoader->image()) 196 return imageLoader->image()->imageSizeForRenderer(element->renderer(), 1).height(); 197 } 198 } 199 200 element->document().updateLayout(); 201 202 RenderBox* box = element->renderBox(); 203 return box ? adjustForAbsoluteZoom(box->contentHeight(), box) : 0; 204 } 205 206 unsigned ImageInputType::width() const 207 { 208 RefPtrWillBeRawPtr<HTMLInputElement> element(this->element()); 209 210 if (!element->renderer()) { 211 // Check the attribute first for an explicit pixel value. 212 unsigned width; 213 if (parseHTMLNonNegativeInteger(element->fastGetAttribute(widthAttr), width)) 214 return width; 215 216 // If the image is available, use its width. 217 if (element->hasImageLoader()) { 218 HTMLImageLoader* imageLoader = element->imageLoader(); 219 if (imageLoader->image()) 220 return imageLoader->image()->imageSizeForRenderer(element->renderer(), 1).width(); 221 } 222 } 223 224 element->document().updateLayout(); 225 226 RenderBox* box = element->renderBox(); 227 return box ? adjustForAbsoluteZoom(box->contentWidth(), box) : 0; 228 } 229 230 bool ImageInputType::hasLegalLinkAttribute(const QualifiedName& name) const 231 { 232 return name == srcAttr || BaseButtonInputType::hasLegalLinkAttribute(name); 233 } 234 235 const QualifiedName& ImageInputType::subResourceAttributeName() const 236 { 237 return srcAttr; 238 } 239 240 } // namespace blink 241