My goal here was to make a submenu with sane keyboard and screenreader behavior, using:
- AngularJS
- jQuery
- Bootstrap 3
- the CSS submenu implementation from 'css - Bootstrap 3 dropdown sub menu missing'
Here's a starting point showing how submenus (don't) work with the keyboard without any customization:
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.selectItem = function (item) {
alert(item);
};
}
/*
* No submenu in Bootstrap 3 - need to put CSS in manually.
* All CSS from https://stackoverflow.com/questions/18023493/bootstrap-3-dropdown-sub-menu-missing
*/
.dropdown-submenu {
position: relative;
}
.dropdown-submenu>.dropdown-menu {
top: 0;
left: 100%;
margin-top: -6px;
margin-left: -1px;
-webkit-border-radius: 0 6px 6px 6px;
-moz-border-radius: 0 6px 6px 6px;
border-radius: 0 6px 6px 6px;
}
.dropdown-submenu:hover > .dropdown-menu {
display: block;
}
.dropdown-submenu > a:after {
display: block;
content: " ";
float: right;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width:5px 0 5px 5px;
border-left-color:#cccccc;
margin-top:5px;
margin-right:-10px;
}
.dropdown-submenu:hover>a:after {
border-left-color: #ffffff;
}
.dropdown-submenu.pull-left {
float: none;
}
.dropdown-submenu.pull-left>.dropdown-menu {
left: -100%;
margin-left: 10px;
-webkit-border-radius: 6px 0 6px 6px;
-moz-border-radius: 6px 0 6px 6px;
border-radius: 6px 0 6px 6px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="MyCtrl">
<div class="dropdown">
<a class="dropdown-toggle btn btn-primary" id="DropdownButton" data-toggle="dropdown" role="button" href="#">DROPDOWN</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="DropdownButton">
<li role="presentation">
<a role="menuitem" tabindex="0" href="#" ng-click="selectItem('1')">option 1</a>
</li>
<li role="presentation">
<a role="menuitem" tabindex="0" href="#" ng-click="selectItem('2')">option 2</a>
</li>
<li role="presentation">
<a role="menuitem" tabindex="0" href="#" ng-click="selectItem('3')">option 3</a>
</li>
<li role="presentation" class="dropdown dropdown-submenu" custom-submenu>
<a class="dropdown-toggle" id="SubmenuButton" role="menuitem" tabindex="0" href="#" aria-haspopup="true">option 4 (has children)</a>
<ul class="dropdown-menu" role="menu" aria-hidden="true" aria-labelledby="SubmenuButton">
<li role="presentation">
<a role="menuitem" tabindex="0" href="#" ng-click="selectItem('submenu item 1')">
child option 1
</a>
</li>
<li role="presentation">
<a role="menuitem" tabindex="0" href="#" ng-click="selectItem('submenu item 2')">
child option 2
</a>
</li>
<li role="presentation">
<a role="menuitem" tabindex="0" href="#" ng-click="selectItem('submenu item 3')">
child option 3
</a>
</li>
</ul>
</li>
<li role="presentation">
<a role="menuitem" tabindex="0" href="#" ng-click="selectItem('item 5')">option 5</a>
</li>
</ul>
</div>
</div>
Here's a JSFiddle of the above. I'll post my solution in the answers, but I don't think it's perfect; I'm interested in feedback or alternatives.