@@ -1180,138 +1180,153 @@ $.extend( _dtButtons, {
1180
1180
} ,
1181
1181
className : 'buttons-collection' ,
1182
1182
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' ) ;
1196
1186
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
+ } ) ;
1200
1191
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
+ } ) ;
1203
1195
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 ) ;
1209
1198
1210
- var position = config . _collection . css ( 'position' ) ;
1199
+ $ ( 'body' ) . off ( '.dtb-collection' ) ;
1200
+ dt . off ( 'buttons-action.b-internal' ) ;
1201
+ } ;
1211
1202
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' ) ;
1223
1204
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 ( ) ;
1238
1206
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' ) ;
1244
1216
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' ) ;
1250
1222
}
1251
1223
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 ;
1256
1226
}
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
+ } ) ;
1263
1244
}
1245
+ else if ( position === 'absolute' ) {
1246
+ config . _collection . css ( {
1247
+ top : hostPosition . top + host . outerHeight ( ) ,
1248
+ left : hostPosition . left
1249
+ } ) ;
1264
1250
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 ;
1267
1255
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 ;
1271
1260
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
+ }
1277
1265
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
+ }
1280
1271
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
+ }
1284
1278
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
+ }
1308
1291
1309
- if ( config . autoClose ) {
1310
- dt . on ( 'buttons-action.b-internal' , function ( ) {
1311
- close ( ) ;
1312
- } ) ;
1292
+ config . _collection . css ( 'marginTop' , top * - 1 ) ;
1313
1293
}
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
+ }
1315
1330
} ,
1316
1331
background : true ,
1317
1332
collectionLayout : '' ,
0 commit comments