Grouping buttons - ARIA - javascript

I have a group of 2~3 buttons inside one flex, is there a way to announce to the user that the buttons are grouped and specify which button is focused?
Example: I have 3 buttons - "Cancel" - "Modify" - "Confirm". I want it to be announced as "Cancel button 1 of 3", not necessary on this order.
PS: Avoid changing the buttons aria-label and role.
<div id="flxButtons">
<div id="wrapper">
<input id="btnCancel" type="button" role="button" value="CANCEL">
</div>
<div id="wrapper">
<input id="btnModify" type="button" role="button" value="MODIFY">
</div>
<div id="wrapper">
<input id="btnNext" type="button" role="button" value="NEXT">
</div>
</div>

One might be tempted to use aria-setsize and aria-posinset on the buttons but those attributes are only valid on listitems and treeitems, so you can't do this:
<input id="btnCancel" type="button" role="button" value="CANCEL" aria-posinset="1" aria-setsize="3">
However, you could add list semantics to the <div> around each button (or use a real <ul>), but that doesn't guarantee you'll hear "X of Y" on each button because that's up to the screen reader and user settings. See focus not going to listitems in browse mode nvda for details.
<div id="flxButtons" role="list" aria-label="my group of buttons">
<div id="wrapper" role="listitem">
<input id="btnCancel" type="button" role="button" value="CANCEL">
</div>
<div id="wrapper" role="listitem">
<input id="btnModify" type="button" role="button" value="MODIFY">
</div>
<div id="wrapper" role="listitem">
<input id="btnNext" type="button" role="button" value="NEXT">
</div>
</div>
As far as the grouping itself, in the example above, specifying role="list" on the outer container will give you a grouping. If you don't want to use lists, you can use role="region" and specify an aria-label.
<div id="flxButtons" role="region" aria-label="my group of buttons">
If you always want to force "X of Y" to be announced, regardless of the users screen reader settings, you'd have to literally add that text. You could either make that text part of the button label (but not visible) or you could associate the text with the button's descrption. The latter might be slightly better since you didn't want to change the button's label. However, it's a little messy to do so with the current ARIA spec because you only have aria-describedby, which requires the ID of the element that has the description, so you have to create a new DOM element that has the description.
In ARIA 1.3, there will be an aria-description which takes a literal string so it'll be easier when that spec is approved.
So in the current ARIA spec, using aria-describedby, you could have something like this:
<div style="display:none">
<div id="desc1">1 of 3</div>
<div id="desc2">2 of 3</div>
<div id="desc3">3 of 3</div>
</div>
<div id="flxButtons" role="region" aria-label="my group of buttons">
<div id="wrapper">
<input id="btnCancel" type="button" role="button" value="CANCEL" aria-describedby="desc1">
</div>
<div id="wrapper">
<input id="btnModify" type="button" role="button" value="MODIFY" aria-describedby="desc2">
</div>
<div id="wrapper">
<input id="btnNext" type="button" role="button" value="NEXT" aria-describedby="desc3">
</div>
</div>

Related

Only first button works, but they are all set to do the same [duplicate]

