Does altering the DOM with JavaScript/jQuery mess with accessibility? - javascript

I'm trying to figure out if altering the DOM of a website will present any accessibility problems. I am placing all of the jQuery in a $(document).ready() function. Will this cause any accessibility issues with the altered elements?
We don't have access to the theme template HTML files, only CSS and JS files. So for example I'm adding a div into our theme using$('[element name]').before('<div>[div content here]</div>') will this content be as accessible as the rest of the DOM as long as I include all the appropriate aria attributes etc.?

In theory, you shouldn't rely on JavaScript to produce the whole HTML code of your site, it's basically a bad practice.
However, it's exactly how big frameworks like angular and react work.
Given that 99% of browsers support JavaScript, it's in fact no longer a problem nowadays.
The true answer is in fact both yes and no, it depends. It depends on the actual HTML code injected.
The key point is that, you must have the same care with generated code as with the code directly written in HTML by hand, i.e. be careful on headings, form labels, alt texts, ARIA attributes if you need them, etc. all the time and in particular each time you add/remove something in the DOM. Additionally, you must pay attention to where the focus is or might be and a few other things.
It's often overlooked precisely because some people assume that it's anyway not accessible, what isn't true.
In order to be accessible, a site with dynamic contents must be accessible at any moment. If it isn't always the case, then you will lose users in need of accessibility at some point. In practice the loss of accessibility often happens at the most critical moment: checkout or paiement, maybe not because of your fault if the paiement site isn't accessible.

You might even improve accessibility by manipulating the DOM via JavaScript (JS). So no, per se, manipulating the DOM does not pose accessibility issues.
If you cannot control the HTML, and the theme is badly accessible, all you can do to improve that is using JavaScript. Think adding role attributes to generic <div> elements. Also, CSS-only solutions seem appealing, but are often not exposing the appropriate state via ARIA-attributes to assistive technology, which needs to be corrected via JS.
Whether your manipulations produce problems or improve accessibility, therefore depends strongly on your implementation.
Here are some examples.
Adding or Removing Content
When adding content, like in your example, it depends on where that content is added in the document, and at which moment.
If it’s being added on DOM Ready, there should be no issue (One exception might be live regions added after the DOM loaded). But if it’s being added at arbitrary moments, it’s problematic.
The Web Content Accessibility Guidelines (WCAG) refer to this as a Change of Context, which must not happen on focus, on input and on user request
See A change of content is not always a change of context. Changes in content, such as an expanding outline, dynamic menu, or a tab control do not necessarily change the context, unless they also change one of the above (e.g., focus).
If it’s being added after DOM Ready, it should happen on user request, or must be a status message and carry the appropriate role to be announced.
For example, in a Disclosure pattern, the aria-expanded of the trigger indicates that new content will become accessible right after the trigger on pressing it. It might just be added to the DOM, depending on the implementation.
Lazy Loading Content
Another, very valid use case would be content that’s added asynchronously. This is tricky to get right, but basically aria-busy can render this more accessible.

Related

Use <a> tags or any tags for javascript links?

Is there a preferred way or advantages to using one over the other ?
i.e.
You can have a hyperlink a where the href points to # with a class or id and then javascript that looks for that elements on-click event.
You can have a simple div or span that has a class or id and bind the javascript on-click to that element.
I have seen both done.
Context is ruby on rails applications that are using javascript for some functionality.
I think the main advantage of using <a> tags is that the default behavior (when including an href) is that the browser cursor signifies an link. Although both can be done, using the <a> tag is also more semantic.
Constructing semantic markup is a staple of good design. By using anchors to signify navigation, you are sticking to the specification. The perfered way would be what the spec outlines, if you need to deviate I would make sure your changes are justified.
One advantage for preferring an anchor tag is screen reader software for the blind will parse the DOM for anchors to help users navigate on the page. By using div's or span's the nav links will be overlooked.
This is more of an HTML question than javascript.
A elements are simple, work in every browser and are utterly reliable whether scripting is available or not.
Browsers support A elements through context menu features to open them in new windows or tabs
A elements have a default presentation in browsers that lets users know they are links without any other scripting or styling support required
Different browsers may present links slightly differently, so users get used to seeing them behave in the particular way their browser presents them. Scripted and styled other elements likely will present in an unfamiliar way to at least some users.
Browsers offer features to support A element links such as tab navigation between links and separate lists of links in the page.
Screen readers and other support mechanisms for accessibility understand A element links and can present them to their users
Browsers typically present the destination of an A element link to a user so they can decide whether to follow the link or not
A element URLs are easily copied and shared without following the link
A elements can be used to create bookmarks without following the link
Scripted and styled links do not have any of the above features, or at least require significant additional effort to support any of them.
I like to write code which actually means something. I generally achieve this by using the most appropriate (semantically speaking) elements.
I use the a element when the purpose is to navigate in the application. To quote the spec:
Links are a conceptual construct [...] that represent a connection between two resources
For other cases, it depends. But I usually use the button element
div are by definition meaningless, you should avoid them for this kind of purpose. To quote the spec:
Authors are strongly encouraged to view the div element as an element of last resort, for when no other element is suitable.
If it's a JavaScript-only link then it doesn't matter what element you attach it but using an <a> gives you built-in link/hover/visited styles whilst being semantically correct. However, the biggest reason for using an actual link is the ability to have a fall-back for browsers without JS enabled.
For example, you could have a link which loaded the next 10 results by ajax if possible else server-side if the link is followed.
<a id="nextByAjax" href="?next=10">Next 10</a>

