Screenreader Chromevox not reading element when focused - javascript

I can't work out how to get Chromevox read an element once you have changed focus to it via Javascript. Take the example found at OpenAjax. When you click on the Show topic 1 button the controlled element is expanded and focus is moved to it. However in Chromevox it does not read the content of the element just the aria-labelledby.
To get Chromevox to read the content of the element after it has been expand I have to move out and back in again. Not a very good user experience.
Is this an issue to do with Chromevox or is there a better way to approach this?
Note: ignore the other three examples they have typos in their aria-labelledby attributes and thus don't function correctly.

The ajax example is not a good one to mimic. In addition to the t2/m2 typo you mentioned, they have competing labels. There's a (hidden) <div> that contains text ("Topic 1 is all about being...") and there's an aria-labelledby.
According to the accessible name computation rules, https://www.w3.org/TR/accname-1.1/#step2, the aria-labelledby is processed in step 2.B.first-bullet and then the process is done. The text inside the <div> should be ignored.
If there were not an aria-labelledby, then you would get to step 2.G and the inner text would be the accessible name (and read by a screen reader).
So, you are seeing/hearing a conflict and it may depend on the how the browser interprets these rules as to what text is read by the screen reader.
NVDA reads both the aria-labelledby and the text.
JAWS reads only the aria-labelledby, which is technically correct.
It sounds like Chromevox is doing the same thing as JAWS, which is correct.

Related

Set text for screen reader and hide children from screen readers

I have an iframe, inside which arbitrary content is served. I want to ensure content within the iframe is not accessible to screen readers, and specify what screen readers should read out when the iframe is selected.
My expectation is when tabbing through different elements on the page, myDiv is selected as a single unit, and it reads out Unknown content.
I tried the following
<div id="myDiv" title="Unknown content">
<iframe id="myIframe" aria-hidden="true">
{arbitraryContent}
</html>
</div>
Problems I face with this are
Not all content within the iframe are being ignored. Perhaps that is because aria-hidden does not work with focusable child elements.
Unknown text is not always being read, especially if the child elements are focusable.
I also tried setting tabIndex=-1 on the iframe. This however causes all the elements (including myDiv) to not be selectable by keyboard.
What is the right approach to achieve what I am looking for?
If you prevent the screen reader from reading the entire iframe and if it still has focusable elements, yes, you have a fatal accessibility problem:
you can focus something but the screen reader isn't allowed to tell what is focused. So what to do ? Should it say nothing, or go against what you have defined ?
Technically, it means that there shouldn't be any focusable element inside aria-hidden=true.
You must ensure that it never happens.
However, the good question you have to ask yourself is why do you want to completely hide what is in the iframe or in other words, explicitely make it totally unaccessible.
IF your fear is that contents out of your control could break the accessibility of your page, then
Administratively speaking, certifications based on WCAG complience know this problem and usually accept exceptions, i.e. don't take into account something you haven't control in.
Pratically speaking as a screen reader user, the badly accessible iframe will probably indeed give the impression that the whole accessibility of your site is bad in general, but it's still certainly better to have some partially accessible content rather than nothing at all.
You'd better remove the aria-hidden=true. Even if you know that it isn't very accessible, leave a chance to access a little of it no matter what, instead of blocking it definitely. Perhaps the accessibility of the content will improve over time.
The exception to this is if the content of the iframe is objectionnable, decorative, or doesn't bring any real information in the context of your page. Typical examples include ads and various kinds of widgets (weather, clock, social network share, etc.)
For those, go ahead, leave the aria-hidden=true and remove all focusable elements of the iframe. They are anyway just useless noise, without any regret if they are completely skipped.

How to manipulate the DOM of a React webapp (with Chrome DevTools)?

I'm using Chrome DevTools to inspect a React webapp. The app has an upload button with a hidden input field. I'm attempting to make the input field visible (and iteractable) in two different ways:
1) In the Elements tab, I find the input HTML tag and click on it. In the Styles panel on the right, I can see that the element has a CSS style applied to it, which sets "display: none!important;". When I uncheck this line in the Styles panel, the style gets disabled, and the input element shows up on the page (and I can click on it to open the file chooser). So far, all this makes sense to me.
2) In the Sources tab, I create a new snippet and I programmatically change the display style of the same element:
form = ...
input = form.getElementsByTagName('input')[0];
console.log(input);
computedStyle = getComputedStyle(input);
console.log(computedStyle['display']);
input.style.setProperty("display", "inline", "important")
console.log(computedStyle['display']);
When I run this, the console output makes sense: I confirm that I'm finding the correct element, the first time I print the display it's "none", and the second time it's "inline". However, nothing changes on the page, I don't see the input as in the other approach.
I'm still wrapping my head around React, and I suspect this is related to the fact that React can and will decide to recreate the actual DOM elements very often (so perhaps the input I'm changing is not the input I'm seeing?). But I'm not super clear, and either way, I was expecting these two approaches to have the same results. What happening here? And how can I programmatically change the hidden input to be not hidden?
You manipulate dom (in react) by changing props and state. There is a browser extension which let's you do that in browser. For chrome is here. There is extension for firefox as well.
I am guessing that your snippet change did not induce a React refresh, thus the shadow DOM was modified but React did not see a reason to update the DOM. Perhaps you could add a forceUpdate() in your snippet?

Find out what file/line in JS is changing the text of an element

I'm working on a pretty large (a lot of files) and poorly organized web project for a client. Somewhere in the mess of things there is some JavaScript that is truncating H3 tags and adding ellipsis to them. I would like to find that line of script and remove it. I just need to find out where it is...
Manually searching through all of the files on the site could take forever (since, due to the poor code of the site, the JS that produces the dom manipulation could exist in a PHP file somewhere, or in a JS file, or...who knows).
I know that with Chrome, for example, you can do DOM manipulation breakpoints. The problem is that from what I can tell the Subtree modifications and Attributes modifications breakpoints don't actually break on simple text modifications.
Are there any options in any browser to listen on the DOM element and see where the script is that is modifying it?
Add debugger calls in each one of your js files to force the execution to pause on each file. If the h3 changes after jumping a specific stop point, chances are the guilty script is in that page (or the function is being called on that page).
To check whether the change happens on the server or client side you should first check the network reponses. If the text is truncated inside the server response, then the change already happens on the server side. If not, it happens on the client side. When it happens on the client side, it may be done either through JavaScript or through CSS.
Firebug
Check server response
Switch to the Net panel, focus the search field, ensure that the Response Bodies option is checked, then enter the heading (untruncated). If it is found, then the change happens on the client side.
Check CSS
In case the change happens on the client side, it may be part of some CSS.
E.g. there is a CSS property called text-overflow, which allows to add an ellipsis to the text.
To check that inspect the related element and search within the Styles or Computed side panel whether the text-overflow property is set for the element.
The ellipsis may also be achieved via some trick setting the content property to an ellipsis.
If you cannot find any CSS like that, the change probably happens via JavaScript.
Check JavaScript
you can stop the script execution at the line that changes it by right-clicking the element you want to inspect within the HTML panel and choose Break On Child Addition or Removal.
Once the text is changed, the script execution stops at the related line.
Example
<p>foo</p>
<button onclick="changeText()">Change text</button>
<script>
function changeText() {
var p = document.querySelector("p");
p.textContent = "bar";
}
</script>
Set the Break On Child Addition or Removal for the <p>foo</p> element to try it out.
Note: Unfortunately Firebug doesn't always jump to the right script or position, but at least it does stop when the change happens within JavaScript.
Chrome DevTools
Check server response
Switch to the Network panel and search for the untruncated heading in the response bodies of the network requests. (As far as I know, there is no way to search automatically within the response bodies.) If it is found, then the change happens on the client side.
Check CSS
As described above, the change may also be part of CSS.
To check that inspect the related element and search within the Styles or Computed side panel whether the text-overflow or the content property is set for the element.
If you cannot find any CSS like that, the change probably happens via JavaScript.
Check JavaScript
Within the Chrome DevTools it works similar like in Firebug. So, in case the change happens on the client side, right-click the element within the Elements panel and choose Break on > Subtree modifications from the context menu.
Once the text is changed, the script execution stops at the related line.

Catching all changes to the contents of an input box using JavaScript/jQuery

I have a page with an input box, and a function that processes the value of this input box and produces piece of text. I want this text to always be up to date in relation to the contents of the input box, so I've attached a couple of event handlers to it with jQuery to catch any changes:
$('#input').bind('keyup cut paste', function(){...});
This works well in most cases. Whenever the user modifies the contents using the keyboard in any way, or right-clicks to use the cut or paste functions, the text is updated immediately. However, there are two events I still haven't figured out how catch, if it's even possible to do so:
When the user selects a of text and drags it do a different position in the input box
When the user uses the Delete action in the right-click context menu
Both of these can of course be detected by binding the change event, but the problem with that approach is that it doesn't fire until the input box loses focus. The whole point of these bindings is to have the text update in real-time as the value of the input box changes, so change is no good.
English is my second language so I could simply be bad at wording my Google searches, but so far they've turned up nothing. I haven't found any solutions to this after digging through a couple of related Stack Overflow pages either, so I'm asking here. Is there an event binding for this that I don't know of? If not, is there a different approach I could take? Or is this simply not possible with plain JavaScript?
In non-IE browsers, you can handle the input event.
In IE, you can handle the propertychange event.
Demo (works in all browsers)
It's possible this SO question (and related jsfiddle) might answer your question.
(On the linked jsfiddle, put text in the top box to test)
In other words, bind to mouseup and mousedown, etc.
If you can't find a combination of events that cover all cases, you may want to use setInterval(function() {... }, period). You could play around with the period to see how well this works.

Stop certain elements from being edited inside a doc having designMode = "on";

I am using an iframe and setting its contendocument.designMode to "on". This allows me to replicate a Rich Text Editor, and achieve much more flexibility in the editing process.
The problem is that I have certain links (test) that are added to the page, and of course these links don't work because i'm in designMode.
At first I thought, well I'll just wrap that link inside another iframe, but still it won't fire the event attached to it.
Is there a way to have certain elements work as they would normally, even though they are inside a designMode="on" document?
Recently had the exact same problem. My solution was to use a div with contentEditable="true" instead of an iframe, which then allows you to set contentEditable="false" on elements within that div.
Not a perfect solution, but gets the job done in my case.
You can place a checkbox to toggle to designmode 'on' and 'off'. To see the action temporarily swich to designMode 'off'. This way you may be able to get the desired behavior of your script.
If you look at google docs, when you focus on the link, they show a small div with different actions for that link.
I guess they have spent already a lot of energy to make it the best they could. So I wouldn't try something different.

Categories

Resources