@@ -255,7 +255,7 @@ Checkboxes.prototype = {
255255 } ) ;
256256
257257 // If state saving is enabled
258- if ( ctx . oFeatures . bStateSave ) {
258+ if ( ctx . oFeatures . bStateSave ) {
259259 // If server-side processing mode is not enabled
260260 // NOTE: Needed to avoid duplicate call to updateCheckboxes() in onDraw()
261261 if ( ! ctx . oFeatures . bServerSide ) {
@@ -544,10 +544,44 @@ Checkboxes.prototype = {
544544 cellSelector = $cell ;
545545 }
546546
547- dt . cell ( cellSelector ) . checkboxes . select ( ctrl . checked , true ) ;
547+ var cell = dt . cell ( cellSelector ) ;
548+ var cellIdx = cell . index ( ) ;
549+ var colIdx = cellIdx . column ;
548550
549- // Prevent click event from propagating to parent
550- e . stopPropagation ( ) ;
551+ // If row selection is not enabled
552+ // NOTE: if row selection is enabled, checkbox selection/deselection
553+ // would be handled by onSelect event instead
554+ if ( ! ctx . aoColumns [ colIdx ] . checkboxes . selectRow ) {
555+ cell . checkboxes . select ( ctrl . checked , true ) ;
556+
557+ // Prevent click event from propagating to parent
558+ e . stopPropagation ( ) ;
559+
560+ // Otherwise, if row selection is enabled
561+ } else {
562+ // WORKAROUND:
563+ // Select extension may keep the row selected
564+ // when checkbox is unchecked with SHIFT key.
565+ //
566+ // We need to update the state of the checkbox AFTER handling
567+ // select/deselect event from Select extension.
568+ //
569+ // Call to setTimeout is needed to let select/deselect event handler
570+ // update the data first.
571+ setTimeout ( function ( ) {
572+ // Get cell data
573+ var cellData = cell . data ( ) ;
574+
575+ // Determine whether data is in the list
576+ var hasData = self . s . data [ colIdx ] . hasOwnProperty ( cellData ) ;
577+
578+ // If state of the checkbox needs to be updated
579+ if ( hasData !== ctrl . checked ) {
580+ self . updateCheckbox ( 'cell' , [ cellIdx ] , hasData ) ;
581+ self . updateSelectAll ( colIdx ) ;
582+ }
583+ } , 0 ) ;
584+ }
551585 } ,
552586
553587 // Handles row select/deselect event
@@ -559,7 +593,21 @@ Checkboxes.prototype = {
559593 if ( self . s . ignoreSelect ) { return ; }
560594
561595 if ( type === 'row' ) {
562- self . updateData ( 'row' , indexes , ( e . type === 'select' ) ? true : false , true ) ;
596+ // By default, allow duplicate data
597+ var allowDup = true ;
598+
599+ // WORKAROUND:
600+ // Select extension may generate multiple select events for the same row
601+ // when selecting rows using SHIFT key and the following styles are used
602+ // 'os', 'multi+shift'.
603+ //
604+ // If user is selecting/deselecting multiple rows using SHIFT key
605+ if ( ( ctx . _select . style === 'os' || ctx . _select . style === 'multi+shift' ) && indexes . length > 1 ) {
606+ // Disallow handling of rows with duplicate data
607+ allowDup = false ;
608+ }
609+
610+ self . updateData ( 'row' , indexes , ( e . type === 'select' ) ? true : false , allowDup ) ;
563611 self . updateCheckbox ( 'row' , indexes , ( e . type === 'select' ) ? true : false ) ;
564612
565613 // Get index of the first column that has checkbox and row selection enabled
0 commit comments