@openui5/sap.m
Version:
OpenUI5 UI Library sap.m
699 lines (616 loc) • 21.2 kB
JavaScript
/*
* OpenUI5
* (c) Copyright 2009-2023 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
// Provides TablePersoDialog
sap.ui.define([
'./Text',
'./Title',
'./Label',
'./Column',
'./Button',
'./Dialog',
'./ColumnListItem',
'./Table',
'./Toolbar',
'./Bar',
'sap/ui/base/ManagedObject',
'sap/ui/base/ManagedObjectRegistry',
'sap/base/Log',
'sap/base/util/deepExtend',
'sap/m/library',
'sap/ui/Device',
'sap/ui/model/Sorter',
'sap/ui/model/Filter',
'sap/ui/model/FilterOperator',
'sap/ui/model/json/JSONModel',
'sap/m/SearchField',
'sap/ui/core/Configuration',
'sap/ui/core/library'
],
function(
Text,
Title,
Label,
Column,
Button,
Dialog,
ColumnListItem,
Table,
Toolbar,
Bar,
ManagedObject,
ManagedObjectRegistry,
Log,
deepExtend,
library,
Device,
Sorter,
Filter,
FilterOperator,
JSONModel,
SearchField,
Configuration,
coreLibrary
) {
"use strict";
// shortcut for sap.m.ButtonType
var ButtonType = library.ButtonType;
// shortcut for sap.m.ListMode
var ListMode = library.ListMode;
// shortcut for sap.m.WrappingType
var WrappingType = library.WrappingType;
// shortcut for sap.ui.core.TitleLevel
var TitleLevel = coreLibrary.TitleLevel;
/**
* The TablePersoDialog can be used to display and allow modification of personalization settings relating to a Table. It displays the columns of the table that it refers to by using
* <ul><li>The result of calling sap.m.TablePersoProvider's 'getCaption' callback if it is implemented and delivers a non-null value for a column</li>
* <li>the column header control's 'text' property if no caption property is available</li>
* <li>the column header control's 'title' property if neither 'text' nor 'caption' property are available</li>
* <li>the column id is displayed as last fallback, if none of the above is at hand. In that case, a warning is logged. </li></ul>
*
* @deprecated since 1.115. Please use the {@link sap.m.p13n.Popup Popup} for personalization instead.
*
* @param {string}
* [sId] optional id for the new control; generated automatically if
* no non-empty id is given Note: this can be omitted, no matter
* whether <code>mSettings</code> will be given or not!
* @param {object}
* [mSettings] optional map/JSON-object with initial settings for the
* new component instance
* @public
* @class Table Personalization Dialog
* @extends sap.ui.base.ManagedObject
* @author SAP
* @version 1.117.4
* @alias sap.m.TablePersoDialog
*/
var TablePersoDialog = ManagedObject.extend("sap.m.TablePersoDialog", /** @lends sap.m.TablePersoDialog.prototype */
{
constructor : function(sId, mSettings) {
ManagedObject.apply(this, arguments);
},
metadata : {
deprecated: true,
properties: {
"contentWidth": {type: "sap.ui.core.CSSSize"},
"contentHeight": {type: "sap.ui.core.CSSSize", since: "1.22"},
"persoMap": {type: "object"},
"columnInfoCallback": {type: "object", since: "1.22"},
"initialColumnState": {type: "object", since: "1.22"},
"hasGrouping": {type: "boolean", since: "1.22"},
"showSelectAll": {type: "boolean", since: "1.22"},
"showResetAll": {type: "boolean", since: "1.22"}
},
aggregations: {
/**
* Refers to the service for reading and writing the personalization.
* @deprecated Since version 1.30.1
* This aggregate is no longer used. It collided with the TablePersoController's
* persoService reference
*/
"persoService": {
type: "Object",
multiple: false,
deprecated: true
}
},
associations: {
/**
* The table which shall be personalized.
*/
"persoDialogFor": "sap.m.Table"
},
events: {
confirm: {},
cancel: {}
},
library: "sap.m"
}
});
// apply the registry mixin
ManagedObjectRegistry.apply(TablePersoDialog, {
onDuplicate: function(sId, oldDialog, newDialog) {
if ( oldDialog._sapui_candidateForDestroy ) {
Log.debug("destroying dangling template " + oldDialog + " when creating new object with same ID");
oldDialog.destroy();
} else {
var sMsg = "adding TablePersoDialog with duplicate id '" + sId + "'";
// duplicate ID detected => fail or at least log a warning
if (Configuration.getNoDuplicateIds()) {
Log.error(sMsg);
throw new Error("Error: " + sMsg);
} else {
Log.warning(sMsg);
}
}
}
});
/**
* Initializes the TablePersoDialog instance after creation.
*
* @protected
*/
TablePersoDialog.prototype.init = function() {
var that = this,
iLiveChangeTimer = 0;
// Resource bundle, for texts
this._oRb = sap.ui.getCore().getLibraryResourceBundle("sap.m");
// To store the column settings
this._oP13nModel = new JSONModel();
// Make sure that model can contain more than the 100 entries
// it may contain by default.
// SUGGESTED IMPROVEMENT: use number of table columns instead
this._oP13nModel.setSizeLimit(Number.MAX_VALUE);
// Template for list inside the dialog - 1 item per column
this._oColumnItemTemplate = new ColumnListItem(this.getId() + "-cli", {
selected: "{Personalization>visible}",
type: "Active",
cells: [
new Label({
wrapping: true,
wrappingType: WrappingType.Hyphenated,
text: "{Personalization>text}"
})
],
press: function(oEvt){
this._oSelectedItem = oEvt.oSource;
this._fnUpdateArrowButtons.call(this);
}.bind(this)
}).addStyleClass("sapMPersoDialogLI");
// Button definition for sorting of the table content(up/down)
this._oButtonUp = new Button(this.getId() + "-buttonUp", {
icon: "sap-icon://navigation-up-arrow",
enabled: false,
tooltip: that._oRb.getText('PERSODIALOG_UP'),
press: function() {
that._moveItem(-1);
}
});
this._oButtonDown = new Button(this.getId() + "-buttonDown",{
icon: "sap-icon://navigation-down-arrow",
enabled: false,
tooltip: that._oRb.getText('PERSODIALOG_DOWN'),
press: function() {
that._moveItem(1);
}
});
this._fnUpdateArrowButtons = function() {
if (this.getHasGrouping()) {
return;
}
// Initialisation of the enabled property
var aFields = this._oInnerTable.getModel("Personalization").getProperty("/aColumns");
var bButtonUpEnabled,bButtonDownEnabled;
if (!this._oSelectedItem || this._oInnerTable.getItems().length == 0){
//no item yet selected
bButtonUpEnabled = false;
bButtonDownEnabled = false;
this._oSelectedItem = null;
} else {
var iItemIndex = aFields.indexOf(this._oSelectedItem.getBindingContext("Personalization").getObject());
bButtonUpEnabled = iItemIndex > 0 ? true : false;
bButtonDownEnabled = iItemIndex < aFields.length - 1 ? true : false;
}
this._updateMarkedItem();
that._oButtonUp.setEnabled(bButtonUpEnabled);
that._oButtonDown.setEnabled(bButtonDownEnabled);
}.bind(this);
this._fnAfterDialogOpen = function () {
// Make sure that arrow buttons are updated when dialog is opened
that._fnUpdateArrowButtons.call(that);
};
this._oInnerTable = new Table(this.getId() + "-colTable",{
noDataText: this._oRb.getText('PERSODIALOG_NO_DATA'),
mode: ListMode.MultiSelect,
width: "100%",
sticky: ["ColumnHeaders"],
columns: [
new Column({
header: new Text({
text: this._oRb.getText("PERSODIALOG_SELECT_ALL")
})
})
]
});
this._oSearchField = new SearchField(this.getId() + "-searchField", {
width: "100%",
liveChange: function (oEvent) {
var sValue = oEvent.getSource().getValue(),
iDelay = (sValue ? 300 : 0); // No delay if value is empty
// Execute search after user stops typing for 300ms
clearTimeout(iLiveChangeTimer);
if (iDelay) {
iLiveChangeTimer = setTimeout(function () {
that._executeSearch();
}, iDelay);
} else {
that._executeSearch();
}
},
// Execute the standard search
search: function () {
that._executeSearch();
}
});
this._resetAllButton = new Button(this.getId() + "-buttonUndo", {
text: this._oRb.getText("VIEWSETTINGS_RESET"),
press : function () {
this._resetAll();
}.bind(this)
}).addStyleClass("sapMPersoDialogResetBtn");
var oHeader = new Bar({
contentLeft:
new Title(this.getId() + "-Dialog-title",{
text: this._oRb.getText("PERSODIALOG_COLUMNS_TITLE"),
level: TitleLevel.H1
}),
contentRight: this._resetAllButton
});
var oSubHeader = new Toolbar(this.getId() + "-toolbar", {
//makes sure that toolbar itself is not clickable and removed from tab chain
active : false,
content: [ this._oSearchField, this._oButtonUp, this._oButtonDown ]
});
this._oDialog = new Dialog(this.getId() + "-Dialog", {
title: this._oRb.getText("PERSODIALOG_COLUMNS_TITLE"),
customHeader: oHeader,
draggable: true,
resizable: true,
stretch: Device.system.phone,
horizontalScrolling: false,
verticalScrolling: true,
initialFocus: (Device.system.desktop ? this._oInnerTable : null),
content : [this._oInnerTable ],
subHeader : oSubHeader,
beginButton : new Button(this.getId() + "-buttonOk", {
text : this._oRb.getText("PERSODIALOG_OK"),
press : function () {
that._oDialog.close();
that._oSelectedItem = null;
that._oSearchField.setValue("");
that.fireConfirm();
},
type : ButtonType.Emphasized
}),
endButton : new Button(this.getId() + "-buttonCancel", {
text: this._oRb.getText("PERSODIALOG_CANCEL"),
press: function () {
that._oDialog.close();
that._oSelectedItem = null;
that._oSearchField.setValue("");
that.fireCancel();
}
}),
afterOpen: this._fnAfterDialogOpen
}).addStyleClass("sapMPersoDialog");
this._oDialog.setTitle = function(sTitle) {
this.setProperty("title", sTitle);
this.getCustomHeader().getContentLeft()[0].setText(sTitle);
};
};
TablePersoDialog.prototype._updateMarkedItem = function(){
if (!this._oSelectedItem) {
this._oSelectedItem = this._oInnerTable && this._oInnerTable.getItems().length > 0 ? this._oInnerTable.getItems()[0] : null;
}
if (this._oSelectedItem){
this._oInnerTable.getItems().forEach(function(oItem){
if (oItem.hasStyleClass("sapMPersoDialogItemSelected")){
oItem.removeStyleClass("sapMPersoDialogItemSelected");
}
});
this._oSelectedItem.addStyleClass("sapMPersoDialogItemSelected");
}
};
/**
* Returns the personalizations made. Currently supports
* a 'columns' property which holds an array of settings,
* one element per column in the associated table. The element
* contains column-specific information as follows: id: column id;
* order: new order; text: the column's header text that was displayed
* in the dialog; visible: visibility (true or false).
*
* @return {object} the personalization data
* @public
*/
TablePersoDialog.prototype.retrievePersonalizations = function () {
return this._oP13nModel.getData();
};
/**
* Sets the content of the dialog, being list items representing
* the associated table's column settings, and opens the dialog
* @public
*/
TablePersoDialog.prototype.open = function () {
var aSorter = null;
if (this.getHasGrouping()) {
aSorter = [new Sorter('group', false, true)];
}
// Get the associated Table's column info and set it into the Personalization model
this._readCurrentSettingsFromTable();
// SUGGESTED IMPROVEMENT: Move the following code block into
// 'init' method. Seems like it is not necessary to call setModel
// and 'bindAggregation' over and over angain, when the dialog is
// opened.
this._oDialog.setModel(this._oP13nModel, "Personalization");
this._oInnerTable.bindAggregation("items", {
path: "Personalization>/aColumns",
key: "text",
sorter: aSorter,
template: this._oColumnItemTemplate
});
// SUGGESTED IMPROVEMENT: until here
if (!this._oInnerTable.getSelectedItem()) {
// Make sure initial selection is set
var aItems = this._oInnerTable.getItems();
if (this.getHasGrouping()) {
aItems = aItems.filter(function (oItem){
return oItem.getMetadata().getName() != "sap.m.GroupHeaderListItem";
});
}
if (aItems.length > 0) {
this._sLastSelectedItemId = aItems[0].getBindingContext('Personalization').getProperty('id');
}
}
// Update 'Move' button's state
this._fnUpdateArrowButtons.call(this);
// Now show the dialog
this._oDialog.open();
};
TablePersoDialog.prototype.setContentHeight = function(sHeight) {
sHeight = sHeight ? sHeight : "28rem";
this.setProperty("contentHeight", sHeight, true);
this._oDialog.setContentHeight(sHeight);
return this;
};
TablePersoDialog.prototype.setContentWidth = function(sWidth) {
sWidth = sWidth ? sWidth : "25rem";
this.setProperty("contentWidth", sWidth, true);
this._oDialog.setContentWidth(sWidth);
return this;
};
/**
* Destroys the control
* @private
*/
TablePersoDialog.prototype.exit = function () {
this._oRb = null;
this._oP13nModel = null;
this._oSelectedItem = null;
if (this._oColumnItemTemplate) {
this._oColumnItemTemplate.destroy();
this._oColumnItemTemplate = null;
}
if (this._oInnerTable) {
this._oInnerTable.destroy();
this._oInnerTable = null;
}
if (this._oSearchField) {
this._oSearchField.destroy();
this._oSearchField = null;
}
if (this._oDialog) {
this._oDialog.destroy();
this._oDialog = null;
}
if (this._oButtonDown) {
this._oButtonDown.destroy();
this._oButtonDown = null;
}
if (this._oButtonUp) {
this._oButtonUp.destroy();
this._oButtonUp = null;
}
};
/* =========================================================== */
/* begin: internal methods */
/* =========================================================== */
/**
* Turn column visibility and order back to initial state (state before table
* was personalized)
* @private
*/
TablePersoDialog.prototype._resetAll = function () {
if (this.getInitialColumnState()) {
// Deep copy of Initial Data, otherwise initial data will be changed
// and can only be used once to restore the initial state
var aInitialStateCopy = deepExtend([], this.getInitialColumnState()),
that = this;
// CSN 0120031469 0000184938 2014
// Remember last selected row, so it can be selected again after
// reset all is done
var oLastSelectedItem = this._oInnerTable.getSelectedItem();
this._sLastSelectedItemId = oLastSelectedItem &&
oLastSelectedItem.getBindingContext('Personalization') &&
oLastSelectedItem.getBindingContext('Personalization').getProperty('id');
// CSN 0120061532 0001380609 2014
// Make sure that captions are not replaced by column id's. This my be the case if
// initalStateCopy has been created too early
if (this._mColumnCaptions) {
aInitialStateCopy.forEach(
function(oColumn) {
oColumn.text = that._mColumnCaptions[oColumn.id];
});
}
this._oP13nModel.getData().aColumns = aInitialStateCopy;
this._oP13nModel.updateBindings();
//Make sure that list is rerendered so that _fnListUpdateFinished is called
//and list items are rendered correctly
sap.ui.getCore().applyChanges();
}
};
/**
* Moves an item up or down, swapping it with the neighbour.
* Does this in the bound model.
* @private
* @param {int} iDirection the move direction (-1 up, 1 down)
*/
TablePersoDialog.prototype._moveItem = function (iDirection) {
var oSelectedItem = this._oSelectedItem;
if (!oSelectedItem) {
return;
}
var aItems = this._oInnerTable.getItems();
var aFields = this._oInnerTable.getModel("Personalization").getProperty("/aColumns");
// index of the item in the model not the index in the aggregation
var iOldIndex = aFields.indexOf(oSelectedItem.getBindingContext("Personalization").getObject());
// limit the minumum and maximum index
var iNewIndex = iOldIndex + iDirection;
// new index of the item in the model
iNewIndex = aFields.indexOf(aItems[iNewIndex].getBindingContext("Personalization").getObject());
if (iNewIndex == iOldIndex) {
return;
}
// remove data from old position and insert it into new position
aFields.splice(iNewIndex, 0, aFields.splice(iOldIndex, 1)[0]);
aFields.forEach(function(oItem, iIndex){
oItem.order = iIndex;
});
this._oInnerTable.getModel("Personalization").setProperty("/aColumns", aFields);
// store the moved item again due to binding
this._oSelectedItem = aItems[iNewIndex];
this._scrollToItem(this._oSelectedItem);
this._fnUpdateArrowButtons.call(this);
if (this._oButtonDown.getEnabled() || this._oButtonUp.getEnabled()) {
if (!this._oButtonDown.getEnabled()) {
setTimeout(function() { // when button was disable, we need a timeout before setting the focus
this._oButtonUp && this._oButtonUp.focus();
}.bind(this), 0);
}
if (!this._oButtonUp.getEnabled()) {
setTimeout(function() { // when button was disable, we need a timeout before setting the focus
this._oButtonDown && this._oButtonDown.focus();
}.bind(this), 0);
}
} else {
this._oSearchField.focus();
}
};
/**
* Scrolls the inner Table based to the passed item and the relative viewport.
*
* @private
* @param {object} oItem the item which should be scrolled to
*/
TablePersoDialog.prototype._scrollToItem = function(oItem){
//update DOM refs for height calculations
sap.ui.getCore().applyChanges();
//check if there is an item
if (oItem.getDomRef()) {
var iNewIndex = this._oInnerTable.getItems().indexOf(oItem);
var oItemDOMRect = oItem.getDomRef().getBoundingClientRect();
var oDialogContainerRect = this._oDialog.getDomRef("cont").getBoundingClientRect();
var iVPStart = oDialogContainerRect.top;
var iVPEnd = oDialogContainerRect.bottom;
var iElementOffset = oItemDOMRect.top;
if (iElementOffset < iVPStart + 18) {
this._oInnerTable.scrollToIndex(iNewIndex);
} else if (iElementOffset > iVPEnd - 18) {
this._oInnerTable.scrollToIndex(iNewIndex);
}
}
};
/**
* Reads current column settings from the table and stores in the model
* @private
*/
TablePersoDialog.prototype._readCurrentSettingsFromTable = function() {
var oTable = sap.ui.getCore().byId(this.getPersoDialogFor()),
that = this,
aCurrentColumns = this.getColumnInfoCallback().call(this, oTable, this.getPersoMap());
this._oP13nModel.setData({
aColumns : aCurrentColumns
});
// Remember column captions, needed for 'Reset All'
// This is a workaround to fix an issue with unavailable column texts
// after executing 'resetAll' (see 'resetAll' and CSN 0120061532 0001380609 2014)
this._mColumnCaptions = {};
aCurrentColumns.forEach(
function(oColumn) {
that._mColumnCaptions[oColumn.id] = oColumn.text;
});
};
/**
* Filters the columns list with the given value
* @return {sap.m.TablePersoDialog} the tablePersoDialog instance.
* @private
*/
TablePersoDialog.prototype._executeSearch = function () {
var sValue = this._oSearchField.getValue(),
oFilter = new Filter("text", FilterOperator.Contains, sValue),
oBinding = this._oInnerTable.getBinding("items");
oBinding.filter([oFilter]);
this._fnUpdateArrowButtons.call(this);
return this;
};
/**
* Setter to turn on/ switch off TablePersoDialog's grouping mode.
* @param {boolean} bHasGrouping groping mode on or off.
* @returns {this} the TablePersoDialog instance.
* @public
*/
TablePersoDialog.prototype.setHasGrouping = function (bHasGrouping) {
this.setProperty("hasGrouping", bHasGrouping, true);
var oBar = this._oDialog.getSubHeader();
if (!bHasGrouping) {
if (oBar.getContent().length === 1) {
// Only search field is displayed, add up- and down
// buttons
oBar.addContent(this._oButtonDown);
oBar.addContent(this._oButtonUp);
}
} else {
oBar.removeContent(this._oButtonUp);
oBar.removeContent(this._oButtonDown);
}
return this;
};
/**
* Setter to show/hide TablePersoDialog's 'selectAll' checkbox.
* @param {boolean} bShowSelectAll selectAll checkbox visible or not.
* @returns {this} the TablePersoDialog instance.
* @public
*/
TablePersoDialog.prototype.setShowSelectAll = function (bShowSelectAll) {
this.setProperty("showSelectAll", bShowSelectAll, true);
var sText = bShowSelectAll ? this._oRb.getText("PERSODIALOG_SELECT_ALL") : this._oRb.getText("PERSODIALOG_COLUMNS_TITLE");
this._oInnerTable.getColumns()[0].setHeader(new Text({
text: sText
}));
this._oInnerTable.bPreventMassSelection = !bShowSelectAll;
return this;
};
/**
* Setter to show/hide TablePersoDialog's 'Undo Personalization' button.
* @param {boolean} bShowResetAll 'undo Personalization' button visible or not.
* @returns {this} the TablePersoDialog instance.
* @public
*/
TablePersoDialog.prototype.setShowResetAll = function (bShowResetAll) {
this.setProperty("showResetAll", bShowResetAll, true);
this._resetAllButton.setVisible(bShowResetAll);
return this;
};
return TablePersoDialog;
});