Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: Source/core/html/HTMLFormControlElement.cpp

Issue 672163002: Fix bug where form/fieldset :valid/:invalid won't be recalculated upon control's willValidate change Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Fixes to the logic Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/html/HTMLFormControlElement.h ('k') | Source/core/html/HTMLFormElement.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 Apple Inc. All rights reserved. 5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 return InsertionDone; 257 return InsertionDone;
258 } 258 }
259 259
260 void HTMLFormControlElement::removedFrom(ContainerNode* insertionPoint) 260 void HTMLFormControlElement::removedFrom(ContainerNode* insertionPoint)
261 { 261 {
262 fieldSetAncestorsSetNeedsValidityCheck(insertionPoint); 262 fieldSetAncestorsSetNeedsValidityCheck(insertionPoint);
263 hideVisibleValidationMessage(); 263 hideVisibleValidationMessage();
264 m_hasValidationMessage = false; 264 m_hasValidationMessage = false;
265 m_ancestorDisabledState = AncestorDisabledStateUnknown; 265 m_ancestorDisabledState = AncestorDisabledStateUnknown;
266 m_dataListAncestorState = Unknown; 266 m_dataListAncestorState = Unknown;
267 setNeedsWillValidateCheck();
267 HTMLElement::removedFrom(insertionPoint); 268 HTMLElement::removedFrom(insertionPoint);
268 FormAssociatedElement::removedFrom(insertionPoint); 269 FormAssociatedElement::removedFrom(insertionPoint);
269 } 270 }
270 271
271 void HTMLFormControlElement::willChangeForm() 272 void HTMLFormControlElement::willChangeForm()
272 { 273 {
273 formOwnerSetNeedsValidityCheck();
274 FormAssociatedElement::willChangeForm(); 274 FormAssociatedElement::willChangeForm();
275 formOwnerSetNeedsValidityCheck(ElementRemoval, isValidElement());
275 } 276 }
276 277
277 void HTMLFormControlElement::didChangeForm() 278 void HTMLFormControlElement::didChangeForm()
278 { 279 {
279 formOwnerSetNeedsValidityCheck();
280 FormAssociatedElement::didChangeForm(); 280 FormAssociatedElement::didChangeForm();
281 formOwnerSetNeedsValidityCheck(ElementAddition, isValidElement());
281 } 282 }
282 283
283 void HTMLFormControlElement::formOwnerSetNeedsValidityCheck() 284 void HTMLFormControlElement::formOwnerSetNeedsValidityCheck(ValidityRecalcReason reason, bool isValid)
284 { 285 {
285 HTMLFormElement* form = formOwner(); 286 HTMLFormElement* form = formOwner();
286 if (form) 287 if (form)
287 form->setNeedsValidityCheck(); 288 form->setNeedsValidityCheck(reason, isValid);
288 } 289 }
289 290
290 void HTMLFormControlElement::fieldSetAncestorsSetNeedsValidityCheck(Node* node) 291 void HTMLFormControlElement::fieldSetAncestorsSetNeedsValidityCheck(Node* node)
291 { 292 {
292 if (!node) 293 if (!node)
293 return; 294 return;
294 HTMLFieldSetElement* fieldSet = Traversal<HTMLFieldSetElement>::firstAncesto rOrSelf(*node); 295 HTMLFieldSetElement* fieldSet = Traversal<HTMLFieldSetElement>::firstAncesto rOrSelf(*node);
295 HTMLFieldSetElement* lastFieldSet = 0; 296 HTMLFieldSetElement* lastFieldSet = 0;
296 while (fieldSet) { 297 while (fieldSet) {
297 lastFieldSet = fieldSet; 298 lastFieldSet = fieldSet;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 m_dataListAncestorState = InsideDataList; 407 m_dataListAncestorState = InsideDataList;
407 else 408 else
408 m_dataListAncestorState = NotInsideDataList; 409 m_dataListAncestorState = NotInsideDataList;
409 } 410 }
410 return m_dataListAncestorState == NotInsideDataList && !isDisabledOrReadOnly (); 411 return m_dataListAncestorState == NotInsideDataList && !isDisabledOrReadOnly ();
411 } 412 }
412 413
413 bool HTMLFormControlElement::willValidate() const 414 bool HTMLFormControlElement::willValidate() const
414 { 415 {
415 if (!m_willValidateInitialized || m_dataListAncestorState == Unknown) { 416 if (!m_willValidateInitialized || m_dataListAncestorState == Unknown) {
416 m_willValidateInitialized = true; 417 const_cast<HTMLFormControlElement*>(this)->setNeedsWillValidateCheck(tru e);
417 bool newWillValidate = recalcWillValidate();
418 if (m_willValidate != newWillValidate) {
419 m_willValidate = newWillValidate;
420 const_cast<HTMLFormControlElement*>(this)->setNeedsValidityCheck();
421 }
422 } else { 418 } else {
423 // If the following assertion fails, setNeedsWillValidateCheck() is not 419 // If the following assertion fails, setNeedsWillValidateCheck() is not
424 // called correctly when something which changes recalcWillValidate() re sult 420 // called correctly when something which changes recalcWillValidate() re sult
425 // is updated. 421 // is updated.
426 ASSERT(m_willValidate == recalcWillValidate()); 422 ASSERT(m_willValidate == recalcWillValidate());
427 } 423 }
428 return m_willValidate; 424 return m_willValidate;
429 } 425 }
430 426
431 void HTMLFormControlElement::setNeedsWillValidateCheck() 427 void HTMLFormControlElement::setNeedsWillValidateCheck(bool hideValidationMessag eIfNeeded)
432 { 428 {
433 // We need to recalculate willValidate immediately because willValidate chan ge can causes style change. 429 // We need to recalculate willValidate immediately because willValidate chan ge can causes style change.
434 bool newWillValidate = recalcWillValidate(); 430 bool newWillValidate = recalcWillValidate();
435 if (m_willValidateInitialized && m_willValidate == newWillValidate) 431 if (m_willValidateInitialized && m_willValidate == newWillValidate)
436 return; 432 return;
437 m_willValidateInitialized = true; 433 m_willValidateInitialized = true;
438 m_willValidate = newWillValidate; 434 m_willValidate = newWillValidate;
439 setNeedsValidityCheck(); 435 setNeedsValidityCheck();
440 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create( StyleChangeReason::Validate)); 436 // No need to trigger style recalculation here because
441 if (!m_willValidate) 437 // setNeedsValidityCheck() does it in the right away. This relies on
438 // the assumption that valid() is always true if willValidate() is false.
439
440 if (hideValidationMessageIfNeeded && !m_willValidate)
442 hideVisibleValidationMessage(); 441 hideVisibleValidationMessage();
443 } 442 }
444 443
445 void HTMLFormControlElement::findCustomValidationMessageTextDirection(const Stri ng& message, TextDirection &messageDir, String& subMessage, TextDirection &subMe ssageDir) 444 void HTMLFormControlElement::findCustomValidationMessageTextDirection(const Stri ng& message, TextDirection &messageDir, String& subMessage, TextDirection &subMe ssageDir)
446 { 445 {
447 bool hasStrongDirection; 446 bool hasStrongDirection;
448 subMessage = fastGetAttribute(titleAttr); 447 subMessage = fastGetAttribute(titleAttr);
449 messageDir = determineDirectionality(message, hasStrongDirection); 448 messageDir = determineDirectionality(message, hasStrongDirection);
450 if (!subMessage.isEmpty()) 449 if (!subMessage.isEmpty())
451 subMessageDir = renderer()->style()->direction(); 450 subMessageDir = renderer()->style()->direction();
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 { 556 {
558 // If the following assertion fails, setNeedsValidityCheck() is not called 557 // If the following assertion fails, setNeedsValidityCheck() is not called
559 // correctly when something which changes validity is updated. 558 // correctly when something which changes validity is updated.
560 ASSERT(m_isValid == valid()); 559 ASSERT(m_isValid == valid());
561 return m_isValid; 560 return m_isValid;
562 } 561 }
563 562
564 void HTMLFormControlElement::setNeedsValidityCheck() 563 void HTMLFormControlElement::setNeedsValidityCheck()
565 { 564 {
566 bool newIsValid = valid(); 565 bool newIsValid = valid();
567 if (willValidate() && newIsValid != m_isValid) { 566 bool changed = newIsValid != m_isValid;
568 formOwnerSetNeedsValidityCheck(); 567 m_isValid = newIsValid;
568 if (changed) {
569 formOwnerSetNeedsValidityCheck(ElementModification, newIsValid);
569 fieldSetAncestorsSetNeedsValidityCheck(parentNode()); 570 fieldSetAncestorsSetNeedsValidityCheck(parentNode());
570 // Update style for pseudo classes such as :valid :invalid. 571 // Update style for pseudo classes such as :valid :invalid.
571 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre ateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Invalid)) ; 572 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre ateWithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Invalid)) ;
572 } 573 }
573 m_isValid = newIsValid;
574 574
575 // Updates only if this control already has a validation message. 575 // Updates only if this control already has a validation message.
576 if (isValidationMessageVisible()) { 576 if (isValidationMessageVisible()) {
577 // Calls updateVisibleValidationMessage() even if m_isValid is not 577 // Calls updateVisibleValidationMessage() even if m_isValid is not
578 // changed because a validation message can be changed. 578 // changed because a validation message can be changed.
579 updateVisibleValidationMessage(); 579 updateVisibleValidationMessage();
580 } 580 }
581 } 581 }
582 582
583 void HTMLFormControlElement::setCustomValidity(const String& error) 583 void HTMLFormControlElement::setCustomValidity(const String& error)
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 622
623 void HTMLFormControlElement::setFocus(bool flag) 623 void HTMLFormControlElement::setFocus(bool flag)
624 { 624 {
625 LabelableElement::setFocus(flag); 625 LabelableElement::setFocus(flag);
626 626
627 if (!flag && wasChangedSinceLastFormControlChangeEvent()) 627 if (!flag && wasChangedSinceLastFormControlChangeEvent())
628 dispatchFormControlChangeEvent(); 628 dispatchFormControlChangeEvent();
629 } 629 }
630 630
631 } // namespace blink 631 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/html/HTMLFormControlElement.h ('k') | Source/core/html/HTMLFormElement.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698