This question already has answers here:
JavaScript and getElementById for multiple elements with the same ID
(13 answers)
Get multiple elements by Id
(14 answers)
Closed 1 year ago.
I am making a menu and I am currently implementing a feature where you can close the menu. I have three different menus inside of an overlay. When you close the menu I want the overlay to be display: none;. I have three buttons that do this (one for each menu). However, only the button at the top of the HTML code works. I know it is only the one at the top, because I tried deleting the one that was on the top, and then the second button would work since that is now the top button. I also tried giving different IDs, but that didn't make a difference.
Here is a shortened version of the parts of my code that I am talking about:
var overlay = document.getElementById("overlay");
var closeMenu = document.getElementById("closeMenu");
closeMenu.addEventListener('click', function() {
overlay.style = "display: none;";
});
<div class="overlay" id="overlay">
<div class="selectMenu" id="selectMenu">
<div class="h2Wrapper">
<h2>Create Canvas</h2>
<button type="button" name="button" class="closeMenu fas fa-times" id="closeMenu"></button>
</div>
</div>
<div class="selectMenu2" id="selectMenu2">
<div class="h2Wrapper">
<h2>Upload Image</h2>
<button type="button" name="button" class="closeMenu fas fa-times" id="closeMenu"></button>
</div>
</div>
<div class="selectMenu3" id="selectMenu3">
<div class="h2Wrapper">
<h2>Create Blank</h2>
<button type="button" name="button" class="closeMenu fas fa-times" id="closeMenu"></button>
</div>
</div>
</div>
First of all, the attribute id must be unique in a document, use class instead. Then you can target all the element with the class to loop through them and attach the event individually:
var overlay = document.getElementById("overlay");
var closeMenu = document.querySelectorAll(".closeMenu");
closeMenu.forEach(function(cm){
cm.addEventListener('click', function() {
overlay.style = "display: none;";
});
});
<div class="overlay" id="overlay">
<div class="selectMenu" id="selectMenu">
<div class="h2Wrapper">
<h2>Create Canvas</h2>
<button type="button" name="button" class="closeMenu fas fa-times" class="closeMenu"></button>
</div>
</div>
<div class="selectMenu2" id="selectMenu2">
<div class="h2Wrapper">
<h2>Upload Image</h2>
<button type="button" name="button" class="closeMenu fas fa-times" class="closeMenu"></button>
</div>
</div>
<div class="selectMenu3" id="selectMenu3">
<div class="h2Wrapper">
<h2>Create Blank</h2>
<button type="button" name="button" class="closeMenu fas fa-times" class="closeMenu"></button>
</div>
</div>
</div>

How to prevent Elements BENEATH a Bootstrap Multiselect dropdown from firing on click of multiselect?

