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 39namespace blink { 40 41using namespace HTMLNames; 42 43inline ImageInputType::ImageInputType(HTMLInputElement& element) 44 : BaseButtonInputType(element) 45{ 46} 47 48PassRefPtrWillBeRawPtr<InputType> ImageInputType::create(HTMLInputElement& element) 49{ 50 return adoptRefWillBeNoop(new ImageInputType(element)); 51} 52 53const AtomicString& ImageInputType::formControlType() const 54{ 55 return InputTypeNames::image; 56} 57 58bool ImageInputType::isFormDataAppendable() const 59{ 60 return true; 61} 62 63bool 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 84String 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 93bool ImageInputType::supportsValidation() const 94{ 95 return false; 96} 97 98static 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 108void 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 120RenderObject* ImageInputType::createRenderer(RenderStyle*) const 121{ 122 RenderImage* image = new RenderImage(&element()); 123 image->setImageResource(RenderImageResource::create()); 124 return image; 125} 126 127void ImageInputType::altAttributeChanged() 128{ 129 RenderImage* image = toRenderImage(element().renderer()); 130 if (!image) 131 return; 132 image->updateAltText(); 133} 134 135void ImageInputType::srcAttributeChanged() 136{ 137 if (!element().renderer()) 138 return; 139 element().imageLoader()->updateFromElement(ImageLoader::UpdateIgnorePreviousError); 140} 141 142void 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 162bool ImageInputType::shouldRespectAlignAttribute() 163{ 164 return true; 165} 166 167bool ImageInputType::canBeSuccessfulSubmitButton() 168{ 169 return true; 170} 171 172bool ImageInputType::isEnumeratable() 173{ 174 return false; 175} 176 177bool ImageInputType::shouldRespectHeightAndWidthAttributes() 178{ 179 return true; 180} 181 182unsigned 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 206unsigned 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 230bool ImageInputType::hasLegalLinkAttribute(const QualifiedName& name) const 231{ 232 return name == srcAttr || BaseButtonInputType::hasLegalLinkAttribute(name); 233} 234 235const QualifiedName& ImageInputType::subResourceAttributeName() const 236{ 237 return srcAttr; 238} 239 240} // namespace blink 241