@refinitiv-ui/efx-grid 6.0.77 → 6.0.79

Sign up to get free protection for your applications and to get access to all the features.
@@ -54,10 +54,13 @@ var CheckboxPlugin = function (options) {
54
54
  t._onPreSectionRender = t._onPreSectionRender.bind(t);
55
55
  t._onPostSectionDataBinding = t._onPostSectionDataBinding.bind(t);
56
56
  t._onCheckboxClicked = t._onCheckboxClicked.bind(t);
57
+ t._onCheckboxKeydown = t._onCheckboxKeydown.bind(t);
58
+ t._onCheckboxMousedown = t._onCheckboxMousedown.bind(t);
57
59
  t._onColumnIndexChanged = t._onColumnIndexChanged.bind(t);
58
60
  t._onColumnAdded = t._onColumnAdded.bind(t);
59
61
  t._requestUIPopulation = t._requestUIPopulation.bind(t);
60
62
  t._populateUIs = t._populateUIs.bind(t);
63
+ t._isCheckboxDisabled = t._isCheckboxDisabled.bind(t);
61
64
  t.selectAll = t.selectAll.bind(t);
62
65
  t.deselectAll = t.deselectAll.bind(t);
63
66
  t._hosts = [];
@@ -68,6 +71,84 @@ var CheckboxPlugin = function (options) {
68
71
  };
69
72
  Ext.inherits(CheckboxPlugin, GridPlugin);
70
73
 
74
+ /** @type {Function}
75
+ * @private
76
+ */
77
+ CheckboxPlugin._emptyFunc = function () { };
78
+ /** @private
79
+ * @function
80
+ * @param {Object} view DataView object
81
+ * @param {string} rid
82
+ * @return {boolean}
83
+ */
84
+ CheckboxPlugin._isRowExpansion = function (view, rid) {
85
+ return view.isRowExpansion(rid); // WARNING: isRowExpansion() is available only in DataView and not DataTable
86
+ };
87
+ /** @private
88
+ * @function
89
+ * @param {Object} view DataView object
90
+ * @param {Function} disablingGetter
91
+ * @param {string} rid
92
+ * @return {boolean}
93
+ */
94
+ CheckboxPlugin._checkableRow = function (view, disablingGetter, rid) {
95
+ if(disablingGetter(view, rid)) {
96
+ return false;
97
+ }
98
+ if(CheckboxPlugin._isRowExpansion(view, rid)) {
99
+ return false;
100
+ }
101
+ return true;
102
+ };
103
+ /** @private
104
+ * @function
105
+ * @param {Element} elem
106
+ */
107
+ CheckboxPlugin._addDisabledProp = function (elem) {
108
+ elem.setAttribute("disabled", "");
109
+ };
110
+ /** @private
111
+ * @function
112
+ * @param {Element} elem
113
+ */
114
+ CheckboxPlugin._removeDisabledProp = function (elem) {
115
+ elem.removeAttribute("disabled");
116
+ };
117
+ /** @private
118
+ * @function
119
+ * @param {Element} elem
120
+ * @param {string} prop
121
+ * @param {boolean} bool
122
+ */
123
+ CheckboxPlugin._setBooleanProp = function (elem, prop, bool) {
124
+ if(bool) {
125
+ elem.setAttribute(prop, "");
126
+ } else {
127
+ elem.removeAttribute(prop);
128
+ }
129
+ };
130
+ /** Collect member row that is in the given view and all members in collapsed group.
131
+ * @private
132
+ * @param {Object} dv DataView object
133
+ * @param {!Array.<string>} rids
134
+ * @param {string} rid
135
+ * @return {!Array.<string>} rids
136
+ */
137
+ CheckboxPlugin._collectRowMemberId = function (dv, rids, rid) {
138
+ if(rid) {
139
+ var subGroup = dv.getGroupByRowId(rid);
140
+ if(subGroup) {
141
+ if(subGroup.isCollapsed()) {
142
+ return rids.concat(subGroup.getAllRowIds(true));
143
+ }
144
+ } else {
145
+ rids.push(rid);
146
+ }
147
+ }
148
+ return rids;
149
+ };
150
+
151
+
71
152
  /** @type {number}
72
153
  * @private
73
154
  */
@@ -108,10 +189,12 @@ CheckboxPlugin.prototype._autoRowSelection = false;
108
189
  * @private
109
190
  */
110
191
  CheckboxPlugin.prototype._topCheckboxHandler = true;
111
- /** @type {Function}
192
+ /** @type {string}
112
193
  * @private
113
194
  */
114
- CheckboxPlugin._emptyFunc = function () { };
195
+ CheckboxPlugin.prototype._anchorRowId = "";
196
+
197
+
115
198
  /** @type {Object.<string, number>}
116
199
  * @private
117
200
  */
@@ -250,17 +333,6 @@ CheckboxPlugin._mergeStates = function(states) {
250
333
  }
251
334
  return state;
252
335
  };
