How to tell screenreader to read a toggled element - javascript

Instead of adding/removing my different sections to/from the DOM, I'm only hiding them with aria-hidden="true", and unhiding them if certain <a> toggles are clicked.
Reasons are performance and an easier noscript fallback. The order in the DOM is not the order in which the questions appear.
The result is a binary question tree (yes/no questions) in which the user clicks from one question to the next.
Now what would be a good solution to make screen readers read a section or at least continue reading it next after unhiding it?
Is there a way with live-region? Do screenreaders read elements that become unhidden in it? I thought aria-current might be appropriate? Or is it more an aria-expanded application?
Thanks for your help!

ARIA live regions are without question the correct way to handle this sort of problem.
By using the aria-live attribute on an HTML element, assistive technology will be alerted when content is changed in one of these areas. Your choice of attribute value will specify how quickly the change is announced (immediately, or at next graceful opportunity). The most common implementation is typically aria-live="polite".
This page outlines some pretty useful (and innovative) techniques for implementing live regions: https://terrillthompson.com/tests/aria/live-scores.html

Related

JS : How to get notified after insertBefore()?

Is there a way to get notified, after inserting an element into the DOM with insertBefore(), when this element becomes actually visible/available to user ? Especially to start applying CSS transforms on it ?
Complete problem
Forgive me if this question is recurrent, I didn't find a suitable answer so far. I'm trying to implement a custom popup dialog system on a website of my own, similar to SweetAlert or some other products.
I would like to apply some special effects when this popup shows up, such as a progressive darkening of the background, as well as a slow vertical motion on the box itself.
To achieve all of this, I spawn one big, fixed div element covering the whole screen (the background) and containing the popup box. When I need it, I first insert this element as body's first child, tagging it with a special invisible class. Once inserted, I remove this invisible class from the element and let the CSS rules do the magic.
The problem is that even if removed the class after having inserted this element, this one will be rendered only when the Javascript function leaves, hence directly in its final state.
When doing this on a complete initial page, the load event helps. I now would like to do the same on an existing page.
As always, I'm interested on both solutions to this (potentially XY) problem: if there's a better way to do it, I'll be happy to discover it, but I'm still interested in solving this particular situation anyway.
Thanks in advance to everyone.
EDIT: currently performing tests on Firefox 82.0.2
Thanks to comments above, here's a valid solution to both exposed problems:
"Mutation Observer", as well as former "Mutation Events" (now deprecated) are the best way to get notified when something is inserted. It won't help with animations issues, though, because it's still not guaranteed to be rendered yet at this time ;
Rather than applying a class then another to perform a transition, it's better to define a regular animation using #keyframes that plays only once. It's guaranteed to be played when the object appears, by definition.
Many thanks to "Pomax", F4st3r and epascarello for their help.

aria-expanded html attribute

I am currently making a navbar and came accross the aria-expanded html attribute. I know of course that the element is used to let an element either expand or collapse. I could find very little information with regard to this and the W3C docs aren't that clear IMO.
Question
How does this attribute work exactly?
The aria-expanded attribute is simply a flag for the user agent. It
Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
...where that indication is for the element's contents, or if aria-controls is also specified, for the target element.
You set its value to indicate what you've done to the page (e.g., you've expanded or contracted a section). It doesn't have any particular behavior associated with it, it's for letting the user agent know what's going on so it can interpret that for its audience (who may be vision-impaired and need some other indication that a section is/isn't expanded).
ARIA attributes are related to accessibility. In this particular case, it's to let users with assistive technology (e.g. screen readers) know whether an element is expanded or not. It does not have any native effect on the styling of the element, but you can target that with CSS attribute selectors: [aria-expanded="true"]. You can toggle the value with JavaScript as needed.
Aria attributes in general are used to make web applications accessible to people with disabilities. They are used primarily by screen readers to determine how to treat html elements.
The aria-expanded attribute provides information about whether an element is in an expanded or collapsed state.
For example, if you have a collapsible element which contains a text, then a screen reader would know that the text is not currently displayed on the screen when the aria-expanded attribute is set to true.
As mentioned here:
WAI-ARIA is a spec defining support for accessible web apps. It defines bunch of markup extensions (mostly as attributes on HTML5 elements), which can be used by the web app developer to provide additional information about the semantics of the various elements to assistive technologies like screen readers.
WAI stands for: Web Accessibility Initiative
ARIA stands for: Accessible Rich Internet Applications
Hope it helps
It depends on whether your anchor element or any other element is active,
Just like dropdown from bootstrap then
which color you wants to apply on the parent while it is on clicked state!

Adding WAI-ARIA attributes with JS

