import lang from 'dojo/_base/lang';
import declare from 'dojo/_base/declare';
import getResource from './I18n';
const resource = getResource('selectionModel');
/**
* @class argos.SelectionModel
* @classdesc SelectionModel provides a simple in-memory store for data that fires events
* when a item is selected (added) or deselected (removed)
*/
const __class = declare('argos.SelectionModel', null, /** @lends argos.SelectionModel# */{
// Localization
requireSelectionText: resource.requireSelectionText,
/**
* @property {Boolean}
* Flag to indicate a selection is required.
*/
requireSelection: false,
/**
* @property {Number}
* Number of selections
*/
count: 0,
/**
* @property {Object}
* Collection of selections where the key is the selections key
*/
selections: null,
/**
* @property {Boolean}
* Flag that determines how to clear:
*
* True: Deselect is called on every item, firing onDeselect for each and firing onClear at the end
*
* False: Collection is immediately wiped and only onClear is fired
*
*/
clearAsDeselect: true,
/**
* @property {Boolean}
* Flag that control the firing of action events: onSelect, onDeselect, onClear
*/
_fireEvents: true,
/**
* Initializes the selections to be empty and mixes the passed object overriding any default properties.
* @param {Object} options The object to be mixed in.
* @constructs
*/
constructor: function constructor(options) {
this.selections = {};
lang.mixin(this, options);
},
/**
* Prevents the firing of action events: onSelect, onDeselect, onClear
*/
suspendEvents: function suspendEvents() {
this._fireEvents = false;
},
/**
* Enables the firing of action events: onSelect, onDeselect, onClear
*/
resumeEvents: function resumeEvents() {
this._fireEvents = true;
},
/**
* Event that happens when an item is selected/added.
* @param {String} key Unique identifier string
* @param {Object} data The item stored
* @param tag
* @param self
* @template
*/
onSelect: function onSelect(/* key, data, tag, self*/) {},
/**
* Event that happens when an item is deselected/removed.
* @param {String} key Unique identifier string
* @param {Object} data The item removed
* @param tag
* @param self
* @template
*/
onDeselect: function onDeselect(/* key, data, tag, self*/) {},
/**
* Event that happens when the store is cleared
* @param self
*/
onClear: function onClear(/* self*/) {},
/**
* Adds an item to the `selections` if it is not already stored.
* @param {String} key Unique identifier string
* @param {Object} data The item being selected
* @param tag
*/
select: function select(key, data, tag) {
if (!this.selections.hasOwnProperty(key)) {
this.selections[key] = {
data,
tag,
};
this.count++;
if (this._fireEvents) {
this.onSelect(key, data, tag, this);
}
}
},
/**
* Adds an item to the `selections` if it is not already stored, if it is
* stored, then it deselects (removes) the item.
* @param {String} key Unique identifier string
* @param {Object} data The item being selected
* @param tag
*/
toggle: function toggle(key, data, tag) {
if (this.isSelected(key)) {
this.deselect(key);
} else {
this.select(key, data, tag);
}
},
/**
* Removes an item from the store
* @param {String} key Unique identifier string that was given when the item was added
*/
deselect: function deslect(key) {
if (this.requireSelection && this.count === 1) {
window.alert(this.requireSelectionText);//eslint-disable-line
return;
}
if (this.selections.hasOwnProperty(key)) {
const selection = this.selections[key];
delete this.selections[key];
this.count--;
if (this._fireEvents) {
this.onDeselect(key, selection.data, selection.tag, this);
}
}
},
/**
* Removes all items from the store
*/
clear: function clear() {
const original = this.requireSelection;
if (this.clearAsDeselect) {
this.requireSelection = false;
for (const key in this.selections) {
if (this.selections.hasOwnProperty(key)) {
this.deselect(key);
}
}
this.requireSelection = original;
} else {
this.selections = {};
this.count = 0;
}
if (this._fireEvents) {
this.onClear(this);
}
},
/**
* Determines if the given key is in the selections collection.
* @param {String} key Unique identifier string that was given when the item was added
* @return {Boolean} True if the item is in the store.
*/
isSelected: function isSelected(key) {
return !!this.selections[key];
},
/**
* Returns the number of items in the store
* @return {Number} Current count of items
*/
getSelectionCount: function getSelectionCount() {
return this.count;
},
/**
* Returns all items in the store
* @return {Object} The entire selection collection
*/
getSelections: function getSelections() {
return this.selections;
},
/**
* Returns a list of unique identifier keys used in the selection collection
* @return {String[]} All keys in the store
*/
getSelectedKeys: function getSelectedKeys() {
return Object.keys(this.selections).filter((key) => {
return this.selections.hasOwnProperty(key);
});
},
});
export default __class;