Skip to content

Commit 5060e96

Browse files
Added aria-expanded on opened collection buttons. The close function now closes all collections. Added a check to see if the collection was open when clicking a collection button, and don't try to reopen the collection in that case.
1 parent 10bc521 commit 5060e96

File tree

1 file changed

+127
-112
lines changed

1 file changed

+127
-112
lines changed

js/dataTables.buttons.js

Lines changed: 127 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,138 +1180,153 @@ $.extend( _dtButtons, {
11801180
},
11811181
className: 'buttons-collection',
11821182
action: function ( e, dt, button, config ) {
1183-
var host = button;
1184-
var collectionParent = $(button).parents('div.dt-button-collection');
1185-
var hostPosition = host.position();
1186-
var tableContainer = $( dt.table().container() );
1187-
var multiLevel = false;
1188-
var insertPoint = host;
1189-
1190-
// Remove any old collection
1191-
if ( collectionParent.length ) {
1192-
multiLevel = $('.dt-button-collection').position();
1193-
insertPoint = collectionParent;
1194-
$('body').trigger( 'click.dtb-collection' );
1195-
}
1183+
var close = function () {
1184+
dt.buttons( '[aria-haspopup="true"][aria-expanded="true"]' ).nodes().each( function() {
1185+
var collection = $(this).siblings('.dt-button-collection');
11961186

1197-
if ( insertPoint.parents('body')[0] !== document.body ) {
1198-
insertPoint = document.body.lastChild;
1199-
}
1187+
if ( collection.length ) {
1188+
collection.fadeOut( config.fade, function () {
1189+
collection.detach();
1190+
} );
12001191

1201-
config._collection.find('.dt-button-collection-title').remove();
1202-
config._collection.prepend('<div class="dt-button-collection-title">'+config.collectionTitle+'</div>');
1192+
$(this).attr( 'aria-expanded', '' );
1193+
}
1194+
});
12031195

1204-
config._collection
1205-
.addClass( config.collectionLayout )
1206-
.css( 'display', 'none' )
1207-
.insertAfter( insertPoint )
1208-
.fadeIn( config.fade );
1196+
$('div.dt-button-background').off( 'click.dtb-collection' );
1197+
Buttons.background( false, config.backgroundClassName, config.fade, insertPoint );
12091198

1210-
var position = config._collection.css( 'position' );
1199+
$('body').off( '.dtb-collection' );
1200+
dt.off( 'buttons-action.b-internal' );
1201+
};
12111202

1212-
if ( multiLevel && position === 'absolute' ) {
1213-
config._collection.css( {
1214-
top: multiLevel.top,
1215-
left: multiLevel.left
1216-
} );
1217-
}
1218-
else if ( position === 'absolute' ) {
1219-
config._collection.css( {
1220-
top: hostPosition.top + host.outerHeight(),
1221-
left: hostPosition.left
1222-
} );
1203+
var wasExpanded = ( button.attr( 'aria-expanded' ) === 'true' );
12231204

1224-
// calculate overflow when positioned beneath
1225-
var tableBottom = tableContainer.offset().top + tableContainer.height();
1226-
var listBottom = hostPosition.top + host.outerHeight() + config._collection.outerHeight();
1227-
var bottomOverflow = listBottom - tableBottom;
1228-
1229-
// calculate overflow when positioned above
1230-
var listTop = hostPosition.top - config._collection.outerHeight();
1231-
var tableTop = tableContainer.offset().top;
1232-
var topOverflow = tableTop - listTop;
1233-
1234-
// if bottom overflow is larger, move to the top because it fits better, or if dropup is requested
1235-
if (bottomOverflow > topOverflow || config.dropup) {
1236-
config._collection.css( 'top', hostPosition.top - config._collection.outerHeight() - 5);
1237-
}
1205+
close();
12381206

1239-
// Right alignment is enabled on a class, e.g. bootstrap:
1240-
// $.fn.dataTable.Buttons.defaults.dom.collection.className += " dropdown-menu-right";
1241-
if ( config._collection.hasClass( config.rightAlignClassName ) ) {
1242-
config._collection.css( 'left', hostPosition.left + host.outerWidth() - config._collection.outerWidth() );
1243-
}
1207+
if (!wasExpanded) {
1208+
var host = button;
1209+
var collectionParent = $(button).parents('div.dt-button-collection');
1210+
var hostPosition = host.position();
1211+
var tableContainer = $( dt.table().container() );
1212+
var multiLevel = false;
1213+
var insertPoint = host;
1214+
1215+
button.attr( 'aria-expanded', 'true' );
12441216

1245-
// Right alignment in table container
1246-
var listRight = hostPosition.left + config._collection.outerWidth();
1247-
var tableRight = tableContainer.offset().left + tableContainer.width();
1248-
if ( listRight > tableRight ) {
1249-
config._collection.css( 'left', hostPosition.left - ( listRight - tableRight ) );
1217+
// Remove any old collection
1218+
if ( collectionParent.length ) {
1219+
multiLevel = $('.dt-button-collection').position();
1220+
insertPoint = collectionParent;
1221+
$('body').trigger( 'click.dtb-collection' );
12501222
}
12511223

1252-
// Right alignment to window
1253-
var listOffsetRight = host.offset().left + config._collection.outerWidth();
1254-
if ( listOffsetRight > $(window).width() ) {
1255-
config._collection.css( 'left', hostPosition.left - (listOffsetRight-$(window).width()) );
1224+
if ( insertPoint.parents('body')[0] !== document.body ) {
1225+
insertPoint = document.body.lastChild;
12561226
}
1257-
}
1258-
else {
1259-
// Fix position - centre on screen
1260-
var top = config._collection.height() / 2;
1261-
if ( top > $(window).height() / 2 ) {
1262-
top = $(window).height() / 2;
1227+
1228+
config._collection.find('.dt-button-collection-title').remove();
1229+
config._collection.prepend('<div class="dt-button-collection-title">'+config.collectionTitle+'</div>');
1230+
1231+
config._collection
1232+
.addClass( config.collectionLayout )
1233+
.css( 'display', 'none' )
1234+
.insertAfter( insertPoint )
1235+
.fadeIn( config.fade );
1236+
1237+
var position = config._collection.css( 'position' );
1238+
1239+
if ( multiLevel && position === 'absolute' ) {
1240+
config._collection.css( {
1241+
top: multiLevel.top,
1242+
left: multiLevel.left
1243+
} );
12631244
}
1245+
else if ( position === 'absolute' ) {
1246+
config._collection.css( {
1247+
top: hostPosition.top + host.outerHeight(),
1248+
left: hostPosition.left
1249+
} );
12641250

1265-
config._collection.css( 'marginTop', top*-1 );
1266-
}
1251+
// calculate overflow when positioned beneath
1252+
var tableBottom = tableContainer.offset().top + tableContainer.height();
1253+
var listBottom = hostPosition.top + host.outerHeight() + config._collection.outerHeight();
1254+
var bottomOverflow = listBottom - tableBottom;
12671255

1268-
if ( config.background ) {
1269-
Buttons.background( true, config.backgroundClassName, config.fade, insertPoint );
1270-
}
1256+
// calculate overflow when positioned above
1257+
var listTop = hostPosition.top - config._collection.outerHeight();
1258+
var tableTop = tableContainer.offset().top;
1259+
var topOverflow = tableTop - listTop;
12711260

1272-
var close = function () {
1273-
config._collection
1274-
.fadeOut( config.fade, function () {
1275-
config._collection.detach();
1276-
} );
1261+
// if bottom overflow is larger, move to the top because it fits better, or if dropup is requested
1262+
if (bottomOverflow > topOverflow || config.dropup) {
1263+
config._collection.css( 'top', hostPosition.top - config._collection.outerHeight() - 5);
1264+
}
12771265

1278-
$('div.dt-button-background').off( 'click.dtb-collection' );
1279-
Buttons.background( false, config.backgroundClassName, config.fade, insertPoint );
1266+
// Right alignment is enabled on a class, e.g. bootstrap:
1267+
// $.fn.dataTable.Buttons.defaults.dom.collection.className += " dropdown-menu-right";
1268+
if ( config._collection.hasClass( config.rightAlignClassName ) ) {
1269+
config._collection.css( 'left', hostPosition.left + host.outerWidth() - config._collection.outerWidth() );
1270+
}
12801271

1281-
$('body').off( '.dtb-collection' );
1282-
dt.off( 'buttons-action.b-internal' );
1283-
};
1272+
// Right alignment in table container
1273+
var listRight = hostPosition.left + config._collection.outerWidth();
1274+
var tableRight = tableContainer.offset().left + tableContainer.width();
1275+
if ( listRight > tableRight ) {
1276+
config._collection.css( 'left', hostPosition.left - ( listRight - tableRight ) );
1277+
}
12841278

1285-
// Need to break the 'thread' for the collection button being
1286-
// activated by a click - it would also trigger this event
1287-
setTimeout( function () {
1288-
// This is bonkers, but if we don't have a click listener on the
1289-
// background element, iOS Safari will ignore the body click
1290-
// listener below. An empty function here is all that is
1291-
// required to make it work...
1292-
$('div.dt-button-background').on( 'click.dtb-collection', function () {} );
1293-
1294-
$('body')
1295-
.on( 'click.dtb-collection', function (e) {
1296-
// andSelf is deprecated in jQ1.8, but we want 1.7 compat
1297-
var back = $.fn.addBack ? 'addBack' : 'andSelf';
1298-
1299-
if ( ! $(e.target).parents()[back]().filter( config._collection ).length ) {
1300-
close();
1301-
}
1302-
} )
1303-
.on( 'keyup.dtb-collection', function (e) {
1304-
if ( e.keyCode === 27 ) {
1305-
close();
1306-
}
1307-
} );
1279+
// Right alignment to window
1280+
var listOffsetRight = host.offset().left + config._collection.outerWidth();
1281+
if ( listOffsetRight > $(window).width() ) {
1282+
config._collection.css( 'left', hostPosition.left - (listOffsetRight-$(window).width()) );
1283+
}
1284+
}
1285+
else {
1286+
// Fix position - centre on screen
1287+
var top = config._collection.height() / 2;
1288+
if ( top > $(window).height() / 2 ) {
1289+
top = $(window).height() / 2;
1290+
}
13081291

1309-
if ( config.autoClose ) {
1310-
dt.on( 'buttons-action.b-internal', function () {
1311-
close();
1312-
} );
1292+
config._collection.css( 'marginTop', top*-1 );
13131293
}
1314-
}, 10 );
1294+
1295+
if ( config.background ) {
1296+
Buttons.background( true, config.backgroundClassName, config.fade, insertPoint );
1297+
}
1298+
1299+
// Need to break the 'thread' for the collection button being
1300+
// activated by a click - it would also trigger this event
1301+
setTimeout( function () {
1302+
// This is bonkers, but if we don't have a click listener on the
1303+
// background element, iOS Safari will ignore the body click
1304+
// listener below. An empty function here is all that is
1305+
// required to make it work...
1306+
$('div.dt-button-background').on( 'click.dtb-collection', function () {} );
1307+
1308+
$('body')
1309+
.on( 'click.dtb-collection', function (e) {
1310+
// andSelf is deprecated in jQ1.8, but we want 1.7 compat
1311+
var back = $.fn.addBack ? 'addBack' : 'andSelf';
1312+
1313+
if ( ! $(e.target).parents()[back]().filter( config._collection ).length ) {
1314+
close();
1315+
}
1316+
} )
1317+
.on( 'keyup.dtb-collection', function (e) {
1318+
if ( e.keyCode === 27 ) {
1319+
close();
1320+
}
1321+
} );
1322+
1323+
if ( config.autoClose ) {
1324+
dt.on( 'buttons-action.b-internal', function () {
1325+
close();
1326+
} );
1327+
}
1328+
}, 10 );
1329+
}
13151330
},
13161331
background: true,
13171332
collectionLayout: '',

0 commit comments

Comments
 (0)