When a user clicks an option in a Bootstrap Multiselect dropdown a Bootstrap Toggle (http://www.bootstraptoggle.com/) Element BELOW is fired.
I'm not sure if this problem is specific to Bootstrap Multiselect and/or Bootstrap Toggle, or the interplay of the two - it is the only Element in my app that overlaps/hides other Elements.
The plugin works great...it's just that when you click Algebra (1 below) or really any option in the dropdown, the Bootstrap Toggles below (2 in the screenshot) are fired as if you clicked them directly.
How do I prevent this without a check-to-see-if-the-multiselect-is-open logic?
Adding HTML to address question...the divs were inside a single parent div and I moved them to be in separate Divs...same result: clicking the dropdown multiselect fires the listener on wordPref class.
<div class="row paddingMenu">
<div class='col-xs-12 alignleft'>
<b>Select</b> from <i>active</i> Libraries<a data-toggle="tooltip" data-placement="bottom" title="Click EDIT then ACTIVATE LIBRARIES to add and remove Libraries." tabindex="-1" class="pull-right"><span class="glyphicon glyphicon-info-sign pull-right" style="font-size: 15px"></span></a>:
</div>
<div class='col-xs-12 aligncenter'>
<div class='form-group'><select id='ddLibName' multiple='multiple'></select>
<div id='ddLibrarySelect'></div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-4 aligncenter" data-toggle="tooltip" data-placement="bottom" title="Choose whether to insert selected Comments as Word comment bubbles OR inline text.">
<input type="checkbox" id="insertMode" class="wordPref" data-toggle="toggle" data-size="small"
data-off="Inline" data-on="Comment"
data-offstyle="info" data-onstyle="success">
</div>
<div class="col-xs-4 aligncenter" data-toggle="tooltip" data-placement="bottom" title="Save document owner/author info with your usage statistics. This setting may be defined by your institution.">
<input type="checkbox" id="logMode" class="wordPref" data-toggle="toggle" data-size="small"
data-off="History OFF" data-on="History ON"
data-offstyle="info" data-onstyle="success">
</div>
<div class="col-xs-4 aligncenter">
<a class="btn btn-primary btn-sm" id="refreshBtn" data-toggle="tooltip" data-placement="bottom" title="Refresh AP to pull down any content changes or purchases." tabindex="-1">Refresh</a>
</div>
<div id='upsellMsgDiv' class='apSidebarAlert col-xs-12 hide'>
<div class="spacer-5"></div>
<div class="panel panel-warning">
<div class="panel-body highlight-cell">
<span class="apAlertMsg"></span>
<div id='closeAlertBtn' class='col-xs-12 spacer-5 hide'>
<button class='btn-sm btn-primary closeSidebarAlert pull-right' type='button'>Close</button>
</div>
</div>
</div>
</div>
</div>
I haven't used it but are those two inside a same div? Is one of them is a parent?.. Share your code as well... You can try doing
e.stopPropagation()
to the below div if the dropdown div is the parent div.

If Session get login in javascript (laravel 5.6)

I got a little problem with Javascript in laravel 5.6.
I have a wizard setup here, and there are 3 steps.
Step 1. login or register
Step 2. another div (hidden)
Step 3. another div (hidden)
If I still don't have a login session (here I use the session for the login)
then I want to go directly to step 2 (hidden div 1 and 2)
And my statement is how do I get login session logic on javascript?
This is the markup for the view:
<div class="container">
<div class="stepwizard1">
<div class="stepwizard-row1 setup-panel">
<div class="stepwizard-step1">
<a id="a-step1" href="#step-1" type="button" class="btn btn-primary btn-circle"></a>Step 1</p>
</div>
<div class="stepwizard-step1">
<a id="a-step2" href="#step-2" type="button" class="btn btn-default btn-circle disabled"></a>
<p>Step 2</p>
</div>
<div class="stepwizard-step1">
<a id="a-step3" href="#step-3" type="button" class="btn btn-default btn-circle disabled"></a>
<p>Step 3</p>
</div>
</div>
</div>
<div class="tab-panel setup-content" id="step-1">
<div class="col-md-12">
<section class="content">
<div class="login">
<h2>masuk</h2>
<div class="alert alert-danger alert-dismissible alert-login" style="display:none;"></div>
<form id="form-login">
<div id="label_email">
<input type="text" placeholder="Email" name="email" id="email"/>
</div>
<div id="label_password">
<input type="password" placeholder="Password" name="password" id="password"/>
</div>
<button type="submit" class="button nextBtn">Masuk</button>
</form>
</div>
</section>
</div>
<div class="tab-panel setup-content " id="step-2">
<div class="col-md-12">
<section class="content">
<div class="login">
<h2>Alamat</h2>
<div class="alert alert-danger alert-dismissible alert-login" style="display:none;"></div>
<div id="label_email">
<input type="text" placeholder="alamat" name="alamat" id="alamat"/>
</div>
<div id="label_password">
<input type="text" placeholder="kodepos" name="kodepos" id="kodepos"/>
</div>
<button type="submit" class="button nextBtn">Next</button>
</div>
</section>
</div>
</div>
</div>
btw, here I use ajax for the login form...
Thanks in advance, and I'm sorry if it's still wrong because I am still relatively new in the world of programs and my bad...very bad English.
First of all, if you are using a laravel then you can take advantage of blade templating engine
#auth
// The user is authenticated...
#endauth
#guest
// The user is not authenticated...
#endguest
Then you could set some classes inside those code blocks and style them. Your steps will be easier to implement.
If, however, you really want to use Ajax to check if user is authenticated, You could make a function in your controller to return a user status like
public function isLogged() {
if (Auth::check()) {
// The user is logged in...
}
}
And set up a root path like
Route::post( '/isUserLogged', 'UserController#isLogged' );
Oh, and one more thing, if you are using steps that could get ugly JS code pretty fast. I would suggest to use a Vuejs framework which has already built in the Laravel.
Good luck :)

