Closed Bug 299766 Opened 19 years ago Closed 19 years ago

Implement accesskey support

Categories

(Core Graveyard :: XForms, enhancement)

x86
All
enhancement
Not set
normal

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: aaronr, Assigned: doronr)

Details

(Keywords: fixed1.8.0.2, fixed1.8.1)

Attachments

(5 files, 2 obsolete files)

The attribute accesskey is mentioned in the spec and unlike navindex, is
actually a part of our most likely host language (xhtml 1.x).  I think that we
should support it.  It will be good for accessibility and the types of forms
that use accelerators (like Bugzilla).  formsPlayer also supports it.

Potential questions that I see:
1) what if a xhtml control already uses that access key.  Who should win?  Or
just a console error?
2) what if the xforms element exists in a non-xhtml host document?  Should we
ignore the attribute?
3) treat like focus when @accesskey is on a group or repeat or just ignore? 
What about label and output and other controls that really don't really have the
concept of input focus?
4) what if you put a @accesskey on a control inside a repeat?  Which one gets
control, the first or last occurance?

If we don't have a clear answer to these or other questions along these lines, I
guess we should strive to be compatible with formsPlayer.
Attached file testcase
testcase that contains various examples that may or may not need to be covered
by the implementation.	I'd think at least support for @accesskey on input,
secret, textarea, select, select1, upload, range, trigger, and submit.
Should output really have accesskeys?  Can an output be focused?
Assignee: aaronr → doronr
Status: NEW → ASSIGNED
Attachment #188437 - Flags: review?(smaug)
Comment on attachment 188437 [details] [diff] [review]
xbl widgets are easy, we just need to inherit the accesskey attribute

This looks ok, but doesn't work with XTF based controls (<select*>)
I think we can check this patch in even now, but keep this bug open.
Attachment #188437 - Flags: review?(smaug) → review+
Comment on attachment 188437 [details] [diff] [review]
xbl widgets are easy, we just need to inherit the accesskey attribute

right, this is just for xblized controls.  Question is, do we want to write the
c++ code for this or wait for xblizing of the remaining controls?
Attachment #188437 - Flags: review?(aaronr)
Yes, I'd say to put in the accesskey stuff in for the non-XBL controls.  If
nothing else it is pretty simple (just forward the attribute to the anonymous
content when ::AttributeSet is called) and it will be there to see for the
person who eventually ports them to XBL so that they don't get implemented in
XBL without them.

Something else that we need to consider is to underline the appropriate
character in the label so that the user has a visual indication what the
accesskey is for a particular control.  That can be done in a seperate bug, though.
Attachment #188437 - Flags: review?(aaronr) → review+
XBL patch checked in, looking at the c++ ones now.
Attached patch make upload support accesskey (obsolete) — Splinter Review
select/select1 are beign xblized so I didn't do them.
Attachment #188542 - Flags: review?(aaronr)
Comment on attachment 188542 [details] [diff] [review]
make upload support accesskey

>Index: extensions/xforms/nsXFormsUploadElement.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/nsXFormsUploadElement.cpp,v
>retrieving revision 1.8
>diff -u -r1.8 nsXFormsUploadElement.cpp
>--- extensions/xforms/nsXFormsUploadElement.cpp	2 Jun 2005 07:48:40 -0000	1.8
>+++ extensions/xforms/nsXFormsUploadElement.cpp	7 Jul 2005 15:27:38 -0000
>@@ -85,6 +85,8 @@
> 
>   // nsIXTFElement overrides
>   NS_IMETHOD OnDestroyed();
>+  NS_IMETHOD AttributeSet(nsIAtom *aName, const nsAString &aValue);
>+  NS_IMETHOD AttributeRemoved(nsIAtom *aName);
> 
>   // nsIXFormsControl
>   NS_IMETHOD Refresh();
>@@ -146,8 +148,6 @@
>   mInput = do_QueryInterface(element);
>   NS_ENSURE_STATE(mInput);
> 
>-  mInput->SetType(NS_LITERAL_STRING("file"));
>-
>   mLabel->AppendChild(mInput, getter_AddRefs(childReturn));
> 

You didn't mean to remove the 'file' type.  With that put back in, r+
Attachment #188542 - Flags: review?(aaronr) → review+
Comment on attachment 188542 [details] [diff] [review]
make upload support accesskey

indeed, did not mean to remove the settype call, not sure how that happend.
Attachment #188542 - Flags: review?(smaug)
Attached patch missed the atoms changes (obsolete) — Splinter Review
Attachment #188542 - Attachment is obsolete: true
Attachment #188571 - Flags: review?(smaug)
Attachment #188542 - Flags: review?(smaug)
Comment on attachment 188571 [details] [diff] [review]
missed the atoms changes

corrupt patch
Attachment #188571 - Attachment is obsolete: true
Attachment #188571 - Flags: review?(smaug)
Attachment #188575 - Flags: review?(smaug)
Attachment #188575 - Flags: review?(smaug) → review+
(In reply to comment #5)
> Something else that we need to consider is to underline the appropriate
> character in the label so that the user has a visual indication what the
> accesskey is for a particular control.  That can be done in a seperate bug, though.

when mnemonic is pressed, make sure proper control gets focus, especially like upload, select with @selection="full", etc.
I have a patch for the underlining part, will attach tomorrow.
Add underlining xbl binding, add accesskey to select/select1 and remove useless repeated accesskey inheriting in upload.
Attachment #203545 - Flags: review?(smaug)
Comment on attachment 203545 [details] [diff] [review]
accesskey underlining patch


>+            } else {
>+              // if we didn't find the accesskey, append it to the end
>+              content.textContent += "(_" + accesskey + ")";
>+            }
>+          }

The accesskey should be underlined and inside ( ) . 
With that r=me
Attachment #203545 - Flags: review?(smaug) → review+
Attachment #203545 - Flags: review?(aaronr)
Comment on attachment 203545 [details] [diff] [review]
accesskey underlining patch

