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

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

Issue 703473003: Fix bug where form/fieldset :valid/:invalid won't be recalculated upon control's willValidate change (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Update a css layout test now that number of SubtreeStyleChange went down Created 6 years, 1 month 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 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 return InsertionDone; 256 return InsertionDone;
257 } 257 }
258 258
259 void HTMLFormControlElement::removedFrom(ContainerNode* insertionPoint) 259 void HTMLFormControlElement::removedFrom(ContainerNode* insertionPoint)
260 { 260 {
261 fieldSetAncestorsSetNeedsValidityCheck(insertionPoint); 261 fieldSetAncestorsSetNeedsValidityCheck(insertionPoint);
262 hideVisibleValidationMessage(); 262 hideVisibleValidationMessage();
263 m_hasValidationMessage = false; 263 m_hasValidationMessage = false;
264 m_ancestorDisabledState = AncestorDisabledStateUnknown; 264 m_ancestorDisabledState = AncestorDisabledStateUnknown;
265 m_dataListAncestorState = Unknown; 265 m_dataListAncestorState = Unknown;
266 setNeedsWillValidateCheck();
266 HTMLElement::removedFrom(insertionPoint); 267 HTMLElement::removedFrom(insertionPoint);
267 FormAssociatedElement::removedFrom(insertionPoint); 268 FormAssociatedElement::removedFrom(insertionPoint);
268 } 269 }
269 270
270 void HTMLFormControlElement::willChangeForm() 271 void HTMLFormControlElement::willChangeForm()
271 { 272 {
272 formOwnerSetNeedsValidityCheck();
273 FormAssociatedElement::willChangeForm(); 273 FormAssociatedElement::willChangeForm();
274 formOwnerSetNeedsValidityCheck(ElementRemoval, isValidElement());
274 } 275 }
275 276
276 void HTMLFormControlElement::didChangeForm() 277 void HTMLFormControlElement::didChangeForm()
277 { 278 {
278 formOwnerSetNeedsValidityCheck();
279 FormAssociatedElement::didChangeForm(); 279 FormAssociatedElement::didChangeForm();
280 formOwnerSetNeedsValidityCheck(ElementAddition, isValidElement());
280 } 281 }
281 282
282 void HTMLFormControlElement::formOwnerSetNeedsValidityCheck() 283 void HTMLFormControlElement::formOwnerSetNeedsValidityCheck(ValidityRecalcReason reason, bool isValid)
283 { 284 {
284 HTMLFormElement* form = formOwner(); 285 HTMLFormElement* form = formOwner();
285 if (form) 286 if (form)
286 form->setNeedsValidityCheck(); 287 form->setNeedsValidityCheck(reason, isValid);
287 } 288 }
288 289
289 void HTMLFormControlElement::fieldSetAncestorsSetNeedsValidityCheck(Node* node) 290 void HTMLFormControlElement::fieldSetAncestorsSetNeedsValidityCheck(Node* node)
290 { 291 {
291 if (!node) 292 if (!node)
292 return; 293 return;
293 for (HTMLFieldSetElement* fieldSet = Traversal<HTMLFieldSetElement>::firstAn cestorOrSelf(*node); fieldSet; fieldSet = Traversal<HTMLFieldSetElement>::firstA ncestor(*fieldSet)) 294 for (HTMLFieldSetElement* fieldSet = Traversal<HTMLFieldSetElement>::firstAn cestorOrSelf(*node); fieldSet; fieldSet = Traversal<HTMLFieldSetElement>::firstA ncestor(*fieldSet))
294 fieldSet->setNeedsValidityCheck(); 295 fieldSet->setNeedsValidityCheck();
295 } 296 }
296 297
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 m_dataListAncestorState = InsideDataList; 400 m_dataListAncestorState = InsideDataList;
400 else 401 else
401 m_dataListAncestorState = NotInsideDataList; 402 m_dataListAncestorState = NotInsideDataList;
402 } 403 }
403 return m_dataListAncestorState == NotInsideDataList && !isDisabledOrReadOnly (); 404 return m_dataListAncestorState == NotInsideDataList && !isDisabledOrReadOnly ();
404 } 405 }
405 406
406 bool HTMLFormControlElement::willValidate() const 407 bool HTMLFormControlElement::willValidate() const
407 { 408 {
408 if (!m_willValidateInitialized || m_dataListAncestorState == Unknown) { 409 if (!m_willValidateInitialized || m_dataListAncestorState == Unknown) {
409 m_willValidateInitialized = true; 410 const_cast<HTMLFormControlElement*>(this)->setNeedsWillValidateCheck();
410 bool newWillValidate = recalcWillValidate();
411 if (m_willValidate != newWillValidate) {
412 m_willValidate = newWillValidate;
413 const_cast<HTMLFormControlElement*>(this)->setNeedsValidityCheck();
414 }
415 } else { 411 } else {
416 // If the following assertion fails, setNeedsWillValidateCheck() is not 412 // If the following assertion fails, setNeedsWillValidateCheck() is not
417 // called correctly when something which changes recalcWillValidate() re sult 413 // called correctly when something which changes recalcWillValidate() re sult
418 // is updated. 414 // is updated.
419 ASSERT(m_willValidate == recalcWillValidate()); 415 ASSERT(m_willValidate == recalcWillValidate());
420 } 416 }
421 return m_willValidate; 417 return m_willValidate;
422 } 418 }
423 419
424 void HTMLFormControlElement::setNeedsWillValidateCheck() 420 void HTMLFormControlElement::setNeedsWillValidateCheck()
425 { 421 {
426 // We need to recalculate willValidate immediately because willValidate chan ge can causes style change. 422 // We need to recalculate willValidate immediately because willValidate chan ge can causes style change.
427 bool newWillValidate = recalcWillValidate(); 423 bool newWillValidate = recalcWillValidate();
428 if (m_willValidateInitialized && m_willValidate == newWillValidate) 424 if (m_willValidateInitialized && m_willValidate == newWillValidate)
429 return; 425 return;
430 m_willValidateInitialized = true; 426 m_willValidateInitialized = true;
431 m_willValidate = newWillValidate; 427 m_willValidate = newWillValidate;
432 setNeedsValidityCheck(); 428 setNeedsValidityCheck();
433 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create( StyleChangeReason::Validate)); 429 // No need to trigger style recalculation here because
430 // setNeedsValidityCheck() does it in the right away. This relies on
431 // the assumption that valid() is always true if willValidate() is false.
432
434 if (!m_willValidate) 433 if (!m_willValidate)
435 hideVisibleValidationMessage(); 434 hideVisibleValidationMessage();
436 } 435 }
437 436
438 void HTMLFormControlElement::findCustomValidationMessageTextDirection(const Stri ng& message, TextDirection &messageDir, String& subMessage, TextDirection &subMe ssageDir) 437 void HTMLFormControlElement::findCustomValidationMessageTextDirection(const Stri ng& message, TextDirection &messageDir, String& subMessage, TextDirection &subMe ssageDir)
439 { 438 {
440 bool hasStrongDirection; 439 bool hasStrongDirection;
441 subMessage = fastGetAttribute(titleAttr); 440 subMessage = fastGetAttribute(titleAttr);
442 messageDir = determineDirectionality(message, hasStrongDirection); 441 messageDir = determineDirectionality(message, hasStrongDirection);
443 if (!subMessage.isEmpty()) 442 if (!subMessage.isEmpty())
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 { 549 {
551 // If the following assertion fails, setNeedsValidityCheck() is not called 550 // If the following assertion fails, setNeedsValidityCheck() is not called
552 // correctly when something which changes validity is updated. 551 // correctly when something which changes validity is updated.
553 ASSERT(m_isValid == valid()); 552 ASSERT(m_isValid == valid());
554 return m_isValid; 553 return m_isValid;
555 } 554 }
556 555
557 void HTMLFormControlElement::setNeedsValidityCheck() 556 void HTMLFormControlElement::setNeedsValidityCheck()
558 { 557 {
559 bool newIsValid = valid(); 558 bool newIsValid = valid();
560 if (willValidate() && newIsValid != m_isValid) { 559 bool changed = newIsValid != m_isValid;
561 formOwnerSetNeedsValidityCheck(); 560 m_isValid = newIsValid;
561 if (changed) {
562 formOwnerSetNeedsValidityCheck(ElementModification, newIsValid);
562 fieldSetAncestorsSetNeedsValidityCheck(parentNode()); 563 fieldSetAncestorsSetNeedsValidityCheck(parentNode());
563 // Update style for pseudo classes such as :valid :invalid. 564 // Update style for pseudo classes such as :valid :invalid.
564 pseudoStateChanged(CSSSelector::PseudoValid); 565 pseudoStateChanged(CSSSelector::PseudoValid);
565 pseudoStateChanged(CSSSelector::PseudoInvalid); 566 pseudoStateChanged(CSSSelector::PseudoInvalid);
566 } 567 }
567 m_isValid = newIsValid;
568 568
569 // Updates only if this control already has a validation message. 569 // Updates only if this control already has a validation message.
570 if (isValidationMessageVisible()) { 570 if (isValidationMessageVisible()) {
571 // Calls updateVisibleValidationMessage() even if m_isValid is not 571 // Calls updateVisibleValidationMessage() even if m_isValid is not
572 // changed because a validation message can be changed. 572 // changed because a validation message can be changed.
573 updateVisibleValidationMessage(); 573 updateVisibleValidationMessage();
574 } 574 }
575 } 575 }
576 576
577 void HTMLFormControlElement::setCustomValidity(const String& error) 577 void HTMLFormControlElement::setCustomValidity(const String& error)
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 616
617 void HTMLFormControlElement::setFocus(bool flag) 617 void HTMLFormControlElement::setFocus(bool flag)
618 { 618 {
619 LabelableElement::setFocus(flag); 619 LabelableElement::setFocus(flag);
620 620
621 if (!flag && wasChangedSinceLastFormControlChangeEvent()) 621 if (!flag && wasChangedSinceLastFormControlChangeEvent())
622 dispatchFormControlChangeEvent(); 622 dispatchFormControlChangeEvent();
623 } 623 }
624 624
625 } // namespace blink 625 } // 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