253
- /** @private
254
- * @function
255
- * @param {number} count
256
- * @param {boolean} bool
257
- * @return {Array.<boolean>}
258
- */
259
- CheckboxPlugin._genData = function (count, bool) {
260
- var data = new Array(count);
261
- for(var i = count; --i >= 0;) { data[i] = bool; }
262
- return data;
263
- };
264
336
 
265
337
  /** @public
266
338
  * @return {string}
@@ -632,6 +704,8 @@ CheckboxPlugin.prototype._createCheckbox = function (sectionSettings, colIndex,
632
704
  chkbox._chkbox = true;
633
705
 
634
706
  chkbox.addEventListener("click", this._onCheckboxClicked, false);
707
+ chkbox.addEventListener("keydown", this._onCheckboxKeydown, false);
708
+ chkbox.addEventListener("mousedown", this._onCheckboxMousedown, false);
635
709
  // chkbox.addEventListener("checked-changed", this._onCheckboxClicked, false); // Elf v3
636
710
 
637
711
  cell.setContent(chkbox);
@@ -660,19 +734,70 @@ CheckboxPlugin.prototype._createCheckbox = function (sectionSettings, colIndex,
660
734
  };
661
735
 
662
736
 
663
- /** Select all checkboxes that are not affected by filtering and pagination logics. This is equivalent to ticking the checkbox at the top header section of the grid
737
+ /** Select/check all checkboxes that are not affected by filtering and pagination logics. This is equivalent to ticking the checkbox at the top header section of the grid
664
738
  * @public
665
739
  */
666
740
  CheckboxPlugin.prototype.selectAll = function () {
667
741
  this.checkAll(true);
668
742
  };
669
- /** Deselect all checkboxes that are not affected by filtering and pagination logics. This is equivalent to un-ticking the checkbox at the top header section of the grid
743
+ /** Deselect/uncheck all checkboxes that are not affected by filtering and pagination logics. This is equivalent to un-ticking the checkbox at the top header section of the grid
670
744
  * @public
671
745
  * @param {boolean} check
672
746
  */
673
747
  CheckboxPlugin.prototype.deselectAll = function () {
674
748
  this.checkAll(false);
675
749
  };
750
+ /** Select/check all spicified content checkboxes that are in view
751
+ * @public
752
+ * @param {Array.<number|string>} rowRefs
753
+ * @param {boolean} checked
754
+ */
755
+ CheckboxPlugin.prototype.selectCheckboxes = function (rowRefs) {
756
+ this.setCheckStates(rowRefs, true);
757
+ };
758
+ /** Select/check all spicified content checkboxes that are in view
759
+ * @public
760
+ * @param {Array.<number|string>} rowRefs
761
+ * @param {boolean} checked
762
+ */
763
+ CheckboxPlugin.prototype.deselectCheckboxes = function (rowRefs) {
764
+ this.setCheckStates(rowRefs, false);
765
+ };
766
+ /** Set check state to all spicified content checkboxes that are in view
767
+ * @public
768
+ * @param {Array.<number|string>} rowRefs
769
+ * @param {boolean} checked
770
+ */
771
+ CheckboxPlugin.prototype.setCheckStates = function (rowRefs, checked) {
772
+ if(!rowRefs) {
773
+ return;
774
+ }
775
+ var ary = Array.isArray(rowRefs) ? rowRefs : [rowRefs];
776
+ var len = ary.length;
777
+ if(!len) {
778
+ return;
779
+ }
780
+
781
+ // TODO: Support multi-table mode
782
+ var host = this._hosts[0];
783
+ var sectionSettings = host.getSectionSettings("content");
784
+ var dv = sectionSettings.getDataSource();
785
+ if(!dv) {
786
+ return;
787
+ }
788
+
789
+ var rids = [];
790
+ var i;
791
+ for (i = 0; i < len; ++i) {
792
+ var ref = ary[i];
793
+ var rid = (typeof ref === "string") ? ref : dv.getRowId(ref);
794
+ rids = CheckboxPlugin._collectRowMemberId(dv, rids, rid);
795
+ }
796
+ if(rids.length) {
797
+ rids = rids.filter(CheckboxPlugin._checkableRow.bind(null, dv, this._isCheckboxDisabled));
798
+ this._setColumnData(dv, this._checkboxField, checked, rids);
799
+ }
800
+ };
676
801
 
