Repository: nvaccess/nvda

Issue:
Single letter navigation to editable text fields should include rich text editors
Hello, I’m Hyongsop Kim in Korea and NVDA 2015.4 user.
In web browser and BrowseMode is on, if I press e, NVDA jump to the next edit field.
By the way, if the edit field is RichText edit such as CkEditor, NVDA can’t recognize it as a edit field.
So to go to this field, I have to go by pressing tab or arrow keys.
So please consider about recognizing such field with BrowseMode quick navigation key.

Thank you.



Discussion:
Is CkEditor contained in an "application"? That is, can you get to the 
editable content in browse mode with the arrow keys or do you only hear 
application? If so, browse mode will never be able to get to this, since 
applications are very intentionally not exposed in browse mode.

Note that there are still some rich text edit fields that aren't inside 
applications and quick navigation doesn't currently move to those, but 
it should.

`data:text/html,<p>Before</p><div contentEditable="true">Content</div><p>After</p>`

STR:

1. Open the above URL in Firefox and focus the document.
2. Press control+home to move to the top.
3. Press e.
 * Expected: NVDA should jump to the editor containing "Content".
 * Actual: It doesn't.

This should also work for the "f" form field navigation command.

Note that the role in this case is section, but the role is irrelevant. The key point in Firefox is that it has the editable state. In IE, the key point is that the element is contentEditable.

P2 because this makes getting to many rich text editors less efficient and because as far as a user is concerned, this is an editor (even though it reports differently).
A lot of rich text editors use role=aplication around the editor and 
controls.


On 1/4/2017 4:14 PM, James Teh wrote:
>
> |data:text/html,<p>Before</p><div 
> contentEditable="true">Content</div><p>After</p>|
>
> STR:
>
>  1. Open the above URL in Firefox and focus the document.
>  2. Press control+home to move to the top.
>  3. Press e.
>
>   * Expected: NVDA should jump to the editor containing "Content".
>   * Actual: It doesn't.
>
> This should also work for the "f" form field navigation command.
>
> Note that the role in this case is section, but the role is 
> irrelevant. The key point in Firefox is that it has the editable 
> state. In IE, the key point is that the element is contentEditable.
>
> P2 because this makes getting to many rich text editors less efficient 
> and because as far as a user is concerned, this is an editor (even 
> though it reports differently).
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub 
> <https://github.com/nvaccess/nvda/issues/5534#issuecomment-270515131>, 
> or mute the thread 
> <https://github.com/notifications/unsubscribe-auth/AFGiverKL7AplQU3IgLCGqWtJd-mTI8xks5rPCftgaJpZM4GoD6G>.
>

-- 
------------------------------------------------------------------------


    Derek Riemer

  * Department of computer science, third year undergraduate student.
  * Proud user of the NVDA screen reader.
  * Open source enthusiast.
  * Member of Bridge Cu
  * Avid skiier.

Websites:
Honors portfolio <http://derekriemer.com>
Awesome little hand built weather app! 
<http://django.derekriemer.com/weather/>

email me at derek.riemer@colorado.edu <mailto:derek.riemer@colorado.edu>
Phone: (303) 906-2194


That we can't cover here, I'm afraid. If something is an application, it's
not included in browse mode unless the user focuses the application and
forces it.

@jcsteh:  as discussed by voice, not only will the editable container have the editable state, but all descendants within it. This includes say a button for instance, which can be focused and has the focusable state. So editable+focusable is not enough here. However, when before an editable, quicknav to editable will find the correct one because it will be the highest parent. When in, we could some how jump out of the current highest editable ancestor before searching again (though  our infrastructure does not quite handle that yet).  And searching backward, the parents would have to be searched before children, which I can't remember if we do that or not. 
Note that #7290 is a pr that will at least be of help for application based editors. Strictly spoken, @khsbory explicitly mentioned CkEditor, and as that seems to be application embedded from my last findings, that can't be fixed. See https://github.com/nvaccess/nvda/issues/5534#issuecomment-159154767

As well as the normal editableText role, We will look for the editable state, but only on document, textFrame, section and paragraph. 

