Home | History | Annotate | Download | only in forms
      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