OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. |
6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 // FIXME: Consolidate this and similar code in FormSubmission.cpp. | 266 // FIXME: Consolidate this and similar code in FormSubmission.cpp. |
267 static inline HTMLFormControlElement* submitElementFromEvent(const Event* event) | 267 static inline HTMLFormControlElement* submitElementFromEvent(const Event* event) |
268 { | 268 { |
269 for (Node* node = event->target()->toNode(); node; node = node->parentOrShad
owHostNode()) { | 269 for (Node* node = event->target()->toNode(); node; node = node->parentOrShad
owHostNode()) { |
270 if (node->isElementNode() && toElement(node)->isFormControlElement()) | 270 if (node->isElementNode() && toElement(node)->isFormControlElement()) |
271 return toHTMLFormControlElement(node); | 271 return toHTMLFormControlElement(node); |
272 } | 272 } |
273 return 0; | 273 return 0; |
274 } | 274 } |
275 | 275 |
276 bool HTMLFormElement::validateInteractively(Event* event) | 276 bool HTMLFormElement::validateInteractively() |
277 { | 277 { |
278 ASSERT(event); | |
279 if (!document().page() || noValidate()) | |
280 return true; | |
281 | |
282 HTMLFormControlElement* submitElement = submitElementFromEvent(event); | |
283 if (submitElement && submitElement->formNoValidate()) | |
284 return true; | |
285 | |
286 const FormAssociatedElement::List& elements = associatedElements(); | 278 const FormAssociatedElement::List& elements = associatedElements(); |
287 for (unsigned i = 0; i < elements.size(); ++i) { | 279 for (unsigned i = 0; i < elements.size(); ++i) { |
288 if (elements[i]->isFormControlElement()) | 280 if (elements[i]->isFormControlElement()) |
289 toHTMLFormControlElement(elements[i])->hideVisibleValidationMessage(
); | 281 toHTMLFormControlElement(elements[i])->hideVisibleValidationMessage(
); |
290 } | 282 } |
291 | 283 |
292 WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> > unhandledInvali
dControls; | 284 WillBeHeapVector<RefPtrWillBeMember<HTMLFormControlElement> > unhandledInval
idControls; |
293 if (!checkInvalidControlsAndCollectUnhandled(&unhandledInvalidControls, Chec
kValidityDispatchInvalidEvent)) | 285 if (!checkInvalidControlsAndCollectUnhandled(&unhandledInvalidControls, Chec
kValidityDispatchInvalidEvent)) |
294 return true; | 286 return true; |
295 // Because the form has invalid controls, we abort the form submission and | 287 // Because the form has invalid controls, we abort the form submission and |
296 // show a validation message on a focusable form control. | 288 // show a validation message on a focusable form control. |
297 | 289 |
298 // Needs to update layout now because we'd like to call isFocusable(), which | 290 // Needs to update layout now because we'd like to call isFocusable(), which |
299 // has !renderer()->needsLayout() assertion. | 291 // has !renderer()->needsLayout() assertion. |
300 document().updateLayoutIgnorePendingStylesheets(); | 292 document().updateLayoutIgnorePendingStylesheets(); |
301 | 293 |
302 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); | 294 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); |
303 // Focus on the first focusable control and show a validation message. | 295 // Focus on the first focusable control and show a validation message. |
304 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { | 296 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { |
305 FormAssociatedElement* unhandledAssociatedElement = unhandledInvalidCont
rols[i].get(); | 297 HTMLFormControlElement* unhandled = unhandledInvalidControls[i].get(); |
306 HTMLElement* unhandled = toHTMLElement(unhandledAssociatedElement); | 298 if (unhandled->isFocusable()) { |
307 if (unhandled->isFocusable() && unhandled->inDocument()) { | 299 unhandled->showValidationMessage(); |
308 unhandled->scrollIntoViewIfNeeded(false); | |
309 unhandled->focus(); | |
310 if (unhandled->isFormControlElement()) | |
311 toHTMLFormControlElement(unhandled)->updateVisibleValidationMess
age(); | |
312 break; | 300 break; |
313 } | 301 } |
314 } | 302 } |
315 // Warn about all of unfocusable controls. | 303 // Warn about all of unfocusable controls. |
316 if (document().frame()) { | 304 if (document().frame()) { |
317 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { | 305 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { |
318 FormAssociatedElement* unhandledAssociatedElement = unhandledInvalid
Controls[i].get(); | 306 HTMLFormControlElement* unhandled = unhandledInvalidControls[i].get(
); |
319 HTMLElement* unhandled = toHTMLElement(unhandledAssociatedElement); | 307 if (unhandled->isFocusable()) |
320 if (unhandled->isFocusable() && unhandled->inDocument()) | |
321 continue; | 308 continue; |
322 String message("An invalid form control with name='%name' is not foc
usable."); | 309 String message("An invalid form control with name='%name' is not foc
usable."); |
323 message.replace("%name", unhandledAssociatedElement->name()); | 310 message.replace("%name", unhandled->name()); |
324 document().addConsoleMessage(ConsoleMessage::create(RenderingMessage
Source, ErrorMessageLevel, message)); | 311 document().addConsoleMessage(ConsoleMessage::create(RenderingMessage
Source, ErrorMessageLevel, message)); |
325 } | 312 } |
326 } | 313 } |
327 return false; | 314 return false; |
328 } | 315 } |
329 | 316 |
330 void HTMLFormElement::prepareForSubmission(Event* event) | 317 void HTMLFormElement::prepareForSubmission(Event* event) |
331 { | 318 { |
332 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); | 319 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); |
333 LocalFrame* frame = document().frame(); | 320 LocalFrame* frame = document().frame(); |
334 if (!frame || m_isSubmittingOrInUserJSSubmitEvent) | 321 if (!frame || m_isSubmittingOrInUserJSSubmitEvent) |
335 return; | 322 return; |
336 | 323 |
| 324 bool skipValidation = !document().page() || noValidate(); |
| 325 ASSERT(event); |
| 326 HTMLFormControlElement* submitElement = submitElementFromEvent(event); |
| 327 if (submitElement && submitElement->formNoValidate()) |
| 328 skipValidation = true; |
| 329 |
337 // Interactive validation must be done before dispatching the submit event. | 330 // Interactive validation must be done before dispatching the submit event. |
338 if (!validateInteractively(event)) | 331 if (!skipValidation && !validateInteractively()) |
339 return; | 332 return; |
340 | 333 |
341 m_isSubmittingOrInUserJSSubmitEvent = true; | 334 m_isSubmittingOrInUserJSSubmitEvent = true; |
342 m_shouldSubmit = false; | 335 m_shouldSubmit = false; |
343 | 336 |
344 frame->loader().client()->dispatchWillSendSubmitEvent(this); | 337 frame->loader().client()->dispatchWillSendSubmitEvent(this); |
345 | 338 |
346 if (dispatchEvent(Event::createCancelableBubble(EventTypeNames::submit))) | 339 if (dispatchEvent(Event::createCancelableBubble(EventTypeNames::submit))) |
347 m_shouldSubmit = true; | 340 m_shouldSubmit = true; |
348 | 341 |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 // validity recalculation. In the near future, implement validity cache and | 722 // validity recalculation. In the near future, implement validity cache and |
730 // recalculate style only if it changed. | 723 // recalculate style only if it changed. |
731 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::createW
ithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Invalid)); | 724 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::createW
ithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Invalid)); |
732 } | 725 } |
733 | 726 |
734 bool HTMLFormElement::checkValidity() | 727 bool HTMLFormElement::checkValidity() |
735 { | 728 { |
736 return !checkInvalidControlsAndCollectUnhandled(0, CheckValidityDispatchInva
lidEvent); | 729 return !checkInvalidControlsAndCollectUnhandled(0, CheckValidityDispatchInva
lidEvent); |
737 } | 730 } |
738 | 731 |
739 bool HTMLFormElement::checkInvalidControlsAndCollectUnhandled(WillBeHeapVector<R
efPtrWillBeMember<FormAssociatedElement> >* unhandledInvalidControls, CheckValid
ityEventBehavior eventBehavior) | 732 bool HTMLFormElement::checkInvalidControlsAndCollectUnhandled(WillBeHeapVector<R
efPtrWillBeMember<HTMLFormControlElement> >* unhandledInvalidControls, CheckVali
dityEventBehavior eventBehavior) |
740 { | 733 { |
741 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); | 734 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); |
742 // Copy associatedElements because event handlers called from | 735 // Copy associatedElements because event handlers called from |
743 // HTMLFormControlElement::checkValidity() might change associatedElements. | 736 // HTMLFormControlElement::checkValidity() might change associatedElements. |
744 const FormAssociatedElement::List& associatedElements = this->associatedElem
ents(); | 737 const FormAssociatedElement::List& associatedElements = this->associatedElem
ents(); |
745 WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> > elements; | 738 WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> > elements; |
746 elements.reserveCapacity(associatedElements.size()); | 739 elements.reserveCapacity(associatedElements.size()); |
747 for (unsigned i = 0; i < associatedElements.size(); ++i) | 740 for (unsigned i = 0; i < associatedElements.size(); ++i) |
748 elements.append(associatedElements[i]); | 741 elements.append(associatedElements[i]); |
749 bool hasInvalidControls = false; | 742 bool hasInvalidControls = false; |
750 for (unsigned i = 0; i < elements.size(); ++i) { | 743 for (unsigned i = 0; i < elements.size(); ++i) { |
751 if (elements[i]->form() == this && elements[i]->isFormControlElement())
{ | 744 if (elements[i]->form() == this && elements[i]->isFormControlElement())
{ |
752 HTMLFormControlElement* control = toHTMLFormControlElement(elements[
i].get()); | 745 HTMLFormControlElement* control = toHTMLFormControlElement(elements[
i].get()); |
753 if (!control->checkValidity(unhandledInvalidControls, eventBehavior)
&& control->formOwner() == this) | 746 if (!control->checkValidity(unhandledInvalidControls, eventBehavior)
&& control->formOwner() == this) |
754 hasInvalidControls = true; | 747 hasInvalidControls = true; |
755 } | 748 } |
756 } | 749 } |
757 return hasInvalidControls; | 750 return hasInvalidControls; |
758 } | 751 } |
759 | 752 |
| 753 bool HTMLFormElement::reportValidity() |
| 754 { |
| 755 return validateInteractively(); |
| 756 } |
| 757 |
760 Element* HTMLFormElement::elementFromPastNamesMap(const AtomicString& pastName) | 758 Element* HTMLFormElement::elementFromPastNamesMap(const AtomicString& pastName) |
761 { | 759 { |
762 if (pastName.isEmpty() || !m_pastNamesMap) | 760 if (pastName.isEmpty() || !m_pastNamesMap) |
763 return 0; | 761 return 0; |
764 Element* element = m_pastNamesMap->get(pastName); | 762 Element* element = m_pastNamesMap->get(pastName); |
765 #if ENABLE(ASSERT) | 763 #if ENABLE(ASSERT) |
766 if (!element) | 764 if (!element) |
767 return 0; | 765 return 0; |
768 ASSERT_WITH_SECURITY_IMPLICATION(toHTMLElement(element)->formOwner() == this
); | 766 ASSERT_WITH_SECURITY_IMPLICATION(toHTMLElement(element)->formOwner() == this
); |
769 if (isHTMLImageElement(*element)) { | 767 if (isHTMLImageElement(*element)) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 } | 857 } |
860 | 858 |
861 void HTMLFormElement::setDemoted(bool demoted) | 859 void HTMLFormElement::setDemoted(bool demoted) |
862 { | 860 { |
863 if (demoted) | 861 if (demoted) |
864 UseCounter::count(document(), UseCounter::DemotedFormElement); | 862 UseCounter::count(document(), UseCounter::DemotedFormElement); |
865 m_wasDemoted = demoted; | 863 m_wasDemoted = demoted; |
866 } | 864 } |
867 | 865 |
868 } // namespace | 866 } // namespace |
OLD | NEW |