Accessibility: Page Loader indicator using aria-live - angularjs

Issue: I have an accessibility issue that I am struggling with. I have an angular web application. A page loading spinner/indicator is shown when content is loading. And when the page content has loaded the spinner is hidden. This "div" is never removed from DOM.
Content of the loading div are not read (by NVDAor jaws) when the loading div is shown.
<div class='loading' aria-live='polite' aria-label='Do not refresh the page' tabindex="-1">Do not refresh the page</div>
I wouldn't like to change the structure of the application but work around using 'aria tags' to resolve this, just wondering if I will have to do anything more to make aria-live work?
Updated (27/July/2016)
Further clarification: I am not removing the content from DOM but using css to show/hide content (display: none to display: block and vice versa)

aria-live triggers screen readers when an element with aria-live (or text within an element with aria-live) is added or removed from the DOM. In contrast, when you unhide a hidden element, neither elements nor text are added or removed from the DOM, so the element's aria-live property doesn’t come into play.
To get screen readers to announce “Do not refresh the page”, either of these options should do the trick:
You can create the <div class='loading' aria-live='polite'> element and its text content from scratch and then add that element to the DOM.
Or you can start with an empty <div class='loading' aria-live='polite'> element and then populate its text content.
A few other tidbits:
As long as the text inside the element is what you want to be read aloud, you can omit the element’s aria-label='Do not refresh the page' attribute.
For icing on the cake, it can’t hurt to include a role attribute on the div that has aria-live. If you’re not sure which role to use, go with role="status"—that’s a pretty safe bet.
When or if the page is at a state where you no longer need to display "Do not refresh the page”, be sure to reverse the steps above. (That is, if you went with the first option and you added the whole element to the DOM, remove that entire element from the DOM. Or if you went with the second option and you populated the element’s text content, clear out the element’s text content.)

There are several issues with dynamically added or shown/hidden live-region.
Firstly a quote from MDN - ARIA live regions:
Simply including an aria-live attribute or a specialized live region role (such as role="alert") in the initial markup as it's loaded will have no effect.
Dynamically adding an element with an aria-live attribute or specialized role to the document also won't result in any announcement by assistive technologies (as, at that point, the browser/assistive technologies are not aware of the live region yet, so cannot monitor it for changes).
Always make sure that the live region is present in the document first, and only then dynamically add/change any content.
From my personal experience, even if a live regoin exists in the DOM on page load if you use show/hide then NVDA also has a bug which requires a small delay before a text update in a live region after it was shown initially. Apparently because the region didn't exist when the first text was added, so this isn't an "update". Regarding the timeout, you'd need to set it to something greater than the browser's refresh tick. I use 100ms. Disclaimer: I am strongly against such workarounds to make up for the issues with screen readers or browsers but it might be useful for someone in some cases.

Related

#Selenium: Presence of an element

What is the purpose of checking the presence of elements rather than visibility of element?
As a Quality Tester, I should be on visibility of elements.
Can anyone provide me some good examples?
As mentioned in the link given by sisanared it explains differences between each method nicely, in short checking present of element only check whether element exist in your html page regardless it visibility and enable flag.
Usually presence of element used when you put some element as hidden, and you need to make sure that element present before you start your test in a page. For example I usually ask developer to add isPageReady element which rendered as hidden to indicate the page and other javascript codes have been loaded successfully since in modern web sometimes it is not enough to only wait using selenium default wait for page load.
Visible element, is on the other hand will be visible to user, and you usually used for interaction, like type, click, etc.

NVDA screen reader reads clickable word on text

Any idea why NVDA reads clickable word when tabbing through text in html example:
<h1 tabindex="1"> testing </h1>
NVDA will read clickable testing
In first place remember that tabindex are not a good practice in a11y, and also headers don't need a tabindex NVDA provides a header navigation with the H key. About the clickable I can say from my experience is a known issue for NVDA, if you check that in other SR (Voice over or Chromebox) should be read properly
Short answer:
the tabindex attribute implies functionality to some screenreaders.
Long answer:
Two primary ways that a screen reader user will navigate your webpage are by skipping through interactive elements or by headings. Interactive elements are things like links, buttons, form fields and any other piece of functionality that the user will initiate on your page. These are navigated by using the 'tab' key.
The other primary way they will navigate your page is by headings. In fact, a survey from webaim lists headings overwhelmingly as the primary method of navigating a page to find information (source). In your example, you have given the heading a tabindex which will give the impression that it has some functionality or interactivity to it. To my understanding, both JAWS and NVDA will read out 'clickable' on elements that have a tabindex, as they could easily (and typically would) have some javascript click handlers that are not evident from the screenreader.
Answer:
It's because of attribute tabindex which makes this element keyboard focusable. One can focus it by pressing TAB key on a keyboard.
Hint #1: Attribute tabindex with value above 0 should be generally avoided!
Don't use tabindex="1", tabindex="2" and so on. Only tabindex="0" or tabindex="-1" can be useful in some cases. Otherwise you can create a complete mess for a user experience.
Read more:
Google: Using a tabindex greater than 0 is considered an anti-pattern.
WebAIM (accessibility): This is almost always a bad idea.
MDN: Avoid using tabindex values greater than 0.
Hint #2: Generally no need to make focusable elements that a user cannot interact with.
As in specific case no sense to make a heading element keyboard focusable if a user cannot interact with it.
If you are concerned about screen reader users have no worries as they read non focusable content just fine. A quote from Accessibility Developer Guide: As opposed to keyboard only users, screen reader users usually do not use the Tab key to read a page! Read the "Screen readers browse and focus modes" to know the difference between navigation using Arrow keys and Tab key.
But... Exception to the rule exists
Exception to the rule exists and it's probably a good idea in cases where developers set tabindex="-1" to headings which they want the focus to be moved programmatically for the purpose of accessibility. Such cases are for example fresh content update with AJAX in single page applications. The focus would be moved to a heading for a user to get aware of the content update and to be able to start from there. Also it can be useful when currently focused content is about to get removed from the DOM (a.g. deleting currently focused table entry) or moving a focus to an error summary heading after a form submit trial etc.
In my case (VoiceOver on MacOS), it seems that H1 is announced as clickable only on Firefox. On Chrome, it's announced correctly.
This leads me to believe it's a Firefox bug.