677
802
  /** This is equivalent to clicking the checkbox at the top header section of the grid. <br>
678
803
  * Use {@link CheckboxPlugin#setAllCheckStates} to set all states regardless of filtering and pagination
@@ -710,9 +835,9 @@ CheckboxPlugin.prototype.setAllCheckStates = function (checked) {
710
835
  var dt = dv ? dv.getDataSource() : null;
711
836
 
712
837
  if(dt) {
713
- var valueList = CheckboxPlugin._genData(dt.getRowCount(), checked);
714
- var rids = dt.getAllRowIds();
715
- this._setColumnData(dv, this._checkboxField, valueList, rids);
838
+ // TODO: Check if we need to omit disabled checkboxes
839
+ var rids = dt.getAllRowIds(true); // TODO: Check if we can use shallow copy
840
+ this._setColumnData(dv, this._checkboxField, checked, rids);
716
841
  }
717
842
  };
718
843
 
@@ -722,27 +847,17 @@ CheckboxPlugin.prototype.setAllCheckStates = function (checked) {
722
847
  * @see {@link CheckboxPlugin#checkAll}
723
848
  */
724
849
  CheckboxPlugin.prototype.selectAllPages = function (checked) {
725
- var state = checked != null ? checked : true;
726
850
  var host = this._hosts[0];
727
851
  var dv = host ? host.getDataSource() : null;
728
-
729
- if(dv) {
730
- var allRids = dv.getSortedRowIds(true); // All row ids with filter applied, including disabled and pagination
731
-
732
- // remove disabled row
733
- var rids = [];
734
- var dataRows = dv.getMultipleRowData(allRids);
735
- var len = dataRows.length;
736
- var dataRow;
737
- for(var i = 0; i < len; i++) {
738
- dataRow = this._rowGetter(dataRows[i]);
739
- if(dataRow && !dataRow[this._disablingField]) {
740
- rids.push(allRids[i]);
741
- }
742
- }
743
- var valueList = CheckboxPlugin._genData(rids.length, state);
744
- this._setColumnData(dv, this._checkboxField, valueList, rids);
852
+ if(!dv) {
853
+ return;
745
854
  }
855
+
856
+ var allRids = dv.getSortedRowIds(true); // All row ids with filter applied, including disabled and pagination
857
+ allRids = allRids.filter(CheckboxPlugin._checkableRow.bind(null, dv, this._isCheckboxDisabled));
858
+
859
+ var state = checked != null ? checked : true;
860
+ this._setColumnData(dv, this._checkboxField, state, allRids);
746
861
  };
747
862
 
748
863
  /** @public
@@ -765,6 +880,18 @@ CheckboxPlugin.prototype.disableCheckbox = function(rowRef, disabled) {
765
880
 
766
881
  this._setData(dv, rowRef, this._disablingField, disabled !== false);
767
882
  };
883
+ /** @private
884
+ * @param {Object} view DataView object
885
+ * @param {string} rowId in the data table or row index
886
+ * @returns {boolean} disabled Truthy or Falsy value
887
+ */
888
+ CheckboxPlugin.prototype._isCheckboxDisabled = function(view, rowId) {
889
+ var rowData = this._getRowFromId(view, rowId);
890
+ if(rowData) {
891
+ return rowData[this._disablingField] ? true : false;
892
+ }
893
+ return false;
894
+ };
768
895
 
769
896
  /** @public
770
897
  * @param {number|string} rowRef Row id in the data table or row index
@@ -833,7 +960,6 @@ CheckboxPlugin.prototype.getFilteredSelectedData = function (field) {
833
960
  * @param {string=} field="" When field is not provided, entire rowData is returned. If field is specified, field values will be returned. Use "ROW_ID" as the field for retrieving internal row ids.
834
961
  * @return {!Array} Returns selected rows
835
962
  * @example
836
- * var chkBoxExtension = new CheckboxExtension();
837
963
  * chkBoxExtension.getSelectedRowData(); // Get all selected row data in this format [{}, {}, ... RowData objects, {}]
838
964
  * chkBoxExtension.getSelectedRowData("field"); // Get all field values from selected row data in this format [value1, value2, ... values, valueN]
839
965
  */
@@ -924,67 +1050,52 @@ CheckboxPlugin.prototype._getCheckboxValue = function (dv, rowId) {
924
1050
  };
925
1051
  /** @private
926
1052
  * @param {Object} dv DataView
927
- * @return {Array.<string>} state
1053
+ * @return {string} state
928
1054
  */
929
- CheckboxPlugin.prototype._getRowMemberIds = function (dv) {
930
- var rowIds = [];
931
- if (!dv) return rowIds;
1055
+ CheckboxPlugin.prototype._getGroupState = function (dv) {
1056
+ if (!dv) {
1057
+ return "unchecked";
1058
+ }
932
1059
 
933
- if (dv.getGroupLevel && 0 === dv.getGroupLevel()) {
934
- // case root group we check state from member that visible in view
1060
+ var rowIds = null;
1061
+ if (dv.getGroupLevel && dv.getGroupLevel() === 0) { // Root group
935
1062
  rowIds = this._getRowMemberIdsInView(dv);
936
- } else {
937
- // case dataTable or subGroup we check state from member in group
1063
+ } else { // Subgroup
938
1064
  rowIds = dv.getAllRowIds(true); // Getting shallow copy and excluding header rows
1065
+ rowIds = rowIds.filter(CheckboxPlugin._checkableRow.bind(null, dv, this._isCheckboxDisabled));
939
1066
  }
940
- return rowIds;
941
- };
942
- /** @private
943
- * @param {Object} dv DataView
944
- * @return {string} state
945
- */
946
- CheckboxPlugin.prototype._getGroupState = function (dv) {
947
- if (!dv) return "unchecked";
948
1067
 
949
- var rowIds = this._getRowMemberIds(dv);
950
-
951
- var dataRows = dv.getMultipleRowData(rowIds);
952
1068
  var len = rowIds.length;
953
- if (0 === len) return "unchecked";
1069
+ if (!len) {
1070
+ return "unchecked";
1071
+ }
954
1072
 
955
- var dataRow;
956
- var states = [];
1073
+ var state = "";
957
1074
  for(var i = 0; i < len; ++i) {
958
- if (dv.getGroupByRowId(rowIds[i])) { continue; }
959
- dataRow = dataRows[i];
960
- if(dataRow && dataRow[this._disablingField]) {
961
- continue;
962
- }
963
- states.push(CheckboxPlugin._toCheckState(this._getCheckboxValue(dv, rowIds[i])));
1075
+ state = CheckboxPlugin._mergeState(
1076
+ state,
1077
+ CheckboxPlugin._toCheckState(this._getCheckboxValue(dv, rowIds[i]))
1078
+ );
964
1079
  }
965
- return CheckboxPlugin._mergeStates(states);
1080
+ return state;
966
1081
  };
967
1082
  /** @private
968
1083
  * @param {Object} dv DataView
969
1084
  * @return {boolean} state
970
1085
  */
971
1086
  CheckboxPlugin.prototype._getGroupDisabledState = function (dv) {
972
- if (!dv) return false;
1087
+ if (!dv) {
1088
+ return false;
1089
+ }
973
1090
 
974
- var rowIds = this._getRowMemberIds(dv);
1091
+ var rowIds = this._getRowMemberIdsInView(dv);
975
1092
  var len = rowIds.length;
976
- if (!len) return true;
977
-
978
- var disabled = true;
979
1093
  for(var i = 0; i < len; ++i) {
980
- var rid = rowIds[i];
981
- var dataRow = this._getRowFromId(dv, rid);
982
- if (!dataRow[this._disablingField]) {
983
- disabled = false;
984
- break;
1094
+ if(!this._isCheckboxDisabled(dv, rowIds[i])) {
1095
+ return false;
985
1096
  }
986
1097
  }
987
- return disabled;
1098
+ return true;
988
1099
  };
989
1100
  /** @private
990
1101
  * @param {Object} sectionSettings Grid sectionSettings object
@@ -1000,12 +1111,12 @@ CheckboxPlugin.prototype._getSectionState = function (sectionSettings) {
1000
1111
  }
1001
1112
  };
1002
1113
  /** @private
1003
- * @param {Object} sectionSettings Grid sectionSettings object
1114
+ * @param {Object} sectionSettings Section or SectionSettings
1004
1115
  * @param {number} rowIndex
1005
1116
  * @return {Element}
1006
1117
  */
1007
1118
  CheckboxPlugin.prototype._getCheckbox = function (sectionSettings, rowIndex) {
1008
- var section = sectionSettings.getSection();
1119
+ var section = sectionSettings.getSection ? sectionSettings.getSection() : sectionSettings;
1009
1120
  var chkbox = /** @type{Element} */(section.getCellContent(this._displayColumn, rowIndex));
1010
1121
  if (!chkbox) {
1011
1122
  return null;
@@ -1091,14 +1202,7 @@ CheckboxPlugin.prototype._syncAscendantState = function (sectionSettings, caller
1091
1202
  var titleSection = host.getSectionSettings("title");
1092
1203
  var disabled = this._getGroupDisabledState(dv);
1093
1204
  var checkboxes = this._getAllCheckboxes(titleSection);
1094
- for(i = 0; i < checkboxes.length; i++){
1095
- var checkbox = checkboxes[i];
1096
- if(disabled) {
1097
- checkbox.setAttribute("disabled", "");
1098
- } else {
1099
- checkbox.removeAttribute("disabled");
1100
- }
1101
- }
1205
+ checkboxes.forEach(disabled ? CheckboxPlugin._addDisabledProp : CheckboxPlugin._removeDisabledProp);
1102
1206
  }
1103
1207
 
1104
1208
  this._setSectionState(parent, state);
@@ -1109,51 +1213,18 @@ CheckboxPlugin.prototype._syncAscendantState = function (sectionSettings, caller
1109
1213
  * @param {string} state
1110
1214
  */
1111
1215
  CheckboxPlugin.prototype._setSectionState = function (sectionSettings, state) {
1112
- var i;
1113
1216
  if (!state) {
1114
1217
  return;
1115
1218
  }
1116
1219
 
1117
1220
  if (this._isDataBound(sectionSettings)) {
1221
+ var checked = (state !== "unchecked");
1118
1222
  var dv = /** @type{DataView} */(sectionSettings.getDataSource());
1119
-
1120
- // create row dict and mark unchecked
1121
- var rowIdDict = {};
1122
- // in state !== unchecked we will get filtered row in group
1123
- // and set rowIdDict[checkID] = true
1124
- var checkIDs = this._getRowMemberIdsInView(dv);
1125
- for (i = 0; i < checkIDs.length; i++) {
1126
- var checkID = checkIDs[i];
1127
-
1128
- // there are header group rows in the case of paging and grouping
1129
- if (dv.getGroupByRowId(checkID)) { continue; }
1130
-
1131
- var dataRow = this._getRowFromId(dv, checkID);
1132
- if (dataRow && dataRow[this._disablingField]) {
1133
- continue;
1134
- }
1135
-
1136
- if (state === "unchecked") {
1137
- // TODO: This will not work in RT grid
1138
- rowIdDict[checkID] = false;
1139
- } else {
1140
- rowIdDict[checkID] = true;
1141
- }
1142
- }
1143
-
1144
- // create data array and rowIds array
1145
- var data = [];
1146
- var allRowIDInGroup = [];
1147
- for (var rowID in rowIdDict) {
1148
- allRowIDInGroup.push(rowID);
1149
- data.push(rowIdDict[rowID]);
1150
- }
1151
-
1152
- // finally set all data
1153
- this._setColumnData(dv, this._checkboxField, data, allRowIDInGroup);
1223
+ var memberRids = this._getRowMemberIdsInView(dv);
1224
+ this._setColumnData(dv, this._checkboxField, checked, memberRids);
1154
1225
  } else {
1155
1226
  var checkboxes = this._getAllCheckboxes(sectionSettings);
1156
- for (i = checkboxes.length; --i >= 0; ) {
1227
+ for (var i = checkboxes.length; --i >= 0; ) {
1157
1228
  CheckboxPlugin._setCheckState(checkboxes[i], state);
1158
1229
  }
1159
1230
  }
@@ -1266,26 +1337,24 @@ CheckboxPlugin.prototype._populateUIs = function () {
1266
1337
  host.requestRowRefresh(); // For content
1267
1338
  this._initializing = false;
1268
1339
  };
1340
+
1269
1341
  /** @private
1270
1342
  * @param {Event} e
1343
+ * @param {boolean=} toggling
1271
1344
  */
1272
- CheckboxPlugin.prototype._onCheckboxClicked = function (e) {
1273
- if(this._coralCheckboxVer === 1) {
1274
- // Workaround for duplicate event from ef-checkbox
1275
- if(e.target.tagName === "LABEL") {
1276
- return;
1277
- }
1345
+ CheckboxPlugin.prototype._onCheckboxChanged = function (e, toggling) {
1346
+ var chkbox = e ? /** @type{Element} */(e.currentTarget) : null;
1347
+ if(!chkbox) {
1348
+ return;
1278
1349
  }
1279
1350
 
1280
- var chkbox = /** @type{Element} */(e.currentTarget);
1281
-
1282
1351
  // after checkbox change by user clicked action
1283
1352
  // the checkbox state is change only 'unchecked' or 'checked' only
1284
1353
  // so we must remove 'square-shape' class that use in only 'partial' state
1285
1354
  chkbox.classList.remove('square-shape');
1286
1355
 
1287
1356
  var newState = CheckboxPlugin._getCheckState(chkbox);
1288
- if(this._coralCheckboxVer === 1) { // State of the ef-checkbox will not be reflected immediately after click
1357
+ if(toggling) {
1289
1358
  newState = CheckboxPlugin._toggleState(newState);
1290
1359
  }
1291
1360
 
@@ -1297,41 +1366,49 @@ CheckboxPlugin.prototype._onCheckboxClicked = function (e) {
1297
1366
  }
1298
1367
 
1299
1368
  if (this._isDataBound(sectionSettings)) {
1300
- var rowIndex = pos["rowIndex"];
1301
- var bool = newState !== "unchecked";
1302
1369
  var dv = sectionSettings.getDataSource();
1370
+ var rowIndex = pos["rowIndex"];
1303
1371
  var rid = dv.getRowId(rowIndex);
1304
- var dataRow = this._getRowFromId(dv, rid);
1305
- if(dataRow) {
1306
- if (dataRow[this._disablingField]) {
1307
- return;
1308
- }
1309
- this._setData(dv, rowIndex, this._checkboxField, bool);
1310
- } else { // Group header
1311
- var subGroup = dv.getGroupByRowId(rid);
1312
- if (subGroup) {
1313
- // prepare data for _setColumnData fn.
1314
- var rowMemberIds = this._getRowMemberIdsOfGroupInView(dv, subGroup);
1315
- var len = rowMemberIds.length;
1316
-
1317
- var dataRows = dv.getMultipleRowData(rowMemberIds);
1318
- var rids = [];
1319
- var data = [];
1320
- for (var i = 0; i < len; i++) {
1321
- dataRow = dataRows[i];
1322
- if (dataRow && dataRow[this._disablingField]) {
1323
- continue;
1372
+
1373
+ if(this._isCheckboxDisabled(dv, rid)) { // TODO: Check if this is necessary
1374
+ return;
1375
+ }
1376
+
1377
+
1378
+ var changeRange = null;
1379
+ if(e.shiftKey && this._anchorRowId) { // Select/deselect range of checkboxes
1380
+ var prevIndex = dv.getRowIndex(this._anchorRowId);
1381
+ if(prevIndex >= 0) {
1382
+ var i;
1383
+ if(prevIndex < rowIndex) {
1384
+ changeRange = [];
1385
+ for(i = prevIndex; i <= rowIndex; ++i) {
1386
+ changeRange.push(i);
1387
+ }
1388
+ } else if(rowIndex < prevIndex) {
1389
+ changeRange = [];
1390
+ for(i = rowIndex; i <= prevIndex; ++i) {
1391
+ changeRange.push(i);
1324
1392
  }
1325
- rids.push(rowMemberIds[i]);
1326
- data.push(bool);
1327
1393
  }
1394
+ }
1395
+ }
1328
1396
 
1329
- this._setColumnData(dv, this._checkboxField, data, rids);
1397
+ if(changeRange) {
1398
+ this.setCheckStates(changeRange, !e.altKey);
1399
+ } else {
1400
+ var bool = newState !== "unchecked";
1401
+ var subGroup = dv.getGroupByRowId(rid);
1402
+ if (subGroup) {
1403
+ var rowMemberIds = this._getRowMemberIdsOfSubgroup(dv, subGroup);
1404
+ this._setColumnData(dv, this._checkboxField, bool, rowMemberIds);
1330
1405
 
1331
1406
  // WORKAROUND: to force group move to next state from partial state
1332
1407
  if (newState === 'checked' && chkbox._prevState === 'partial') {
1333
1408
  chkbox._forceNewState = newState;
1334
1409
  }
1410
+ } else {
1411
+ this._setData(dv, rowIndex, this._checkboxField, bool);
1335
1412
  }
1336
1413
  }
1337
1414
  }
@@ -1348,107 +1425,118 @@ CheckboxPlugin.prototype._onCheckboxClicked = function (e) {
1348
1425
 
1349
1426
  e.stopPropagation();
1350
1427
  };
1428
+ /** @private
1429
+ * @param {Event} e
1430
+ */
1431
+ CheckboxPlugin.prototype._onCheckboxClicked = function (e) {
1432
+ var v1 = this._coralCheckboxVer === 1;
1433
+ if(v1) {
1434
+ // Workaround for duplicate event from ef-checkbox
1435
+ if(e.target.tagName === "LABEL") {
1436
+ return;
1437
+ }
1438
+ }
1439
+
1440
+ // State of the ef-checkbox will not be reflected immediately after click in ELF v1
1441
+ this._onCheckboxChanged(e, v1);
1442
+ };
1443
+ /** @private
1444
+ * @param {Event} e
1445
+ */
1446
+ CheckboxPlugin.prototype._onCheckboxKeydown = function (e) {
1447
+ var keyCode = e.keyCode;
1448
+ if(keyCode === 32) {
1449
+ this._onCheckboxMousedown(e); // Set anchor if no shift key is pressed
1450
+ this._onCheckboxChanged(e, true);
1451
+ e.preventDefault();
1452
+ } if(keyCode === 38 || keyCode === 40) { // Arrow key up and down
1453
+ var host = this._hosts[0];
1454
+ var pos = host.getRelativePosition(e.currentTarget);
1455
+ if(pos.sectionType === "content") {
1456
+ var dv = host.getDataSource();
1457
+ var offset = (keyCode === 38) ? -1 : 1;
1458
+ var nextIndex = pos.rowIndex + offset;
1459
+ var rowId = dv.getRowId(nextIndex);
1460
+ if(rowId) {
1461
+ host.scrollToRow(null, nextIndex);
1462
+ var chkbox = this._getCheckbox(pos.section, nextIndex);
1463
+ if(chkbox) {
1464
+ chkbox.focus();
1465
+ }
1466
+ e.preventDefault();
1467
+ }
1468
+ }
1469
+
1470
+
1471
+ }
1472
+ };
1473
+ /** @private
1474
+ * @param {Event} e
1475
+ */
1476
+ CheckboxPlugin.prototype._onCheckboxMousedown = function (e) {
1477
+ if(!e.shiftKey) {
1478
+ this._anchorRowId = "";
1479
+ var host = this._hosts[0];
1480
+ var pos = host.getRelativePosition(e.currentTarget);
1481
+ if(pos.sectionType === "content") {
1482
+ var dv = host.getDataSource();
1483
+ this._anchorRowId = dv.getRowId(pos.rowIndex);
1484
+ }
1485
+ }
1486
+ };
1351
1487
 
1352
1488
  /** get member items in view. the items in view are items on current page and already filtered , include items in collapsed group
1353
1489
  * @private
1354
- * @param {Object} view dataview object
1355
- * @param {Object} targetGroup dataview object
1490
+ * @param {Object} view Root DataView object
1491
+ * @param {Object} targetGroup Subgroup DataView object
1356
1492
  * @return {!Array.<string>} list of row member ids of group in view
1357
1493
  */
1358
- CheckboxPlugin.prototype._getRowMemberIdsOfGroupInView = function (view, targetGroup) {
1359
- var visibleRowIds = view.getVisibleRowIds(true);
1360
- var beginPos = 0;
1494
+ CheckboxPlugin.prototype._getRowMemberIdsOfSubgroup = function (view, targetGroup) {
1495
+ var memberIds = this._getRowMemberIdsInView(view); // Slow
1361
1496
 
1362
- // if group header is in view and collapsed we can return all id in view immediately
1363
- var pos = visibleRowIds.indexOf(targetGroup.getGroupRowId());
1364
- if (pos >= 0) {
1365
- if (targetGroup.isCollapsed()) return targetGroup.getAllRowIds(true);
1366
- else beginPos = pos + 1;
1367
- } else { // not support case group header not in view or inside group parent that collapsed
1368
- return [];
1369
- }
1370
-
1371
- // loop to check which member is in view
1372
- var groupVisibleRowIds = targetGroup.getVisibleRowIds(true);
1373
- var result = [], id, childGroup, i;
1374
- var len = groupVisibleRowIds.length;
1375
- for (i = 0; i < len; i++) {
1376
- id = groupVisibleRowIds[i];
1377
- pos = visibleRowIds.indexOf(id, beginPos);
1497
+ // WARNING: Subgroup header row may not be in the view
1498
+ var subgroupMembers = targetGroup.isCollapsed() ? targetGroup.getAllRowIds(true) : targetGroup.getVisibleRowIds(true);
1499
+ var beginPos = 0;
1500
+ var result = [];
1501
+ var len = subgroupMembers.length;
1502
+ // TODO: Use object map instead of indexOf for checking
1503
+ for (var i = 0; i < len; i++) {
1504
+ var subgroupMember = subgroupMembers[i];
1505
+ var pos = memberIds.indexOf(subgroupMember, beginPos);
1378
1506
  if (pos >= 0) {
1379
1507
  beginPos = pos + 1;
1380
- childGroup = view.getGroupByRowId(id);
1381
- if (childGroup) {
1382
- if (childGroup.isCollapsed()) {
1383
- // child group collapsed then all rows in childGroup are in view
1384
- result = result.concat(childGroup.getAllRowIds(true) || []);
1385
- }
1386
- } else {
1387
- result.push(id);
1388
- }
1508
+ result.push(subgroupMember);
1389
1509
  }
1390
1510
  }
1391
1511
 
1392
1512
  return result;
1393
1513
  };
1394
1514
 
1395
- /** @private
1396
- * @param {Object} view dataview or datatable object
1515
+ /** Get all member rows that are in the given view and all members in a collapsed group. This excludes group header row ids.
1516
+ * Only valid row ids are returned. Row expansions and disabled rows are excluded.
1517
+ * @private
1518
+ * @param {Object} view DataView or DataTable object
1397
1519
  * @return {!Array.<string>} list of row member ids in view
1398
1520
  */
1399
1521
  CheckboxPlugin.prototype._getRowMemberIdsInView = function (view) {
1400
- // 1. get All member and group rowIds
1401
- // 2. loop check whether rowIds is group or just row member
1402
- // 3. if rowId is not group then it's just a row member
1403
- // 4. in case rowId is group and collapsed we will get all member rowIds of group and add to memberRowIds
1404
-
1405
1522
  if (view.getDataSource()) { // check is dataView
1406
1523
  // TODO: support multi-level grouping
1407
1524
  // if view is DataView -> view.getVisibleRowIds(true) will get member and group rowIds in view
1408
- var rids = view.getVisibleRowIds(true);
1525
+ var rids = view.isCollapsed() ? view.getAllRowIds(true) : view.getVisibleRowIds(true); // get All member and group rowIds
1409
1526
  var len = rids.length;
1410
1527
  var allRids = [];
1411
- var rid, group, i;
1412
- for (i = 0; i < len; i++) { // 2
1413
- rid = rids[i];
1414
- group = view.getGroupByRowId(rid);
1415
- if (!group) {
1416
- allRids.push(rid); // 3
1417
- } else if (group.isCollapsed()) { // 4
1418
- allRids = allRids.concat(group.getAllRowIds(true) || []);
1419
- }
1528
+ for (var i = 0; i < len; i++) { // loop check whether rowIds is group or just row member
1529
+ allRids = CheckboxPlugin._collectRowMemberId(view, allRids, rids[i]);
1420
1530
  }
1421
1531
 
1422
- // remove disabled row
1423
- rids = [];
1424
- var dataRows = view.getMultipleRowData(allRids);
1425
- len = dataRows.length;
1426
- var dataRow;
1427
- for(i = 0; i < len; i++) {
1428
- dataRow = dataRows[i];
1429
- if(dataRow && dataRow[this._disablingField]) {
1430
- continue;
1431
- }
1432
- rids.push(allRids[i]);
1433
- }
1434
1532
  // if view is DataView, the intention is to get data with applied filter/hidden. row expansion should also filtered out.
1435
- return rids.filter(this._isNotRowExpansion.bind(null, view));
1533
+ return allRids.filter(CheckboxPlugin._checkableRow.bind(null, view, this._isCheckboxDisabled));
1436
1534
  } else {
1437
1535
  // if view is DataTable -> view.getAllRowIds(true) will get all member in grid regardless of hidden/filtered state.
1438
1536
  return view.getAllRowIds(true);
1439
1537
  }
1440
1538
  };
1441
1539
 
1442
- /** @private
1443
- * @param {Object} view DataView object
1444
- * @param {string} rid
1445
- * @return {boolean}
1446
- */
1447
- CheckboxPlugin.prototype._isNotRowExpansion = function (view, rid) {
1448
- // NOTE: isRowExpansion() is only available in DataView.
1449
- return !view.isRowExpansion(rid);
1450
- };
1451
-
1452
1540
  /** @private
1453
1541
  * @param {Object} e
1454
1542
  */
@@ -1533,7 +1621,7 @@ CheckboxPlugin.prototype._onPostSectionDataBinding = function (e) {
1533
1621
  chkbox = checkboxes[i] = this._createCheckbox(sectionSettings, this._displayColumn, rowIndex);
1534
1622
  }
1535
1623
  var rowId = dv.getRowId(rowIndex); // Slow
1536
- rowData = this._rowGetter(dv.getRowData(rowId));
1624
+ rowData = this._getRowFromId(dv, rowId);
1537
1625
  if(hasBinding && chkbox) {
1538
1626
  arg["checkbox"] = chkbox;
1539
1627
  arg["rowIndex"] = rowIndex;
@@ -1556,11 +1644,7 @@ CheckboxPlugin.prototype._onPostSectionDataBinding = function (e) {
1556
1644
  }
1557
1645
 
1558
1646
  if(chkbox) {
1559
- if(disabled) {
1560
- chkbox.setAttribute("disabled", "");
1561
- } else {
1562
- chkbox.removeAttribute("disabled");
1563
- }
1647
+ CheckboxPlugin._setBooleanProp(chkbox, "disabled", disabled);
1564
1648
  CheckboxPlugin._setCheckState(chkbox, state);
1565
1649
  }
1566
1650
  }
@@ -1569,5 +1653,6 @@ CheckboxPlugin.prototype._onPostSectionDataBinding = function (e) {
1569
1653
  };
1570
1654
 
1571
1655
 
1656
+
1572
1657
  export default CheckboxPlugin;
1573
1658
  export { CheckboxPlugin, CheckboxPlugin as Checkbox, CheckboxPlugin as CheckboxExtension };