Multiple Bourbon Refills Modals

I have a layout that is using the Bourbon Refills UI elements and I have a question regarding modals. More specifically, I have a case where I need multiple modals opened at once.
So...this is what is supposed to happen: A user clicks on a button that opens a normal Bourbon Refills Modal. Within that modal, the user has the option to click on a button to open an additional settings modal.
Currently I have one main modal and one nested inside of it. Sadly, the nested modal is constrained within the bounds of the first in Webkit and Gecko browsers. On IE...it doesn't at all :(
Is there any other way of pulling this off with Refills? I was thinking...maybe assigning a click event to the button to open a second (separate) modal that would sit on top of the first in z-index order?
Thanks in advance for your help - any is appreciated.
<div class="modal">
<label for="modal-1">
<div href="#" class="btn modal-trigger">Modal 1 Trigger Button</div>
</label>
<input class="modal-state modal-state-a" id="modal-1" type="checkbox" />
<div class="modal-fade-screen modal-fade-a">
<div class="modal-inner">
<div class="modal-close modal-close-a" for="modal-1"></div>
<h2>Modal 1 Title</h2>
<label>Input Label</label>
<input value="Input" />
<!-- Begin Nested Modal 2 -->
<div class="modal">
<label for="modal-2">
<div href="#" class="btn modal-trigger">Modal 2 Trigger Button</div>
</label>
<input class="modal-state modal-state-b" id="modal-2" type="checkbox" />
<div class="modal-fade-screen modal-fade-b">
<div class="modal-inner">
<div class="modal-close modal-close-b" for="modal-2"></div>
<h2>Modal 2 Title</h2>
<label>Input Label</label>
<input value="Input" />
</div>
</div>
</div>
<!-- End Nested Modal 2 -->
</div>
</div>
</div>
OK, I figured it out. Admittedly, this threw me off a bit because these are not JS-powered modals, but instead they rely on the ability to style an an element based on a hidden checkbox and its sibling element (in this case: < label >)
Easy-peasy. All we need to do is separate the modals and assign the :checked state to the hidden checkbox of the modal we want to open. For example:
First, separate the modals as you normally would. Then in Modal 1, create the link/button you want to have users click to open Modal 2. For the sake of argument, we will give it an ID of #update.
<div class="modal">
<label for="modal-1">
<div href="#" class="btn modal-trigger">Modal 1 Trigger Button</div>
</label>
<input class="modal-state modal-state-a" id="modal-1" type="checkbox" />
<div class="modal-fade-screen modal-fade-a">
<div class="modal-inner">
<div class="modal-close modal-close-a" for="modal-1"></div>
<h2>Modal 1 Title</h2>
<label>Input Label</label>
<input value="Input" />
<a class="btn btn__active" id="update">Update</a> <!-- New Button to open Modal 2-->
</div>
</div>
</div>
<div class="modal">
<label for="modal-2">
<div href="#" class="btn modal-trigger">Modal 2 Trigger Button</div>
</label>
<input class="modal-state modal-state-b" id="modal-2" type="checkbox" />
<div class="modal-fade-screen modal-fade-b">
<div class="modal-inner">
<div class="modal-close modal-close-b" for="modal-2"></div>
<h2>Modal 2 Title</h2>
<label>Input Label</label>
<input value="Input" />
</div>
</div>
</div>
Now...write a little bit of jQuery to assign the :checked state to the appropriate modal.
$("#update").click(function() {
var modalTrigger = $("input#modal-2");
modalTrigger.prop("checked", !modalTrigger.prop("checked"));
});
Done. Now the second modal opens up correctly over the first. I just tested this and it works in most browsers (including IE9-11) since we're not doing anything different from the base refills modals.

Reveal Hidden Elements with Buttons