>Index: extensions/xforms/resources/content/xforms.css
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/resources/content/xforms.css,v
>retrieving revision 1.7
>diff -1 -0 -u -r1.7 xforms.css
>--- extensions/xforms/resources/content/xforms.css	14 Nov 2005 08:42:36 -0000	1.7
>+++ extensions/xforms/resources/content/xforms.css	18 Nov 2005 19:46:58 -0000
>@@ -109,20 +109,31 @@
> }
> 
> trigger[appearance="minimal"]:hover, submit[appearance="minimal"]:hover {
>   cursor: pointer;
> }
> 
> label {
>   -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-label');
> }
> 
>+input > label,
>+secret > label,
>+textarea > label,
>+trigger > label,
>+submit > label,
>+select > label,
>+select1 > label,
>+upload > label {
>+  -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-label-accesskey');
>+}
>+
> select1 {
>   -moz-binding: url('chrome://xforms/content/select1.xml#xformswidget-select1');
> }
> 
> select1 itemset,
> select itemset {
>   -moz-binding: url('chrome://xforms/content/select1.xml#xformswidget-itemset');
> }
> 
> /* Most of the select1 specific CSS is copied from forms.css */
>Index: extensions/xforms/resources/content/xforms.xml
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/resources/content/xforms.xml,v
>retrieving revision 1.19
>diff -1 -0 -u -r1.19 xforms.xml
>--- extensions/xforms/resources/content/xforms.xml	14 Nov 2005 08:42:36 -0000	1.19
>+++ extensions/xforms/resources/content/xforms.xml	18 Nov 2005 19:46:58 -0000
>@@ -191,21 +191,89 @@
>             anoncontent.removeAttribute("style");
>           }
> 
>           document.getAnonymousElementByAttribute(this, "anonid", "content").textContent =
>             this.stringValue;
>           return true;
>         </body>
>       </method>
>     </implementation>
>   </binding>
>-  
>+
>+  <!-- LABEL: <ACCESKEY SUPPORT> -->
>+  <binding id="xformswidget-label-accesskey"
>+           extends="chrome://xforms/content/xforms.xml#xformswidget-base">
>+    <content>
>+      <html:span anonid="content"></html:span>
>+      <html:span anonid="anoncontent" style="display:none;">
>+        <children/>
>+      </html:span>
>+    </content>
>+    <implementation implements="nsIXFormsUIWidget">
>+      <method name="refresh">
>+        <body>
>+        <![CDATA[
>+          // we cannot access the <children/> content in XBL1, so we switch to
>+          // always cloning the content into the conctent span.

nit: spelling of 'conctent'

If we are only going to be handling accesskey via xbl now, could you remove accesskey from nsxformsatoms.cpp and nsxformsatoms.h, please?
Comment on attachment 203545 [details] [diff] [review]
accesskey underlining patch

removing review request...new patch coming
Attachment #203545 - Flags: review?(aaronr)
Attachment #204473 - Flags: review?(aaronr)
Comment on attachment 204473 [details] [diff] [review]
patch with nits fixed and atoms removed

>? extensions/xforms/attachment.cgi?id=191913
>? extensions/xforms/attachment.cgi?id=203428
>Index: extensions/xforms/nsXFormsAtoms.cpp
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/nsXFormsAtoms.cpp,v
>retrieving revision 1.16
>diff -u -1 -0 -r1.16 nsXFormsAtoms.cpp
>--- extensions/xforms/nsXFormsAtoms.cpp	10 Oct 2005 19:11:20 -0000	1.16
>+++ extensions/xforms/nsXFormsAtoms.cpp	29 Nov 2005 19:02:04 -0000
>@@ -54,21 +54,20 @@
> nsIAtom *nsXFormsAtoms::ref;
> nsIAtom *nsXFormsAtoms::value;
> nsIAtom *nsXFormsAtoms::nodeset;
> nsIAtom *nsXFormsAtoms::model;
> nsIAtom *nsXFormsAtoms::selected;
> nsIAtom *nsXFormsAtoms::appearance;
> nsIAtom *nsXFormsAtoms::incremental;
> nsIAtom *nsXFormsAtoms::clazz;
> nsIAtom *nsXFormsAtoms::deferredBindListProperty;
> nsIAtom *nsXFormsAtoms::readyForBindProperty;
>-nsIAtom *nsXFormsAtoms::accesskey;
> nsIAtom *nsXFormsAtoms::fatalError;
> nsIAtom *nsXFormsAtoms::isInstanceDocument;
> nsIAtom *nsXFormsAtoms::instanceDocumentOwner;
> 
> const nsStaticAtom nsXFormsAtoms::Atoms_info[] = {
>   { "src",                      &nsXFormsAtoms::src },
>   { "bind",                     &nsXFormsAtoms::bind },
>   { "type",                     &nsXFormsAtoms::type },
>   { "readonly",                 &nsXFormsAtoms::readonly },
>   { "required",                 &nsXFormsAtoms::required },
>@@ -82,21 +81,20 @@
>   { "ref",                      &nsXFormsAtoms::ref },
>   { "value",                    &nsXFormsAtoms::value },
>   { "nodeset",                  &nsXFormsAtoms::nodeset },
>   { "model",                    &nsXFormsAtoms::model },
>   { "selected",                 &nsXFormsAtoms::selected },
>   { "appearance",               &nsXFormsAtoms::appearance },
>   { "incremental",              &nsXFormsAtoms::incremental },
>   { "class",                    &nsXFormsAtoms::clazz },
>   { "DeferredBindListProperty", &nsXFormsAtoms::deferredBindListProperty },
>   { "ReadyForBindProperty",     &nsXFormsAtoms::readyForBindProperty },
>-  { "accesskey",                &nsXFormsAtoms::accesskey },
>   { "fatalError",               &nsXFormsAtoms::fatalError },
>   { "isInstanceDocument",       &nsXFormsAtoms::isInstanceDocument },
>   { "instanceDocumentOwner",    &nsXFormsAtoms::instanceDocumentOwner }
> };
> 
> void
> nsXFormsAtoms::InitAtoms()
> {
>   NS_RegisterStaticAtoms(Atoms_info, NS_ARRAY_LENGTH(Atoms_info));
> }
>Index: extensions/xforms/nsXFormsAtoms.h
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/nsXFormsAtoms.h,v
>retrieving revision 1.18
>diff -u -1 -0 -r1.18 nsXFormsAtoms.h
>--- extensions/xforms/nsXFormsAtoms.h	10 Oct 2005 19:11:20 -0000	1.18
>+++ extensions/xforms/nsXFormsAtoms.h	29 Nov 2005 19:02:04 -0000
>@@ -62,21 +62,20 @@
>   static NS_HIDDEN_(nsIAtom *) ref;
>   static NS_HIDDEN_(nsIAtom *) nodeset;
>   static NS_HIDDEN_(nsIAtom *) model;
>   static NS_HIDDEN_(nsIAtom *) selected;
>   static NS_HIDDEN_(nsIAtom *) appearance;
>   static NS_HIDDEN_(nsIAtom *) incremental;
>   static NS_HIDDEN_(nsIAtom *) value;
>   static NS_HIDDEN_(nsIAtom *) clazz;
>   static NS_HIDDEN_(nsIAtom *) deferredBindListProperty;
>   static NS_HIDDEN_(nsIAtom *) readyForBindProperty;
>-  static NS_HIDDEN_(nsIAtom *) accesskey;
>   static NS_HIDDEN_(nsIAtom *) fatalError;
>   static NS_HIDDEN_(nsIAtom *) isInstanceDocument;
>   static NS_HIDDEN_(nsIAtom *) instanceDocumentOwner;
> 
>   static NS_HIDDEN_(void) InitAtoms();
> 
>  private:
>   static NS_HIDDEN_(const nsStaticAtom) Atoms_info[];
> };
> 
>Index: extensions/xforms/resources/content/select.xml
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/resources/content/select.xml,v
>retrieving revision 1.10
>diff -u -1 -0 -r1.10 select.xml
>--- extensions/xforms/resources/content/select.xml	22 Nov 2005 14:01:37 -0000	1.10
>+++ extensions/xforms/resources/content/select.xml	29 Nov 2005 19:02:05 -0000
>@@ -75,21 +75,21 @@
>           xmlns:xforms="http://www.w3.org/2002/xforms">
> 
>  <!-- SELECT: <DEFAULT> -->
>   <binding id="xformswidget-select"
>            extends="chrome://xforms/content/xforms.xml#xformswidget-base">
>     <content>
>       <html:label>
>         <html:span>
>            <children includes="label"/>
>         </html:span>
>-        <html:select xbl:inherits="style"
>+        <html:select xbl:inherits="style, accesskey"
>                      class="xf-value"
>                      onchange="this.parentNode.parentNode.selectionChanged();"
>                      onfocus="this.parentNode.parentNode.dispatchDOMUIEvent('DOMFocusIn');"
>                      onblur="this.parentNode.parentNode.handleBlur(); this.parentNode.parentNode.dispatchDOMUIEvent('DOMFocusOut');"
>                      multiple="true"
>                      size="5"
>                      anonid="select"/>
>         <children/>
>       </html:label>
>     </content>
>Index: extensions/xforms/resources/content/select1.xml
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/resources/content/select1.xml,v
>retrieving revision 1.10
>diff -u -1 -0 -r1.10 select1.xml
>--- extensions/xforms/resources/content/select1.xml	17 Nov 2005 22:00:26 -0000	1.10
>+++ extensions/xforms/resources/content/select1.xml	29 Nov 2005 19:02:06 -0000
>@@ -55,20 +55,21 @@
>                 onmouseover="this.parentNode.shouldHandleBlur = false;
>                              this.parentNode.mouseOver(event);"
>                 onmouseup="this.parentNode.mouseUp(event);"
>                 onmouseout="this.parentNode.shouldHandleBlur = true;">
>         <children/>
>       </html:div>
>       <html:span class="-moz-select1-container"
>                  anonid="container"><html:input
>                  class="-moz-xforms-select1-input"
>                  anonid="control"
>+                 xbl:inherits="accesskey"
>                  onfocus="this.parentNode.parentNode.dispatchDOMUIEvent('DOMFocusIn')"
>                  onblur="this.parentNode.parentNode.handleBlur(); this.parentNode.parentNode.dispatchDOMUIEvent('DOMFocusOut');"
>                  onclick="this.parentNode.parentNode.handleControlClick();"
>                  onkeypress="this.parentNode.parentNode.handleKeyPress(event);"
>                  onkeyup="this.parentNode.parentNode.handleKeyUp(event);"
>       /><html:input class="-moz-xforms-select1-dropdown xf-value"
>                     type="button"
>                     anonid="dropmarker"
>                     tabindex="-1"
>                     onmousedown="this.parentNode.parentNode.shouldHandleBlur = false;"
>Index: extensions/xforms/resources/content/xforms.css
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/resources/content/xforms.css,v
>retrieving revision 1.8
>diff -u -1 -0 -r1.8 xforms.css
>--- extensions/xforms/resources/content/xforms.css	22 Nov 2005 18:53:33 -0000	1.8
>+++ extensions/xforms/resources/content/xforms.css	29 Nov 2005 19:02:06 -0000
>@@ -184,20 +184,31 @@
> }
> 
> trigger[appearance="minimal"]:hover, submit[appearance="minimal"]:hover {
>   cursor: pointer;
> }
> 
> label {
>   -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-label');
> }
> 
>+input > label,
>+secret > label,
>+textarea > label,
>+trigger > label,
>+submit > label,
>+select > label,
>+select1 > label,
>+upload > label {
>+  -moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-label-accesskey');
>+}
>+
> select1 {
>   -moz-binding: url('chrome://xforms/content/select1.xml#xformswidget-select1');
> }
> 
> select1 itemset,
> select itemset {
>   -moz-binding: url('chrome://xforms/content/select1.xml#xformswidget-itemset');
> }
> 
> /* Most of the select1 specific CSS is copied from forms.css */
>Index: extensions/xforms/resources/content/xforms.xml
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/resources/content/xforms.xml,v
>retrieving revision 1.20
>diff -u -1 -0 -r1.20 xforms.xml
>--- extensions/xforms/resources/content/xforms.xml	22 Nov 2005 18:53:32 -0000	1.20
>+++ extensions/xforms/resources/content/xforms.xml	29 Nov 2005 19:02:07 -0000
>@@ -191,21 +191,89 @@
>             anoncontent.removeAttribute("style");
>           }
> 
>           document.getAnonymousElementByAttribute(this, "anonid", "content").textContent =
>             this.stringValue;
>           return true;
>         </body>
>       </method>
>     </implementation>
>   </binding>
>-  
>+
>+  <!-- LABEL: <ACCESKEY SUPPORT> -->
>+  <binding id="xformswidget-label-accesskey"
>+           extends="chrome://xforms/content/xforms.xml#xformswidget-base">
>+    <content>
>+      <html:span anonid="content"></html:span>
>+      <html:span anonid="anoncontent" style="display:none;">
>+        <children/>
>+      </html:span>
>+    </content>
>+    <implementation implements="nsIXFormsUIWidget">
>+      <method name="refresh">
>+        <body>
>+        <![CDATA[
>+          // we cannot access the <children/> content in XBL1, so we switch to
>+          // always cloning the content into the content span.
>+          var content =
>+            document.getAnonymousElementByAttribute(this, "anonid", "content");
>+
>+          var hasElementChildren = false;
>+          var hasBoundValue = false;
>+
>+          if (this.accessors.hasBoundNode() || this.accessors.getValue() != null) {
>+            content.textContent = this.stringValue;
>+            hasBoundValue = true;
>+          } else {
>+            // clone the contents child by child
>+            var node;
>+            for (var i = 0; i < this.childNodes.length; i++) {
>+              if (!hasElementChildren && this.childNodes[i].nodeType == Node.ELEMENT_NODE)
>+                hasElementChildren = true;
>+
>+              content.appendChild(this.childNodes[i].cloneNode(true));
>+            }
>+          }
>+
>+          // XXX: if label has element node children, we skip accesskey underlining
>+          if (!hasElementChildren && this.parentNode.hasAttribute("accesskey")) {
>+            var accesskey = this.parentNode.getAttribute("accesskey");
>+
>+            // bail if no accesskey or accesskey is longer than 1 character
>+            if (!accesskey || accesskey.length != 1)
>+              return true;
>+
>+            var str = content.textContent;
>+            var location = str.indexOf(accesskey);
>+
>+            if (location > -1) {
>+              // we create a range around the character we want and surround it
>+              // with an <html:u>
>+              var range = document.createRange();
>+              range.setStart(content.firstChild, location)
>+              range.setEnd(content.firstChild, location+1)
>+
>+              var u = document.createElementNS("http://www.w3.org/1999/xhtml", "u");
>+              range.surroundContents(u);
>+            } else {
>+              // if we didn't find the accesskey, append it to the end
>+              content.textContent += "(" + accesskey + ")";
>+            }
>+          }
>+
>+          return true;
>+        ]]>
>+        </body>
>+      </method>
>+    </implementation>
>+  </binding>
>+
>   <!-- INPUT: <DEFAULT> -->
>   <binding id="xformswidget-input"
>            extends="chrome://xforms/content/xforms.xml#xformswidget-base">
>     <content>
>       <children includes="label"/>
>       <html:input anonid="control"
>                   class="xf-value"
>                   onblur="this.parentNode.accessors.setValue(this.value); this.parentNode.dispatchDOMUIEvent('DOMFocusOut')"
>                   onfocus="this.parentNode.dispatchDOMUIEvent('DOMFocusIn')"
>                   onclick="this.parentNode._change();"
>@@ -1171,32 +1239,31 @@
>     </implementation>
>   </binding>
> 
>   <!-- UPLOAD: <DEFAULT> -->
>   <binding id="xformswidget-upload"
>            extends="chrome://xforms/content/xforms.xml#xformswidget-base">
>     <content>
>       <children includes="label"/>
>       <html:input anonid="upload_text_control"
>                   class="xf-value"
>-                  readonly="true"
>-                  xbl:inherits="accesskey"/>
>+                  readonly="true"/>
>       <html:button anonid="upload_browse_button"
>                    type="button"
>                    onclick="this.parentNode.uploadElem.pickFile();"
>                    onkeypress="if (event.keyCode == event.DOM_VK_RETURN) this.parentNode.dispatchDOMUIEvent('DOMActivate');"
>                    xbl:inherits="accesskey"> &xforms.upload.browsetext; </html:button>
>       <html:button anonid="upload_clear_button"
>                    type="button"
>                    onclick="this.parentNode.uploadElem.clearFile();"
>                    onkeypress="if (event.keyCode == event.DOM_VK_RETURN) this.parentNode.dispatchDOMUIEvent('DOMActivate');"
>-                   xbl:inherits="accesskey"> &xforms.upload.cleartext; </html:button>
>+                   > &xforms.upload.cleartext; </html:button>
>       <children/>
>     </content>
> 
>     <implementation implements="nsIXFormsUIWidget, nsIXFormsUploadUIElement">
>       <destructor>
>         this._uploadElem = null;
>         this._textControl = null;
>         this._browseButton = null;
>         this._clearButton = null;
>       </destructor>
Attachment #204473 - Flags: review?(aaronr) → review+
checked into trunk
Whiteboard: xf-to-branch
checked into MOZILLA_1_8_BRANCH via bug 323691.  Leaving open for now until it gets into 1.8.0
Whiteboard: xf-to-branch
Status: ASSIGNED → RESOLVED
Closed: 19 years ago
Keywords: fixed1.8.0.2
Resolution: --- → FIXED
verfied fixed on MOZILLA_1_8_BRANCH
Keywords: fixed1.8.1
Product: Core → Core Graveyard
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: