зеркало из https://github.com/mozilla/pjs.git
Bug 472662 - no reorder event for most display property & DOM changes, r=marcoz, davidb
This commit is contained in:
Родитель
ca78c132e1
Коммит
de059fe421
|
@ -46,6 +46,7 @@
|
|||
#include "nsAccessibleEventData.h"
|
||||
#include "nsHyperTextAccessible.h"
|
||||
#include "nsAccessibilityAtoms.h"
|
||||
#include "nsAccessibleTreeWalker.h"
|
||||
#include "nsAccessible.h"
|
||||
#include "nsARIAMap.h"
|
||||
|
||||
|
@ -356,6 +357,33 @@ nsAccUtils::FireAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
|
|||
return pAccessible->FireAccessibleEvent(event);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsAccUtils::HasAccessibleChildren(nsIDOMNode *aNode)
|
||||
{
|
||||
if (!aNode)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
|
||||
if (!content)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = nsCoreUtils::GetPresShellFor(aNode);
|
||||
if (!presShell)
|
||||
return PR_FALSE;
|
||||
|
||||
nsIFrame *frame = presShell->GetPrimaryFrameFor(content);
|
||||
if (!frame)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
|
||||
nsAccessibleTreeWalker walker(weakShell, aNode, PR_FALSE);
|
||||
|
||||
walker.mState.frame = frame;
|
||||
|
||||
walker.GetFirstChild();
|
||||
return walker.mState.accessible ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIAccessible>
|
||||
nsAccUtils::GetAncestorWithRole(nsIAccessible *aDescendant, PRUint32 aRole)
|
||||
{
|
||||
|
|
|
@ -151,6 +151,11 @@ public:
|
|||
static nsresult FireAccEvent(PRUint32 aEventType, nsIAccessible *aAccessible,
|
||||
PRBool aIsAsynch = PR_FALSE);
|
||||
|
||||
/**
|
||||
* Return true if the given DOM node contains accessible children.
|
||||
*/
|
||||
static PRBool HasAccessibleChildren(nsIDOMNode *aNode);
|
||||
|
||||
/**
|
||||
* If an ancestor in this document exists with the given role, return it
|
||||
* @param aDescendant Descendant to start search with
|
||||
|
|
|
@ -318,6 +318,11 @@ nsAccEvent::ApplyEventRules(nsCOMArray<nsIAccessibleEvent> &aEventsToFire)
|
|||
continue; // Do not need to check
|
||||
|
||||
if (thisEvent->mDOMNode == tailEvent->mDOMNode) {
|
||||
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
CoalesceReorderEventsFromSameSource(thisEvent, tailEvent);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Dupe
|
||||
thisEvent->mEventRule = nsAccEvent::eDoNotEmit;
|
||||
continue;
|
||||
|
@ -325,6 +330,11 @@ nsAccEvent::ApplyEventRules(nsCOMArray<nsIAccessibleEvent> &aEventsToFire)
|
|||
if (nsCoreUtils::IsAncestorOf(tailEvent->mDOMNode,
|
||||
thisEvent->mDOMNode)) {
|
||||
// thisDOMNode is a descendant of tailDOMNode
|
||||
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
CoalesceReorderEventsFromSameTree(tailEvent, thisEvent);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do not emit thisEvent, also apply this result to sibling
|
||||
// nodes of thisDOMNode.
|
||||
thisEvent->mEventRule = nsAccEvent::eDoNotEmit;
|
||||
|
@ -335,6 +345,11 @@ nsAccEvent::ApplyEventRules(nsCOMArray<nsIAccessibleEvent> &aEventsToFire)
|
|||
if (nsCoreUtils::IsAncestorOf(thisEvent->mDOMNode,
|
||||
tailEvent->mDOMNode)) {
|
||||
// tailDOMNode is a descendant of thisDOMNode
|
||||
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
CoalesceReorderEventsFromSameTree(thisEvent, tailEvent);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do not emit tailEvent, also apply this result to sibling
|
||||
// nodes of tailDOMNode.
|
||||
tailEvent->mEventRule = nsAccEvent::eDoNotEmit;
|
||||
|
@ -387,7 +402,92 @@ nsAccEvent::ApplyToSiblings(nsCOMArray<nsIAccessibleEvent> &aEventsToFire,
|
|||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsAccEvent::CoalesceReorderEventsFromSameSource(nsAccEvent *aAccEvent1,
|
||||
nsAccEvent *aAccEvent2)
|
||||
{
|
||||
// Do not emit event2 if event1 is unconditional.
|
||||
nsAccReorderEvent* reorderEvent1 = nsnull;
|
||||
CallQueryInterface(aAccEvent1, &reorderEvent1);
|
||||
if (reorderEvent1->IsUnconditionalEvent()) {
|
||||
aAccEvent2->mEventRule = nsAccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not emit event1 if event2 is unconditional.
|
||||
nsAccReorderEvent* reorderEvent2 = nsnull;
|
||||
CallQueryInterface(aAccEvent2, &reorderEvent2);
|
||||
if (reorderEvent2->IsUnconditionalEvent()) {
|
||||
aAccEvent1->mEventRule = nsAccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not emit event2 if event1 is valid, otherwise do not emit event1.
|
||||
if (reorderEvent1->HasAccessibleInReasonSubtree())
|
||||
aAccEvent2->mEventRule = nsAccEvent::eDoNotEmit;
|
||||
else
|
||||
aAccEvent1->mEventRule = nsAccEvent::eDoNotEmit;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccEvent::CoalesceReorderEventsFromSameTree(nsAccEvent *aAccEvent,
|
||||
nsAccEvent *aDescendantAccEvent)
|
||||
{
|
||||
// Do not emit descendant event if this event is unconditional.
|
||||
nsAccReorderEvent* reorderEvent = nsnull;
|
||||
CallQueryInterface(aAccEvent, &reorderEvent);
|
||||
if (reorderEvent->IsUnconditionalEvent()) {
|
||||
aDescendantAccEvent->mEventRule = nsAccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not emit descendant event if this event is valid otherwise do not emit
|
||||
// this event.
|
||||
if (reorderEvent->HasAccessibleInReasonSubtree())
|
||||
aDescendantAccEvent->mEventRule = nsAccEvent::eDoNotEmit;
|
||||
else
|
||||
aAccEvent->mEventRule = nsAccEvent::eDoNotEmit;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccReorderEvent
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsAccReorderEvent, nsAccEvent,
|
||||
nsAccReorderEvent)
|
||||
|
||||
nsAccReorderEvent::nsAccReorderEvent(nsIAccessible *aAccTarget,
|
||||
PRBool aIsAsynch,
|
||||
PRBool aIsUnconditional,
|
||||
nsIDOMNode *aReasonNode) :
|
||||
nsAccEvent(::nsIAccessibleEvent::EVENT_REORDER, aAccTarget,
|
||||
aIsAsynch, nsAccEvent::eCoalesceFromSameSubtree),
|
||||
mUnconditionalEvent(aIsUnconditional), mReasonNode(aReasonNode)
|
||||
{
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsAccReorderEvent::IsUnconditionalEvent()
|
||||
{
|
||||
return mUnconditionalEvent;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsAccReorderEvent::HasAccessibleInReasonSubtree()
|
||||
{
|
||||
if (!mReasonNode)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> accessible;
|
||||
nsAccessNode::GetAccService()->GetAccessibleFor(mReasonNode,
|
||||
getter_AddRefs(accessible));
|
||||
|
||||
return accessible || nsAccUtils::HasAccessibleChildren(mReasonNode);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccStateChangeEvent
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsAccStateChangeEvent, nsAccEvent,
|
||||
nsIAccessibleStateChangeEvent)
|
||||
|
||||
|
|
|
@ -187,10 +187,61 @@ private:
|
|||
PRUint32 aStart, PRUint32 aEnd,
|
||||
PRUint32 aEventType, nsIDOMNode* aDOMNode,
|
||||
EEventRule aEventRule);
|
||||
|
||||
/**
|
||||
* Do not emit one of two given reorder events fired for the same DOM node.
|
||||
*/
|
||||
static void CoalesceReorderEventsFromSameSource(nsAccEvent *aAccEvent1,
|
||||
nsAccEvent *aAccEvent2);
|
||||
|
||||
/**
|
||||
* Do not emit one of two given reorder events fired for DOM nodes in the case
|
||||
* when one DOM node is in parent chain of second one.
|
||||
*/
|
||||
static void CoalesceReorderEventsFromSameTree(nsAccEvent *aAccEvent,
|
||||
nsAccEvent *aDescendantAccEvent);
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsAccEvent, NS_ACCEVENT_IMPL_CID)
|
||||
|
||||
|
||||
#define NS_ACCREORDEREVENT_IMPL_CID \
|
||||
{ /* f2629eb8-2458-4358-868c-3912b15b767a */ \
|
||||
0xf2629eb8, \
|
||||
0x2458, \
|
||||
0x4358, \
|
||||
{ 0x86, 0x8c, 0x39, 0x12, 0xb1, 0x5b, 0x76, 0x7a } \
|
||||
}
|
||||
|
||||
class nsAccReorderEvent : public nsAccEvent
|
||||
{
|
||||
public:
|
||||
|
||||
nsAccReorderEvent(nsIAccessible *aAccTarget, PRBool aIsAsynch,
|
||||
PRBool aIsUnconditional, nsIDOMNode *aReasonNode);
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCREORDEREVENT_IMPL_CID)
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
/**
|
||||
* Return true if event is unconditional, i.e. must be fired.
|
||||
*/
|
||||
PRBool IsUnconditionalEvent();
|
||||
|
||||
/**
|
||||
* Return true if changed DOM node has accessible in its tree.
|
||||
*/
|
||||
PRBool HasAccessibleInReasonSubtree();
|
||||
|
||||
private:
|
||||
PRBool mUnconditionalEvent;
|
||||
nsCOMPtr<nsIDOMNode> mReasonNode;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsAccReorderEvent, NS_ACCREORDEREVENT_IMPL_CID)
|
||||
|
||||
|
||||
class nsAccStateChangeEvent: public nsAccEvent,
|
||||
public nsIAccessibleStateChangeEvent
|
||||
{
|
||||
|
|
|
@ -1704,6 +1704,18 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (eventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
// Fire reorder event if it's unconditional (see InvalidateCacheSubtree
|
||||
// method) or if changed node (that is the reason of this reorder event)
|
||||
// is accessible or has accessible children.
|
||||
nsAccReorderEvent* reorderEvent = nsnull;
|
||||
CallQueryInterface(accessibleEvent, &reorderEvent);
|
||||
if (reorderEvent->IsUnconditionalEvent() ||
|
||||
reorderEvent->HasAccessibleInReasonSubtree()) {
|
||||
nsAccEvent::PrepareForEvent(accessibleEvent);
|
||||
FireAccessibleEvent(accessibleEvent);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The input state was previously stored with the nsIAccessibleEvent,
|
||||
// so use that state now when firing the event
|
||||
|
@ -2050,15 +2062,29 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
|
|||
|
||||
FireValueChangeForTextFields(containerAccessible);
|
||||
|
||||
if (childAccessible) {
|
||||
// Fire an event so the MSAA clients know the children have changed. Also
|
||||
// the event is used internally by MSAA part.
|
||||
nsCOMPtr<nsIAccessibleEvent> reorderEvent =
|
||||
new nsAccEvent(nsIAccessibleEvent::EVENT_REORDER, containerAccessible,
|
||||
isAsynch, nsAccEvent::eCoalesceFromSameSubtree);
|
||||
NS_ENSURE_TRUE(reorderEvent, NS_ERROR_OUT_OF_MEMORY);
|
||||
FireDelayedAccessibleEvent(reorderEvent);
|
||||
}
|
||||
// Fire an event so the MSAA clients know the children have changed. Also
|
||||
// the event is used internally by MSAA part.
|
||||
|
||||
// We need to fire reorder event for accessible parent of the changed node if
|
||||
// the changed node is accessible or has accessible children. In this case
|
||||
// we fire delayed unconditional reorder event which means it will be fired
|
||||
// after timeout in any case (of course if it won't be coalesced from event
|
||||
// queue). But at this point in the case of show events accessible object may
|
||||
// be not created for generally accessible changed node (because its frame may
|
||||
// be not constructed yet). Therefore we can to check whether the changed node
|
||||
// is accessible or has accessible children after timeout only. In the case we
|
||||
// fire conditional reorder event.
|
||||
|
||||
PRBool isUnconditionalEvent = childAccessible ||
|
||||
aChild && nsAccUtils::HasAccessibleChildren(childNode);
|
||||
|
||||
nsCOMPtr<nsIAccessibleEvent> reorderEvent =
|
||||
new nsAccReorderEvent(containerAccessible, isAsynch,
|
||||
isUnconditionalEvent,
|
||||
aChild ? childNode : nsnull);
|
||||
NS_ENSURE_TRUE(reorderEvent, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
FireDelayedAccessibleEvent(reorderEvent);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// General
|
||||
|
||||
/**
|
||||
* Set up this variable to dump events into DOM.
|
||||
*/
|
||||
var gA11yEventDumpID = "";
|
||||
|
||||
/**
|
||||
* Register accessibility event listener.
|
||||
*
|
||||
|
@ -203,6 +208,20 @@ function eventQueue(aEventType)
|
|||
// We wait for events in order specified by eventSeq variable.
|
||||
var idx = this.mEventSeqIdx + 1;
|
||||
|
||||
if (gA11yEventDumpID) { // debug stuff
|
||||
var eventType = this.mEventSeq[idx][0];
|
||||
var target = this.mEventSeq[idx][1];
|
||||
|
||||
var info = "Event queue processing. Event type: ";
|
||||
info += gAccRetrieval.getStringEventType(eventType) + ". Target: ";
|
||||
info += (target.localName ? target.localName : target);
|
||||
if (target.nodeType == nsIDOMNode.ELEMENT_NODE &&
|
||||
target.hasAttribute("id"))
|
||||
info += " '" + target.getAttribute("id") + "'";
|
||||
|
||||
dumpInfoToDOM(info);
|
||||
}
|
||||
|
||||
if (aEvent.eventType == this.mEventSeq[idx][0] &&
|
||||
aEvent.DOMNode == this.mEventSeq[idx][1]) {
|
||||
|
||||
|
@ -242,7 +261,7 @@ function eventQueue(aEventType)
|
|||
|
||||
if (this.mEventSeq) {
|
||||
aInvoker.wasCaught = new Array(this.mEventSeq.length);
|
||||
|
||||
|
||||
for (var idx = 0; idx < this.mEventSeq.length; idx++)
|
||||
addA11yEventListener(this.mEventSeq[idx][0], this);
|
||||
}
|
||||
|
@ -279,7 +298,6 @@ var gObserverService = null;
|
|||
|
||||
var gA11yEventListeners = {};
|
||||
var gA11yEventApplicantsCount = 0;
|
||||
var gA11yEventDumpID = ""; // set up this variable to dump events into DOM.
|
||||
|
||||
var gA11yEventObserver =
|
||||
{
|
||||
|
@ -292,9 +310,8 @@ var gA11yEventObserver =
|
|||
var listenersArray = gA11yEventListeners[event.eventType];
|
||||
|
||||
if (gA11yEventDumpID) { // debug stuff
|
||||
var dumpElm = document.getElementById(gA11yEventDumpID);
|
||||
|
||||
var target = event.DOMNode;
|
||||
var dumpElm = document.getElementById(gA11yEventDumpID);
|
||||
|
||||
var parent = target;
|
||||
while (parent && parent != dumpElm)
|
||||
|
@ -302,14 +319,17 @@ var gA11yEventObserver =
|
|||
|
||||
if (parent != dumpElm) {
|
||||
var type = gAccRetrieval.getStringEventType(event.eventType);
|
||||
var info = "event type: " + type + ", target: " + target.localName;
|
||||
var info = "Event type: " + type + ". Target: ";
|
||||
info += (target.localName ? target.localName : target);
|
||||
|
||||
if (target.nodeType == nsIDOMNode.ELEMENT_NODE &&
|
||||
target.hasAttribute("id"))
|
||||
info += " '" + target.getAttribute("id") + "'";
|
||||
|
||||
if (listenersArray)
|
||||
info += ", registered listeners count is " + listenersArray.length;
|
||||
info += ". Listeners count: " + listenersArray.length;
|
||||
|
||||
var div = document.createElement("div");
|
||||
div.textContent = info;
|
||||
|
||||
dumpElm.appendChild(div);
|
||||
dumpInfoToDOM(info);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,3 +383,11 @@ function removeA11yEventListener(aEventType, aEventHandler)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
function dumpInfoToDOM(aInfo)
|
||||
{
|
||||
var dumpElm = document.getElementById(gA11yEventDumpID);
|
||||
var div = document.createElement("div");
|
||||
div.textContent = aInfo;
|
||||
dumpElm.appendChild(div);
|
||||
}
|
||||
|
|
|
@ -36,38 +36,71 @@
|
|||
var kHideEvents = kHideEvent | kReorderEvent;
|
||||
var kHideAndShowEvents = kHideEvents | kShowEvent;
|
||||
|
||||
function mutateA11yTree(aNodeOrID, aEventTypes, aDoNotExpectEvents,
|
||||
aIsDOMChange)
|
||||
/**
|
||||
* Base class to test mutation a11y events.
|
||||
*
|
||||
* @param aNodeOrID [in] node invoker's action is executed for
|
||||
* @param aEventTypes [in] events to register (see constants above)
|
||||
* @param aDoNotExpectEvents [in] boolean indicates if events are expected
|
||||
* @param aIsDOMChange [in] boolean indicates if these are DOM events
|
||||
* layout events.
|
||||
*/
|
||||
function mutateA11yTree(aNodeOrID, aEventTypes,
|
||||
aDoNotExpectEvents, aIsDOMChange)
|
||||
{
|
||||
// Interface
|
||||
this.DOMNode = getNode(aNodeOrID);
|
||||
|
||||
this.doNotExpectEvents = aDoNotExpectEvents;
|
||||
this.eventSeq = [];
|
||||
|
||||
if (aIsDOMChange) {
|
||||
if (aEventTypes & kHideEvent)
|
||||
this.eventSeq.push([nsIAccessibleEvent.EVENT_DOM_DESTROY,
|
||||
this.DOMNode]);
|
||||
|
||||
if (aEventTypes & kShowEvent)
|
||||
this.eventSeq.push([nsIAccessibleEvent.EVENT_DOM_CREATE,
|
||||
this.DOMNode]);
|
||||
} else {
|
||||
if (aEventTypes & kHideEvent)
|
||||
this.eventSeq.push([nsIAccessibleEvent.EVENT_ASYNCH_HIDE,
|
||||
this.DOMNode]);
|
||||
|
||||
if (aEventTypes & kShowEvent)
|
||||
this.eventSeq.push([nsIAccessibleEvent.EVENT_ASYNCH_SHOW,
|
||||
this.DOMNode]);
|
||||
this.setTarget = function mutateA11yTree_setTarget(aEventType, aTarget)
|
||||
{
|
||||
var type = this.getA11yEventType(aEventType);
|
||||
for (var idx = 0; idx < this.eventSeq.length; idx++) {
|
||||
if (this.eventSeq[idx][0] == type) {
|
||||
this.eventSeq[idx][1] = aTarget;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aEventTypes & kReorderEvent)
|
||||
this.eventSeq.push([nsIAccessibleEvent.EVENT_REORDER,
|
||||
this.DOMNode.parentNode]);
|
||||
// Implementation
|
||||
this.getA11yEventType = function mutateA11yTree_getA11yEventType(aEventType)
|
||||
{
|
||||
if (aEventType == kReorderEvent)
|
||||
return nsIAccessibleEvent.EVENT_REORDER;
|
||||
|
||||
this.doNotExpectEvents = aDoNotExpectEvents;
|
||||
if (this.mIsDOMChange) {
|
||||
if (aEventType == kHideEvent)
|
||||
return nsIAccessibleEvent.EVENT_DOM_DESTROY;
|
||||
|
||||
if (aEventType == kShowEvent)
|
||||
return nsIAccessibleEvent.EVENT_DOM_CREATE;
|
||||
} else {
|
||||
if (aEventType == kHideEvent)
|
||||
return nsIAccessibleEvent.EVENT_ASYNCH_HIDE;
|
||||
|
||||
if (aEventType == kShowEvent)
|
||||
return nsIAccessibleEvent.EVENT_ASYNCH_SHOW;
|
||||
}
|
||||
}
|
||||
|
||||
this.mIsDOMChange = aIsDOMChange;
|
||||
|
||||
if (aEventTypes & kHideEvent)
|
||||
this.eventSeq.push([this.getA11yEventType(kHideEvent), this.DOMNode]);
|
||||
|
||||
if (aEventTypes & kShowEvent)
|
||||
this.eventSeq.push([this.getA11yEventType(kShowEvent), this.DOMNode]);
|
||||
|
||||
if (aEventTypes & kReorderEvent)
|
||||
this.eventSeq.push([this.getA11yEventType(kReorderEvent),
|
||||
this.DOMNode.parentNode]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change CSS style for the given node.
|
||||
*/
|
||||
function changeStyle(aNodeOrID, aProp, aValue, aEventTypes)
|
||||
{
|
||||
this.__proto__ = new mutateA11yTree(aNodeOrID, aEventTypes, false, false);
|
||||
|
@ -83,6 +116,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change class name for the given node.
|
||||
*/
|
||||
function changeClass(aParentNodeOrID, aNodeOrID, aClassName, aEventTypes)
|
||||
{
|
||||
this.__proto__ = new mutateA11yTree(aNodeOrID, aEventTypes, false, false);
|
||||
|
@ -100,7 +136,11 @@
|
|||
this.parentDOMNode = getNode(aParentNodeOrID);
|
||||
}
|
||||
|
||||
function cloneAndAppendToDOM(aNodeOrID, aEventTypes)
|
||||
/**
|
||||
* Clone the node and append it to its parent.
|
||||
*/
|
||||
function cloneAndAppendToDOM(aNodeOrID, aEventTypes,
|
||||
aTargetFunc, aReorderTargetFunc)
|
||||
{
|
||||
var eventTypes = aEventTypes || kShowEvents;
|
||||
var doNotExpectEvents = (aEventTypes == kNoEvents);
|
||||
|
@ -112,7 +152,16 @@
|
|||
{
|
||||
var newElm = this.DOMNode.cloneNode(true);
|
||||
newElm.removeAttribute('id');
|
||||
this.eventSeq[0][1] = newElm;
|
||||
|
||||
var target = this.mTargetFunc ?
|
||||
this.mTargetFunc.call(null, newElm) : newElm;
|
||||
this.setTarget(kShowEvent, target);
|
||||
|
||||
if (this.mReorderTargetFunc) {
|
||||
var reorderTarget = this.mReorderTargetFunc.call(null, this.DOMNode);
|
||||
this.setTarget(kReorderEvent, reorderTarget);
|
||||
}
|
||||
|
||||
this.DOMNode.parentNode.appendChild(newElm);
|
||||
}
|
||||
|
||||
|
@ -120,9 +169,16 @@
|
|||
{
|
||||
return aNodeOrID + " clone and append to DOM.";
|
||||
}
|
||||
|
||||
this.mTargetFunc = aTargetFunc;
|
||||
this.mReorderTargetFunc = aReorderTargetFunc;
|
||||
}
|
||||
|
||||
function removeFromDOM(aNodeOrID, aEventTypes)
|
||||
/**
|
||||
* Removes the node from DOM.
|
||||
*/
|
||||
function removeFromDOM(aNodeOrID, aEventTypes,
|
||||
aTargetFunc, aReorderTargetFunc)
|
||||
{
|
||||
var eventTypes = aEventTypes || kHideEvents;
|
||||
var doNotExpectEvents = (aEventTypes == kNoEvents);
|
||||
|
@ -139,8 +195,18 @@
|
|||
{
|
||||
return aNodeOrID + " remove from DOM.";
|
||||
}
|
||||
|
||||
if (aTargetFunc && (eventTypes & kHideEvent))
|
||||
this.setTarget(kHideEvent, aTargetFunc.call(null, this.DOMNode));
|
||||
|
||||
if (aReorderTargetFunc && (eventTypes & kReorderEvent))
|
||||
this.setTarget(kReorderEvent,
|
||||
aReorderTargetFunc.call(null, this.DOMNode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the node and replace the original node by cloned one.
|
||||
*/
|
||||
function cloneAndReplaceInDOM(aNodeOrID)
|
||||
{
|
||||
this.__proto__ = new mutateA11yTree(aNodeOrID, kHideAndShowEvents,
|
||||
|
@ -160,6 +226,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
function getFirstChild(aNode) { return aNode.firstChild; }
|
||||
function getParent(aNode) { return aNode.parentNode; }
|
||||
|
||||
/**
|
||||
* Do tests.
|
||||
*/
|
||||
|
@ -175,9 +244,7 @@
|
|||
var id = "link1";
|
||||
getAccessible(id); // ensure accessible is created
|
||||
gQueue.push(new changeStyle(id, "display", "none", kHideEvents));
|
||||
|
||||
// XXX: bug 472662 - there is no expected reorder event
|
||||
gQueue.push(new changeStyle(id, "display", "inline", kShowEvent));
|
||||
gQueue.push(new changeStyle(id, "display", "inline", kShowEvents));
|
||||
|
||||
// Show/hide events by changing of visibility style of accessible DOM node
|
||||
// from 'visible' to 'hidden', 'hidden' to 'visible'.
|
||||
|
@ -201,8 +268,7 @@
|
|||
|
||||
// Show/hide events by adding new accessible DOM node and removing old one.
|
||||
var id = "link5";
|
||||
// XXX: bug 472662 - there is no expected reorder event
|
||||
gQueue.push(new cloneAndAppendToDOM(id, kShowEvent));
|
||||
gQueue.push(new cloneAndAppendToDOM(id));
|
||||
gQueue.push(new removeFromDOM(id));
|
||||
|
||||
// No show/hide events by adding new not accessible DOM node and removing
|
||||
|
@ -214,17 +280,25 @@
|
|||
// Show/hide events by adding new accessible DOM node and removing
|
||||
// old one, there is reorder event for their parent.
|
||||
var id = "child2";
|
||||
gQueue.push(new cloneAndAppendToDOM(id, kShowEvent));
|
||||
gQueue.push(new cloneAndAppendToDOM(id));
|
||||
gQueue.push(new removeFromDOM(id));
|
||||
|
||||
// Show/hide events by adding new DOM node containing accessible DOM and
|
||||
// removing old one, there is reorder event for their parent.
|
||||
var id = "child3";
|
||||
gQueue.push(new cloneAndAppendToDOM(id, kShowEvents, getFirstChild,
|
||||
getParent));
|
||||
|
||||
// XXX: bug 475503, there is no hide event
|
||||
gQueue.push(new removeFromDOM(id, kReorderEvent, getFirstChild, getParent));
|
||||
|
||||
// Show/hide events by creating new accessible DOM node and replacing
|
||||
// old one.
|
||||
// XXX: bug 472810
|
||||
// gQueue.push(new cloneAndReplaceInDOM("link6"));
|
||||
|
||||
// Show/hide events by changing class name on the parent node.
|
||||
// XXX: bug 472662 - there is no expected reorder event
|
||||
gQueue.push(new changeClass("container2", "link7", "", kShowEvent));
|
||||
gQueue.push(new changeClass("container2", "link7", "", kShowEvents));
|
||||
gQueue.push(new changeClass("container2", "link7", "displayNone",
|
||||
kHideEvents));
|
||||
gQueue.push(new changeClass("container3", "link8", "", kShowEvents));
|
||||
|
@ -256,19 +330,25 @@
|
|||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
<div id="eventdump"/>
|
||||
<div id="eventdump"></div>
|
||||
|
||||
<a id="link1" href="http://www.google.com">Link #1</a>
|
||||
<a id="link2" href="http://www.google.com">Link #2</a>
|
||||
<a id="link3" href="http://www.google.com">Link #3</a>
|
||||
<a id="link4" href="http://www.google.com" style="visibility:collapse">Link #4</a>
|
||||
<a id="link5" href="http://www.google.com">Link #5</a>
|
||||
<div id="testContainer">
|
||||
<a id="link1" href="http://www.google.com">Link #1</a>
|
||||
<a id="link2" href="http://www.google.com">Link #2</a>
|
||||
<a id="link3" href="http://www.google.com">Link #3</a>
|
||||
<a id="link4" href="http://www.google.com" style="visibility:collapse">Link #4</a>
|
||||
<a id="link5" href="http://www.google.com">Link #5</a>
|
||||
|
||||
<div id="container" role="list"><span id="child1"></span><span id="child2" role="listitem"></span></div>
|
||||
<div id="container" role="list">
|
||||
<span id="child1"></span>
|
||||
<span id="child2" role="listitem"></span>
|
||||
<span id="child3"><span role="listitem"></span></span>
|
||||
</div>
|
||||
|
||||
<a id="link6" href="http://www.google.com">Link #6</a>
|
||||
<a id="link6" href="http://www.google.com">Link #6</a>
|
||||
|
||||
<div id="container2" class="displayNone"><a id="link7">Link #7</a></div>
|
||||
<div id="container3" class="visibilityHidden"><a id="link8">Link #8</a></div>
|
||||
<div id="container2" class="displayNone"><a id="link7">Link #7</a></div>
|
||||
<div id="container3" class="visibilityHidden"><a id="link8">Link #8</a></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Загрузка…
Ссылка в новой задаче