Bug 301737. Fix keyboard and accessibility API support for multiple selection for listboxes. r=mconnor, sr=neil, a=mkaply

This commit is contained in:
aaronleventhal%moonset.net 2005-08-05 18:16:32 +00:00
Родитель 42b6117d58
Коммит 9dfc5a19c5
3 изменённых файлов: 104 добавлений и 162 удалений

Просмотреть файл

@ -54,6 +54,7 @@
#include "nsIDOMDocumentType.h"
#include "nsIDOMNSDocument.h"
#include "nsIDOMNSHTMLDocument.h"
#include "nsIDOMMutationEvent.h"
#include "nsIDOMWindow.h"
#include "nsIEditingSession.h"
#include "nsIEventStateManager.h"
@ -770,10 +771,15 @@ nsDocAccessible::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
if (multiSelect) {
// Need to find the right event to use here, SELECTION_WITHIN would
// seem right but we had started using it for something else
FireToolkitEvent(nsIAccessibleEvent::EVENT_SELECTION_WITHIN,
multiSelect, nsnull);
nsCOMPtr<nsIAccessNode> multiSelectAccessNode =
do_QueryInterface(multiSelect);
nsCOMPtr<nsIDOMNode> multiSelectDOMNode;
multiSelectAccessNode->GetDOMNode(getter_AddRefs(multiSelectDOMNode));
NS_ASSERTION(multiSelectDOMNode, "A new accessible without a DOM node!");
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_SELECTION_WITHIN,
multiSelectDOMNode, nsnull, PR_TRUE);
nsAutoString attrValue;
aContent->GetAttr(kNameSpaceID_WAIProperties,
aContent->GetAttr(aNameSpaceID,
nsAccessibilityAtoms::selected, attrValue);
if (attrValue.IsEmpty() || attrValue.EqualsLiteral("false")) {
eventType = nsIAccessibleEvent::EVENT_SELECTION_REMOVE;
@ -884,7 +890,8 @@ nsDocAccessible::ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
nsresult nsDocAccessible::FireDelayedToolkitEvent(PRUint32 aEvent,
nsIDOMNode *aDOMNode,
void *aData)
void *aData,
PRBool aAllowDupes)
{
PRBool isTimerStarted = PR_TRUE;
PRInt32 numQueuedEvents = mEventsToFire.Count();
@ -896,7 +903,7 @@ nsresult nsDocAccessible::FireDelayedToolkitEvent(PRUint32 aEvent,
}
isTimerStarted = PR_FALSE;
}
else {
else if (!aAllowDupes) {
// Check for repeat events. If a redundant event exists remove
// original and put the new event at the end of the queue
// so it is fired after the others

Просмотреть файл

@ -106,7 +106,7 @@ class nsDocAccessible : public nsBlockAccessible,
static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure);
virtual void CheckForEditor();
nsresult FireDelayedToolkitEvent(PRUint32 aEvent, nsIDOMNode *aDOMNode,
void *aData);
void *aData, PRBool aAllowDupes = PR_FALSE);
nsInterfaceHashtable<nsVoidHashKey, nsIAccessNode> mAccessNodeCache;
void *mWnd;

Просмотреть файл

@ -28,8 +28,6 @@
</content>
<implementation implements="nsIDOMXULMultiSelectControlElement, nsIAccessibleProvider">
<field name="_isUpSelection">0</field>
<field name="_isDownSelection">0</field>
<field name="_suppressOnSelect">false</field>
<field name="_selectionStart">null</field>
<field name="_currentItem">null</field>
@ -219,8 +217,12 @@
if (this._currentItem)
this._currentItem.current = false;
this._currentItem = val;
if (val)
val.current = true;
if (val) {
val.current = true;
var event = document.createEvent("Events");
event.initEvent("DOMMenuItemActive", true, true);
val.dispatchEvent(event);
}
return val;
]]>
</setter>
@ -339,7 +341,6 @@
var suppressSelect = this._suppressOnSelect;
this._suppressOnSelect = true;
this.clearSelection();
this._selectionStart = startItem;
@ -357,11 +358,23 @@
while (currentItem) {
if (currentItem.localName == "listitem")
this.addItemToSelection(currentItem);
if (currentItem == endItem)
if (currentItem == endItem) {
currentItem = this.getNextItem(currentItem, 1);
break;
}
currentItem = this.getNextItem(currentItem, 1);
}
// Clear around new selection
// Don't use clearSelection() because it causes a lot of noise
// with respect to selection removed notifications used by the
// accessibility API support.
for (; currentItem; currentItem = this.getNextItem(currentItem, 1))
this.removeItemFromSelection(currentItem);
for (currentItem = this.getItemAtIndex(0); currentItem != startItem;
currentItem = this.getNextItem(currentItem, 1))
this.removeItemFromSelection(currentItem);
this._suppressOnSelect = suppressSelect;
this._fireOnSelect();
@ -501,9 +514,78 @@
return this.listBoxObject.getRowCount();
</body>
</method>
<method name="moveByOffset">
<parameter name="offset"/>
<parameter name="isSelecting"/>
<parameter name="isSelectingRange"/>
<body>
<![CDATA[
if ((isSelectingRange || !isSelecting) && this.selType != "multiple")
return;
var newIndex = this.currentIndex + offset;
if (newIndex < 0)
newIndex = 0;
var numItems = this.getRowCount();
if (newIndex > numItems - 1)
var newIndex = numItems - 1;
var newItem = this.getItemAtIndex(newIndex);
if (newItem) {
this.ensureIndexIsVisible(newIndex);
if (isSelectingRange) {
this.selectItemRange(null, newItem);
}
else if (isSelecting) {
this.selectItem(newItem);
}
this.currentItem = newItem;
}
]]>
</body>
</method>
<method name="scrollOnePage">
<parameter name="direction"/> <!-- Must be -1 or 1 -->
<body>
<![CDATA[
var pageOffset = this.getNumberOfVisibleRows() * direction;
var newTop = this.getIndexOfFirstVisibleRow() + pageOffset;
if (direction == 1) {
var maxTop = this.getRowCount() - pageOffset;
if (newTop >= maxTop && maxTop > this.currentIndex) {
newTop = maxTop;
}
}
else if (newTop < 0)
newTop = 0;
this.scrollToIndex(newTop);
return pageOffset;
]]>
</body>
</method>
</implementation>
<handlers>
<handler event="keypress" keycode="vk_up" modifiers="control shift any"
phase="target" action="moveByOffset(-1, !event.ctrlKey, event.shiftKey);"/>
<handler event="keypress" keycode="vk_down" modifiers="control shift any"
phase="target" action="moveByOffset(1, !event.ctrlKey, event.shiftKey);"/>
<handler event="keypress" keycode="vk_home" modifiers="control shift any"
phase="target" action="moveByOffset(-this.currentIndex, !event.ctrlKey, event.shiftKey);"/>
<handler event="keypress" keycode="vk_end" modifiers="control shift any"
phase="target" action="moveByOffset(this.getRowCount() - this.currentIndex - 1, !event.ctrlKey, event.shiftKey);"/>
<handler event="keypress" keycode="vk_page_up" modifiers="control shift any"
phase="target" action="moveByOffset(this.scrollOnePage(-1), !event.ctrlKey, event.shiftKey);"/>
<handler event="keypress" keycode="vk_page_down" modifiers="control shift any"
phase="target" action="moveByOffset(this.scrollOnePage(1), !event.ctrlKey, event.shiftKey);"/>
<handler event="keypress" key=" " phase="target">
<![CDATA[
if (this.currentItem) {
if (this.currentItem.getAttribute("type") != "checkbox")
this.addItemToSelection(this.currentItem);
else if (!this.currentItem.disabled)
this.currentItem.checked = !this.currentItem.checked;
}
]]>
</handler>
<handler event="focus">
<![CDATA[
if (this.currentIndex == -1 && this.getRowCount() > 0) {
@ -517,157 +599,12 @@
}
]]>
</handler>
<handler event="keypress" keycode="vk_up" phase="target">
<handler event="keypress" key=" " modifiers="control" phase="target">
<![CDATA[
if (this.selectedItems.length < 1)
return;
this._isUpSelection=0;
this._isDownSelection=0;
var n = this.getPreviousItem(this.selectedItems[this.selectedItems.length-1], 1);
if (n) {
this.ensureIndexIsVisible(this.getIndexOfItem(n));
this.timedSelect(n, this._selectDelay);
}
if (this.currentItem && this.selType == "multiple")
this.toggleItemSelection(this.currentItem);
]]>
</handler>
<handler event="keypress" keycode="vk_down" phase="target">
<![CDATA[
var n;
if (this.selectedItems.length == 0) {
n = this.getItemAtIndex(0);
}
else {
this._isUpSelection=0;
this._isDownSelection=0;
n = this.getNextItem(this.selectedItems[this.selectedItems.length-1], 1);
}
if (n) {
this.ensureIndexIsVisible(this.getIndexOfItem(n));
this.timedSelect(n, this._selectDelay);
}
]]>
</handler>
<handler event="keypress" modifiers="shift" keycode="vk_up" phase="target">
<![CDATA[
var l=this.selectedItems.length;
if (l < 1 || this.selType != "multiple")
return;
var n = this.getPreviousItem(this.selectedItems[l-1], 1);
if (n) {
this.ensureElementIsVisible(n);
if ( this._isDownSelection) {
if ( l > 1 )
this.removeItemFromSelection(this.selectedItems[l-1]);
if ( l <= 2 )
this._isDownSelection=0;
}
else {
this.addItemToSelection(n);
this._isUpSelection=1;
}
}
]]>
</handler>
<handler event="keypress" modifiers="shift" keycode="vk_down" phase="target">
<![CDATA[
var l=this.selectedItems.length;
if (l < 1 || this.selType != "multiple")
return;
var n = this.getNextItem(this.selectedItems[l-1], 1);
if (n) {
this.ensureElementIsVisible(n);
if ( this._isUpSelection) {
if ( l > 1 )
this.removeItemFromSelection(this.selectedItems[l-1]);
if ( l <= 2 )
this._isUpSelection=0;
}
else {
this.addItemToSelection(n);
this._isDownSelection=1;
}
}
]]>
</handler>
<handler event="keypress" keycode="vk_page_up" phase="target">
<![CDATA[
var l = this.selectedItems.length;
if (l < 1)
return;
this._isUpSelection=0;
this._isDownSelection=0;
var i = this.getIndexOfFirstVisibleRow();
if ( i == 0 )
var n=this.getItemAtIndex(0);
else {
var v = this.getNumberOfVisibleRows();
n = this.getPreviousItem(this.selectedItems[l-1], v);
var newIndex = i - v;
if ( ! n || newIndex < 0 ) {
newIndex=0;
n=this.getItemAtIndex(this.getIndexOfItem(this.selectedItems[l-1]) - i);
}
this.scrollToIndex(newIndex);
}
this.timedSelect(n, this._selectDelay);
]]>
</handler>
<handler event="keypress" keycode="vk_page_down" phase="target">
<![CDATA[
var l = this.selectedItems.length;
if (l < 1)
return;
this._isUpSelection=0;
this._isDownSelection=0;
var i = this.getIndexOfFirstVisibleRow();
var v = this.getNumberOfVisibleRows();
var count = this.getRowCount();
var n;
if ( i >= count - v )
n=this.getItemAtIndex(count - 1);
else {
n = this.getNextItem(this.selectedItems[l-1], v);
var newIndex = i + v;
if ( ! n || newIndex > count - v ) {
newIndex = count - v;
n = this.getItemAtIndex(newIndex + this.getIndexOfItem(this.selectedItems[l-1]) - i);
}
this.scrollToIndex(newIndex);
}
this.timedSelect(n, this._selectDelay);
]]>
</handler>
<handler event="keypress" keycode="vk_home" phase="target">
<![CDATA[
if (this.selectedItems.length < 1)
return;
this._isUpSelection=0;
this._isDownSelection=0;
this.scrollToIndex(0);
this.selectItem(this.getItemAtIndex(0));
]]>
</handler>
<handler event="keypress" keycode="vk_end" phase="target">
<![CDATA[
if (this.selectedItems.length < 1)
return;
this._isUpSelection=0;
this._isDownSelection=0;
var count = this.getRowCount();
this.ensureIndexIsVisible(count-1);
this.selectItem(this.getItemAtIndex(count-1));
]]>
</handler>
<handler event="keypress" key=" " phase="target">
<![CDATA[
if (this.currentItem &&
this.currentItem.getAttribute("type") == "checkbox" &&
!this.currentItem.disabled)
this.currentItem.checked = !this.currentItem.checked;
]]>
</handler>
<handler event="keypress" phase="target">
<![CDATA[
if (!this.disableKeyNavigation && event.charCode > 0 &&
@ -710,8 +647,6 @@
var cellText = item.getAttribute("label");
cellText = cellText.substring(0, length).toLowerCase();
if (cellText == incrementalString) {
this._isUpSelection=0;
this._isDownSelection=0;
this.ensureIndexIsVisible(k);
this.timedSelect(item, this._selectDelay);
break;