Conditionally showing elements: should I createElement or hide the elements?

I have a section on my website, which I would like to have users see depending on whether the user is logged in or not.
I was wondering if it would be more efficient to create/remove the elements conditionally (or even dynamically write) with jQuery, or to simply hide/show the elements.
Which would be the best practice method that you would use? jQuery tutorials that I've done always makes me add and remove the elements.
Further(I hope I do not anger the meta gods with this), what is the general guidelines on when I should be creating/removing elements and when I should be showing/hiding them?
Thank you in advance!
At one point, long ago, the recommendation was that you never put elements on the document that you weren't using, and you removed the element once it was done.
You have to realize, however, that this recommendation was at a time when browsers didn't always handle CSS and layout control was horrible. This was an era of text-based browsers such as lynx.
The world is much different now and even most blind users [citation needed] use full-fledged browsers with screen readers and these screen readers are smart enough to understand hidden elements.
Today, it is much easier to simply put everything that isn't sensitive in the document and style sheet rules or JavaScript to hide, unhide and re-arrange as needed.
That said, sensitive information should be restricted. If a end user isn't allowed to see something, then don't give it to them, even hidden.
Remember, the client can never be trusted.
EDIT PER COMMENT
Lets imagine that your system has a sensitive field that we'll call coolness. Coolness is something that regular users can't ever see, but the web admins get to set on folks they like and don't like.
If you simply say:
<div id="coolness_rating" style="display:none">
<label>Coolness
<input name="coolness" value="4">
</label>
</div>
then even though it is hidden on the screen, a user can still look at the HTML markup and see that value. Its hidden, but easily findable.
Continuing on the same though, the back end code also needs a guard around that coolness value, so that someone can't tweak what is being sent and add that in.
The back end code needs to look something like this:
if (loggedInuser.AccessLevel === AccessLevel.Admin) {
// Only let Admins change the level
referencedAccount.Coolness = formData.coolness;
}

Diffing the DOM - how to write a unit test that checks that a script doesn't make any user-visible changes to elements on the page?

A JavaScript plugin that I've been writing recently has various failsafes built in that tell either the whole plugin or parts of it to hide itself and die under circumstances where it can't function. For example, let's say that one piece of functionality we offer is automatically generating a popover that shows competitors' prices for an item when the user hovers over it in an online store. Then we'd also have some checks that say that if we don't know any of the competitor's prices, or we can't identify the item, then don't show a popover.
I want to test that functionality-disabling using tests that follow roughly this structure:
Load our plugin onto a page where certain functionality ought to be disabled
Spoof some user action that would otherwise trigger that functionality
Assert that no visible changes have been made to the DOM. (i.e. no styling changes to visible elements, no addition or removal of elements unless they have display:none on)
Step #3 is the interesting one, of course. Is there an easy way to write that 'DOM unchanged' test in JavaScript? (Or alternatively in Selenium for Python, which is what I'm using to write my tests - but writing the check in JavaScript is probably more broadly useful since it can then be used in any JavaScript-testing environment.)
P.S. A couple of notes to head off the "You're doing it wrong!" crowd:
Yes, I know that I could just replace step #3 in the test above with a check that the specific changes that the plugin would otherwise make have not been made, and I may even decide to do this. But where those specific changes are poorly-specced and liable to change, this catch-all approach could be useful.
Yes, I also realise that just checking there are no immediate visual changes to the DOM when a event that's meant to be effect-free is triggered isn't strictly sufficient to prove that the nothing has broken. It's what'd be best for my current purposes, though. Plus it's interesting and fun even if it turns out not to be useful.
Use Mutation observers to detect that no mutations have occurred. You might want to checkout Mutation Summary, a very nice high-level wrapper for mutation observers. Checking that no mutations have occurred could be easy as checking that the returned array has length 0. See https://code.google.com/p/mutation-summary/.

Why focus an input on page load instead of inline?