Resolving patch:
diff --git a/source/virtualBuffers/MSHTML.py b/source/virtualBuffers/MSHTML.py
--- a/source/virtualBuffers/MSHTML.py
+++ b/source/virtualBuffers/MSHTML.py
@@ -264,14 +264,23 @@ def _searchableAttribsForNodeType(self,nodeType):
 		elif nodeType=="formField":
 			attrs=[
 				{"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON,oleacc.ROLE_SYSTEM_RADIOBUTTON,oleacc.ROLE_SYSTEM_CHECKBUTTON,oleacc.ROLE_SYSTEM_OUTLINE],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None]},
-				{"IAccessible::role":[oleacc.ROLE_SYSTEM_COMBOBOX,oleacc.ROLE_SYSTEM_TEXT]},
+				{"IAccessible::role":[oleacc.ROLE_SYSTEM_COMBOBOX]},
+				# Focusable edit fields (input type=text, including readonly ones)
+				{"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]},
+				# Any top-most content editable element (E.g. an editable div for rhich text editing) 
+				{"IHTMLElement::isContentEditable":[1],"parent::IHTMLElement::isContentEditable":[0,None]},
 				{"IHTMLDOMNode::nodeName":["SELECT"]},
 				{"HTMLAttrib::role":["listbox"]},
 			]
 		elif nodeType=="button":
 			attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON]}
 		elif nodeType=="edit":
-			attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT,oleacc.ROLE_SYSTEM_COMBOBOX],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1],"IHTMLElement::isContentEditable":[1]}
+			attrs=[
+				# Focusable edit fields (input type=text, including readonly ones)
+				{"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]},
+				# Any top-most content editable element (E.g. an editable div for rhich text editing) 
+				{"IHTMLElement::isContentEditable":[1],"parent::IHTMLElement::isContentEditable":[0,None]},
+			]
 		elif nodeType=="radioButton":
 			attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_RADIOBUTTON],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_FOCUSABLE:[1]}
 		elif nodeType=="comboBox":
diff --git a/source/virtualBuffers/gecko_ia2.py b/source/virtualBuffers/gecko_ia2.py
--- a/source/virtualBuffers/gecko_ia2.py
+++ b/source/virtualBuffers/gecko_ia2.py
@@ -210,6 +210,7 @@ def _searchableAttribsForNodeType(self,nodeType):
 			attrs=[
 				{"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON,oleacc.ROLE_SYSTEM_BUTTONMENU,oleacc.ROLE_SYSTEM_RADIOBUTTON,oleacc.ROLE_SYSTEM_CHECKBUTTON,oleacc.ROLE_SYSTEM_COMBOBOX,oleacc.ROLE_SYSTEM_LIST,oleacc.ROLE_SYSTEM_OUTLINE,IAccessibleHandler.IA2_ROLE_TOGGLE_BUTTON],"IAccessible::state_%s"%oleacc.STATE_SYSTEM_READONLY:[None]},
 				{"IAccessible::role":[oleacc.ROLE_SYSTEM_COMBOBOX,oleacc.ROLE_SYSTEM_TEXT],"IAccessible2::state_%s"%IAccessibleHandler.IA2_STATE_EDITABLE:[1]},
+				{"IAccessible2::state_%s"%IAccessibleHandler.IA2_STATE_EDITABLE:[1],"parent::IAccessible2::state_%s"%IAccessibleHandler.IA2_STATE_EDITABLE:[None]},
 			]
 		elif nodeType=="list":
 			attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_LIST]}
@@ -218,7 +219,10 @@ def _searchableAttribsForNodeType(self,nodeType):
 		elif nodeType=="button":
 			attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_PUSHBUTTON,oleacc.ROLE_SYSTEM_BUTTONMENU,IAccessibleHandler.IA2_ROLE_TOGGLE_BUTTON]}
 		elif nodeType=="edit":
-			attrs={"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT,oleacc.ROLE_SYSTEM_COMBOBOX],"IAccessible2::state_%s"%IAccessibleHandler.IA2_STATE_EDITABLE:[1]}
+			attrs=[
+				{"IAccessible::role":[oleacc.ROLE_SYSTEM_TEXT],"IAccessible2::state_%s"%IAccessibleHandler.IA2_STATE_EDITABLE:[1]},
+				{"IAccessible2::state_%s"%IAccessibleHandler.IA2_STATE_EDITABLE:[1],"parent::IAccessible2::state_%s"%IAccessibleHandler.IA2_STATE_EDITABLE:[None]},
+			]
 		elif nodeType=="frame":
 			attrs={"IAccessible::role":[IAccessibleHandler.IA2_ROLE_INTERNAL_FRAME]}
 		elif nodeType=="separator":


Test patch: