Dual Listbox
Dynamic updates are changes that happen when users interact with any interactive element on a webpage. These changes SHOULD be available for all users. Though it is visible for users who can see the page, assistive technology users need to be notified of these changes. Through appropriate use of ARIA live regions, this CAN be achieved.
NOTE:
- New to accessibility or uncertain of requirements, it will be helpful to review all sections below.
- Already familiar with requirements, skip to the “Working Example” section for sample HTML, CSS and JavaScript (when needed), along with a working demo.
- Ensure that screen readers announce alerts for users when content on a page is updated or new page is opened.
-
This CAN be implemented using
aria-live
attribute. All page content or just the part that gets updated SHOULD be announced. -
The
aria-live
attribute is used to indicate that an element will be updated, and describe the types of updates the user agents, assistive technologies, and user can expect from the live region. -
Its value CAN be set to
- assertive – Has the highest priority and is presented to the user immediately.
- polite – Updates to the region is presented to the user when the user is in idle state.
- off – Updates to the live region is not intimated to the user unless the focus is on the region.
- A live region CAN be defined to any container where the dynamic updates are going to happen.
- The live region MUST be there within the DOM by default wherein the dynamic update messages will get injected.
-
Alternatively, roles such as
log
,status
,alert
,progressbar
,marquee
andtimer
CAN be used for dynamic content. -
OnChange
event handlers SHOULD be avoided in order to perform the dynamic updates.
For example, instead of updating the content dynamically on selecting an option from the dropdown, provide a “Go” button instead. -
An approach CAN also be taken by informing users in advance about the dynamic
changes that will happen through visual or off-screen instructions.
For example, if on activating any pagination links like 1, 2, 3 and so on, the data in the table above will get updated, an instruction CAN be provided to inform users in advance about the dynamic changes.
For more information on how to handle Dynamic Alerts and Notifications, refer to Alerts and Notifications components.
For example,
<h1>Dynamic Update</h1>
<h2>Contact US</h2>
<h3>Please Select Your Query</h3>
<p>
Please select the appropriate item from the drop-down menu below, so we can
route your inquiry to the correct person.
</p>
<label for="questionType">Select a Topic:</label>
<select class="questionType" id="questionType" name="questionType" aria-controls="inquiry_desc">
<option value="please select">Please Select Your Query</option>
<option value="Cert Flash Cards Online">Cert Flash Cards Online</option>
<option value="Corporate Sales">Corporate Sales</option>
...
</select>
<button id="goButton">Go</button>
<div id="inquiry_desc" role="region">
<h2 id="selectedHeading">No Inquiry Selected</h2>
<p id="selectedParagraph">Select a Inquiry to view its description</p>
</div>
A well-defined dynamic update benefits majorly the below users.
- People with visual disabilities
- People with cognitive disabilities
- In certain scenarios, it will also help People using speech input, People using keyboard only or People with limited dexterity.
<h2>Contact Us</h2>
<h3>Please Select Your Query</h3>
<p>
Please select the appropriate item from the drop-down menu below, so we can
route your inquiry to the correct person.
</p>
<label for="questionType">Select a Topic:</label>
<select id="questionType" class="questionType" name="questionType" aria-controls="inquiry_desc">
<option value="please select">Please Select Your Query</option>
<option value="Cert Flash Cards Online">Cert Flash Cards Online</option>
<option value="Corporate Sales">Corporate Sales</option>
<option value="Defective Products">Defective Products</option>
<option value="Digital Products Help">Digital Products Help</option>
<option value="Education Sales">Education Sales</option>
<option value="Network Simulator">Network Simulator</option>
<option value="Government Sales">Government Sales</option>
<option value="Pearson IT Certification Practice Test">
Pearson IT Certification Practice Test
</option>
</select>
<button id="goButton">Go</button>
<div id="inquiry_desc" role="region">
<h2 id="selectedHeading">No Inquiry Selected</h2>
<p id="selectedParagraph">Select a Inquiry to view its description</p>
</div>
const selectBox = document.querySelector('.questionType');
const selectedHeading = document.getElementById('selectedHeading');
const selectedParagraph = document.getElementById('selectedParagraph');
const goButton = document.getElementById('goButton');
goButton.addEventListener('click', function () {
const selectedOption = selectBox.options[selectBox.selectedIndex];
const optionText = selectedOption.text;
const optionValue = selectedOption.value;
const contentMapping = {
"Cert Flash Cards Online": "<p>Do you need technical support for help using our Cert Flash Cards Online application? Visit our Help Center for self-help options as well as live chat, web and phone support from a team of trained agents.<a href='#'>http://pearsonitp.echelp.org</a></p>",
"Corporate Sales": "<p>As a Corporate customer, you may be eligible for discounts on our products. You also have opportunities to become a reseller of these products, to bundle these products with your own as software documentation or value-adds, or to work with us to create a new book for your unique needs. Please use this form to inquire about discounts and opportunities.</p>",
"Defective Products": "<p>Need to report a physical defect of a product you received, such as a broken or scratched CD, missing pages, etc.? Visit our Help Center for self-help options as well as live chat, web, and phone support from a team of trained agents. <a href='#'>http://pearsonitp.echelp.org</a></p>",
"Digital Products Help": "<p>Do you have questions about our digital products, including downloadable PDFs and video? Visit our Help Center for self-help options as well as live chat, web, and phone support from a team of trained agents. <a href='#'>http://pearsonitp.echelp.org</a></p>",
"Education Sales": "<p><Strong>Please use the Pearson <a href='#'>Sales Rep Locator</a> to find your contact for review copy requests or to place an order.</strong></p><p>If you teach at an academic institution or other qualified training organization, your affiliated bookstore may be eligible to sell under our educational pricing schedules. Please use this form for additional inquiries.</p>",
"Network Simulator": "<p>Do you have questions about our Network Simulator software downloads? Visit our Help Center for self-help options as well as live chat, web, and phone support from a team of trained agents. <a href='#'>http://pearsonitp.echelp.org</a></p>",
"Government Sales": "<p>As a Government customer, you may be eligible for discounts on our products. You also have opportunities to bundle these products with your own as software documentation or value-adds, or to work with us to create a new book for your unique needs. Please EMAIL your request to the government team.</p>",
"Pearson IT Certification Practice Test": "<p>Do you have questions about a Pearson IT Certification practice test application installation and performance? Visit our Help Center for self-help options as well as live chat, web, and phone support from a team of trained agents. NOTE: If you have corrections for exam question content, please use the <strong>“Feedback”</strong> button from within the application. <a href='#'>http://pearsonitp.echelp.org</a></p>",
};
if (optionValue !== 'please select') {
selectedHeading.textContent = optionText;
selectedParagraph.innerHTML = contentMapping[optionValue];
} else {
selectedHeading.textContent = '';
selectedParagraph.textContent = '';
}
});
Contact Us
Please Select Your Query
Please select the appropriate item from the drop-down menu below, so we can route your inquiry to the correct person.
No Inquiry Selected
Select a Inquiry to view its description
<div class="container" id="container">
<p>Complete the activity in the given time.</p>
<p>Time remaining to complete the activity</p>
<div role="alert" id="timer">10<span class="hidethis">seconds remaining</span></div>
<form id="demo-form">
<div id="question">
<h2>Question No. 10</h2>
<p>The area of science that studies life and its processes is called:</p>
<div>
<input type="radio" name="answer" value="Archeology" id="Archeology">
<label for="Archeology">Archeology</label>
</div>
<div>
<input type="radio" name="answer" value="Astronomy" id="Astronomy">
<label for="Astronomy">Astronomy</label>
</div>
<div>
<input type="radio" name="answer" value="Geology" id="Geology">
<label for="Geology">Geology</label>
</div>
<div>
<input type="radio" name="answer" value="Biology" id="Biology">
<label for="Biology">Biology</label>
</div>
<div>
<input type="radio" name="answer" value="Anthropology" id="Anthropology">
<label for="Anthropology">Anthropology</label>
</div>
</div>
<button type="button" id="submit">Submit</button>
<button type="reset">Reset</button>
</form>
</div>
<div id="alert" role="alert"></div>
#timer {
font-size: 24px;
color: #333;
}
#alert {
display: none;
font-size: 18px;
color: #e60202;
margin-top: 20px;
}
input[type="radio"] {
display: inline;
width: auto;
margin: 10px;
}
#submit {
background-color: #003057;
border: 2px solid #000;
border-radius: 10px;
color: #fff;
padding: 0.35rem 1rem;
margin: 1rem 2rem 0 0;
font-size: 1rem;
}
#submit:focus {
outline: .10em solid #000000;
outline-offset: 1px;
}
.hidethis {
position: absolute;
overflow: hidden;
white-space: nowrap;
margin: 0;
padding: 0;
height: 1px;
width: 1px;
clip: rect(0 0 0 0);
clip-path: inset(100%);
}
const tabs = document.querySelectorAll('.tab');
tabs.forEach(tab => {
tab.addEventListener('click', (e) => {
let manualtab = document.querySelectorAll('.tab');
manualtab.forEach(mtab => {
mtab.setAttribute('aria-selected','false');
mtab.setAttribute('tabindex','-1')
});
const panels = document.querySelectorAll('.tab-panel');
panels.forEach(panel => {
panel.setAttribute('aria-hidden','true');
panel.setAttribute('hidden','');
panel.classList.remove('active');
});
const tabPanelId = tab.getAttribute('aria-controls');
const tabPanel = document.getElementById(tabPanelId);
tabPanel.removeAttribute('hidden');
tabPanel.setAttribute('aria-hidden','false');
tabPanel.classList.add('active');
tab.setAttribute('aria-selected','true')
tab.removeAttribute('tabindex')
});
tab.addEventListener('keydown', event => {
const key = event.key;
if (key === 'Enter' || key === ' ') {
event.preventDefault();
tab.click();
}
if (key === 'ArrowLeft' && document.activeElement !== tabs[0]) {
const index = Array.from(tabs).indexOf(document.activeElement) - 1;
tabs[index].focus();
} else if (key === 'ArrowRight' && document.activeElement !== tabs[tabs.length - 1]) {
const index = Array.from(tabs).indexOf(document.activeElement) + 1;
tabs[index].focus();
}
});
});
const demo2Tab = document.getElementById('demo-2-tab');
const timerElement = document.getElementById('timer');
const question = document.getElementById('question');
const submitButton = document.getElementById('submit');
const alertElement = document.getElementById('alert');
const resetform = document.getElementById('demo-form');
let timeLeft = 10;
let responseSubmitted = false;
let timerExpired = false;
submitButton.addEventListener('click', () => {
const selectedOption = document.querySelector('input[name="answer"]:checked');
if (selectedOption) {
responseSubmitted = true;
document.getElementById('container').style.display = 'none';
alertElement.style.display = 'block';
alertElement.innerHTML = '<p>✓ Your answers have been submitted.</p>';
if (timerExpired) {
alertElement.innerHTML = '<p>✓ The time to complete the activity has been exhausted and answers have been submitted</p>';
alertElement.setAttribute('tabindex','-1');
alertElement.focus();
}
alertElement.setAttribute('tabindex','-1');
alertElement.focus();
} else {
alertElement.style.display = 'block';
alertElement.textContent = 'Please select an option before submitting.';
alertElement.setAttribute('tabindex','-1');
alertElement.focus();
}
});
let timerInterval = null;
demo2Tab.addEventListener('click', () => {
resetform.reset();
timeLeft = 10;
responseSubmitted = false;
timerExpired = false;
timerElement.innerHTML = `${timeLeft} <span class="hidethis">seconds remaining</span>`;
document.getElementById('container').style.display = 'block';
alertElement.style.display = 'none';
alertElement.removeAttribute('tabindex');
if (timerInterval !== null) {
clearInterval(timerInterval);
}
const updateTimer = () => {
timerElement.innerHTML = `${timeLeft} <span class="hidethis">seconds remaining</span>`;
if (timeLeft <= 0) {
clearInterval(timerInterval);
if (!responseSubmitted) {
document.getElementById('container').style.display = 'none';
alertElement.style.display = 'block';
alertElement.innerHTML = '<p>✓ The time to complete the activity has been exhausted, and answers have been submitted</p>';
timerExpired = true;
alertElement.setAttribute('tabindex', '-1');
alertElement.focus();
}
}
timeLeft--;
};
timerInterval = setInterval(updateTimer, 1000);
});
Complete the activity in the given time.
Time remaining to complete the activity