I have a row made of three buttons, and I need these three buttons to remain on the same row.
With that said, I am trying to make it so that each time one of these buttons is clicked, hidden content is displayed underneath them. Each button would show hidden content that is different from the other.
Is there anyway I can accomplish such a task using $(this) or must I assign a unique ID to each button and the relevant content it's supposed to show?
I have tried placing each button within a superclass called .items and the relevant content within this class as a child, called .description--so that I can access it using jQuery's .children() function--but this tends to mess up the row that my buttons are on (so that they are not all on the same row). Is there anyway to get around this?
What would be the simplest way to go about this?
Edit to show code:
<div class="displayers">
<div class="items">
<button type="button" class="btn btn-custom">Button 1</button>
<div class="row">
<div class="description">
<p> content here </p>
</div>
</div>
</div>
<div class="items">
<button type="button" class="btn btn-custom">Button 2</button>
<div class="row">
<div class="description">
<p> content here </p>
</div>
</div>
</div>
<div class="items">
<button type="button" class="btn btn-custom">Button 3</button>
<div class="row">
<div class="description">
<p> content here </p>
</div>
</div>
</div>
</div>
In order to make the buttons fit on the same row, I changed the ".items" class to have the property of "inline-block". The ".description" class is hidden, and I have some jQuery to reveal it.
var main = function() {
$('.items').click(function() {
$('.description').hide();
$(this).children('.description').show();
});
};
$(document).ready(main);
The problem with this is that my buttons are no longer on the same row.
I like to use data attributes and css selectors (easy to change later on), so I would use:
$('[data-show]').on('click', function(e) {
var toShow = $( $(this).data('show') );
toShow.siblings().hide();
toShow.show();
});
li {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>
<button data-show=".content > *:nth-child(1)">Open 1st</button>
<button data-show=".content > *:nth-child(2)">Open 2nd</button>
<button data-show=".content > *:nth-child(3)">Open 3rd</button></p>
<ul class="content">
<li>1st Container</li>
<li>2nd Container</li>
<li>3rd Container</li>
</ul>
Looks pretty simple to me, but does not mean others would agree. It really depends on your needs.
You can just toggle the elements which is next to your button with just class added to each element as below:
$('.btnshowdes').on('click',function(){
$(this).next('.desc').toggle();
});
.desc{
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="items">
<div class="internal">
<input type="button" class="btnshowdes" value="Toggle Description"/>
<div class="desc">Description 1</div>
</div>
<br/>
<div class="internal">
<input type="button" class="btnshowdes" value="Toggle Description"/>
<div class="desc">Description 2</div>
</div>
<br/>
<div class="internal">
<input type="button" class="btnshowdes" value="Toggle Description"/>
<div class="desc">Description 3</div>
</div>
<br/>
<div class="internal">
<input type="button" class="btnshowdes" value="Toggle Description"/>
<div class="desc">Description 4</div>
</div>
<br/>
</div>
FIDDLE DEMO
UPDATE
Based on your updated question to make it in the same row you just need to put an extra style to your .items as below:
.items{
display:inline-table; //helps to keep it in same row
padding:10px;//Just to make it feel good
}
Your js according to your html structure will be:
$('.btn-custom').on('click',function(){
$(this).next('.row').find('.description').toggle();
});
DEMO FIDDLE HERE
To solve your problem i would split my elements. Why don't you put each button in a different container (a div for instance), each container having his own id and his own content.
So when you click on a button you display the content inside of one div and the style of other buttons will not be affected.
Something like
<div class="container" id="1">
<button id="btn1"> Button one </button>
<!-- your content here linked to the script you use to display -->
</div>
<div class="container" id="2">
<button id="btn2"> Button two </button>
<!-- your content here linked to the script you use to display -->
</div>
<!-- etc... -->
So you don't have to worry and use complicated scripts, and each style will not be affected by the others modifications.

Categories

Resources