Is there an event that is sure to fire when google maps is loaded, when using angular js?

I am using angularjs and ngmap (https://ngmap.github.io).
The map is initially hidden from view (using ng-show), and i want to be able to toggle between views without having to reload the whole map.
I also want to display a kml on the map.
The map is only initialized (using lazy initialization) when that part of the page is shown.
It seems to work fine, except that sometimes the map can't zoom into the kml (using fitBounds). I think I have established that this is because the height of the containing div is zero (due to the controller code firing before the view is actually rendered), and fitBounds needs that.
I am trying to wait until I am sure the map is good and ready. I have tried the following events:
bounds_changed
tilesloaded
but neither do what I want.
Currently I am using a $timeout, but I don't like it, as I don't know how long it takes to initialize the map, and whether or not my code will fire between that time.
My next idea is to repeatedly check for the height of the map, but I would prefer something more explicit.
Another idea is to always have the map in the background, and use absolute positioning to cover it with the other information when that part is visible, but that breaks my current design.
I've decided to avoid the issue.
The map is always going to be there, but I use some ng-class s to make it "visibility: hidden" and hide an unneeded scroll bar when the map tab is unselected.
As long as the visibility is hidden (instead of display: none) the initialization and positioning of the map goes okay.
It isn't perfect (I might need to scroll the other tabs one day), but it works for me for now.

Get margin-top value from transcluded block's child element

My question is based on the image here
The above uses the angular plugin br-fullpage (angular version of the jquery's fullpage.js plugin) to create a vertical scrolling website. However unlike fullpage.js, br-fullpage is somewhat lacking, and makes it hard for me to determine the current page being displayed on the screen. The only way that i can possibly use (unless if i didn't aware of other methods) to determine which page is being displayed right now, is by using the margin-top value (yellow highlighted).
However everytime i tried to get the margin-top value, i always get 0px instead of the highlighted value. I don't understand what is the problem with this, and it makes me hard to do the animation if i don't know which page that i am currently on when the page is refreshed.
So how can i get the correct margin-top value below? Or is there any other method that i can use to know the current active page displayed on the screen?
Thanks
Can you use sessionStorage.getItem('br-fullpage-index')? This won't give you the margin, but should contain the current page index.

how to prevent AngularJs from having old view and new view on dom when route changes

I am using a directive "slideable" which creates a slideout area and has a toggle. This code that was not written by me but it demonstrates a larger issue for me. When I changing views (most commonly /user/:id type), slideable is a directive used on the template. The directive searches for an element during its link function and binds a click event. The issue is that when I am changing routes and the new view ( same type but different id ) is being loaded the directive is re-binding to the old view. If I stop the browser in chrome during the link then I will see two ng-views on the dom and the issue is it binds to the one that is leaving.
I also have other issues that appear to be related to this phenomenon. Is it normal that the old view would still be on the dom while the new view is being formulated?? Why wouldnt the old-view be destroyed before the new one is rendered? How do I get around this issue in a directive like this?
Thanks.
I am looking to understand conceptually what is happening. I already modified the directive to select the latest view and to appropriately search and bind to the correct element. But I am a bit perplexed as to why there would be a state where both co-exist on the dom.
One definitive reason why the old HTML fragment is briefly present along with the new one is to support animation of transitions from the old to the new. Take a look at the ngView documentation and you'll see an example of an animated transition, and it'll be clear that this is not a bug or a design flaw.
Usually when someone has problems with binding to the right element or element's event, it's because they are selecting the element without limiting the scope of the selector to the HTML fragment being added or updated, or trying to target parts of the DOM outside of the directive. So that's the first place to check, that the directive is doing things right, but like I said we'll need code to check on that.

Resources