Almost all web pages that I see designed to set the focus to an input box add the code into a body onload event. This causes the code to execute once the entire html document has loaded. In theory, this seems like good practice.
However, in my experience, what this usually causes is double work on the user, as they have already entered data into two or three fields and are typing into another when their cursor is jumped back without their knowledge. I've seen a staggering number of users type the last 2/3 of their password into the beginning of a username field. As such, I've always placed the JS focus code immediately after the input to insure there is no delay.
My question is: Is there any technical reason not to place this focus code inline? Is there an advantage to calling it at the end of the page, or within an onload event? I'm curious why it has become common practice considering the obvious practical drawbacks.
A couple thoughts:
I would use a framework like jQuery and have this type of code run on $(document).ready(.... window.onload doesn't run until everything on the page is fully loaded, which explains the delay you have experienced. $(document).ready(... runs when jQuery determines the DOM has been loaded. You could probably write the same sort of logic without jQuery, but it varies by browser.
I prefer to keep my Javascript separate from my HTML because it allows for a cleaner separation of concerns. Then your behavior is then kept separate from your document structure which is separate from your presentation in your CSS. This also allows you to more easily re-use logic and maintain that code — possibly across projects.
Google and Yahoo both suggest placing scripts at the bottom of the html page for performance reasons.
The Yahoo article: http://developer.yahoo.com/performance/rules.html#js_bottom
You should definitely place the script in the appropriate place if it means the correct user experience -- in fact I would load that part of the script (Used for tabbing inputs) before the inputs to ensure it always works no matter how slow the connection.
The "document.ready" function allows you to ensure the elements you want to reference are in the dom and fires right when your whole document dom is loaded (This does not mean images are fully loaded).
If you want you could have the inputs start out as disabled and then reenable them on document ready. This would handle the rare case the script is not ready yet when the inputs are displayed.
Well if you call it before whole page has loaded you really don't know if the element already has been loaded when you make your call. And if you make your call in pre-hand you should check if the element really exists even if you know it always should.
Then to make the call inline, which might seem ideal. But on the other hand it's really bad if a page takes that long to load that you can make several inputs during the loading phase.
Also you could check if input has been made etc.
Also it is possible to check if any input on page contains focus if($("input::focus, textarea::focus").length)... and otherwise set focus on desired input.
Use the autofocus HTML attribute to specify which element should initially receive focus. This decouples JavaScript and gracefully degrades in older browsers.

Using jQuery to disable everything on a page. Break my code

For my current project, I require the facility to be able to remove all functionality from a page, so that it is complete and literal static page. Removing the ability to follow any links, and disabling and javascript listeners allowing content to be changed on the page. Here is my attempt so far:
$("*").unbind().attr("href", "#");
But in the pursuit of a perfect script, and to allow it to work in every eventuality for any possible page (and with the uncertainty of a on liner being effective enough), I thought i'd consult the experts here at stackOverflow.
In summary, my question is, 'Can this be (and has it been) done in a one liner, is there anything this could miss?'. Please break this as best you can.
No. Nothing in this stops meta redirects, or timeouts or intervals already in flight, and it does nothing about same origin iframes (or ones that can become same origin via document.domain) that can reach back into the parent page to redynamize content.
EDIT:
The sheer number of ways scripts can stay submerged to pop up later is large, so unless you control all the code that can run before you want to do this, I would be inclined to say that it's impossible in practice to lock this down unless you have a team including some browser implementors working on this for some time.
Other possible sources of submarine scripts : XMLHttpRequests (and their onreadystatechange handlers), flash objects that canscript, web workers, and embedding code to run in things like Object.prototype.toString.
I did not want to write a lengthy comment so I'm posting this instead.
As #Felix Kling said, I don't think your code will remove the href attributes on every element but rather remove every element and then select their href attributes.
You probably need to write:
$("*").attr("href", "#").detach() ;
to remove the attributes instead of the elements.
Other than that, I doubt that you could remove the event handlers in one line. For one thing you would need to account for DOM level 2 Event registration (only settable with scripting) and DOM level 1 Event registration (via attributes or scripting).
As far as I'm concerned, your best bet is to make a shallow document copy using an XML parser and replace the old document (which you could backup-save to the window).
First: Your code will remove everything from the page, leaving a blank page. I cannot see how it would make the page "static".
$('*').detach();
will remove every element form the DOM. Nothing left. So yes, you remove every functionality in a way, but you also remove all the content.
Update: Even with the change from detach to unbind, the below points are still valid.
Event listeners added in the markup via oneventname="foo()" won't be affected.
javascript: URLs e.g. in images might still be triggered.
Event listeners added to window and document will persist.
See a DEMO.

Categories

Resources