selection.strategy.standard.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /**
  2. * DevExtreme (ui/selection/selection.strategy.standard.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var commonUtils = require("../../core/utils/common");
  11. var typeUtils = require("../../core/utils/type");
  12. var getKeyHash = commonUtils.getKeyHash;
  13. var dataQuery = require("../../data/query");
  14. var deferredUtils = require("../../core/utils/deferred");
  15. var SelectionFilterCreator = require("../../core/utils/selection_filter").SelectionFilterCreator;
  16. var when = deferredUtils.when;
  17. var Deferred = deferredUtils.Deferred;
  18. var errors = require("../widget/ui.errors");
  19. var SelectionStrategy = require("./selection.strategy");
  20. module.exports = SelectionStrategy.inherit({
  21. ctor: function(options) {
  22. this.callBase(options);
  23. this._initSelectedItemKeyHash()
  24. },
  25. _initSelectedItemKeyHash: function() {
  26. this._setOption("keyHashIndices", this.options.equalByReference ? null : {})
  27. },
  28. getSelectedItemKeys: function() {
  29. return this.options.selectedItemKeys.slice(0)
  30. },
  31. getSelectedItems: function() {
  32. return this.options.selectedItems.slice(0)
  33. },
  34. _preserveSelectionUpdate: function(items, isDeselect) {
  35. var keyOf = this.options.keyOf;
  36. var keyIndicesToRemoveMap;
  37. var keyIndex;
  38. var i;
  39. if (!keyOf) {
  40. return
  41. }
  42. var isBatchDeselect = isDeselect && items.length > 1 && !this.options.equalByReference;
  43. if (isBatchDeselect) {
  44. keyIndicesToRemoveMap = {}
  45. }
  46. for (i = 0; i < items.length; i++) {
  47. var item = items[i];
  48. var key = keyOf(item);
  49. if (isDeselect) {
  50. keyIndex = this.removeSelectedItem(key, keyIndicesToRemoveMap);
  51. if (keyIndicesToRemoveMap && keyIndex >= 0) {
  52. keyIndicesToRemoveMap[keyIndex] = true
  53. }
  54. } else {
  55. this.addSelectedItem(key, item)
  56. }
  57. }
  58. if (isBatchDeselect) {
  59. this._batchRemoveSelectedItems(keyIndicesToRemoveMap)
  60. }
  61. },
  62. _batchRemoveSelectedItems: function(keyIndicesToRemoveMap) {
  63. var selectedItemKeys = this.options.selectedItemKeys.slice(0);
  64. var selectedItems = this.options.selectedItems.slice(0);
  65. this.options.selectedItemKeys.length = 0;
  66. this.options.selectedItems.length = 0;
  67. for (var i = 0; i < selectedItemKeys.length; i++) {
  68. if (!keyIndicesToRemoveMap[i]) {
  69. this.options.selectedItemKeys.push(selectedItemKeys[i]);
  70. this.options.selectedItems.push(selectedItems[i])
  71. }
  72. }
  73. this._initSelectedItemKeyHash();
  74. this.updateSelectedItemKeyHash(this.options.selectedItemKeys)
  75. },
  76. _loadSelectedItemsCore: function(keys, isDeselect, isSelectAll) {
  77. var deferred = new Deferred;
  78. var key = this.options.key();
  79. if (!keys.length && !isSelectAll) {
  80. deferred.resolve([]);
  81. return deferred
  82. }
  83. var filter = this.options.filter();
  84. if (isSelectAll && isDeselect && !filter) {
  85. deferred.resolve(this.getSelectedItems());
  86. return deferred
  87. }
  88. var selectionFilterCreator = new SelectionFilterCreator(keys, isSelectAll);
  89. var combinedFilter = selectionFilterCreator.getCombinedFilter(key, filter);
  90. var deselectedItems = [];
  91. if (isDeselect) {
  92. deselectedItems = combinedFilter ? dataQuery(this.options.selectedItems).filter(combinedFilter).toArray() : this.options.selectedItems.slice(0)
  93. }
  94. var filteredItems = deselectedItems.length ? deselectedItems : this.options.plainItems(true).filter(this.options.isSelectableItem).map(this.options.getItemData);
  95. var localFilter = selectionFilterCreator.getLocalFilter(this.options.keyOf, this.equalKeys.bind(this), this.options.equalByReference, key);
  96. filteredItems = filteredItems.filter(localFilter);
  97. if (deselectedItems.length || !isSelectAll && filteredItems.length === keys.length) {
  98. deferred.resolve(filteredItems)
  99. } else {
  100. deferred = this._loadFilteredData(combinedFilter, localFilter, null, isSelectAll)
  101. }
  102. return deferred
  103. },
  104. _replaceSelectionUpdate: function(items) {
  105. var internalKeys = [];
  106. var keyOf = this.options.keyOf;
  107. if (!keyOf) {
  108. return
  109. }
  110. for (var i = 0; i < items.length; i++) {
  111. var item = items[i];
  112. var key = keyOf(item);
  113. internalKeys.push(key)
  114. }
  115. this.setSelectedItems(internalKeys, items)
  116. },
  117. _warnOnIncorrectKeys: function(keys) {
  118. var allowNullValue = this.options.allowNullValue;
  119. for (var i = 0; i < keys.length; i++) {
  120. var key = keys[i];
  121. if ((!allowNullValue || null !== key) && !this.isItemKeySelected(key)) {
  122. errors.log("W1002", key)
  123. }
  124. }
  125. },
  126. _loadSelectedItems: function(keys, isDeselect, isSelectAll) {
  127. var that = this;
  128. var deferred = new Deferred;
  129. when(that._lastLoadDeferred).always(function() {
  130. that._loadSelectedItemsCore(keys, isDeselect, isSelectAll).done(deferred.resolve).fail(deferred.reject)
  131. });
  132. that._lastLoadDeferred = deferred;
  133. return deferred
  134. },
  135. selectedItemKeys: function(keys, preserve, isDeselect, isSelectAll) {
  136. var that = this;
  137. var deferred = that._loadSelectedItems(keys, isDeselect, isSelectAll);
  138. deferred.done(function(items) {
  139. if (preserve) {
  140. that._preserveSelectionUpdate(items, isDeselect)
  141. } else {
  142. that._replaceSelectionUpdate(items)
  143. }
  144. that.onSelectionChanged()
  145. });
  146. return deferred
  147. },
  148. addSelectedItem: function(key, itemData) {
  149. var keyHash = this._getKeyHash(key);
  150. if (this._indexOfSelectedItemKey(keyHash) === -1) {
  151. if (!typeUtils.isObject(keyHash) && this.options.keyHashIndices) {
  152. this.options.keyHashIndices[keyHash] = [this.options.selectedItemKeys.length]
  153. }
  154. this.options.selectedItemKeys.push(key);
  155. this.options.addedItemKeys.push(key);
  156. this.options.addedItems.push(itemData);
  157. this.options.selectedItems.push(itemData)
  158. }
  159. },
  160. _getSelectedIndexByKey: function(key, ignoreIndicesMap) {
  161. var selectedItemKeys = this.options.selectedItemKeys;
  162. for (var index = 0; index < selectedItemKeys.length; index++) {
  163. if ((!ignoreIndicesMap || !ignoreIndicesMap[index]) && this.equalKeys(selectedItemKeys[index], key)) {
  164. return index
  165. }
  166. }
  167. return -1
  168. },
  169. _getSelectedIndexByHash: function(key, ignoreIndicesMap) {
  170. var indices = this.options.keyHashIndices[key];
  171. if (indices && indices.length > 1 && ignoreIndicesMap) {
  172. indices = indices.filter(function(index) {
  173. return !ignoreIndicesMap[index]
  174. })
  175. }
  176. return indices && indices[0] >= 0 ? indices[0] : -1
  177. },
  178. _indexOfSelectedItemKey: function(key, ignoreIndicesMap) {
  179. var selectedIndex;
  180. if (this.options.equalByReference) {
  181. selectedIndex = this.options.selectedItemKeys.indexOf(key)
  182. } else {
  183. if (typeUtils.isObject(key)) {
  184. selectedIndex = this._getSelectedIndexByKey(key, ignoreIndicesMap)
  185. } else {
  186. selectedIndex = this._getSelectedIndexByHash(key, ignoreIndicesMap)
  187. }
  188. }
  189. return selectedIndex
  190. },
  191. _shiftSelectedKeyIndices: function(keyIndex) {
  192. for (var currentKeyIndex = keyIndex; currentKeyIndex < this.options.selectedItemKeys.length; currentKeyIndex++) {
  193. var currentKey = this.options.selectedItemKeys[currentKeyIndex];
  194. var currentKeyHash = getKeyHash(currentKey);
  195. var currentKeyIndices = this.options.keyHashIndices[currentKeyHash];
  196. if (!currentKeyIndices) {
  197. continue
  198. }
  199. for (var i = 0; i < currentKeyIndices.length; i++) {
  200. if (currentKeyIndices[i] > keyIndex) {
  201. currentKeyIndices[i]--
  202. }
  203. }
  204. }
  205. },
  206. removeSelectedItem: function(key, keyIndicesToRemoveMap) {
  207. var keyHash = this._getKeyHash(key);
  208. var isBatchDeselect = !!keyIndicesToRemoveMap;
  209. var keyIndex = this._indexOfSelectedItemKey(keyHash, keyIndicesToRemoveMap);
  210. if (keyIndex < 0) {
  211. return keyIndex
  212. }
  213. this.options.removedItemKeys.push(key);
  214. this.options.removedItems.push(this.options.selectedItems[keyIndex]);
  215. if (isBatchDeselect) {
  216. return keyIndex
  217. }
  218. this.options.selectedItemKeys.splice(keyIndex, 1);
  219. this.options.selectedItems.splice(keyIndex, 1);
  220. if (typeUtils.isObject(keyHash) || !this.options.keyHashIndices) {
  221. return keyIndex
  222. }
  223. var keyIndices = this.options.keyHashIndices[keyHash];
  224. if (!keyIndices) {
  225. return keyIndex
  226. }
  227. keyIndices.shift();
  228. if (!keyIndices.length) {
  229. delete this.options.keyHashIndices[keyHash]
  230. }
  231. this._shiftSelectedKeyIndices(keyIndex);
  232. return keyIndex
  233. },
  234. _updateAddedItemKeys: function(keys, items) {
  235. for (var i = 0; i < keys.length; i++) {
  236. if (!this.isItemKeySelected(keys[i])) {
  237. this.options.addedItemKeys.push(keys[i]);
  238. this.options.addedItems.push(items[i])
  239. }
  240. }
  241. },
  242. _updateRemovedItemKeys: function(keys, oldSelectedKeys, oldSelectedItems) {
  243. for (var i = 0; i < oldSelectedKeys.length; i++) {
  244. if (!this.isItemKeySelected(oldSelectedKeys[i])) {
  245. this.options.removedItemKeys.push(oldSelectedKeys[i]);
  246. this.options.removedItems.push(oldSelectedItems[i])
  247. }
  248. }
  249. },
  250. _getKeyHash: function(key) {
  251. return this.options.equalByReference ? key : getKeyHash(key)
  252. },
  253. setSelectedItems: function(keys, items) {
  254. this._updateAddedItemKeys(keys, items);
  255. var oldSelectedKeys = this.options.selectedItemKeys;
  256. var oldSelectedItems = this.options.selectedItems;
  257. if (!this.options.equalByReference) {
  258. this._initSelectedItemKeyHash();
  259. this.updateSelectedItemKeyHash(keys)
  260. }
  261. this._setOption("selectedItemKeys", keys);
  262. this._setOption("selectedItems", items);
  263. this._updateRemovedItemKeys(keys, oldSelectedKeys, oldSelectedItems)
  264. },
  265. isItemDataSelected: function(itemData) {
  266. var key = this.options.keyOf(itemData);
  267. return this.isItemKeySelected(key)
  268. },
  269. isItemKeySelected: function(key) {
  270. var keyHash = this._getKeyHash(key);
  271. var index = this._indexOfSelectedItemKey(keyHash);
  272. return index !== -1
  273. },
  274. getSelectAllState: function(visibleOnly) {
  275. if (visibleOnly) {
  276. return this._getVisibleSelectAllState()
  277. } else {
  278. return this._getFullSelectAllState()
  279. }
  280. }
  281. });