When programming/designing for accessibility, is there a proper method for conveying that a particular item is "completed"?
Currently building some accessible e-learning. In a particular activity there are a number of buttons that must be pressed, where activating each button reveals further information in a separate panel. In this particular example, I am using a tablist.
Once all tabs have been visited, the user can move forward to the next activity.
Would changing the aria-label's to something like "Tab 1 - complete" or "Tab 1 - not complete" suffice for indicating their state?
Update 1
For clarification, in this particular example I'm using a tablist, using the methodology from Inclusive Components - Tabbed Interfaces. The unordered list is required to have a role="tablist", so I can't use the role="progressbar".
ie:
<ul role="tablist">
<li role="presentation"> <a role="tab" href="javascript:void(0)">Tab 1</a> </li>
<li role="presentation"> <a role="tab" href="javascript:void(0)">Tab 2</a> </li>
</ul>
You can tell assistive technologies such as screen readers that an element shows progress by giving it role="progressbar". Then, you can set up minimum and maximum values with aria-valuemin and aria-valuemax, respectively, and display the current value with aria-valuenow. By default, screen readers speak aria-valuenow as a percentage based on min and max. However, you can set aria-valuetext to tell the screen reader to present the value in a different format. It can look something like this:
<ol tabindex="0" role="progressbar" aria-valuemin="1" aria-valuemax="3" aria-valuenow="1" aria-valuetext="Step 1 of 3: First Step">
<li>First Step</li>
<li>Second Step</li>
<li>Last Step</li>
</ol>
Giving the element tabindex="0" will assure that the user tabs to it after each completed step, thus getting the new information.
Be sure to give the non-current sections of content aria-hidden="true" to make the screen reader skip them.
Update 1
In the case of role="tablist" there are a few different elements that can assist you. In your case, you can use aria-hidden and aria-selected as your states and control focus with tabindex. So let's say the screen reader user is on the first tab, your code can look something like this:
<ul role="tablist">
<li role="presentation">
<a role="tab" href="#section1" id="tab1" aria-selected="true" tabindex="0">Tab 1</a>
</li>
<li role="presentation">
<a role="tab" href="#section2" id="tab2" aria-selected="false" tabindex="-1">Tab 2</a>
</li>
</ul>
<section role="tabpanel" id="section1" aria-labelledby="tab1" aria-hidden="false">
// Tab1 content here
</section>
<section role="tabpanel" id="section2" aria-labelledby="tab2" aria-hidden="true">
// Tab2 content here
</section>
With this setup your screen reader user is unable to tab to the second tab, and its content is also hidden to the screen reader. You can trigger the appropriate tab when the screen reader user clicks the corresponding button by changing tabindex, aria-hidden, and aria-selected.
If you want to inform the screen reader user of the progress you can simply give the buttons aria-label. For example, the button for tab 1 can have: aria-label="Complete step 1 out of 3".
Hope it helps!
Related
TLDR: Can I force a column layout refresh after dynamically updating the 'css-column' css with javascript/jquery?
I have a navigation menu that I am using css columns for (I cannot work out how to use the Magento2 menu column functionality). I cannot really change the markup much. I want to stop 'widow' titles from happening (titles at the bottom of the column, with all the content on the next column - see 3rd pink title in screenshot below). It cannot be set with css as the nav items are dynamic and will change.
(I have tried "break-after:avoid" on the parent list, but this stops the list from breaking altogether - i.e. it should be able to break anywhere in the middle of the list).
I came up with a hacky solution that almost works - with javascript I am dynamically adding "break-before: column" to any list that has a widow title. (It checks the left offset of the title, compared with the offset of the first list child. If it is different then it means the title starts on the previous column).
This (sometimes) works BUT it (sometimes) does not update the columns until you resize the screen a bit.
I have been been trying out these kinds of solutions and many of these too. However none of them seem to work, for example I have tried:
console.log(elt.offsetHeight);
console.log(elt.getBoundingClientRect());
Tried 'elt' being all sorts, the parent elements, the whole body/doc wrapper etc. I thought maybe this was because the element in question is hidden until you hover over the nav link. But I forced it to be open using chrome devtools and ran the same 'reflow triggering' javascript and it still made no difference?
Is there a (preferably nice and not forcing reflow of the whole document every pageload??) way to force a recalculation of the css columns?
OR is a better solution possible using css grid / any other way?
Thanks!
In case it is relevant to another possible solution, the markup is like this:
<ul class="level0 submenu">
<li class="navigation_item__back hidden-desktop">
Back
</li>
<li class="navigation_item__link hidden-desktop">
Title
</li>
<li class="level1 nav-3-1 category-item first parent">
<a href="">
<span>Sub Title</span>
</a>
<ul class="level1 submenu">
<li class="navigation_item__back hidden-desktop">
Back
</li>
<li class="navigation_item__link hidden-desktop">
Sub Title
</li>
<li class="level2 nav-3-1-1 category-item first">
<a href="/">
<span>Lorem 1psum</span>
</a>
</li>
<li class="level2 nav-3-1-2 category-item">
<a href="/">
<span>Lorem 2psum</span>
</a>
</li>
</ul>
</li>
...
</ul>
I have a well-known problem of the iPhone users with my current website.
I have two tabs allowing my users to switch between two weeks:
<ul class="nav nav-tabs justify-content-center" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="home-tab" data-toggle="tab" href="#currentWeekTab" role="tab" aria-controls="home" aria-selected="true" >
{{{weekInterval 1}}}
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="profile-tab" data-toggle="tab" href="#nextWeekTab" role="tab" aria-controls="profile" aria-selected="false" >
{{{weekInterval 0}}}
</a>
</li>
</ul>
My problem is that my iPhone users need to click twice to actually change the tab. I read that the problem was coming from the hover but no answer fixed my problem.
How can I allow my customers using iPhone to change tab with just one click? Thanks in advance.
You can let Blaze solve your problem by listening to the "click, touchstart" (=tap) event (I am not sure if cordova automatically converts click to tap but I think you will get the point) and force a redraw based on a reactive variable:
First rewrite your ul to not use any bootstrap based events but Blaze helpers:
<ul class="nav nav-tabs justify-content-center" id="myTab">
<li class="nav-item">
<a class="nav-link week-tab-link {{#if active 'currentWeek'}}active{{/if}}"
id="home-tab"
data-state="currentWeek"
href="#currentWeekTab"
aria-controls="home" aria-selected="{{active 'currentWeek'}}">
1
</a>
</li>
<li class="nav-item">
<a class="nav-link week-tab-link {{#if active 'nextWeek'}}active{{/if}}"
id="profile-tab"
data-state="nextWeek"
href="#nextWeekTab"
aria-controls="profile" aria-selected="{{active 'nextWeek'}}">
2
</a>
</li>
</ul>
{{#if active 'currentWeek'}}
<p>render current week</p>
{{/if}}
{{#if active 'nextWeek'}}
<p>render next week</p>
{{/if}}
As you can see the template relies on some state to determine a) which tab is active and b) which content to render.
To resolve this active state a helper is required:
Template.myTemplate.helpers({
active (tabName) {
return Template.instance().state.get('active') === tabName
}
})
There also needs to be a default state to be set in order to determine what to render when the page is loaded:
Template.myTemplate.onCreated(function helloOnCreated () {
const instance = this
instance.state = new ReactiveDict(0)
instance.state.set('active', 'currentWeek')
})
In order to save lines of code (=less possible errors) you can create an event map for a common class selector .week-tab-link which triggers an event callback if any of the tab is clicked. In this callback you can "read" the data-state attribute from the tab in order to set the active state:
Template.myTemplate.events({
'click, touchstart .week-tab-link' (event, templateInstance) {
// event.preventDefault() // uncomment this to prevent href update
const $target = templateInstance.$(event.currentTarget)
const activeState = $target.data('state')
templateInstance.state.set('active', activeState)
}
})
Note, that this uses ReactiveDict but you can also implement this using ReactiveVar.
Related:
Touch events in Meteor
I added a dropdown list to the navbar on another site and added the class .open to the list. My intention is as follows: upon load the webpage navbar list contains an img element and opens displaying a promotional offer. So far so good, the page loads and the list drops displaying the ad, and if clicked it then closes.
Ok what I am aiming for is adding a function via jquery or JavaScript or css which will automatically CLOSE the dropdown list after about 5 seconds. I have read that the .open class in bootstraps.min.css is not cleared by default and therefore will remain open unless it is 'clicked' to close it.
<div class="navbar-responsive">
<ul class="nav navbar-nav">
<li class="active">
<li class="open dropdown-menu">
<a href="#" Id="test" class="dropdown-toggle" data- toggle="dropdown"><strong class="caret">
<ul class="dropdown-menu">
<li>
Click to close.
</li>
<li>
<img src="image folder/my_ad_image.png"
</li>
</ul>
</li>
</li>
</ul>
</div><!---end nav collapse--->
</div><!---end container--->
</div>>!---end main navbar--->
This above is what I have written. It rests atop an already existing navbar.
Thanks for reading.
If anyone has any suggestion or could point me in the right direction with respect to tying a jquery timeout function to my .open class or id that would be great. So far I have been unable to tie a jquery function or css to my dropdown list
Thanks.
You can use setTimeout() to implement timers in javascript.
The setTimeout() method calls a function or evaluates an expression
after a specified number of milliseconds.
Adapting your code it can be implemented like this:
CSS:
...
<li id="myid" class="open dropdown-menu">
<strong class="caret"></strong>
<ul class="dropdown-menu">
<li>
Click to close.
</li>
<li> ... </li>
</ul>
</li>
...
jScript (assuming you're using jQuery):
$(function() {
setTimeout(function() {
$("#myid").removeClass("open")
}, 5000);
});
This question already has answers here:
How can I keep selected Bootstrap tab on page refresh?
(19 answers)
Closed 7 years ago.
I have implemented nav-tabs in my project using bootstrap.When we enter the application,Home tab is active.When i make changes in the other tabs and press save button,the page is going to the Home tab.
I want the tab on which i've made changes to be active.
The below is similar code i've used in my project.
HTML
<div class="nav">
<div class="container">
<div class="tabbable">
<ul class="nav nav-tabs" data-tabs="tabs" id="myTab">
<li class="active"><a data-toggle="tab" href="#home">Home</a></li>
<li><a data-toggle="tab" href="#about">About</a></li>
<li><a data-toggle="tab" href="#subscribe">Subscribe</a></li>
<li><a data-toggle="tab" href="#search">Search</a></li>
<li><a data-toggle="tab" href="#logout">Logout</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="home">
<h1>Hospital Data Solutions</h1>
<p>Financial Analysis Database</p>
</div>
<div class="tab-pane" id="about">
<h1>About Us</h1>
<p>Cost Reports and Financial Analysis Nationwide Database</p>
</div>
<div class="tab-pane" id="subscribe">
<h1>Annual Subscription</h1>
<p>Purchase an annual subscription to access all cost reports.</p>
<h2>Individual Cost Reports</h2>
<p>Purchase individual cost reports directly from us in .pdf, .xs, .csv formats.</p>
</div>
<div class="tab-pane" id="search">
<h1>Search our database</h1>
<p>Search content goes here.</p>
</div>
<div class="tab-pane" id="logout">
<h1>logout</h1>
<p>Logout fx goes here.</p>
</div>
</div>
</div>
</div>
</div>
Fiddle here
First, you need to add the selected tab hash to the url.
Here's an example with JQuery :
$('a[data-toggle="tab"]').click(function(e) {
var hash = $(this).attr('href');
location.hash = hash;
});
Next, you need to show the tab linked to the hash added to the url when you load the page :
$(function() {
var hash = window.location.hash;
var $nav = $('ul.nav a[href="' + hash + '"]');
hash && $nav.trigger('click');
});
It seems, basically what you need to do, is to add the class active to the <li> tag, when entering the page, and removing it from other <li> elements.
<li class="active">
<a data-toggle="tab" href="#about" aria-expanded="false">
About
</a>
</li>
You could achieve that with jQuery. Just set the appropriate class during page initialization. With jQuery you will also have to bind the appropriate events to the elements, as Martin Lezer explains in his answer:
The question is, how to you remember the state of the application between refreshs. Here are some possibilities:
Cookies: Set a cookie with the status, each time you click on a tab
Local storage or session storage of the browser. Same principle as 1
Location-Hash: see answer of Martin Lezer here.
URL-Parameters: You could use those to remember the app-state, but I would recommend against it, because usually you do not want to have this kind of information in the URL.
1 and 2 are persistent, that means, you can come back tomorrow and the application can init with the same state
3 and 4 are not persistent, you need to pass that information each time you enter the application (which is fine, during a session)
Hope that helps.
I have a side bar menu collapsible submenu in my Angular project. I used isActive comment for showing active state. When i refresh any page it should show the particular menu with active state. it works on when i refresh submenu's first link. If i click submenu's second link, it doesn't work.
I dont know how to declare active more than a link. ng-class="{show:isActive('/create-workorder')}"
My code is below
<ul>
<li>Work
<ul class="second_level" ng-class="{show:isActive('/create-workorder')}">
<li>
<a href="#/create-workorder" class="" ng-class="{active_sub:isActive('/create-workorder')}">
<div class="create_wo"></div>Create WO</a>
</li>
<li>
<a href="#/workorder-all" class="" ng-class="{active_sub:isActive('/workorder-all')}">
<div class="overall_queue"></div>Overall all</a>
</li>
</ul>
</li>
<li>Status
<ul class="second_level" ng-class="{show:isActive('/history')}">
<li>
<a href="#/history" class="" ng-class="{active_sub:isActive('/history')}">
<div class="status"></div>History</a>
</li>
<li>
<a href="#/recent" class="" ng-class="{active_sub:isActive('/recent')}">
<div class="recent"></div>Recent</a>
</li>
</ul>
</li>
</ul>
A common technique to use to determine active menu is to use the URL itself.
On page refresh you can check the URL and highlight corresponding menu.
For parent-child menu, you can choose to code the relationship, e.g. specify that you should also highlight "status" when you highlight "history".
Or you can use URL itself for the structure, e.g. #/status/history instead of #/history.