Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      5  * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
      6  *           (C) 2006 Alexey Proskuryakov (ap (at) nypop.com)
      7  *
      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.
     12  *
     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.
     17  *
     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.
     22  *
     23  */
     24 
     25 #include "config.h"
     26 #include "FormAssociatedElement.h"
     27 
     28 #include "HTMLFormControlElement.h"
     29 #include "HTMLFormElement.h"
     30 #include "HTMLNames.h"
     31 #include "HTMLObjectElement.h"
     32 #include "ValidityState.h"
     33 
     34 namespace WebCore {
     35 
     36 using namespace HTMLNames;
     37 
     38 FormAssociatedElement::FormAssociatedElement(HTMLFormElement* form)
     39     : m_form(form)
     40 {
     41 }
     42 
     43 FormAssociatedElement::~FormAssociatedElement()
     44 {
     45 }
     46 
     47 ValidityState* FormAssociatedElement::validity()
     48 {
     49     if (!m_validityState)
     50         m_validityState = ValidityState::create(this);
     51 
     52     return m_validityState.get();
     53 }
     54 
     55 void FormAssociatedElement::willMoveToNewOwnerDocument()
     56 {
     57     HTMLElement* element = toHTMLElement(this);
     58     if (element->fastHasAttribute(formAttr))
     59         element->document()->unregisterFormElementWithFormAttribute(this);
     60 }
     61 
     62 void FormAssociatedElement::insertedIntoDocument()
     63 {
     64     HTMLElement* element = toHTMLElement(this);
     65     if (element->fastHasAttribute(formAttr))
     66         element->document()->registerFormElementWithFormAttribute(this);
     67 }
     68 
     69 void FormAssociatedElement::removedFromDocument()
     70 {
     71     HTMLElement* element = toHTMLElement(this);
     72     if (element->fastHasAttribute(formAttr))
     73         element->document()->unregisterFormElementWithFormAttribute(this);
     74 }
     75 
     76 void FormAssociatedElement::insertedIntoTree()
     77 {
     78     HTMLElement* element = toHTMLElement(this);
     79     if (element->fastHasAttribute(formAttr)) {
     80         Element* formElement = element->document()->getElementById(element->fastGetAttribute(formAttr));
     81         if (formElement && formElement->hasTagName(formTag)) {
     82             if (m_form)
     83                 m_form->removeFormElement(this);
     84             m_form = static_cast<HTMLFormElement*>(formElement);
     85             m_form->registerFormElement(this);
     86         }
     87     }
     88     if (!m_form) {
     89         // This handles the case of a new form element being created by
     90         // JavaScript and inserted inside a form.  In the case of the parser
     91         // setting a form, we will already have a non-null value for m_form,
     92         // and so we don't need to do anything.
     93         m_form = element->findFormAncestor();
     94         if (m_form)
     95             m_form->registerFormElement(this);
     96     }
     97 }
     98 
     99 static inline Node* findRoot(Node* n)
    100 {
    101     Node* root = n;
    102     for (; n; n = n->parentNode())
    103         root = n;
    104     return root;
    105 }
    106 
    107 void FormAssociatedElement::removedFromTree()
    108 {
    109     HTMLElement* element = toHTMLElement(this);
    110 
    111     // If the form and element are both in the same tree, preserve the connection to the form.
    112     // Otherwise, null out our form and remove ourselves from the form's list of elements.
    113     if (m_form && findRoot(element) != findRoot(m_form))
    114         removeFromForm();
    115 }
    116 
    117 void FormAssociatedElement::removeFromForm()
    118 {
    119     if (!m_form)
    120         return;
    121     m_form->removeFormElement(this);
    122     m_form = 0;
    123 }
    124 
    125 void FormAssociatedElement::resetFormOwner(HTMLFormElement* form)
    126 {
    127     HTMLElement* element = toHTMLElement(this);
    128     const AtomicString& formId(element->fastGetAttribute(formAttr));
    129     if (m_form) {
    130         if (formId.isNull())
    131             return;
    132         m_form->removeFormElement(this);
    133     }
    134     m_form = 0;
    135     if (!formId.isNull() && element->inDocument()) {
    136         // The HTML5 spec says that the element should be associated with
    137         // the first element in the document to have an ID that equal to
    138         // the value of form attribute, so we put the result of
    139         // document()->getElementById() over the given element.
    140         Element* firstElement = element->document()->getElementById(formId);
    141         if (firstElement && firstElement->hasTagName(formTag))
    142             m_form = static_cast<HTMLFormElement*>(firstElement);
    143         else
    144             m_form = form;
    145     } else
    146         m_form = element->findFormAncestor();
    147     if (m_form)
    148         m_form->registerFormElement(this);
    149 }
    150 
    151 void FormAssociatedElement::formAttributeChanged()
    152 {
    153     HTMLElement* element = toHTMLElement(this);
    154     if (!element->fastHasAttribute(formAttr)) {
    155         // The form attribute removed. We need to reset form owner here.
    156         if (m_form)
    157             m_form->removeFormElement(this);
    158         m_form = element->findFormAncestor();
    159         if (m_form)
    160             form()->registerFormElement(this);
    161         element->document()->unregisterFormElementWithFormAttribute(this);
    162     } else
    163         resetFormOwner(0);
    164 }
    165 
    166 const HTMLElement* toHTMLElement(const FormAssociatedElement* associatedElement)
    167 {
    168     if (associatedElement->isFormControlElement())
    169         return static_cast<const HTMLFormControlElement*>(associatedElement);
    170     // Assumes the element is an HTMLObjectElement
    171     const HTMLElement* element = static_cast<const HTMLObjectElement*>(associatedElement);
    172     ASSERT(element->hasTagName(objectTag));
    173     return element;
    174 }
    175 
    176 HTMLElement* toHTMLElement(FormAssociatedElement* associatedElement)
    177 {
    178     return const_cast<HTMLElement*>(toHTMLElement(static_cast<const FormAssociatedElement*>(associatedElement)));
    179 }
    180 
    181 } // namespace Webcore
    182