Bug 926812 - State change event not fired when both disabled and aria-disabled are toggled, r=tbsaunde

This commit is contained in:
Alexander Surkov 2013-11-20 13:24:30 -05:00
parent d31039039b
commit 51a40576c1
5 changed files with 83 additions and 15 deletions

View File

@ -244,6 +244,16 @@ public:
return state;
}
/**
* Return if accessible is unavailable.
*/
bool Unavailable() const
{
uint64_t state = NativelyUnavailable() ? states::UNAVAILABLE : 0;
ApplyARIAState(&state);
return state & states::UNAVAILABLE;
}
/**
* Return the states of accessible, not taking into account ARIA states.
* Use State() to get complete set of states.

View File

@ -870,7 +870,12 @@ DocAccessible::AttributeWillChange(nsIDocument* aDocument,
aAttribute == nsGkAtoms::aria_pressed) {
mARIAAttrOldValue = (aModType != nsIDOMMutationEvent::ADDITION) ?
nsAccUtils::GetARIAToken(aElement, aAttribute) : nullptr;
return;
}
if (aAttribute == nsGkAtoms::aria_disabled ||
aAttribute == nsGkAtoms::disabled)
mStateBitWasOn = accessible->Unavailable();
}
void
@ -938,22 +943,24 @@ DocAccessible::AttributeChangedImpl(Accessible* aAccessible,
// Universal boolean properties that don't require a role. Fire the state
// change when disabled or aria-disabled attribute is set.
// Note. Checking the XUL or HTML namespace would not seem to gain us
// anything, because disabled attribute really is going to mean the same
// thing in any namespace.
// Note. We use the attribute instead of the disabled state bit because
// ARIA's aria-disabled does not affect the disabled state bit.
if (aAttribute == nsGkAtoms::disabled ||
aAttribute == nsGkAtoms::aria_disabled) {
// Note. Checking the XUL or HTML namespace would not seem to gain us
// anything, because disabled attribute really is going to mean the same
// thing in any namespace.
// Note. We use the attribute instead of the disabled state bit because
// ARIA's aria-disabled does not affect the disabled state bit.
// Do nothing if state wasn't changed (like @aria-disabled was removed but
// @disabled is still presented).
if (aAccessible->Unavailable() == mStateBitWasOn)
return;
nsRefPtr<AccEvent> enabledChangeEvent =
new AccStateChangeEvent(aAccessible, states::ENABLED);
new AccStateChangeEvent(aAccessible, states::ENABLED, mStateBitWasOn);
FireDelayedEvent(enabledChangeEvent);
nsRefPtr<AccEvent> sensitiveChangeEvent =
new AccStateChangeEvent(aAccessible, states::SENSITIVE);
new AccStateChangeEvent(aAccessible, states::SENSITIVE, mStateBitWasOn);
FireDelayedEvent(sensitiveChangeEvent);
return;
}

View File

@ -533,10 +533,16 @@ protected:
nsCOMPtr<nsIContent> mAnchorJumpElm;
/**
* Keep the ARIA attribute old value that is initialized by
* AttributeWillChange and used by AttributeChanged notifications.
* A generic state (see items below) before the attribute value was changed.
* @see AttributeWillChange and AttributeChanged notifications.
*/
nsIAtom* mARIAAttrOldValue;
union {
// ARIA attribute value
nsIAtom* mARIAAttrOldValue;
// True if the accessible state bit was on
bool mStateBitWasOn;
};
nsTArray<nsRefPtr<DocAccessible> > mChildDocuments;

View File

@ -1959,7 +1959,12 @@ var gA11yEventObserver =
var type = eventTypeToString(event.eventType);
var info = "Event type: " + type;
if (event instanceof nsIAccessibleTextChangeEvent) {
if (event instanceof nsIAccessibleStateChangeEvent) {
var stateStr = statesToString(event.isExtraState ? 0 : event.state,
event.isExtraState ? event.state : 0);
info += ", state: " + stateStr + ", is enabled: " + event.isEnabled;
} else if (event instanceof nsIAccessibleTextChangeEvent) {
info += ", start: " + event.start + ", length: " + event.length +
", " + (event.isInserted ? "inserted" : "removed") +
" text: " + event.modifiedText;

View File

@ -143,18 +143,46 @@
new stateChangeChecker(aState, aIsExtraState, true, getNode(aID))
];
this.invoke = function dupeStateChange_invoke()
this.invoke = function oppositeStateChange_invoke()
{
getNode(aID).setAttribute(aAttr, "false");
getNode(aID).setAttribute(aAttr, "true");
}
this.getID = function dupeStateChange_getID()
this.getID = function oppositeStateChange_getID()
{
return "opposite state change events";
}
}
/**
* Change concomitant ARIA and native attribute at once.
*/
function echoingStateChange(aID, aARIAAttr, aAttr, aValue,
aState, aIsExtraState, aIsEnabled)
{
this.eventSeq = [
new stateChangeChecker(aState, aIsExtraState, aIsEnabled, getNode(aID))
];
this.invoke = function echoingStateChange_invoke()
{
if (aValue == null) {
getNode(aID).removeAttribute(aARIAAttr);
getNode(aID).removeAttribute(aAttr);
} else {
getNode(aID).setAttribute(aARIAAttr, aValue);
getNode(aID).setAttribute(aAttr, aValue);
}
}
this.getID = function echoingStateChange_getID()
{
return "enchoing ARIA and native attributes change";
}
}
////////////////////////////////////////////////////////////////////////////
// Do tests
@ -193,6 +221,11 @@
gQueue.push(new oppositeStateChange("div", "aria-busy",
STATE_BUSY, false));
gQueue.push(new echoingStateChange("text1", "aria-disabled", "disabled", "true",
EXT_STATE_ENABLED, true, false));
gQueue.push(new echoingStateChange("text1", "aria-disabled", "disabled", null,
EXT_STATE_ENABLED, true, true));
gQueue.invoke(); // Will call SimpleTest.finish();
}
@ -223,6 +256,11 @@
title="Fire statechange event whenever checked state is changed not depending on focused state">
Bug 788389
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=926812"
title="State change event not fired when both disabled and aria-disabled are toggled">
Bug 926812
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -242,6 +280,8 @@
<div id="div"></div>
<input id="text1">
<div id="eventdump"></div>
</body>
</html>