TinyMCE Accessibility: Label For
Asked Answered
S

3

7

One of our web applications just went through 508 compliance testing. We use TinyMCE version 3 for content development and I understand it generally has good accessibility. However, one of our pages contains 3 or more TinyMCE instances each preceded by a label indicating what the TinyMCE instance is for but we are being told that these are "implicit" labels when they should be "explicit" labels (i.e. with the for attribute). Problem is, TinyMCE instances are just iframes with a complex assortment of custom html "controls", whereas as far as I know the label/for technique only works with traditional form elements. What's the best strategy for achieving an "explicit" label for a TinyMCE instance?

Thanks!

Edit

Solutions explored using label + for which don't work: pointing the label at the initial textarea, pointing the label at the generated iframe.

One possible solution I am exploring is encompassing each TinyMCE instance with a ledgend + fieldset but testing this out with JAWS 9.0 it doesn't seem to make any difference unless the fieldset contains form elements (e.g. input, type=text) and JAWS is in forms mode.

Squeak answered 23/11, 2010 at 17:3 Comment(0)
M
5

There is an emerging standard for exactly this kind of problem: ARIA (Accessible Rich Internet Applications). It's still a working draft, but support is beginning to show up in recent screen readers (JAWS 9, recent versions of NVDA) when used with recent browsers (IE 9, Firefox 3.6 (partial) and 4.0, Chrome).

In this particular case, take a look at aria-label and aria-labelledby. These are attributes which would be added to the BODY element in TinyMCE's widget -- or to the IFRAME, whichever of the two actually takes focus when the user is entering data. Thus:

<body aria-label="Edit document">

The aria-label attribute just specifies a string that serves as the label. The aria-labelledby (note the two L's, as per British spelling) works like the traditional LABEL element in reverse. That is, you feed it an ID:

<body aria-labelledby="edit-label">

And then you would have this someplace else in the code:

<label id="edit-label">Edit document</label>

It doesn't necessarily have to be a LABEL element, you could use a SPAN or whatever, but LABEL seems semantically appropriate.

ARIA attributes will not validate under HTML 4, or XHTML DTD's. However, they WILL validate under HTML 5 (itself still in development). If validation is important to you under an older DTD, you can add the attributes programmatically using JavaScript when the page has loaded.

Ideally, if you have a visible label for the widget already, then you should be using aria-labelledby to prevent redundancy. However, I have no idea if it'll work across document boundaries. That is, if the BODY is in an IFRAME, and the visible label is defined in the IFRAME's parent document, I don't know if it'll work. The browser/screen reader may treat the two as separate documents which don't talk to one another. You'll have to experiment to find out. But if it turns out they don't work, try http://www.w3.org/TR/wai-aria/states_and_properties#aria-hidden. Thus, in the parent document:

<label aria-hidden="true">Edit document</label>

And in the TinyMCE document:

<body aria-label="Edit document">

The aria-hidden attribute will prevent the label in the parent document from being read, and the aria-label attribute in the child document (which is not visible) will take its place. Voila, a widget labeled both visibly and audibly with no redundant reading.

If you use aria-hidden this way, be very careful that the bit you're hiding (or an equivalent) is always made available for reading someplace else.

This solution will only work for people using web browsers and screen readers that support ARIA. People with older screen readers or browsers will be out of luck, which is discussed at length in the recent article on A List Apart, The Accessibility of WAI ARIA. The author makes a good case for preferring traditional semantic HTML solutions whenever possible; but in your case I don't think you have any other option. At the very least, adding ARIA attributes will let you reasonably claim that you've done your due diligence and made a good faith effort to make it as accessible as possible.

Good luck!

Note to far future readers: The links to the ARIA specification given here refer to the September 2010 working draft. If it's been more than a few months since then, check for more recent specs.

Malikamalin answered 12/12, 2010 at 20:31 Comment(0)
C
1

Using the information Will Martin provided regarding the aria-label attribut, I wrote the following line of code which works for TinyCME 4:

tinymce.init({
    …
    init_instance_callback: function(editor) {
        jQuery(editor.getBody()).attr('aria-label', jQuery('label[for="' + editor.id + '"]').text())
    }
});

It uses the callback function triggered after initialisation of the editor.

There has to be a label targeted at the original element on which TinyMCE is call upon, in my case a textarea. e.g.:

<label for="id_of_textarea">Shiny wysiwyg editor"</label><textarea id="id_of_textarea"></textarea>

The content of the label (text only) is added as aria-label attribute to the body tag inside the TinyMCE-iframe.

OSX screenreader is propperly returing the label when selecting the TinyMCE

Some inspiration from TinyMCE: How bind on event after its initialized

Cellarer answered 19/12, 2017 at 9:14 Comment(0)
C
0

If I read the specs right, the for property must indeed point to another control on the same page, as you already say.

Therefore, I think the only valid option is to point the for attribute to the <textarea> element that TinyMCE replaces. It makes the most sense, seeing as that element gets sent to the server when editing is finished.

Crossexamine answered 23/11, 2010 at 17:7 Comment(2)
Thanks @Pekka, I had tried pointing the label at the textarea, but I think it doesn't work because the textarea is made invisible (JAWS, for example, typically does not read display:none or visibility:hidden elements).Squeak
@Stephen yeah, I think you are somewhat screwed with this :) I guess you could make it point to the iframe's id when TinyMCE has replaced it, but it's not valid as such. Maybe still better than the alternative, I can't judge thatCrossexamine

© 2022 - 2024 — McMap. All rights reserved.