At work I have been optimizing one of the sites I have helped developed for one of our clients (I can't say who) for be ADA compliant using WAI-ARIA attributes. I've been wondering if it wouldn't just be easier to create a small JS library that does things like add "role=button" to anchors I've styled to look like a button, add "tabindex=0" to elements I want to be "tabable" etc.
I was wondering if it is a good practice to add in WAI-ARIA attributes with JS or is that frowned upon. Some accessibility evaluation tools won't run the page's JS when evaluating it so it will think these are pain points when they are really not.
this may be helpful Add ARIA inline or via script?
Also note that if you use role=button it needs to act like a button (i.e. provide appropriate keyboard interaction behaviour)
I think in the interests of progressive enhancement, it might be best to put all your ARIA inline and not rely on script to add it.
If there are other script errors, if the connection gets dropped, if there is a blocking script in the way, etc., then your library may not come into play and your efforts at remediation will be lost.
I'd also like to build on what Steve said above about using role=button on a link. Especially when you consider that a visual style (to make a link look like a button) is meaningless to a screen reader use (for whom many ARIA roles benefit). I addressed other keyboard interaction gotchas in more detail in another SO answer, but here is one to consider when you try to turn a link into a button:
A hyperlink (<a href>) can be fired by pressing the enter key. But a true <button> can be fired by pressing the enter key or the space bar. When a hyperlink has focus and the user presses the space bar, the page will scroll one screenful. Users of some assistive technology will expect behavior based on the element used.
Also, I caution against putting a tabindex=0 an an element you want to be tabbable unless it is an interactive element. For example, do not put it on a heading (<h#>) just so someone can tab to it as screen readers (for example) already allow navigation by headings.

disableSelection on everything but input[type=text]

I have a requirement to disable selection on a web page for everything except input[type=text] elements.
This accepted answer to a similar question almost does the trick, but it doesn't disable selection for containers that contain input[type=text] elements. Therefore the user can still select by starting a drag operation from within one of these containers.
Is this even possible, i.e. is it possible to disable selection for a container element, while enabling it for child elements (specifically, child input=text elements).
#Pointy, "Why not just take out that first .not() call?"
Taking out the first .not call, will give:
$('body').not('input').disableSelection();
which, as pointed out in the linked question, will still disable everything on the page, including the input[type=text] elements.
#David Thomas, "Do you have a live demo ..."
I don't have a live demo, but it's fairly trivial. For example, a div with a bit of padding that contains an input[type=text] element. The result is:
With $('body').not('input').disableSelection(); selectiopn is disabled for all the page, including the input elements.
With $('body *').not(':has(input)').not('input').disableSelection(); selection is disabled for all elements that don't contain an input element. But it is possible to select the whole page by starting a drag operation from within a container that contains an input element.
Well, cinch up your suspenders and get ready for a really dirty hack.
Disclaimer:
I don't think this is a good way to do things. I simply wanted to tackle the challenge of getting the OP's desired functionality. If someone else can get this to work in a cleaner way, please post it.
After playing around with the disableSelection() function, it seemed that if a parent element had been disabled, all of its children would be unselectable as well (please correct me if I'm wrong). So, I decided that if you wanted everything to be unselectable except small parts, you could put all of your markup in one unselectable <div> and use absolute positioning to place selectable clones of your <input> tags (or any tag, really) on top of the unselectable ones. These clones would reside in a second <div> that was not disabled.
Here's an example of this idea: http://jsfiddle.net/pnCxE/2/.
Drawbacks:
Styling becomes a big headache. Any element that relies on a parent's style (i.e., position, size, colors, etc.) cannot be cloned since the clones reside in a separate place.
Forms become much harder to manage since (again) the clone isn't in the same place as the cloned element.
You have to deal with naming collisions since the clone will have the same ID as the cloned element. (It's doable; I just didn't want to code it since it would probably need specific attention by anyone that uses this idea)
So, while you can work around the selectable limitations, you might be better off just accepting the container selection. I would think long and hard before putting this code into a production environment.
I've found a solution that appears to do what I want, and would be interested in comments / improvements from jquery / javascript experts.
$(document).ready(function () {
$("body").disableSelection();
$("body").delegate('input[type=text],textarea', "focus", function () {
$("body").enableSelection();
});
$("body").delegate("input[type=text],textarea", "blur", function () {
$("body").disableSelection();
});
});
When a textbox (input[type=text] or textarea) has the focus, then dragging with the mouse only selects text within the textbox. Therefore it's "safe" to enable selection for the whole page while a textbox has focus (between focus and blur events).
There is a noticeable delay when tabbing between textboxes on IE8/9. It's not noticeable on Google Chrome, which I understand has a faster javascript engine. So I can live with the performance hit, especially since IE10 is going to have a faster javascript engine.
UPDATE
When using ASP.NET UpdatePanel, this needs to be modified to disable selection after each partial postback:
Sys.Application.add_load(function () {
$("body").disableSelection();
});
Try this, although it is same with what you're already using:
$('* :not(input)').disableSelection();
I don't get though why do you have to use entire body element and not narrow it down to text nodes (p, h[..], ul, ol etc.)
And I agree with #David Thomas - it would be easier to see a test page you're working on.

Open dropdown from javascript

I there ANY way in javascript that we could trigger a select element (dropdown list) to open (i.e. drop)?
After searching alot on the web, it seems the answer to this question is no, but I decided to give it a try on here as well.
I know there are some css tricks that you can set the opacity of your select to 0 and place it over other elements to receive click, but that is not useful in my case.
Also there are tons of js APIs that bring the same dropdown functionality to browsers but they are not good solutions for me because then on mobile browsers (where the OS has a totally different mobile-friendly popup for dropdowns) the functionality would be seriously poor.
[Note] I specifically need to do this in an android browser, in case there is a hack for this special case.
Thanks.
You could assign a value to the size attribute. This causes the number of visible options to change. This simulates a "drop-down". Add position:relative to a container, and position:absolute to the select to prevent the element from pushing other elements away.
Demo: http://jsfiddle.net/HQwXj/

Categories