devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
344 lines (268 loc) • 11.7 kB
JavaScript
"use strict";
var commonUtils = require("../../core/utils/common"),
typeUtils = require("../../core/utils/type"),
getKeyHash = commonUtils.getKeyHash,
dataQuery = require("../../data/query"),
deferredUtils = require("../../core/utils/deferred"),
SelectionFilterCreator = require("../../core/utils/selection_filter").SelectionFilterCreator,
when = deferredUtils.when,
Deferred = deferredUtils.Deferred,
errors = require("../widget/ui.errors"),
SelectionStrategy = require("./selection.strategy");
module.exports = SelectionStrategy.inherit({
ctor: function ctor(options) {
this.callBase(options);
this._initSelectedItemKeyHash();
},
_initSelectedItemKeyHash: function _initSelectedItemKeyHash() {
this._setOption("keyHashIndices", this.options.equalByReference ? null : {});
},
getSelectedItemKeys: function getSelectedItemKeys() {
return this.options.selectedItemKeys.slice(0);
},
getSelectedItems: function getSelectedItems() {
return this.options.selectedItems.slice(0);
},
_preserveSelectionUpdate: function _preserveSelectionUpdate(items, isDeselect) {
var keyOf = this.options.keyOf,
keyIndicesToRemoveMap,
keyIndex,
i;
if (!keyOf) return;
var isBatchDeselect = isDeselect && items.length > 1 && !this.options.equalByReference;
if (isBatchDeselect) {
keyIndicesToRemoveMap = {};
}
for (i = 0; i < items.length; i++) {
var item = items[i],
key = keyOf(item);
if (isDeselect) {
keyIndex = this.removeSelectedItem(key, keyIndicesToRemoveMap);
if (keyIndicesToRemoveMap && keyIndex >= 0) {
keyIndicesToRemoveMap[keyIndex] = true;
}
} else {
this.addSelectedItem(key, item);
}
}
if (isBatchDeselect) {
this._batchRemoveSelectedItems(keyIndicesToRemoveMap);
}
},
_batchRemoveSelectedItems: function _batchRemoveSelectedItems(keyIndicesToRemoveMap) {
var selectedItemKeys = this.options.selectedItemKeys.slice(0);
var selectedItems = this.options.selectedItems.slice(0);
this.options.selectedItemKeys.length = 0;
this.options.selectedItems.length = 0;
for (var i = 0; i < selectedItemKeys.length; i++) {
if (!keyIndicesToRemoveMap[i]) {
this.options.selectedItemKeys.push(selectedItemKeys[i]);
this.options.selectedItems.push(selectedItems[i]);
}
}
this._initSelectedItemKeyHash();
this.updateSelectedItemKeyHash(this.options.selectedItemKeys);
},
_loadSelectedItemsCore: function _loadSelectedItemsCore(keys, isDeselect, isSelectAll) {
var deferred = new Deferred(),
key = this.options.key;
if (!keys.length && !isSelectAll) {
deferred.resolve([]);
return deferred;
}
var filter = this.options.filter();
if (isSelectAll && isDeselect && !filter) {
deferred.resolve(this.getSelectedItems());
return deferred;
}
var selectionFilterCreator = new SelectionFilterCreator(keys, isSelectAll),
combinedFilter = selectionFilterCreator.getCombinedFilter(key(), filter);
var deselectedItems = [];
if (isDeselect) {
deselectedItems = combinedFilter ? dataQuery(this.options.selectedItems).filter(combinedFilter).toArray() : this.options.selectedItems.slice(0);
}
var filteredItems = deselectedItems.length ? deselectedItems : this.options.plainItems().filter(this.options.isSelectableItem).map(this.options.getItemData);
var localFilter = selectionFilterCreator.getLocalFilter(this.options.keyOf, this.equalKeys.bind(this), this.options.equalByReference);
filteredItems = filteredItems.filter(localFilter);
if (deselectedItems.length || !isSelectAll && filteredItems.length === keys.length) {
deferred.resolve(filteredItems);
} else {
deferred = this._loadFilteredData(combinedFilter, localFilter);
}
return deferred;
},
_replaceSelectionUpdate: function _replaceSelectionUpdate(items) {
var internalKeys = [],
keyOf = this.options.keyOf;
if (!keyOf) return;
for (var i = 0; i < items.length; i++) {
var item = items[i],
key = keyOf(item);
internalKeys.push(key);
}
this.setSelectedItems(internalKeys, items);
},
_warnOnIncorrectKeys: function _warnOnIncorrectKeys(keys) {
for (var i = 0; i < keys.length; i++) {
if (!this.isItemKeySelected(keys[i])) {
errors.log("W1002", keys[i]);
}
}
},
_loadSelectedItems: function _loadSelectedItems(keys, isDeselect, isSelectAll) {
var that = this,
deferred = new Deferred();
when(that._lastLoadDeferred).always(function () {
that._loadSelectedItemsCore(keys, isDeselect, isSelectAll).done(deferred.resolve).fail(deferred.reject);
});
that._lastLoadDeferred = deferred;
return deferred;
},
selectedItemKeys: function selectedItemKeys(keys, preserve, isDeselect, isSelectAll) {
var that = this,
deferred = that._loadSelectedItems(keys, isDeselect, isSelectAll);
deferred.done(function (items) {
if (preserve) {
that._preserveSelectionUpdate(items, isDeselect);
} else {
that._replaceSelectionUpdate(items);
}
///#DEBUG
if (!isSelectAll && !isDeselect) {
that._warnOnIncorrectKeys(keys);
}
///#ENDDEBUG
that.onSelectionChanged();
});
return deferred;
},
addSelectedItem: function addSelectedItem(key, itemData) {
var keyHash = this._getKeyHash(key);
if (this._indexOfSelectedItemKey(keyHash) === -1) {
if (!typeUtils.isObject(keyHash) && this.options.keyHashIndices) {
this.options.keyHashIndices[keyHash] = [this.options.selectedItemKeys.length];
}
this.options.selectedItemKeys.push(key);
this.options.addedItemKeys.push(key);
this.options.addedItems.push(itemData);
this.options.selectedItems.push(itemData);
}
},
_getSelectedIndexByKey: function _getSelectedIndexByKey(key, ignoreIndicesMap) {
var selectedItemKeys = this.options.selectedItemKeys;
for (var index = 0; index < selectedItemKeys.length; index++) {
if ((!ignoreIndicesMap || !ignoreIndicesMap[index]) && this.equalKeys(selectedItemKeys[index], key)) {
return index;
}
}
return -1;
},
_getSelectedIndexByHash: function _getSelectedIndexByHash(key, ignoreIndicesMap) {
var indices = this.options.keyHashIndices[key];
if (indices && indices.length > 1 && ignoreIndicesMap) {
indices = indices.filter(function (index) {
return !ignoreIndicesMap[index];
});
}
return indices && indices[0] >= 0 ? indices[0] : -1;
},
_indexOfSelectedItemKey: function _indexOfSelectedItemKey(key, ignoreIndicesMap) {
var selectedIndex;
if (this.options.equalByReference) {
selectedIndex = this.options.selectedItemKeys.indexOf(key);
} else if (typeUtils.isObject(key)) {
selectedIndex = this._getSelectedIndexByKey(key, ignoreIndicesMap);
} else {
selectedIndex = this._getSelectedIndexByHash(key, ignoreIndicesMap);
}
return selectedIndex;
},
_shiftSelectedKeyIndices: function _shiftSelectedKeyIndices(keyIndex) {
for (var currentKeyIndex = keyIndex; currentKeyIndex < this.options.selectedItemKeys.length; currentKeyIndex++) {
var currentKey = this.options.selectedItemKeys[currentKeyIndex],
currentKeyHash = getKeyHash(currentKey),
currentKeyIndices = this.options.keyHashIndices[currentKeyHash];
if (!currentKeyIndices) continue;
for (var i = 0; i < currentKeyIndices.length; i++) {
if (currentKeyIndices[i] > keyIndex) {
currentKeyIndices[i]--;
}
}
}
},
removeSelectedItem: function removeSelectedItem(key, keyIndicesToRemoveMap) {
var keyHash = this._getKeyHash(key),
isBatchDeselect = !!keyIndicesToRemoveMap,
keyIndex = this._indexOfSelectedItemKey(keyHash, keyIndicesToRemoveMap);
if (keyIndex < 0) {
return keyIndex;
}
this.options.removedItemKeys.push(key);
this.options.removedItems.push(this.options.selectedItems[keyIndex]);
if (isBatchDeselect) {
return keyIndex;
}
this.options.selectedItemKeys.splice(keyIndex, 1);
this.options.selectedItems.splice(keyIndex, 1);
if (typeUtils.isObject(keyHash) || !this.options.keyHashIndices) {
return keyIndex;
}
var keyIndices = this.options.keyHashIndices[keyHash];
if (!keyIndices) {
return keyIndex;
}
keyIndices.shift();
if (!keyIndices.length) {
delete this.options.keyHashIndices[keyHash];
}
this._shiftSelectedKeyIndices(keyIndex);
return keyIndex;
},
_updateAddedItemKeys: function _updateAddedItemKeys(keys, items) {
for (var i = 0; i < keys.length; i++) {
if (!this.isItemKeySelected(keys[i])) {
this.options.addedItemKeys.push(keys[i]);
this.options.addedItems.push(items[i]);
}
}
},
_updateRemovedItemKeys: function _updateRemovedItemKeys(keys, oldSelectedKeys, oldSelectedItems) {
for (var i = 0; i < oldSelectedKeys.length; i++) {
if (!this.isItemKeySelected(oldSelectedKeys[i])) {
this.options.removedItemKeys.push(oldSelectedKeys[i]);
this.options.removedItems.push(oldSelectedItems[i]);
}
}
},
_getKeyHash: function _getKeyHash(key) {
return this.options.equalByReference ? key : getKeyHash(key);
},
setSelectedItems: function setSelectedItems(keys, items) {
this._updateAddedItemKeys(keys, items);
var oldSelectedKeys = this.options.selectedItemKeys,
oldSelectedItems = this.options.selectedItems;
if (!this.options.equalByReference) {
this._initSelectedItemKeyHash();
this.updateSelectedItemKeyHash(keys);
}
this._setOption("selectedItemKeys", keys);
this._setOption("selectedItems", items);
this._updateRemovedItemKeys(keys, oldSelectedKeys, oldSelectedItems);
},
isItemDataSelected: function isItemDataSelected(itemData) {
var key = this.options.keyOf(itemData);
return this.isItemKeySelected(key);
},
isItemKeySelected: function isItemKeySelected(key) {
var keyHash = this._getKeyHash(key);
var index = this._indexOfSelectedItemKey(keyHash);
return index !== -1;
},
getSelectAllState: function getSelectAllState(visibleOnly) {
if (visibleOnly) {
return this._getVisibleSelectAllState();
} else {
return this._getFullSelectAllState();
}
}
});