UNPKG

@openui5/sap.m

Version:

OpenUI5 UI Library sap.m

1,367 lines (1,250 loc) 125 kB
/*! * OpenUI5 * (c) Copyright 2009-2023 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ sap.ui.define([ "./library", "sap/m/library", "sap/m/MessageBox", "sap/m/Dialog", "sap/ui/core/Control", "sap/ui/core/Icon", "sap/ui/core/IconPool", "sap/m/Image", "sap/m/Text", "sap/m/Title", "sap/m/Button", "sap/m/List", "sap/m/BusyIndicator", "sap/m/StandardListItem", "sap/ui/unified/FileUploaderParameter", "sap/ui/unified/FileUploader", "sap/ui/core/format/FileSizeFormat", "sap/m/OverflowToolbar", "sap/m/ToolbarSpacer", "sap/m/ObjectAttribute", "sap/m/UploadCollectionItem", "sap/m/UploadCollectionParameter", "sap/m/UploadCollectionToolbarPlaceholder", "sap/ui/core/HTML", "sap/ui/core/InvisibleText", "sap/m/CustomListItem", "sap/ui/core/ResizeHandler", "sap/ui/Device", "./UploadCollectionRenderer", "sap/ui/thirdparty/jquery", "sap/ui/events/KeyCodes", "sap/base/Log", "sap/ui/core/Configuration", "sap/ui/dom/jquery/selectText" // jQuery Plugin "selectText" ], function( Library, MobileLibrary, MessageBox, Dialog, Control, Icon, IconPool, Image, Text, Title, Button, List, BusyIndicator, StandardListItem, FileUploaderParameter, FileUploader, FileSizeFormat, OverflowToolbar, ToolbarSpacer, ObjectAttribute, UploadCollectionItem, UploadCollectionParameter, UploadCollectionToolbarPlaceholder, HTML, InvisibleText, CustomListItem, ResizeHandler, Device, UploadCollectionRenderer, jQuery, KeyCodes, Log, Configuration ) { "use strict"; /** * Constructor for a new UploadCollection. * * @param {string} [sId] id for the new control, generated automatically if no id is given * @param {object} [mSettings] initial settings for the new control * * @class * This control allows you to upload single or multiple files from your devices (desktop, tablet or phone) and attach them to the application. * * The consuming application needs to take into account that the consistency checks of the model during the upload of the file need to be performed, for example, if the user is editing or deleting a file. * <br> As of version 1.63, there is an {@link sap.m.upload.UploadSet} control available that is based on this control. * {@link sap.m.upload.UploadSet} provides enhanced handling of headers and requests, unified behavior of instant * and deferred uploads, as well as improved progress indication. * @extends sap.ui.core.Control * * @author SAP SE * @version 1.117.4 * * @constructor * @public * @deprecated as of version 1.88, replaced by {@link sap.m.upload.UploadSet} * @alias sap.m.UploadCollection */ var UploadCollection = Control.extend("sap.m.UploadCollection", /** @lends sap.m.UploadCollection.prototype */ { constructor: function(sId, mSettings) { // Delete 'instantUpload' before calling the super constructor to avoid unwanted error logs var bInstantUpload; if (mSettings && mSettings.instantUpload !== undefined ) { if (mSettings.instantUpload === false){ bInstantUpload = mSettings.instantUpload; } delete mSettings.instantUpload; } else if (sId && sId.instantUpload !== undefined ) { if (sId.instantUpload === false){ bInstantUpload = sId.instantUpload; } delete sId.instantUpload; } if (mSettings && mSettings.mode === Library.ListMode.MultiSelect && bInstantUpload === false) { mSettings.mode = Library.ListMode.None; Log.info("sap.m.ListMode.MultiSelect is not supported by UploadCollection for Upload Pending scenario. Value has been resetted to 'None'"); } else if (sId && sId.mode === Library.ListMode.MultiSelect && bInstantUpload === false) { sId.mode = Library.ListMode.None; Log.info("sap.m.ListMode.MultiSelect is not supported by UploadCollection for Upload Pending scenario. Value has been resetted to 'None'"); } try { Control.apply(this, arguments); if (bInstantUpload === false) { this.bInstantUpload = bInstantUpload; this._oFormatDecimal = FileSizeFormat.getInstance({ binaryFilesize: false, maxFractionDigits: 1, maxIntegerDigits: 4 }); } } catch (e) { this.destroy(); throw e; } }, metadata: { library: "sap.m", properties: { /** * Defines the allowed file types for the upload. * The chosen files will be checked against an array of file types. * If at least one file does not fit the file type requirements, the upload is prevented. Example: ["jpg", "png", "bmp"]. */ fileType: {type: "string[]", group: "Data", defaultValue: null}, /** * Specifies the maximum length of a file name. * If the maximum file name length is exceeded, the corresponding event 'filenameLengthExceed' is triggered. */ maximumFilenameLength: {type: "int", group: "Data", defaultValue: null}, /** * Specifies a file size limit in megabytes that prevents the upload if at least one file exceeds the limit. * This property is not supported by Internet Explorer 8 and 9. */ maximumFileSize: {type: "float", group: "Data", defaultValue: null}, /** * Defines the allowed MIME types of files to be uploaded. * The chosen files will be checked against an array of MIME types. * If at least one file does not fit the MIME type requirements, the upload is prevented. * This property is not supported by Internet Explorer 8 and 9. Example: mimeType ["image/png", "image/jpeg"]. */ mimeType: {type: "string[]", group: "Data", defaultValue: null}, /** * Lets the user select multiple files from the same folder and then upload them. * Internet Explorer 8 and 9 do not support this property. * Please note that the various operating systems for mobile devices can react differently to the property so that fewer upload functions may be available in some cases. * * If multiple property is set to false, the control shows an error message if more than one file is chosen for drag & drop. */ multiple: {type: "boolean", group: "Behavior", defaultValue: false}, /** * Allows you to set your own text for the 'No data' text label. */ noDataText: {type: "string", group: "Appearance", defaultValue: null}, /** * Allows you to set your own text for the 'No data' description label. * @since 1.46.0 */ noDataDescription: {type: "string", group: "Appearance", defaultValue: null}, /** * Allows the user to use the same name for a file when editing the file name. 'Same name' refers to an already existing file name in the list. */ sameFilenameAllowed: {type: "boolean", group: "Behavior", defaultValue: false}, /** * Defines whether separators are shown between list items. */ showSeparators: { type: "sap.m.ListSeparators", group: "Appearance", defaultValue: "All" }, /** * Enables the upload of a file. * If property instantUpload is false it is not allowed to change uploadEnabled at runtime. */ uploadEnabled: {type: "boolean", group: "Behavior", defaultValue: true}, /** * Specifies the URL where the uploaded files have to be stored. */ uploadUrl: {type: "string", group: "Data", defaultValue: "../../../upload"}, /** * If false, no upload is triggered when a file is selected. In addition, if a file was selected, a new FileUploader instance is created to ensure that multiple files can be chosen. * @since 1.30.0 */ instantUpload: {type: "boolean", group: "Behavior", defaultValue: true}, /** * Sets the title text in the toolbar of the list of attachments. * To show as well the number of attachments in brackets like the default text does. The number of attachments could be retrieved via "getItems().length". * If a new title is set, the default is deactivated. * The default value is set to language-dependent "Attachments (n)". * @since 1.30.0 */ numberOfAttachmentsText: {type: "string", group: "Appearance", defaultValue: null}, /** * Defines the selection mode of the control (e.g. None, SingleSelect, MultiSelect, SingleSelectLeft, SingleSelectMaster). * Since the UploadCollection reacts like a list for attachments, the API is close to the ListBase Interface. * sap.m.ListMode.Delete mode is not supported and will be automatically set to sap.m.ListMode.None. * In addition, if instant upload is set to false the mode sap.m.ListMode.MultiSelect is not supported and will be automatically set to sap.m.ListMode.None. * * @since 1.34.0 */ mode: {type: "sap.m.ListMode", group: "Behavior", defaultValue: "None"}, /** * If true, the button used for uploading files is invisible. * @since 1.42.0 */ uploadButtonInvisible: {type: "boolean", group: "Appearance", defaultValue: false}, /** * If true, the button that is used to terminate the instant file upload gets visible. * The button normally appears when a file is being uploaded. * @since 1.42.0 */ terminationEnabled: {type: "boolean", group: "Behavior", defaultValue: true} }, defaultAggregation: "items", aggregations: { /** * Uploaded items. */ items: { type: "sap.m.UploadCollectionItem", multiple: true, singularName: "item", bindable: "bindable" }, /** * Specifies the header parameters for the FileUploader that are submitted only with XHR requests. * Header parameters are not supported by Internet Explorer 8 and 9. */ headerParameters: { type: "sap.m.UploadCollectionParameter", multiple: true, singularName: "headerParameter" }, /** * Specifies the parameters for the FileUploader that are rendered as a hidden input field. */ parameters: {type: "sap.m.UploadCollectionParameter", multiple: true, singularName: "parameter"}, /** * Specifies the toolbar. * @since 1.34.0 */ toolbar: {type: "sap.m.OverflowToolbar", multiple: false}, /** * Specifies the info toolbar for filtering information. Sorting information will not displayed. * @since 1.44.0 */ infoToolbar: {type: "sap.m.Toolbar", multiple: false, forwarding: {idSuffix: "-list", aggregation: "infoToolbar"}}, /** * Internal aggregation to hold the list in controls tree. * @since 1.34.0 */ _list: { type: "sap.m.List", multiple: false, visibility: "hidden" }, /** * The icon is displayed in no data page * @since 1.46.0 */ _noDataIcon: { type: "sap.ui.core.Icon", multiple: false, visibility: "hidden" }, /** * Internal aggregation to hold the drag and drop icon of indicator. * @since 1.46.0 */ _dragDropIcon: { type: "sap.ui.core.Icon", multiple: false, visibility: "hidden" }, /** * Internal aggregation to hold the drag and drop text of indicator. * @since 1.46.0 */ _dragDropText: { type: "sap.m.Text", multiple: false, visibility: "hidden" } }, events: { /** * The event is triggered when files are selected in the FileUploader dialog. Applications can set parameters and headerParameters which will be dispatched to the embedded FileUploader control. * Restriction: parameters and headerParameters are not supported by Internet Explorer 9. */ change: { parameters: { /** * A unique Id of the attached document. * This parameter is deprecated since 1.28.0. Use the <code>files</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>files</code> parameter instead. */ documentId: {type: "string"}, /** * A FileList of individually selected files from the underlying system. See www.w3.org for the FileList Interface definition. * Restriction: Internet Explorer 9 supports only single file with property file.name. * Since version 1.28.0. * @since 1.28.0 */ files: {type: "object[]"} } }, /** * The event is triggered when an uploaded attachment is selected and the Delete button is pressed. */ fileDeleted: { parameters: { /** * A unique Id of the attached document. * This parameter is deprecated since 1.28.0. Use the <code>item</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>item</code> parameter instead. */ documentId: {type: "string"}, /** * An item to be deleted from the collection. * Since version 1.28.0. * @since 1.28.0 */ item: {type: "sap.m.UploadCollectionItem"} } }, /** * The event is triggered when the name of a chosen file is longer than the value specified with the maximumFilenameLength property (only if provided by the application). */ filenameLengthExceed: { parameters: { /** * A unique Id of the attached document. * This parameter is deprecated since 1.28.0. Use the <code>files</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>files</code> parameter instead. */ documentId: {type: "string"}, /** * A FileList of individually selected files from the underlying system. * Restriction: Internet Explorer 9 supports only single file with property file.name. * Since version 1.28.0. * @since 1.28.0 */ files: {type: "object[]"} } }, /** * The event is triggered when the file name is changed. */ fileRenamed: { parameters: { /** * A unique Id of the attached document. * This parameter is deprecated since 1.28.0. Use the <code>item</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>item</code> parameter instead. */ documentId: {type: "string"}, /** * The new file name. * This parameter is deprecated since 1.28.0. Use the <code>item</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>item</code> parameter instead. */ fileName: {type: "string"}, /** * The renamed UI element as an UploadCollectionItem. * Since 1.28.0. * @since 1.28.0 */ item: {type: "sap.m.UploadCollectionItem"} } }, /** * The event is triggered when the file size of an uploaded file is exceeded (only if the maxFileSize property was provided by the application). * This event is not supported by Internet Explorer 9. */ fileSizeExceed: { parameters: { /** * A unique Id of the attached document. * This parameter is deprecated since 1.28.0. Use the <code>files</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>files</code> parameter instead. */ documentId: {type: "string"}, /** * The size in MB of a file to be uploaded. * This parameter is deprecated since 1.28.0. Use the <code>files</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>files</code> parameter instead. */ fileSize: {type: "string"}, /** * A FileList of individually selected files from the underlying system. * Restriction: Internet Explorer 9 supports only single file with property file.name. * Since 1.28.0. * @since 1.28.0 */ files: {type: "object[]"} } }, /** * The event is triggered when the file type or the MIME type don't match the permitted types (only if the fileType property or the mimeType property are provided by the application). */ typeMissmatch: { parameters: { /** * A unique Id of the attached document. * This parameter is deprecated since 1.28.0. Use the <code>files</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>files</code> parameter instead. */ documentId: {type: "string"}, /** * File type. * This parameter is deprecated since 1.28.0. Use the <code>files</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>files</code> parameter instead. */ fileType: {type: "string"}, /** * MIME type. * This parameter is deprecated since 1.28.0. Use the <code>files</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>files</code> parameter instead. */ mimeType: {type: "string"}, /** * A FileList of individually selected files from the underlying system. * Restriction: Internet Explorer 9 supports only single file. * Since 1.28.0. * @since 1.28.0 */ files: {type: "object[]"} } }, /** * The event is triggered as soon as the upload request is completed. */ uploadComplete: { parameters: { /** * Ready state XHR. * This parameter is deprecated since 1.28.0. Use the <code>files</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>files</code> parameter instead. */ readyStateXHR: {type: "string"}, /** * Response of the completed upload request. * This parameter is deprecated since 1.28.0. Use the <code>files</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>files</code> parameter instead. */ response: {type: "string"}, /** * Status Code of the completed upload event. * This parameter is deprecated since 1.28.0. Use the <code>files</code> parameter instead. * @deprecated Since 1.28.0. Use the <code>files</code> parameter instead. */ status: {type: "string"}, /** * A list of uploaded files. Each entry contains the following members. * fileName : The name of a file to be uploaded. * response : Response message which comes from the server. On the server side, this response has to be put within the 'body' tags of the response document of the iFrame. It can consist of a return code and an optional message. This does not work in cross-domain scenarios. * reponse : deprecated Since version 1.48.0. This parameter is deprecated, use parameter response instead. * responseRaw : HTTP-Response which comes from the server. This property is not supported by Internet Explorer Versions lower than 9. * status : Status of the XHR request. This property is not supported by Internet Explorer 9 and lower. * headers : HTTP-Response-Headers which come from the server. Provided as a JSON-map, i.e. each header-field is reflected by a property in the header-object, with the property value reflecting the header-field's content. This property is not supported by Internet Explorer 9 and lower. * Since 1.28.0. * @since 1.28.0 */ files: {type: "object[]"} } }, /** * The event is triggered as soon as the upload request was terminated by the user. */ uploadTerminated: { parameters: { /** * Specifies the name of the file of which the upload is to be terminated. */ fileName: {type: "string"}, /** * A function that returns the corresponding header parameter (type <code>sap.m.UploadCollectionParameter</code>) if available. * The function accepts one optional parameter of type <code>string</code>, which is the name of the header parameter. If no parameter is provided all header parameters are returned. */ getHeaderParameter: { type: "function" } } }, /** * The event is triggered before the actual upload starts. An event is fired per file. All the necessary header parameters should be set here. */ beforeUploadStarts: { parameters: { /** * Specifies the name of the file to be uploaded. */ fileName: {type: "string"}, /** * A function that adds a header parameter to the file that will be uploaded. * The function accepts one parameter of type <code>sap.m.UploadCollectionParameter</code> which specifies the header parameter that will be added. */ addHeaderParameter: { type: "function" }, /** * A function that returns the corresponding header parameter (type <code>sap.m.UploadCollectionParameter</code>) if available. * The function accepts one optional parameter of type <code>string</code>, which is the name of the header parameter. If no parameter is provided all header parameters are returned. */ getHeaderParameter: { type: "function" } } }, /** * Fires when selection is changed via user interaction inside the control. * @since 1.36.0 */ selectionChange: { parameters: { /** * The item whose selection has changed. In <code>MultiSelect</code> mode, only the topmost selected item is returned. This parameter can be used for single-selection modes. */ selectedItem: {type: "sap.m.UploadCollectionItem"}, /** * Array of items whose selection has changed. This parameter can be used for <code>MultiSelect</code> mode. */ selectedItems: {type: "sap.m.UploadCollectionItem[]"}, /** * Indicates whether the <code>listItem</code> parameter is selected or not. */ selected: {type: "boolean"} } } } }, renderer: UploadCollectionRenderer }); UploadCollection._uploadingStatus = "uploading"; UploadCollection._displayStatus = "display"; UploadCollection._toBeDeletedStatus = "toBeDeleted"; UploadCollection._pendingUploadStatus = "pendingUploadStatus"; // UploadCollectionItem has this status only if UploadCollection is used with the property 'instantUpload' = false UploadCollection._placeholderCamera = "sap-icon://card"; UploadCollection._markerMargin = 8; // the left margin for each marker in px if (Device.system.phone) { UploadCollection._resizeTimeoutInterval = 500; // the time interval after the resize is applied for phones (in msec) } else { UploadCollection._resizeTimeoutInterval = 100; // the time interval after the resize is applied for other devices (in msec) } UploadCollection.prototype.init = function() { UploadCollection.prototype._oRb = sap.ui.getCore().getLibraryResourceBundle("sap.m"); this._headerParamConst = { requestIdName: "requestId" + jQuery.now(), fileNameRequestIdName: "fileNameRequestId" + jQuery.now(), acceptLanguage: "accept-language" }; this._requestIdValue = 0; this._iFUCounter = 0; // it is necessary to count FileUploader instances in case of 'instantUpload' = false var sNoDataTextDescription = this.getNoDataText() + " " + this.getNoDataDescription(); this._oList = new List(this.getId() + "-list", { selectionChange: [this._handleSelectionChange, this], noDataText:sNoDataTextDescription }); this.setAggregation("_list", this._oList, true); this._oList.addStyleClass("sapMUCList"); this.setAggregation("_noDataIcon", new Icon(this.getId() + "-no-data-icon", { src: "sap-icon://document", size: "6rem", noTabStop: true }), true); this.setAggregation("_dragDropIcon", new Icon(this.getId() + "-drag-drop-icon", { src: "sap-icon://upload-to-cloud", size: "4rem", noTabStop: true }), true); this.setAggregation("_dragDropText", new Text(this.getId() + "-drag-drop-text", { text: this._oRb.getText("UPLOADCOLLECTION_DRAG_FILE_INDICATOR") }), true); this._iUploadStartCallCounter = 0; this.aItems = []; this._aDeletedItemForPendingUpload = []; this._aFileUploadersForPendingUpload = []; this._aFilesFromDragAndDropForPendingUpload = []; this._iFileUploaderPH = null; // Index of the place holder for the File Uploader this._oListEventDelegate = null; this._oItemToUpdate = null; this._sReziseHandlerId = null; this.oInvisibleText = new InvisibleText().toStatic(); }; /* =========================================================== */ /* Redefinition of setter and getter methods */ /* =========================================================== */ UploadCollection.prototype.setFileType = function(aFileTypes) { if (!aFileTypes) { return this; } if (!this.getInstantUpload()) { Log.info("As property instantUpload is false it is not allowed to change fileType at runtime."); } else { var cLength = aFileTypes.length; for (var i = 0; i < cLength; i++) { aFileTypes[i] = aFileTypes[i].toLowerCase(); } if (this.getFileType() !== aFileTypes) { this.setProperty("fileType", aFileTypes, true); this._getFileUploader().setFileType(aFileTypes); } } return this; }; UploadCollection.prototype.setMaximumFilenameLength = function(iMaximumFilenameLength) { if (!this.getInstantUpload()) { Log.info("As property instantUpload is false it is not allowed to change maximumFilenameLength at runtime."); } else if (this.getMaximumFilenameLength() !== iMaximumFilenameLength) { this.setProperty("maximumFilenameLength", iMaximumFilenameLength, true); this._getFileUploader().setMaximumFilenameLength(iMaximumFilenameLength); } return this; }; UploadCollection.prototype.setMaximumFileSize = function(iMaximumFileSize) { if (!this.getInstantUpload()) { Log.info("As property instantUpload is false it is not allowed to change maximumFileSize at runtime."); } else if (this.getMaximumFileSize() !== iMaximumFileSize) { this.setProperty("maximumFileSize", iMaximumFileSize, true); this._getFileUploader().setMaximumFileSize(iMaximumFileSize); } return this; }; UploadCollection.prototype.setMimeType = function(aMimeTypes) { if (!this.getInstantUpload()) { Log.info("As property instantUpload is false it is not allowed to change mimeType at runtime."); } else if (this.getMimeType() !== aMimeTypes) { this.setProperty("mimeType", aMimeTypes, true); this._getFileUploader().setMimeType(aMimeTypes); } return this; }; UploadCollection.prototype.setMultiple = function(bMultiple) { if (!this.getInstantUpload()) { Log.info("As property instantUpload is false it is not allowed to change multiple at runtime."); } else if (this.getMultiple() !== bMultiple) { this.setProperty("multiple", bMultiple); this._getFileUploader().setMultiple(bMultiple); } return this; }; UploadCollection.prototype.setShowSeparators = function(bShowSeparators) { if (this.getShowSeparators() !== bShowSeparators) { this.setProperty("showSeparators", bShowSeparators); this._oList.setShowSeparators(bShowSeparators); } return this; }; UploadCollection.prototype.setUploadEnabled = function(bUploadEnabled) { if (!this.getInstantUpload()) { Log.info("As property instantUpload is false it is not allowed to change uploadEnabled at runtime."); } else if (this.getUploadEnabled() !== bUploadEnabled) { this.setProperty("uploadEnabled", bUploadEnabled); this._getFileUploader().setEnabled(bUploadEnabled); } return this; }; UploadCollection.prototype.setUploadUrl = function(sUploadUrl) { if (!this.getInstantUpload()) { Log.info("As property instantUpload is false it is not allowed to change uploadUrl at runtime."); } else if (this.getUploadUrl() !== sUploadUrl) { this.setProperty("uploadUrl", sUploadUrl); this._getFileUploader().setUploadUrl(sUploadUrl); } return this; }; UploadCollection.prototype.setInstantUpload = function() { Log.error("It is not supported to change the behavior at runtime."); return this; }; UploadCollection.prototype.setMode = function(mode) { if (mode === Library.ListMode.Delete) { this._oList.setMode(Library.ListMode.None); Log.info("sap.m.ListMode.Delete is not supported by UploadCollection. Value has been resetted to 'None'"); } else if (mode === Library.ListMode.MultiSelect && !this.getInstantUpload()) { this._oList.setMode(Library.ListMode.None); Log.info("sap.m.ListMode.MultiSelect is not supported by UploadCollection for Pending Upload. Value has been resetted to 'None'"); } else { this._oList.setMode(mode); } return this; }; UploadCollection.prototype.getMode = function() { return this._oList.getMode(); }; UploadCollection.prototype.getToolbar = function() { return this._oHeaderToolbar; }; UploadCollection.prototype.getNoDataText = function() { var sNoDataText = this.getProperty("noDataText"); sNoDataText = sNoDataText || this._oRb.getText("UPLOADCOLLECTION_NO_DATA_TEXT"); return sNoDataText; }; UploadCollection.prototype.getNoDataDescription = function() { var sNoDataDescription = this.getProperty("noDataDescription"); sNoDataDescription = sNoDataDescription || this._oRb.getText("UPLOADCOLLECTION_NO_DATA_DESCRIPTION"); return sNoDataDescription; }; UploadCollection.prototype.setNoDataText = function(sNoDataText) { this.setProperty("noDataText", sNoDataText, true); this.$().find("#" + this.getId() + "-no-data-text").text(sNoDataText); var sNoDataTextDescription = sNoDataText + " " + this.getNoDataDescription(); this._oList.setNoDataText(sNoDataTextDescription); return this; }; UploadCollection.prototype.setNoDataDescription = function(sNoDataDescription) { this.setProperty("noDataDescription", sNoDataDescription, true); var sNoDataTextDescription = this.getNoDataText() + " " + sNoDataDescription; this._oList.setNoDataText(sNoDataTextDescription); if (this.getUploadEnabled() && this._oList.getItems().length == 0) { this.rerender(); } return this; }; UploadCollection.prototype.setUploadButtonInvisible = function(uploadButtonInvisible) { if (this.getUploadButtonInvisible() === uploadButtonInvisible) { return this; } this.setProperty("uploadButtonInvisible", uploadButtonInvisible, true); if (this.getInstantUpload()) { this._getFileUploader().setVisible(!uploadButtonInvisible); } else { this._setFileUploaderVisibility(uploadButtonInvisible); } if (this._bDragDropEnabled) { this._unbindDragEnterLeave(); this._bDragDropEnabled = false; } else { this._bindDragEnterLeave(); } return this; }; /** * Provides access to the internally used request headers to allow adding them to the "Access-Control-Allow-Headers" header parameter if needed. * @returns {string[]} An array of request header strings * @since 1.50.0 * @public */ UploadCollection.prototype.getInternalRequestHeaderNames = function() { return [this._headerParamConst.fileNameRequestIdName, this._headerParamConst.requestIdName]; }; /* =========================================================== */ /* API methods */ /* =========================================================== */ /** * Starts the upload for all selected files. * @public * @since 1.30.0 */ UploadCollection.prototype.upload = function() { if (this.getInstantUpload()) { Log.error("Not a valid API call. 'instantUpload' should be set to 'false'."); } var iFileUploadersCounter = this._aFileUploadersForPendingUpload.length; // upload files that are selected through popup for (var i = 0; i < iFileUploadersCounter; i++) { this._iUploadStartCallCounter = 0; // if the FU comes from drag and drop (without files), ignore it if (this._aFileUploadersForPendingUpload[i].getValue()) { this._aFileUploadersForPendingUpload[i].upload(); } } // upload files that are pushed through drag and drop if (this._aFilesFromDragAndDropForPendingUpload.length > 0) { // upload the files that are saved in the array this._oFileUploader._sendFilesFromDragAndDrop(this._aFilesFromDragAndDropForPendingUpload); // clean up the array this._aFilesFromDragAndDropForPendingUpload = []; } }; /** * Returns an array containing the selected UploadCollectionItems. * @returns {sap.m.UploadCollectionItem[]} Array of all selected items * @public * @since 1.34.0 */ UploadCollection.prototype.getSelectedItems = function() { var aSelectedListItems = this._oList.getSelectedItems(); return this._getUploadCollectionItemsByListItems(aSelectedListItems); }; /** * Retrieves the currently selected UploadCollectionItem. * @returns {sap.m.UploadCollectionItem | null} The currently selected item or <code>null</code> * @since 1.34.0 * @public */ UploadCollection.prototype.getSelectedItem = function() { var oSelectedListItem = this._oList.getSelectedItem(); if (oSelectedListItem) { return this._getUploadCollectionItemByListItem(oSelectedListItem); } return null; }; /** * Sets an UploadCollectionItem to be selected by ID. In single selection mode, the method removes the previous selection. * @param {string} id The ID of the item whose selection is to be changed. * @param {boolean} [select=true] The selection state of the item. * @returns {this} this to allow method chaining * @since 1.34.0 * @public */ UploadCollection.prototype.setSelectedItemById = function(id, select) { this._oList.setSelectedItemById(id + "-cli", select); this._setSelectedForItems([this._getUploadCollectionItemById(id)], select); return this; }; /** * Selects or deselects the given list item. * @param {sap.m.UploadCollectionItem} uploadCollectionItem The item whose selection is to be changed. This parameter is mandatory. * @param {boolean} [select=true] The selection state of the item. * @returns {this} this to allow method chaining * @since 1.34.0 * @public */ UploadCollection.prototype.setSelectedItem = function(uploadCollectionItem, select) { return this.setSelectedItemById(uploadCollectionItem.getId(), select); }; /** * Select all items in "MultiSelection" mode. * @returns {this} this to allow method chaining * @since 1.34.0 * @public */ UploadCollection.prototype.selectAll = function() { var aSelectedList = this._oList.selectAll(); if (aSelectedList.getItems().length !== this.getItems().length) { Log.info("Internal 'List' and external 'UploadCollection' are not in sync."); } this._setSelectedForItems(this.getItems(), true); return this; }; /** * Downloads the given item. * This function delegates to {@link sap.m.UploadCollectionItem#download uploadCollectionItem.download}. * @param {sap.m.UploadCollectionItem} uploadCollectionItem The item to download. This parameter is mandatory. * @param {boolean} askForLocation Decides whether to ask for a location to download or not. * @returns {boolean} True if the download has started successfully. False if the download couldn't be started. * @since 1.36.0 * @public */ UploadCollection.prototype.downloadItem = function(uploadCollectionItem, askForLocation) { if (!this.getInstantUpload()) { Log.info("Download is not possible on Pending Upload mode"); return false; } else { return uploadCollectionItem.download(askForLocation); } }; /** * Opens the FileUploader dialog. When an UploadCollectionItem is provided, this method can be used to update a file with a new version. * In this case, the upload progress can be sequenced using the events: beforeUploadStarts, uploadComplete and uploadTerminated. For this use, * multiple properties from the UploadCollection have to be set to false. If no UploadCollectionItem is provided, only the dialog opens * and no further configuration of the UploadCollection is needed. * @param {sap.m.UploadCollectionItem} item The item to update with a new version. This parameter is mandatory. * @returns {this} this to allow method chaining * @since 1.38.0 * @public */ UploadCollection.prototype.openFileDialog = function(item) { if (this._oFileUploader) { if (item) { if (!this._oFileUploader.getMultiple()) { this._oItemToUpdate = item; this._oFileUploader.$().find("input[type=file]").trigger("click"); } else { Log.warning("Version Upload cannot be used in multiple upload mode"); } } else { this._oFileUploader.$().find("input[type=file]").trigger("click"); } } return this; }; UploadCollection.prototype.removeAggregation = function(sAggregationName, vObject, bSuppressInvalidate) { var oFileFromDragDrop, iIndexOfFile, aItems; if (!this.getInstantUpload() && sAggregationName === "items" && vObject) { oFileFromDragDrop = vObject._internalFileIdWithinDragDropArray; // if the deleted file is from drag and drop, removes it from the drag and drop array if (oFileFromDragDrop) { iIndexOfFile = this._aFilesFromDragAndDropForPendingUpload.indexOf(oFileFromDragDrop); if (iIndexOfFile !== -1) { this._aFilesFromDragAndDropForPendingUpload.splice(iIndexOfFile, 1); } } else if (typeof vObject === "number") { aItems = this.getItems(); this._aDeletedItemForPendingUpload.push(aItems[vObject]); } else { this._aDeletedItemForPendingUpload.push(vObject); } } return Control.prototype.removeAggregation.apply(this, arguments); }; UploadCollection.prototype.removeAllAggregation = function(sAggregationName, bSuppressInvalidate) { if (!this.getInstantUpload() && sAggregationName === "items") { if (this._aFileUploadersForPendingUpload) { for (var i = 0; i < this._aFileUploadersForPendingUpload.length; i++) { this._aFileUploadersForPendingUpload[i].destroy(); this._aFileUploadersForPendingUpload[i] = null; } this._aFileUploadersForPendingUpload = []; } } return Control.prototype.removeAllAggregation.apply(this, arguments); }; /* =========================================================== */ /* Lifecycle methods */ /* =========================================================== */ UploadCollection.prototype.onBeforeRendering = function() { this._RenderManager = this._RenderManager || sap.ui.getCore().createRenderManager(); var i, cAitems; if (this._oListEventDelegate) { this._oList.removeEventDelegate(this._oListEventDelegate); this._oListEventDelegate = null; } this._deregisterSizeHandler(); this._unbindDragEnterLeave(); checkInstantUpload.bind(this)(); if (!this.getInstantUpload()) { this.aItems = this.getItems(); this._getListHeader(this.aItems.length); this._clearList(); this._fillList(this.aItems); this._oList.setHeaderToolbar(this._oHeaderToolbar); return; } if (this.aItems.length > 0) { cAitems = this.aItems.length; // collect items with the status "uploading" var aUploadingItems = []; for (i = 0; i < cAitems; i++) { if (this.aItems[i] && this.aItems[i]._status === UploadCollection._uploadingStatus) { aUploadingItems.push(this.aItems[i]); } else if (this.aItems[i] && this.aItems[i]._status !== UploadCollection._uploadingStatus && this.aItems[i]._percentUploaded === 100 && this.getItems().length === 0) { // Skip this rendering because of model refresh only aUploadingItems.push(this.aItems[i]); } } if (aUploadingItems.length !== 0) { this.aItems = []; this.aItems = this.getItems(); this.aItems = aUploadingItems.concat(this.aItems); } else { this.aItems = this.getItems(); } } else { // this.aItems is empty this.aItems = this.getItems(); } //prepare the list with list items this._getListHeader(this.aItems.length); this._clearList(); this._fillList(this.aItems); this._oList.setAggregation("headerToolbar", this._oHeaderToolbar, true); // note: suppress re-rendering // enable/disable FileUploader according to error state if (this.sErrorState !== "Error") { if (this.getUploadEnabled() !== this._oFileUploader.getEnabled()) { this._oFileUploader.setEnabled(this.getUploadEnabled()); } } else { this._oFileUploader.setEnabled(false); } if (this.sDeletedItemId) { jQuery(document.activeElement).trigger("blur"); } // This function checks if instantUpload needs to be set. In case of the properties like fileType are set by the // model instead of the constructor, the setting happens later and is still valid. To support this as well, you // need to wait for modification until the first rendering. function checkInstantUpload() { if (this.bInstantUpload === false) { this.setProperty("instantUpload", this.bInstantUpload, true); delete this.bInstantUpload; } } }; UploadCollection.prototype.onAfterRendering = function() { this._bindDragEnterLeave(); if (this.getInstantUpload()) { if (this.aItems || (this.aItems === this.getItems())) { if (this.editModeItem) { var $oEditBox = jQuery(document.getElementById(this.editModeItem + "-ta_editFileName-inner")); if ($oEditBox) { var sId = this.editModeItem; if (!Device.os.ios) { $oEditBox.on("focus", function() { $oEditBox.selectText(0, $oEditBox.val().length); }); } $oEditBox.trigger("focus"); //Create dummy InvisibleText to reset the ariaLabel value read out this.oInvisibleText.setText(""); sap.ui.getCore().byId(this.editModeItem + "-cli").removeAllAriaLabelledBy(); sap.ui.getCore().byId(this.editModeItem + "-cli").addAriaLabelledBy(this.oInvisibleText.getId()); this._oListEventDelegate = { onclick: function(event) { this._handleClick(event, sId); }.bind(this) }; this._oList.addDelegate(this._oListEventDelegate); } } else if (this.sFocusId) { //set focus on line item after status = Edit this._setFocusToLineItem(this.sFocusId); this.sFocusId = null; } else if (this.sDeletedItemId) { //set focus on line item after an item was deleted this._setFocusAfterDeletion(); } } } else if (this.sFocusId) { //set focus after removal of file from upload list this._setFocusToLineItem(this.sFocusId); this.sFocusId = null; } }; UploadCollection.prototype.exit = function() { var i, iPendingUploadsNumber, oItemToDestroy; // _unbindDragEnterLeave has to be called before setting $RootNode to null, because if $RootNode is null, the unbind will only partially be performed as it depends on $RootNode this._unbindDragEnterLeave(); if (this._$RootNode) { this._$RootNode = null; } if (this._oFileUploader) { this._oFileUploader.destroy(); this._oFileUploader = null; } if (this._oHeaderToolbar) { this._oHeaderToolbar.destroy(); this._oHeaderToolbar = null; } if (this._oNumberOfAttachmentsTitle) { this._oNumberOfAttachmentsTitle.destroy(); this._oNumberOfAttachmentsTitle = null; } if (this._RenderManager) { this._RenderManager.destroy(); } if (this._aFileUploadersForPendingUpload) { iPendingUploadsNumber = this._aFileUploadersForPendingUpload.length; for (i = 0; i < iPendingUploadsNumber; i++) { this._aFileUploadersForPendingUpload[i].destroy(); this._aFileUploadersForPendingUpload[i] = null; } this._aFileUploadersForPendingUpload = null; } // destroy items with status "uploading" because they are not destroyed with "items" aggregation if (this.aItems && this.aItems.length > 0) { for (i = 0; i < this.aItems.length; i++) { if (this.aItems[i]._status === UploadCollection._uploadingStatus) { oItemToDestroy = this.aItems.splice(i, 1)[0]; if (oItemToDestroy.destroy) { oItemToDestroy.destroy(); } } } } this._deregisterSizeHandler(); //Destroy the created InvisibleText if (this.oInvisibleText) { this.oInvisibleText.destroy(); } }; /* =========================================================== */ /* Private methods */ /* =========================================================== */ /** * Binds the handlers for drag and drop events. * * @private */ UploadCollection.prototype._bindDragEnterLeave = function() { this._bDragDropEnabled = this._isDragAndDropAllowed(); if (!this._bDragDropEnabled) { return; } // handlers need to be saved intermediately in order to unbind successfully if (!this._oDragDropHandler) { this._oDragDropHandler = { dragEnterUIArea: this._onDragEnterUIArea.bind(this), dragLeaveUIArea: this._onDragLeaveUIArea.bind(this), dragOverUIArea: this._onDragOverUIArea.bind(this), dropOnUIArea: this._onDropOnUIArea.bind(this), dragEnterUploadCollection: this._onDragEnterUploadCollection.bind(this), dragLeaveUploadCollection: this._onDragLeaveUploadCollection.bind(this), dragOverUploadCollection: this._onDragOverUploadCollection.bind(this), dropOnUploadCollection: this._onDropOnUploadCollection.bind(this) }; } // bind events on body element this._$RootNode = jQuery(document.body); this._$RootNode.on("dragenter", this._oDragDropHandler.dragEnterUIArea); this._$RootNode.on("dragleave", this._oDragDropHandler.dragLeaveUIArea); this._$RootNode.on("dragover", this._oDragDropHandler.dragOverUIArea); this._$RootNode.on("drop", this._oDragDropHandler.dropOnUIArea); // bind events on UploadCollection this._$DragDropArea = this.$("drag-drop-area"); this.$().on("dragenter", this._oDragDropHandler.dragEnterUploadCollection); this.$().on("dragleave", this._oDragDropHandler.dragLeaveUploadCollection); this.$().on("dragover", this._oDragDropHandler.dragOverUploadCollection); this.$().on("drop", this._oDragDropHandler.dropOnUploadCollection); }; /** * Unbinds the handlers for drag and drop events. * * @private */ UploadCollection.prototype._unbindDragEnterLeave = function() { if (!this._bDragDropEnabled && !this._oDragDropHandler) { return; } if (this._$RootNode) { this._$RootNode.off("dragenter", this._oDragDropHandler.dragEnterUIArea); this._$RootNode.off("dragleave", this._oDragDropHandler.dragLeaveUIArea); this._$RootNode.off("dragover", this._oDragDropHandler.dragOverUIArea); this._$RootNode.off("drop", this._oDragDropHandler.dropOnUIArea); } this.$().off("dragenter", this._oDragDropHandler.dragEnterUploadCollection); this.$().off("dragleave", this._oDragDropHandler.dragLeaveUploadCollection); this.$().off("dragover", this._oDragDropHandler.dragOverUploadCollection); this.$().off("drop", this._oDragDropHandler.dropOnUploadCollection); }; /** * Handler when file is dragged in UIArea. * @param {jQuery.Event} event The jQuery event object * @private */ UploadCollection.prototype._onDragEnterUIArea = function(event) { if (!this._checkForFiles(event)) { return; } this._oLastEnterUIArea = event.target; this._$DragDropArea.removeClass("sapMUCDragDropOverlayHide"); this._adjustDragDropIcon(); }; /** * Handler when file is dragged over UIArea. * @param {jQuery.Event} event The jQuery event object * @private */ UploadCollection.prototype._onDragOverUIArea = function(event) { event.preventDefault(); if (!this._checkForFiles(event)) { return; } this._$DragDropArea.removeClass("sapMUCDragDropOverlayHide"); }; /** * Handler when file is dragged away from UIArea. * @param {jQuery.Event} event The jQuery event object * @private */ UploadCollection.prototype._onDragLeaveUIArea = function(event) { if (this._oLastEnterUIArea === event.target) { this._$DragDropArea.addClass("sapMUCDragDropOverlayHide"); } }; /** * Handler when file is dropped on UIArea. * @param {jQuery.Event} event The jQuery event object * @private */ UploadCollection.prototype._onDropOnUIArea = function(event) { this._$DragDropArea.addClass("sapMUCDragDropOverlayHide"); }; /** * Handler when file is dragged in UploadCollection drop enabled area. * @param {jQuery.Event} event The jQuery event object * @private */ UploadCollection.prototype._onDragEnterUploadCollection = function(event) { if (!this._checkForFiles(event)) { return; } if (event.target === this._$DragDropArea[0]) { this._$DragDropArea.addClass("sapMUCDropIndicator"); this._adjustDragDropIcon(); this.getAggregation("_dragDropText").setText(this._oRb.getText("UPLOADCOLLECTION_DROP_FILE_INDICATOR")); } }; /** * Handler when file is dragged over UploadCollection drop enabled area. * @param {jQuery.Event} event The jQuery event object * @private */ UploadCollection.prototype._onDragOverUploadCollection = function(event) { event.preventDefault(); event.originalEvent.dataTransfer.dropEffect = "copy"; }; /** * Handler when file is dragged away from UploadCollection drop enabled area. * @param {jQuery.Event} event The jQuery event object * @private */ UploadCollection.prototype._onDragLeaveUploadCollection = function(event) { if (event.target === this._$DragDropArea[0]) { this._$DragDropArea.removeClass("sapMUCDropIndicator"); this.getAggregation("_dragDropText").setText(this._oRb.getText("UPLOADCOLLECTION_DRAG_FILE_INDICATOR")); } }; /** * Checks if at least one element in the data that are to be transferred while dragging is a File. * @param {jQuery.Event} event The jQuery event object. * @returns {boolean} True if at least one file exists * @private */ UploadCollection.prototype._checkForFiles = function(event) { var aTypes = event.originalEvent.dataTransfer.types; if (aTypes) { for (var i = 0; i < aTypes.length; i++) { if (aTypes[i] === "Files") { return true; } } } return false; }; /** * Checks if Drag and Drop is allowed. * @returns {boolean} True if Drag and Drop is supported based on the running use cases. * @private */ UploadCollection.prototype._isDragAndDropAllowed = function() { return this.getUploadEnabled() && !this.getUploadButtonInvisible(); }; /** * Handler when file is dropped on UploadCollection drop enabled area. * @param {jQuery.Event} event The jQuery event object * @private */ UploadCollection.prototype._onDropOnUploadCollection = function(event)