Bug 942321 - Changing a select option field via javascript updates validity state. r=bz
authorGiovanni Sferro <agi.novanta@gmail.com>
Tue, 06 May 2014 19:19:00 +0200
changeset 181919 ed7414cee1d8cf57b2ddd41321c3d958909081e4
parent 181918 aceefcfd37084cf007c4c99b5526f307dfbb8cf8
child 181920 446230ff2bdbfaa4f82234a3b51ac66c826fee61
push id26738
push usercbook@mozilla.com
push dateWed, 07 May 2014 12:08:22 +0000
treeherdermozilla-central@14194fb0cba0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs942321
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 942321 - Changing a select option field via javascript updates validity state. r=bz
content/html/content/src/HTMLOptionElement.cpp
content/html/content/src/HTMLOptionElement.h
content/html/content/src/HTMLSelectElement.h
content/html/content/test/forms/mochitest.ini
content/html/content/test/forms/test_select_validation.html
--- a/content/html/content/src/HTMLOptionElement.cpp
+++ b/content/html/content/src/HTMLOptionElement.cpp
@@ -238,16 +238,35 @@ HTMLOptionElement::BeforeSetAttr(int32_t
   mIsInSetDefaultSelected = inSetDefaultSelected;
   // mIsSelected might have been changed by SetOptionsSelectedByIndex.  Possibly
   // more than once; make sure our mSelectedChanged state is set correctly.
   mSelectedChanged = mIsSelected != defaultSelected;
 
   return NS_OK;
 }
 
+nsresult
+HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+                                const nsAttrValue* aValue, bool aNotify)
+{
+  if (aNameSpaceID == kNameSpaceID_None &&
+      aName == nsGkAtoms::value && Selected()) {
+    // Since this option is selected, changing value
+    // may have changed missing validity state of the
+    // Select element
+    HTMLSelectElement* select = GetSelect();
+    if (select) {
+      select->UpdateValueMissingValidityState();
+    }
+  }
+
+  return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
+                                            aValue, aNotify);
+}
+
 NS_IMETHODIMP
 HTMLOptionElement::GetText(nsAString& aText)
 {
   nsAutoString text;
 
   nsIContent* child = nsINode::GetFirstChild();
   while (child) {
     if (child->NodeType() == nsIDOMNode::TEXT_NODE ||
--- a/content/html/content/src/HTMLOptionElement.h
+++ b/content/html/content/src/HTMLOptionElement.h
@@ -46,16 +46,18 @@ public:
   bool DefaultSelected() const;
 
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               int32_t aModType) const MOZ_OVERRIDE;
 
   virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) MOZ_OVERRIDE;
+  virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+                                const nsAttrValue* aValue, bool aNotify) MOZ_OVERRIDE;
 
   void SetSelectedInternal(bool aValue, bool aNotify);
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) MOZ_OVERRIDE;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) MOZ_OVERRIDE;
--- a/content/html/content/src/HTMLSelectElement.h
+++ b/content/html/content/src/HTMLSelectElement.h
@@ -390,16 +390,17 @@ public:
   {
     return mOptions;
   }
 
   // nsIConstraintValidation
   nsresult GetValidationMessage(nsAString& aValidationMessage,
                                 ValidityStateType aType) MOZ_OVERRIDE;
 
+  void UpdateValueMissingValidityState();
   /**
    * Insert aElement before the node given by aBefore
    */
   void Add(nsGenericHTMLElement& aElement, nsGenericHTMLElement* aBefore,
            ErrorResult& aError);
   void Add(nsGenericHTMLElement& aElement, int32_t aIndex, ErrorResult& aError)
   {
     // If item index is out of range, insert to last.
@@ -506,17 +507,16 @@ protected:
   nsresult RemoveOptionsFromListRecurse(nsIContent* aOptions,
                                         int32_t aRemoveIndex,
                                         int32_t* aNumRemoved,
                                         int32_t aDepth);
 
   // nsIConstraintValidation
   void UpdateBarredFromConstraintValidation();
   bool IsValueMissing();
-  void UpdateValueMissingValidityState();
 
   /**
    * Find out how deep this content is from the select (1=direct child)
    * @param aContent the content to check
    * @return the depth
    */
   int32_t GetContentDepth(nsIContent* aContent);
   /**
--- a/content/html/content/test/forms/mochitest.ini
+++ b/content/html/content/test/forms/mochitest.ini
@@ -69,16 +69,17 @@ skip-if = e10s
 [test_output_element.html]
 [test_pattern_attribute.html]
 [test_progress_element.html]
 [test_required_attribute.html]
 skip-if = e10s
 [test_restore_form_elements.html]
 [test_save_restore_radio_groups.html]
 [test_select_selectedOptions.html]
+[test_select_validation.html]
 [test_set_range_text.html]
 [test_step_attribute.html]
 skip-if = e10s
 [test_stepup_stepdown.html]
 [test_submit_invalid_file.html]
 [test_textarea_attributes_reflection.html]
 [test_validation.html]
 skip-if = buildapp == 'b2g' || e10s # b2g(374 total, bug 901848, no keygen support) b2g-debug(374 total, bug 901848, no keygen support) b2g-desktop(374 total, bug 901848, no keygen support)
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/forms/test_select_validation.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=942321
+-->
+<head>
+  <title>Test for Bug 942321</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=942321">Mozilla Bug 942321</a>
+<p id="display"></p>
+<form id="form" href="">
+  <select required id="testselect">
+    <option id="placeholder" value="" selected>placeholder</option>
+    <option value="test" id="actualvalue">test</option>
+  <select>
+  <input type="submit" />
+</form>
+<script class="testbody" type="text/javascript">
+/** Test for Bug 942321 **/
+var option = document.getElementById("actualvalue");
+option.selected = true;
+is(form.checkValidity(), true, "Select is required and should be valid");
+
+var placeholder = document.getElementById("placeholder");
+placeholder.selected = true;
+is(form.checkValidity(), false, "Select is required and should be invalid");
+
+placeholder.value = "not-invalid-anymore";
+is(form.checkValidity(), true, "Select is required and should be valid when option's value is changed by javascript");
+</script>
+</pre>
+</body>
+</html>
+