/**
* Copyright (C) 2005-2016 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* <p>This module can be mixed into widgets that need to maintain the state of any selected items. Item
* selection is typically actioned by either individual [Selector]{@link module:alfresco/renderers/Selector}
* widgets in a [list]{@link module:alfresco/lists/AlfList} or by a menu action such as the ones provided by
* the [AlfSelectDocumentListItems]{@link module:alfresco/documentlibrary/AlfSelectDocumentListItems}.</P>
* <p>Mixing modules should call the
* [createSelectedItemSubscriptions]{@link module:alfresco/lists/SelectedItemStateMixin#createSelectedItemSubscriptions}
* on creation to keep track of selected items. The can also call the
* [publishSelectedItems]{@link module:alfresco/lists/SelectedItemStateMixin#publishSelectedItems} function
* to broadcast the details of changes to item selection.</p>
*
* @module alfresco/lists/SelectedItemStateMixin
* @author Dave Draper
* @since 1.0.39
*/
define(["dojo/_base/declare",
"alfresco/core/Core",
"alfresco/core/topics",
"alfresco/documentlibrary/_AlfDocumentListTopicMixin",
"dojo/_base/lang",
"dojo/_base/array"],
function( declare, Core, topics, _AlfDocumentListTopicMixin, lang, array) {
return declare([Core, _AlfDocumentListTopicMixin], {
/**
* This is used to keep track of the items that are currently selected.
* [onItemSelected]{@link module:alfresco/lists/SelectedItemStateMixin#onItemSelected}
* adds items and the [onItemDeselected]{@link module:alfresco/lists/SelectedItemStateMixin#onItemDeselected}
* removes them. The [itemKeyProperty]{@link module:alfresco/lists/SelectedItemStateMixin#itemKeyProperty}
* is used as the key and the entire item is the value.
*
* @instance
* @type {object}
* @default
*/
currentlySelectedItems: null,
/**
* The number of milliseconds to wait after a selection event before publishing the latest selected item
* data.
*
* @instance
* @type {number}
* @default
*/
debounceTime: 50,
/**
* Indicates whether or not the [disable]{@link module:alfresco/lists/SelectedItemStateMixin#disable}
* function should be called when no items are selected.
*
* @instance
* @type {boolean}
* @default
*/
disableWhenNothingSelected: false,
/**
* This is the dot-notation addressed property within the selection/de-selection publication payload that
* uniquely identifies the item.
*
* @instance
* @type {string}
* @default
*/
itemKeyProperty: "node.nodeRef",
/**
* This is assigned the [currentlySelectedItems]{@link module:alfresco/lists/SelectedItemStateMixin#currentlySelectedItems}
* when [item selection is cleared]{@link module:alfresco/lists/SelectedItemStateMixin#onItemSelectionCleared}. If the
* [retainPreviousItemSelectionState]{@link module:alfresco/lists/SelectedItemStateMixin#retainPreviousItemSelectionState}
* function is called then these items will be compared against the supplied list for consideration to be republished.
*
* @instance
* @type {object}
* @default
* @since 1.0.47
*/
previouslySelectedItems: null,
/**
* An array of the currently selected items.
*
* @instance
* @type {object[]}
* @default
*/
selectedItems: null,
/**
* This is used to keep a reference to a timeout that is started on the publication of a selected document
* topic. It is important that multiple selection events can be captured so that only one publication of
* selected items occurs.
*
* @instance
* @type {number}
* @default
*/
selectionTimeout: null,
/**
*
* @instance
*/
createSelectedItemSubscriptions: function alfresco_lists_SelectedItemStateMixin__createSelectedItemSubscriptions() {
this.currentlySelectedItems = {};
this.alfSubscribe(this.documentSelectedTopic, lang.hitch(this, this.onItemSelected));
this.alfSubscribe(this.documentDeselectedTopic, lang.hitch(this, this.onItemDeselected));
this.alfSubscribe(topics.CLEAR_SELECTED_ITEMS, lang.hitch(this, this.onItemSelectionCleared));
},
/**
* This is called from [onItemSelected]{@link module:alfresco/lists/SelectedItemStateMixin#onItemSelected}
* when the [selectionTimeout]{@link module:alfresco/lists/SelectedItemStateMixin#selectionTimeout} times out. It
* resets the [selectionTimeout]{@link module:alfresco/lists/SelectedItemStateMixin#selectionTimeout} to null and
* calls [onSelectedItemsChanged]{@link module:alfresco/lists/SelectedItemStateMixin#deselectionTimeout}
*
* @instance
*/
deferredSelectionHandler: function alfresco_lists_SelectedItemStateMixin__deferredSelectionHandler() {
this.selectedItems = [];
for (var key in this.currentlySelectedItems)
{
if (this.currentlySelectedItems.hasOwnProperty(key)) {
this.selectedItems.push(this.currentlySelectedItems[key]);
}
}
if (this.disableWhenNothingSelected)
{
this.setDisabled(this.selectedItems.length === 0);
}
this.publishSelectedItems(this.selectedItems);
this.selectionTimeout = null;
},
/**
* This function is called if
* [disableWhenNothingSelected]{@link module:alfresco/lists/SelectedItemStateMixin#disableWhenNothingSelected}
* is configured to be true and a selection update occurs that results in no items being selected. By
* default it will attempt to toggle the disable state of the widget.
*
* @instance
* @param {boolean} disable Indicates whether to disable or enable the widget
* @overridable
*/
setDisabled: function alfresco_lists_SelectedItemStateMixin__setDisabled(disable) {
this.set("disabled", disable);
},
/**
* Updates the array of documents that are currently selected.
*
* @instance
* @param {object} payload The details of the item selected
*/
onItemDeselected: function alfresco_lists_SelectedItemStateMixin__onItemDeselected(payload) {
if (payload && payload.value)
{
var itemKey = lang.getObject(this.itemKeyProperty, false, payload.value);
if (typeof itemKey !== "undefined")
{
delete this.currentlySelectedItems[itemKey];
if (this.selectionTimeout)
{
clearTimeout(this.selectionTimeout);
}
this.selectionTimeout = setTimeout(lang.hitch(this, this.deferredSelectionHandler), this.debounceTime);
}
else
{
this.alfLog("warn", "Could not find item key property: '" + this.itemKeyProperty + "' in deselected item value", payload, this);
}
}
},
/**
* Updates the aray of documents that are currently selected.
* @instance
* @param {object} payload The details of the document selected
*/
onItemSelected: function alfresco_lists_SelectedItemStateMixin__onItemSelected(payload) {
if (payload && payload.value)
{
var itemKey = lang.getObject(this.itemKeyProperty, false, payload.value);
if (typeof itemKey !== "undefined")
{
this.currentlySelectedItems[itemKey] = payload.value;
if (this.selectionTimeout)
{
clearTimeout(this.selectionTimeout);
}
this.selectionTimeout = setTimeout(lang.hitch(this, this.deferredSelectionHandler), 50);
}
else
{
this.alfLog("warn", "Could not find item key property: '" + this.itemKeyProperty + "' in selected item value", payload, this);
}
}
},
/**
* This clears the currently selected items. It it bound to the
* [CLEAR_SELECTED_ITEMS topic]{@link module:alfresco/core/topics#CLEAR_SELECTED_ITEMS} that is published
* by the [AlfSelectedItemsMenuItem]{@link module:alfresco/menus/AlfSelectedItemsMenuItem} when clicked.
*
* @instance
* @param {object} payload This is not expected to contain any usable data.
*/
onItemSelectionCleared: function alfresco_lists_SelectedItemStateMixin__onItemSelectionCleared(/*jshint unused:false*/ payload) {
this.previouslySelectedItems = this.currentlySelectedItems;
this.currentlySelectedItems = {};
if (this.selectionTimeout)
{
clearTimeout(this.selectionTimeout);
}
this.selectionTimeout = setTimeout(lang.hitch(this, this.deferredSelectionHandler), 50);
},
/**
* Tracks the currently selected items and stores them as the
* [selectedItems]{@link module:alfresco/lists/SelectedItemStateMixin#selectedItems} variable.
*
* @instance
* @param {object} payload A payload expected to contain a "selectedItems" attribute
*/
onSelectedItemsChange: function alfresco_lists_SelectedItemStateMixin__onSelectedItemsChange(payload) {
if (payload.selectedItems)
{
this.selectedItems = payload.selectedItems;
}
else
{
this.alfLog("warn", "A publication was made indicating an item selection update, but no 'selectedItems' attribute was provided in the payload", payload, this);
}
},
/**
* This is called from the [deferredSelectionHandler]{@link module:alfresco/lists/SelectedItemStateMixin#deferredSelectionHandler}
* function and publishes on the [selectedDocumentsChangeTopic]
* {@link module:alfresco/documentlibrary/_AlfDocumentListTopicMixin#selectedDocumentsChangeTopic}.
*
* @instance
* @fires module:alfresco/documentlibrary/_AlfDocumentListTopicMixin#selectedDocumentsChangeTopic
* @fires module:alfresco/documentlibrary/_AlfDocumentListTopicMixin#documentSelectionTopic
*/
publishSelectedItems: function alfresco_lists_SelectedItemStateMixin__publishSelectedItems() {
this.alfPublish(this.selectedDocumentsChangeTopic, {
selectedItems: this.selectedItems || []
});
this.alfPublish(this.documentSelectionTopic, {
selectedItems: this.selectedItems || []
});
},
/**
* This function can be called to determine whether it is necessary to republish any items that were
* [previously selected]{@link module:alfresco/lists/SelectedItemStateMixin#previouslySelectedItems} before
* item selection was [cleared]{@link module:alfresco/lists/SelectedItemStateMixin#onItemSelectionCleared}.
* The [previously selected]{@link module:alfresco/lists/SelectedItemStateMixin#previouslySelectedItems} are compared
* against the array of items provided and any that were previously selected will be re-published as the
* currently selected items.
*
* @instance
* @param {object[]} items The items to check for the selected items among
* @since 1.0.47
* @fires module:alfresco/documentlibrary/_AlfDocumentListTopicMixin#selectedDocumentsChangeTopic
* @fires module:alfresco/documentlibrary/_AlfDocumentListTopicMixin#documentSelectionTopic
*/
retainPreviousItemSelectionState: function alfresco_lists_SelectedItemStateMixin__retainPreviousItemSelectionState(items) {
var itemsToRepublish = [];
if (this.previouslySelectedItems)
{
array.forEach(items, function(item) {
var itemKey = lang.getObject(this.itemKeyProperty, false, item);
if (itemKey && this.previouslySelectedItems[itemKey])
{
itemsToRepublish.push(item);
this.currentlySelectedItems[itemKey] = item;
}
}, this);
}
if (itemsToRepublish.length)
{
this.alfPublish(this.selectedDocumentsChangeTopic, {
selectedItems: itemsToRepublish
});
this.alfPublish(this.documentSelectionTopic, {
selectedItems: itemsToRepublish
});
}
}
});
});