I am trying to position a checkbox on the right side of a dropdown
<li>
<a class="drop-option" data-toggle="tab" href="#bizq">Business</a>
<input type="checkbox" value="" style="display: inline; float: right">
</li>
What I'm trying to have is the checkbox be a separate entity from the actual option itself. So that when I click on the option it goes to a page, and when I toggle the checkbox it does something else.
Essentially the goal is to have multiple pages with iframes. Each time I go to a page it load the iframe. If the checkbox is checked then the iframe can be persistent instead of getting destroyed each time a page is switched.
Should look something like this:
when I click on the option it goes to a page, and when I toggle the checkbox it does something else.
This can be implemented by following steps:
Add event listener to the option element.
When option element is clicked, check whether user clicks the checkbox inside the option. If it is the checkbox clicked, do nothing. Otherwise, go to step 3.
Check the current option element's checkbox status. Do different things according to different checkbox status.
Here is a code snippet:
var $option = $('a.option');
$option.on('click', function(e) {
var $target = $(e.target);
var $this = $(this);
if ($target.hasClass('toggle')) {
// checkbox clicked.
return;
}
var childToggle = $this.find('input.toggle').prop('checked');
var label = $this.find('.label').text();
if (childToggle) {
alert('Page ' + label + ' clicked, WITH checkbox checked.');
} else {
alert('Page ' + label + ' clicked, WITHOUT checkbox checked.');
}
});
ul>li {
list-style: none;
}
a.option {
background: darkcyan;
color: white;
display: block;
width: 100px;
padding: 10px;
text-decoration: none;
border-bottom: 1px solid white;
}
a.option input.toggle {
float: right;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
<a href="javascript:;" class="option">
<span class="label">Business</span>
<input type="checkbox" class="toggle" value="isSelected">
</a>
</li>
<li>
<a href="javascript:;" class="option">
<span class="label">Tech</span>
<input type="checkbox" class="toggle" value="isSelected">
</a>
</li>
</ul>
Related
I have created a JavaScript-free, HTML- and CSS-only drop-down menu using the checkbox hack. I am trying to avoid using JS as some users disable it. For touch-screens and mouse it works fine, but I am attempting to make it work so that anyone using keyboard navigation can use it.
It does work more or less:
The [Enter] key opens links and [spacebar] opens some (see further) sub-menus using checkboxes which are invisible to the naked eye by using the class opacity: 0;.
However, I have two contradictory problems with keyboard navigation:
The <a> tags and pseudo ::after elements associated with some checkboxes focus visibly with a faint dotted highlight but do not open when the spacebar is pressed.
When using a <span> tag instead of an <a> tag, the menus open when the spacebar is pressed but they are not visibly 'focused' with the dotted outline.
Also, the 'invisible' checkbox is positioned behind the ::after pseudo element of '+' but, because it's invisible, there is no focus outline.
Here is my simplified code with examples of the different combinations I have tried:
ul.menubar {
padding: 1rem 0 0 0.5rem;
}
[id^=chk] {
opacity: 0;
}
[id^=chk]+ul {
display: none;
}
[id^=chk]:checked+ul {
display: block;
}
label.link::after,
label span.separator::after,
label a.separator::after {
position: relative;
content: "+";
right: -1.25rem;
top: 0;
}
a {
text-decoration: none;
}
li {
line-height: 2.5rem;
font-size: 1.25rem;
list-style: none;
}
li a,
li span,
li label,
li input,
.inline {
display: inline;
position: relative;
}
<body>
<nav>
<ul class="menubar" role="menubar">
<li>
<div class="inline">Item link plus dropdown using span. + works but no keyboard focus |
<label for="chk-101" class="link" title="Item 1 link" aria-label="Item 1 link"></label></div><input id="chk-101" type="checkbox" class="chkbox" tabindex="1" aria-checked="false">
<ul>
<li>Dropdown 1a</li>
<li>Dropdown 1b</li>
</ul>
</li>
<li>Item link plus dropdown using 'a' tag with href; + works but not keyboard focused |
<label class="link" for="chk-102"></label><input id="chk-102" type="checkbox" class="chkbox" tabindex="1" aria-checked="false">
<ul>
<li role="menuitem" tabindex="1">Dropdown 2a</li>
<li role="menuitem" tabindex="1">Dropdown 2b</li>
</ul>
</li>
<li>
<label for="chk-103"><span class="separator">Separator with span - does not focus</span></label><input id="chk-103" type="checkbox" class="chkbox" tabindex="1" aria-checked="false">
<ul>
<li role="menuitem" tabindex="1">Dropdown 3a</li>
<li role="menuitem" tabindex="1">Dropdown 3b</li>
</ul>
</li>
<li>
<label for="chk-104">Separator with href - focus does not respond to spacebar</label><input id="chk-104" type="checkbox" class="chkbox" tabindex="-1" aria-checked="false">
<ul>
<li role="menuitem" tabindex="1">Dropdown 3a</li>
<li role="menuitem" tabindex="1">Dropdown 3b</li>
</ul>
</li>
<li>
<label for="chk-105"><span class="separator" role="checkbox" tabindex="1" aria-checked="false" aria-label="Separator 2">Separator with span role="checkbox"; focus but does not respond to spacebar</span></label>
<input id="chk-105" type="checkbox" class="chkbox" tabindex="-1" aria-checked="false">
<ul>
<li role="menuitem" tabindex="1">Dropdown 3a</li>
<li role="menuitem" tabindex="1">Dropdown 3b</li>
</ul>
</li>
</ul>
</nav>
</body>
Short Answer
The checkbox hack is not a good practice, especially for navigational menus and is not semantically correct, generally causing accessibility nightmares.
As "JavaScriptless" users are around 1.3% of users you should provide a usable but perhaps ugly version of the menu for them and make sure that for the majority of users everything is semantically correct.
Please note: The advice here is for navigational drop-downs, if this is for a complex application where the drop-down triggers functions on the current page rather than navigation then other patterns may be better.
Long Answer
I would normally address the question being asked but you are making things very difficult for yourself and I think it would be better to provide an alternative.
I have listed the reasons why not to use the checkbox hack and provided an explanation of a much simpler, more robust and much more accessible solution which should hopefully help you going forward.
First, the bad news
I hate to say it but you will never make the above accessible without JavaScript and your current implementation has quite a few accessibility issues.
First of all aria-checked needs to be toggled and you can only do that with JavaScript. Also a checkbox is not a logical / semantically correct element to use here and does not convey the right information to screen readers. If you then add role="button" to counter this then aria-checked is not a valid attribute.
Secondly the "checkbox hack" is not intended for navigational menus it is intended to be used for complex menus as part of an application, it is still not a good pattern to use then and should only be used if you are really struggling to make other options work.
Thirdly pseudo elements (your "+" symbol) are not focusable and a lot of screen readers ignore them / don't behave well with them, so that is a big accessibility problem.
Fourthly anywhere where you are using <a href="#" is an accessibility anti-pattern. Anchors should only be used for navigation, <button> elements are for same page actions / functions. This is down to how they are announced to screen readers and expected behaviour. If you use a hyperlink it must contain a full and valid href either to an anchor on the current page or an entirely new page.
There are other issues but hopefully you get the idea!
Never fear, there is an easier way to do this!
Your main concern is that your menu works without JavaScript, which is causing you to choose hacks over the best and easiest ways to do things.
Here is the simplest way to create an accessible experience for all.
Create an HTML sitemap with anchors at key points.
Make the "button" an anchor and point the href to the relevant part of the sitemap.
Use JavaScript to intercept the request and open the drop-down menu / toggle aria attributes for the majority of users who have JavaScript enabled.
This way there is still a way to navigate the site if JavaScript is disabled, but for majority of users you have a drop-down menu.
Rough example
In the below example I have covered most accessibility issues.
No JavaScript
The raw HTML is valid and points to an HTML sitemap (which in the example is simulated with anchors further down the page, you should obviously have this on another page!).
If your sitemap is particularly large then you should use ids at the relevant parts of the page and link to those anchors directly (i.e. yoursite.com/sitemap#a-particular-category-or-main-menu-item). I have included this as part of the example as well.
To test the above I have included a checkbox that removes all the relevant event handlers and aria attributes so you can experience the "javaScriptless" experience.
With JavaScript
If JavaScript is available then we add the relevant role="button" to the link, we also add the aria-expanded attribute that we can later toggle to tell screen reader users if the menu is open or not and the aria-haspopup attribute so they know that the "button" will open a popup.
As we have told screen readers that the hyperlink is now a button with role="button" we allow them to activate the "button" with the space key as that is expected behaviour.
Finally they can close the drop-down with the Esc key as a "nice to have", this is not essential for navigational menus as they should not trap focus but I always like to add it, although I haven't dealt with returning focus to the parent item (something for you to consider).
I also ensured that the tap target was 44px by 44px to ensure it passes 2.5.5 tap target size as that was another issue with your example.
As a "+" is not very informative for screen reader users I also added some visually hidden text to explain what the toggle button does. I also toggle this button text depending on whether the drop-down is open or closed. This is done at the same time as toggling aria-expanded to make things perfectly clear for screen reader users.
There may be things I have missed in the following example so please test it thoroughly before using it in production. Also apologies I wrote this as I thought of things that needed addressing so the code is probably a bit messy.
var toggles = document.querySelectorAll(".menu-toggle");
// add the relevant aria, role and handler
var init = function(){
for(var x = 0; x < toggles.length; x++){
var el = toggles[x];
el.setAttribute("role", "button");
el.setAttribute("aria-expanded", "false");
el.setAttribute("aria-haspopup", "true");
el.addEventListener('click', openToggle);
el.addEventListener('keydown', keydownHandler);
document.addEventListener('keydown', closeAllHandler);
}
}
init();
function keydownHandler (e) {
//space key
if (e.keyCode === 32) {
openToggle(e);
}
}
function closeAllHandler(e){
// esc key
if (e.keyCode === 27) {
var openItems = document.querySelectorAll(".open");
for(var x = 0; x < openItems.length; x++){
openItems[x].classList = "";
}
}
}
//handler for when the "+" button is pressed, the second parameter is a quick way to recycle the function as a close function
function openToggle(e, close){
e.preventDefault();
var self = e.currentTarget;
var dropDown = getNextSibling(self, "ul");
if(dropDown.classList == "open" || close){
dropDown.classList = "";
self.setAttribute("aria-expanded", "false");
self.querySelector('.icon').innerHTML = "+";
self.querySelector('.toggleText').innerHTML = "show submenu";
}else{
dropDown.classList = "open";
self.setAttribute("aria-expanded", "true");
self.querySelector('.icon').innerHTML = "-";
self.querySelector('.toggleText').innerHTML = "close submenu";
}
}
// helper function to grab next sibling by selector.
var getNextSibling = function (el, sel) {
var sib = el.nextElementSibling;
if (!sel) return sib;
while (sib) {
if (sib.matches(sel)) return sib;
sib = sib.nextElementSibling
}
};
//////////////////////////////DEMO ONLY NOT NEEDED IN PRODUCTION///////////////////////////////////
//just for the demo, allows usa to simulate JavaScript being switched off
document.getElementById("jsActivated").addEventListener('change', adjustJS);
function adjustJS(e){
if (!e.target.checked) {
init();
} else {
destroy();
}
};
// just for the demo, used to remove event listener and role
var destroy = function(){
for(var x = 0; x < toggles.length; x++){
var el = toggles[x];
el.removeAttribute("role");
el.removeAttribute("aria-expanded");
el.removeAttribute("aria-haspopup");
el.removeEventListener('click', openToggle);
el.removeEventListener('keydown', keydownHandler);
}
}
.has-submenu>ul{
display: none;
}
.has-submenu>ul.open{
display: block;
}
li{
padding: 10px;
}
.visually-hidden {
border: 0;
padding: 0;
margin: 0;
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
.menu-toggle{
height: 44px;
width: 44px;
outline: 2px solid #666;
display: inline-block;
line-height: 44px;
font-size: 25px;
text-align: center;
text-decoration: none;
margin-left: 10px;
}
<label>Simulate JavaScript Off?
<input type="checkbox" id="jsActivated"/>
</label>
<h1>Example Accessible Menu</h1>
<nav aria-label="Main Navigation">
<ul>
<li class="has-submenu">
Some Category
<a class="menu-toggle" href="#sitemap-item1">
<span class="icon">+</span>
<span class="visually-hidden">
<span class="toggleText">show submenu</span> for "Some Category"
</span>
</a>
<ul>
<li>Some Category Item 1</li>
<li>Some Category Item 2</li>
</ul>
</li>
<li class="has-submenu">
This is a different category
<a class="menu-toggle" href="#sitemap-item2" aria-expanded="false" aria-haspopup="true">
<span class="icon">+</span>
<span class="visually-hidden">
<span class="toggleText">show submenu</span> for "This is a different category"
</span>
</a>
<ul>
<li>Different Category Item 1</li>
<li>Different Category Item 2</li>
</ul>
</li>
</ul>
</nav>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<strong>Scroll up to get back to menu, this is to simulate another page</strong>
<h2>The sitemap located on another page</h2>
<ul>
<li id="sitemap-item1">Some Category
<ul>
<li>Some Category Item 1</li>
<li>Some Category Item 2</li>
</ul>
</li>
<li id="sitemap-item2">This is a different category
<ul>
<li>Different Category Item 1</li>
<li>Different Category Item 2</li>
</ul>
</li>
</ul>
<strong>Scroll up to get back to menu, this is to simulate another page</strong>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
For instance, I'd like a column of buttons on the left:
Option 1
Option 2
Option 3
Option 4
And a column of paragraphs on the right:
OPTION 1 TEXT PARAGRAPH
OPTION 2 TEXT PARAGRAPH
OPTION 3 PHOTO LIBRARY
OPTION 4 REGISTRATION FORM
When the user clicks on Option 1, I'd like to have it do nothing except adjust the CSS style of Option 1 TEXT PARAGRAPH from display: none; to display: block;, and to change the styles of Options 2-4 to display: none;.
This way only one category would be visible at a time.
I'm pretty familiar with HTML and CSS but haven't come across a need for this function before.
Unfortunately, I'm brand new to JavaScript and would prefer not to use it for this, if it's possible to handle with CSS. So my question is, is it?
By the way, I have searched a lot for an answer before creating a new account here to ask, and maybe I just can't figure out how to phrase this, but please forgive me if the answer exists elsewhere.
You can do it using labels and hidden radios.
columnHolder {
display:flex;
}
rightColumnItem {
display:none;
}
[linkedTo="option1"] {
background:green;
}
[linkedTo="option2"] {
background:gold;
}
[linkedTo="option3"] {
background:tan;
}
[linkedTo="option4"] {
background:gray;
}
input[type=radio] {
display:none;
}
#option1:checked ~ columnHolder rightColumn [linkedTo="option1"] {
display:block;
}
#option2:checked ~ columnHolder rightColumn [linkedTo="option2"] {
display:block;
}
#option3:checked ~ columnHolder rightColumn [linkedTo="option3"] {
display:block;
}
#option4:checked ~ columnHolder rightColumn [linkedTo="option4"] {
display:block;
}
<input type="radio" name="radioSelector" id="option1" checked>
<input type="radio" name="radioSelector" id="option2">
<input type="radio" name="radioSelector" id="option3">
<input type="radio" name="radioSelector" id="option4">
<columnHolder>
<leftColumn>
<label for="option1"><div>Option 1</div><label>
<label for="option2"><div>Option 2</div><label>
<label for="option3"><div>Option 3</div><label>
<label for="option4"><div>Option 4</div><label>
</leftColumn>
<rightColumn>
<rightColumnItem linkedTo="option1">OPTION 1 TEXT PARAGRAPH</rightColumnItem>
<rightColumnItem linkedTo="option2">OPTION 2 TEXT PARAGRAPH</rightColumnItem>
<rightColumnItem linkedTo="option3">OPTION 3 PHOTO LIBRARY</rightColumnItem>
<rightColumnItem linkedTo="option4">OPTION 4 REGISTRATION FORM</rightColumnItem>
</rightColumn>
</columnHolder>
Here is how you can do it using javascript. You can add click event in the buttons and use id in the paragraphs. And then set html css property display using javascript. I do not think you can do this using css only.
Added fiddle link of the example
http://jsfiddle.net/cu2xaz86/12/
lets say below is your html. May be not exactly how you want.. but an example
<button onclick="javascript:op('s1')">
Option 1
</button>
<button onclick="javascript:op('s2')">
Option 2
</button>
<button onclick="javascript:op('s3')">
Option 3
</button>
<button onclick="javascript:op('s1')">
Option 4
</button>
<span id="s1" style="display: none;">
OPTION 1 TEXT PARAGRAPH
</span>
<span id="s2" style="display: none;">
OPTION 2 TEXT PARAGRAPH
</span>
<span id="s3" style="display: none;">
OPTION 3 PHOTO LIBRARY
</span>
<span id="s4" style="display: none;">
OPTION 4 REGISTRATION FORM
</span>
and then the javascript function can be something like below , where you make all the element display none first and then set display block for the element you want to show.
function op1(v) {
var x = document.getElementById("s1");
x.style.display = "none";
x = document.getElementById("s2");
x.style.display = "none";
x = document.getElementById("s3");
x.style.display = "none";
x = document.getElementById("s4");
x.style.display = "none";
x = document.getElementById(v);
x.style.display = "block";
}
I have customized the radio buttons for the product attributes on a Prestashop store but now the selected size does not change appearance (desired background:#000;color:#fff) when selected.
Product page here: http://catwalk-boutique.ro/pantofi/11-pantofi-piele-4578-burgundy.html
What I want to find out is either where to edit the "selected" state of the radio button or what could block the display of the selected state (if that is the case).
Below are the bits of code altered so far:
• in product.tpl:
{elseif ($group.group_type == 'radio')}
<ul style="padding-left:5px">{assign var=groupquantity value= $group.attributes_quantity}
{foreach from=$group.attributes key=id_attribute item=group_attribute}
<li>
<input id="radio_{$groupName|escape:'html':'UTF-8'}-{$id_attribute}" type="radio" class="attribute_radio" name="{$groupName|escape:'html':'UTF-8'}" value="{$id_attribute}" {if ($group.default == $id_attribute)} checked="checked"{/if} />
<label for="radio_{$groupName|escape:'html':'UTF-8'}-{$id_attribute}" data-comb-quantity="{*$groupquantity[$id_attribute]*}{foreach from=$combinations item=foo}{if $group_attribute == $foo.attributes_values[2]}{$foo.quantity}{/if}{/foreach}" class="radio_btn_round" >{$group_attribute|replace:' EU':''|escape:'html':'UTF-8'}</label>
</li>
{/foreach}
</ul>
{/if}
• and the CSS:
label.radio_btn_round {
background-color: #F8F8F8;
border: 1px solid #C8CCD2;
width: 30px;
height: 30px;
text-align: center;
vertical-align: middle!important;
line-height: 29px;}
input.attribute_radio {display: none;}
Any ideas are much appreciated. Thanks.
The markup that Prestashop has generated for this makes this not possible with straight CSS:
<li>
<div>
<span class="checked"><input value="37" selected></span>
</div>
<label>37</label>
</li>
CSS has no way of going "up" the DOM (selecting the parent div or li from the "selected" radio button).
Because jQuery is available on your site, I think your best bet is to add some light jQuery that can do this for you, and provide a class on the label which you can then address via CSS:
// wait until the document is ready
jQuery(function($) {
// watch for changes to the radio inputs
$(document).on('change', 'input[type="radio"]', function() {
$('.attribute_list li')
// remove the class from all li elements
.removeClass('checked')
// find the "checked" radio button
.find('input[type="radio"]:checked')
// go up the dom to the nearest li
.closest('li')
// and add the "checked" class
.addClass('checked');
});
});
Then, in your CSS, this selector will allow you to change the styles you want:
li.checked label.radio_btn_round {
background: #000;
color: white;
}
Once the button is clicked I want it to stay with the active style instead of going back to normal style. Can this be done with CSS please? Im using blurb button from DIVI Theme (WordPress). Please help me!
code:
#blurb-hover.et_pb_blurb .et_pb_blurb_content
.et_pb_main_blurb_image .et-pb-icon:hover {
color: red !important; }
#blurb-hover.et_pb_blurb .et_pb_blurb_content
.et_pb_main_blurb_image .et-pb-icon:selected {
background-color: #ff4b46;
color: #fff; }
#blurb-hover.et_pb_blurb .et_pb_blurb_content
.et_pb_main_blurb_image .et-pb-icon:active {
color: white !important;
background-color: red;
width: 140px;
height: 100px; }
CSS
:active denotes the interaction state (so for a button will be applied during press), :focus may be a better choice here. However, the styling will be lost once another element gains focus.
The final potential alternative using CSS would be to use :target, assuming the items being clicked are setting routes (e.g. anchors) within the page- however this can be interrupted if you are using routing (e.g. Angular), however this doesnt seem the case here.
.active:active {
color: red;
}
.focus:focus {
color: red;
}
:target {
color: red;
}
<button class='active'>Active</button>
<button class='focus'>Focus</button>
<a href='#target1' id='target1' class='target'>Target 1</a>
<a href='#target2' id='target2' class='target'>Target 2</a>
<a href='#target3' id='target3' class='target'>Target 3</a>
Javascript / jQuery
As such, there is no way in CSS to absolutely toggle a styled state- if none of the above work for you, you will either need to combine with a change in your HTML (e.g. based on a checkbox) or programatically apply/remove a class using e.g. jQuery
$('button').on('click', function(){
$('button').removeClass('selected');
$(this).addClass('selected');
});
button.selected{
color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Item</button><button>Item</button><button>Item</button>
We're going to to be using a hidden checkbox.
This example includes one "on click - off click 'hover / active' state"
--
To make content itself clickable:
HTML
<input type="checkbox" id="activate-div">
<label for="activate-div">
<div class="my-div">
//MY DIV CONTENT
</div>
</label>
CSS
#activate-div{display:none}
.my-div{background-color:#FFF}
#activate-div:checked ~ label
.my-div{background-color:#000}
To make button change content:
HTML
<input type="checkbox" id="activate-div">
<div class="my-div">
//MY DIV CONTENT
</div>
<label for="activate-div">
//MY BUTTON STUFF
</label>
CSS
#activate-div{display:none}
.my-div{background-color:#FFF}
#activate-div:checked +
.my-div{background-color:#000}
Hope it helps!!
In the Divi Theme Documentation, it says that the theme comes with access to 'ePanel' which also has an 'Integration' section.
You should be able to add this code:
<script>
$( ".et-pb-icon" ).click(function() {
$( this ).toggleClass( "active" );
});
</script>
into the the box that says 'Add code to the head of your blog' under the 'Integration' tab, which should get the jQuery working.
Then, you should be able to style your class to what ever you need.
I am trying to get a button inside a list view in bootstrap to get to two different links and it always follows the list view link, not the button link if I press the button. How do I achieve this?
<a href="foo.html" class="list-group-item">
<p>This links somewhere different than the button</p>
<button href="bar.html" class="btn btn-success">Example</button>
</a>
This doesn't appear to be easily accomplished with Bootstrap as-is, but a few tweaks can get us what we want. The main problem is that nested anchors aren't really valid HTML. However, we can achieve the same result by absoultely positioning a link above another link.
Have a look at this JS Bin:
http://jsbin.com/febivi/2/
In summary:
Add a new class to the list-group that will define our new container:
<ul class="list-group action-list-group">
<li class="list-group-item">
<a class="list-group-link" href="http://stackoverflow.com">Cras justo odio</a>
<a class="btn btn-sm btn-default" href="http://google.com">Go</a>
</li>
<li class="list-group-item">
<a class="list-group-link" href="http://stackoverflow.com">Cras justo odio</a>
<a class="btn btn-sm btn-default" href="http://google.com">Go</a>
</li>
</ul>
The primary link is ".list-group-link" and the secondary link is the ".btn" action.
Next we add some CSS to style list-group-item's inside action-list-group:
.action-list-group {
position: relative;
}
/* remove the list group padding since our nested anchor tag will now have it */
.action-list-group .list-group-item {
padding: 0;
}
.action-list-group .list-group-item > a.list-group-link {
display: block;
/* inherit from .list-group-item */
padding: 10px 15px;
color: #555;
}
/* re-add the link styling */
.action-list-group .list-group-item > a.list-group-link:hover {
background: #f5f5f5;
text-decoration: none;
}
.action-list-group .btn {
position: absolute;
right: 5px;
margin-top: 5px;
top: 0;
}
Where it says "inherit", if you were using the Sass version of Bootstrap you could use sass's #include or #extend to include the same styling as bootstrap's .list-group-item > a.
There is javascript solution that you can use as well. The one benefit being that you can then have your button element in the flow of the list-group.
HTML:
<a href="foo.html" class="list-group-item">
<p>This links somewhere different than the button</p>
<button data-href="bar.html" class="btn btn-success">Example #1</button>
</a>
JQUERY:
$('.list-group-item').on('click', function (event) {
event.preventDefault();
$target = $(event.target);
if ($target.is('button')) {
window.location=$target.data('href');
} else {
window.location=$target.closest('a').prop('href');
}
});
Basically, the click handler works to prevent the normal behavior of the list-group-item anchor tag using event.preventDefault(). Then using event.target, you can get the element that dispatched the event. If the target was a button, you retrieve its data property and set the window.location to it. Otherwise, the jQuery closest() method is used to find the nearest anchor tag and use its href value to set the window.location. In jQuery, the closest method starts with the current element (which could be the anchor itself or any of its ancestors that are not button elements) and travels up the DOM from there.
Also, note that since the button element does not have an href attribute, this example uses a data attribute to store the link reference.