Bug 670083 - expose placeholder as description if wasn't used as name r?surkov
- Pass nameFlag to NativeDescription to prepare further implementation of HTML Accessibility API Mappings
- Use placeholder as description if it wasn't used as name
MozReview-Commit-ID: ApuMKpUi8iM
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -140,26 +140,28 @@ Accessible::Name(nsString& aName)
}
ENameValueFlag nameFlag = NativeName(aName);
if (!aName.IsEmpty())
return nameFlag;
// In the end get the name from tooltip.
if (mContent->IsHTMLElement()) {
+ // https://w3c.github.io/aria/html-aam/html-aam.html
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aName)) {
aName.CompressWhitespace();
return eNameFromTooltip;
}
} else if (mContent->IsXULElement()) {
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aName)) {
aName.CompressWhitespace();
return eNameFromTooltip;
}
} else if (mContent->IsSVGElement()) {
+ // https://w3c.github.io/aria/svg-aam/svg-aam.html
// If user agents need to choose among multiple ‘desc’ or ‘title’ elements
// for processing, the user agent shall choose the first one.
for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
childElm = childElm->GetNextSibling()) {
if (childElm->IsSVGElement(nsGkAtoms::desc)) {
nsTextEquivUtils::AppendTextEquivFromContent(this, childElm, &aName);
return eNameFromTooltip;
}
@@ -183,43 +185,51 @@ Accessible::Description(nsString& aDescr
if (!HasOwnContent() || mContent->IsNodeOfType(nsINode::eTEXT))
return;
nsTextEquivUtils::
GetTextEquivFromIDRefs(this, nsGkAtoms::aria_describedby,
aDescription);
+ nsAutoString name;
+ bool didNameInitialized = false;
+
if (aDescription.IsEmpty()) {
- NativeDescription(aDescription);
-
- if (aDescription.IsEmpty()) {
+ ENameValueFlag nameFlag = Name(name);
+ NativeDescription(aDescription, nameFlag);
+ didNameInitialized = true;
+
+ if (aDescription.IsEmpty() && nameFlag != eNameFromTooltip) {
// Keep the Name() method logic.
if (mContent->IsHTMLElement()) {
+ // https://w3c.github.io/aria/html-aam/html-aam.html
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aDescription);
} else if (mContent->IsXULElement()) {
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aDescription);
} else if (mContent->IsSVGElement()) {
+ // https://w3c.github.io/aria/svg-aam/svg-aam.html
for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
childElm = childElm->GetNextSibling()) {
if (childElm->IsSVGElement(nsGkAtoms::desc)) {
nsTextEquivUtils::AppendTextEquivFromContent(this, childElm,
&aDescription);
break;
}
}
}
}
}
if (!aDescription.IsEmpty()) {
aDescription.CompressWhitespace();
- nsAutoString name;
- Name(name);
// Don't expose a description if it is the same as the name.
+ if (!didNameInitialized) {
+ Name(name);
+ }
if (aDescription.Equals(name))
aDescription.Truncate();
}
}
KeyBinding
Accessible::AccessKey() const
{
@@ -1963,17 +1973,17 @@ Accessible::NativeName(nsString& aName)
}
}
return eNameOK;
}
// Accessible protected
void
-Accessible::NativeDescription(nsString& aDescription)
+Accessible::NativeDescription(nsString& aDescription, ENameValueFlag nameFlag)
{
bool isXUL = mContent->IsXULElement();
if (isXUL) {
// Try XUL <description control="[id]">description text</description>
XULDescriptionIterator iter(Document(), mContent);
Accessible* descr = nullptr;
while ((descr = iter.Next())) {
nsTextEquivUtils::AppendTextEquivFromContent(this, descr->GetContent(),
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -80,17 +80,22 @@ enum ENameValueFlag {
/**
* Name was computed from the subtree.
*/
eNameFromSubtree,
/**
* Tooltip was used as a name.
*/
- eNameFromTooltip
+ eNameFromTooltip,
+
+ /**
+ * HTML placeholder attribute was used as a name.
+ */
+ eNameFromHTMLPlaceholder
};
/**
* Group position (level, position in set and set size).
*/
struct GroupPos
{
GroupPos() : level(0), posInSet(0), setSize(0) { }
@@ -964,17 +969,18 @@ protected:
* into account ARIA markup used to specify the name.
*/
virtual mozilla::a11y::ENameValueFlag NativeName(nsString& aName);
/**
* Return the accessible description provided by native markup. It doesn't take
* into account ARIA markup used to specify the description.
*/
- virtual void NativeDescription(nsString& aDescription);
+ virtual void NativeDescription(nsString& aDescription,
+ mozilla::a11y::ENameValueFlag nameFlag);
/**
* Return object attributes provided by native markup. It doesn't take into
* account ARIA.
*/
virtual already_AddRefed<nsIPersistentProperties> NativeAttributes();
//////////////////////////////////////////////////////////////////////////////
--- a/accessible/html/HTMLFormControlAccessible.cpp
+++ b/accessible/html/HTMLFormControlAccessible.cpp
@@ -327,22 +327,39 @@ HTMLTextFieldAccessible::NativeName(nsSt
// If part of compound of XUL widget then grab a name from XUL widget element.
nsIContent* widgetElm = XULWidgetElm();
if (widgetElm)
XULElmName(mDoc, widgetElm, aName);
if (!aName.IsEmpty())
return eNameOK;
+ // https://w3c.github.io/aria/html-aam/html-aam.html#input-type-text-input-type-password-input-type-search-input-type-tel-input-type-url-and-textarea-element
// text inputs and textareas might have useful placeholder text
mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, aName);
- return eNameOK;
+ return eNameFromHTMLPlaceholder;
}
void
+HTMLTextFieldAccessible::NativeDescription(nsString& aDescription,
+ ENameValueFlag nameFlag)
+{
+ Accessible::NativeDescription(aDescription, nameFlag);
+ if (!aDescription.IsEmpty())
+ return;
+
+ // https://w3c.github.io/aria/html-aam/html-aam.html#input-type-text-input-type-password-input-type-search-input-type-tel-input-type-url-and-textarea-element
+ // Use description from placeholder.
+ if (nameFlag != eNameFromHTMLPlaceholder) {
+ mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, aDescription);
+ }
+}
+
+
+void
HTMLTextFieldAccessible::Value(nsString& aValue)
{
aValue.Truncate();
if (NativeState() & states::PROTECTED) // Don't return password text!
return;
nsCOMPtr<nsIDOMHTMLTextAreaElement> textArea(do_QueryInterface(mContent));
if (textArea) {
--- a/accessible/html/HTMLFormControlAccessible.h
+++ b/accessible/html/HTMLFormControlAccessible.h
@@ -134,16 +134,17 @@ public:
virtual bool IsWidget() const override;
virtual Accessible* ContainerWidget() const override;
protected:
virtual ~HTMLTextFieldAccessible() {}
// Accessible
virtual ENameValueFlag NativeName(nsString& aName) override;
+ virtual void NativeDescription(nsString& aName, ENameValueFlag nameFlag) override;
/**
* Return a XUL widget element this input is part of.
*/
nsIContent* XULWidgetElm() const { return mContent->GetBindingParent(); }
};
--- a/accessible/tests/mochitest/name/test_general.html
+++ b/accessible/tests/mochitest/name/test_general.html
@@ -201,19 +201,28 @@
testName("textboxinend", "This day was sunny");
testName("textbox2", "This day was");
// placeholder
testName("ph_password", "a placeholder");
testName("ph_text", "a placeholder");
testName("ph_textarea", "a placeholder");
+
+ // placeholder does not win labels
testName("ph_text2", "a label");
+ testDescr("ph_text2", "meh");
testName("ph_textarea2", "a label");
+ testDescr("ph_textarea2", "meh");
testName("ph_text3", "a label");
+ testDescr("ph_text3", "meh");
+
+ // placeholder wins title attribute
+ testName("ph_text4", "meh");
+ testDescr("ph_text4", "title");
// Test equation image
testName("img_eq", "x^2 + y^2 + z^2")
testName("input_img_eq", "x^2 + y^2 + z^2")
testName("txt_eq", "x^2 + y^2 + z^2")
////////////////////////////////////////////////////////////////////////
// tests for duplicate announcement of content
@@ -602,24 +611,28 @@
</label>
</form>
<!-- placeholder -->
<input id="ph_password" type="password" value="" placeholder="a placeholder" />
<input id="ph_text" type="text" placeholder="a placeholder" />
<textarea id="ph_textarea" cols="5" placeholder="a placeholder"></textarea>
- <!-- placeholder does not win -->
+ <!-- placeholder does not win labels -->
<input id="ph_text2" type="text" aria-label="a label" placeholder="meh" />
<textarea id="ph_textarea2" cols="5" aria-labelledby="ph_text2"
placeholder="meh"></textarea>
<label for="ph_text3">a label</label>
<input id="ph_text3" placeholder="meh" />
+ <!-- placeholder wins title attribute -->
+ <input id="ph_text4" type="text" placeholder="meh" title="title" />
+
+ <!-- Test equation image -->
<p>Image:
<img id="img_eq" role="math" src="foo" alt="x^2 + y^2 + z^2">
<input type="image" id="input_img_eq" src="foo" alt="x^2 + y^2 + z^2">
</p>
<p>Text:
<span id="txt_eq" role="math" title="x^2 + y^2 + z^2">x<sup>2</sup> +
y<sup>2</sup> + z<sup>2</sup></span>