@openui5/sap.ui.commons 1.143.0 → 1.144.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/THIRDPARTY.txt +1 -1
  2. package/package.json +4 -4
  3. package/src/sap/ui/commons/.library +2 -2
  4. package/src/sap/ui/commons/Accordion.js +2 -2
  5. package/src/sap/ui/commons/AccordionRenderer.js +1 -1
  6. package/src/sap/ui/commons/AccordionSection.js +2 -2
  7. package/src/sap/ui/commons/ApplicationHeader.js +2 -2
  8. package/src/sap/ui/commons/ApplicationHeaderRenderer.js +1 -1
  9. package/src/sap/ui/commons/Area.js +2 -2
  10. package/src/sap/ui/commons/AutoComplete.js +2 -2
  11. package/src/sap/ui/commons/AutoCompleteRenderer.js +1 -1
  12. package/src/sap/ui/commons/Button.js +2 -2
  13. package/src/sap/ui/commons/ButtonRenderer.js +2 -2
  14. package/src/sap/ui/commons/Callout.js +2 -2
  15. package/src/sap/ui/commons/CalloutBase.js +2 -2
  16. package/src/sap/ui/commons/CalloutBaseRenderer.js +1 -1
  17. package/src/sap/ui/commons/CalloutRenderer.js +1 -1
  18. package/src/sap/ui/commons/Carousel.js +2 -2
  19. package/src/sap/ui/commons/CarouselRenderer.js +1 -1
  20. package/src/sap/ui/commons/CheckBox.js +2 -2
  21. package/src/sap/ui/commons/CheckBoxRenderer.js +1 -1
  22. package/src/sap/ui/commons/ColorPicker.js +2 -2
  23. package/src/sap/ui/commons/ComboBox.js +2 -2
  24. package/src/sap/ui/commons/ComboBoxRenderer.js +1 -1
  25. package/src/sap/ui/commons/DatePicker.js +2 -2
  26. package/src/sap/ui/commons/DatePickerRenderer.js +1 -1
  27. package/src/sap/ui/commons/Dialog.js +2 -2
  28. package/src/sap/ui/commons/DialogRenderer.js +1 -1
  29. package/src/sap/ui/commons/DropdownBox.js +2 -2
  30. package/src/sap/ui/commons/DropdownBoxRenderer.js +1 -1
  31. package/src/sap/ui/commons/FileUploader.js +2150 -22
  32. package/src/sap/ui/commons/FileUploaderHttpRequestMethod.js +41 -0
  33. package/src/sap/ui/commons/FileUploaderParameter.js +25 -15
  34. package/src/sap/ui/commons/FileUploaderRenderer.js +114 -5
  35. package/src/sap/ui/commons/FileUploaderXHRSettings.js +49 -0
  36. package/src/sap/ui/commons/FormattedTextView.js +2 -2
  37. package/src/sap/ui/commons/FormattedTextViewRenderer.js +1 -1
  38. package/src/sap/ui/commons/HorizontalDivider.js +2 -2
  39. package/src/sap/ui/commons/HorizontalDividerRenderer.js +1 -1
  40. package/src/sap/ui/commons/Image.js +2 -2
  41. package/src/sap/ui/commons/ImageMap.js +2 -2
  42. package/src/sap/ui/commons/ImageMapRenderer.js +1 -1
  43. package/src/sap/ui/commons/ImageRenderer.js +1 -1
  44. package/src/sap/ui/commons/InPlaceEdit.js +2 -2
  45. package/src/sap/ui/commons/InPlaceEditRenderer.js +1 -1
  46. package/src/sap/ui/commons/Label.js +2 -2
  47. package/src/sap/ui/commons/LabelRenderer.js +1 -1
  48. package/src/sap/ui/commons/Link.js +2 -2
  49. package/src/sap/ui/commons/LinkRenderer.js +1 -1
  50. package/src/sap/ui/commons/ListBox.js +2 -2
  51. package/src/sap/ui/commons/ListBoxRenderer.js +2 -2
  52. package/src/sap/ui/commons/Menu.js +2 -2
  53. package/src/sap/ui/commons/MenuBar.js +2 -2
  54. package/src/sap/ui/commons/MenuBarRenderer.js +1 -1
  55. package/src/sap/ui/commons/MenuButton.js +2 -2
  56. package/src/sap/ui/commons/MenuButtonRenderer.js +1 -1
  57. package/src/sap/ui/commons/MenuItem.js +2 -2
  58. package/src/sap/ui/commons/MenuItemBase.js +2 -2
  59. package/src/sap/ui/commons/MenuRenderer.js +1 -1
  60. package/src/sap/ui/commons/MenuTextFieldItem.js +2 -2
  61. package/src/sap/ui/commons/Message.js +2 -2
  62. package/src/sap/ui/commons/MessageBar.js +2 -2
  63. package/src/sap/ui/commons/MessageBarRenderer.js +1 -1
  64. package/src/sap/ui/commons/MessageBox.js +2 -2
  65. package/src/sap/ui/commons/MessageList.js +2 -2
  66. package/src/sap/ui/commons/MessageListRenderer.js +1 -1
  67. package/src/sap/ui/commons/MessageRenderer.js +1 -1
  68. package/src/sap/ui/commons/MessageToast.js +2 -2
  69. package/src/sap/ui/commons/MessageToastRenderer.js +1 -1
  70. package/src/sap/ui/commons/Paginator.js +2 -2
  71. package/src/sap/ui/commons/PaginatorRenderer.js +1 -1
  72. package/src/sap/ui/commons/Panel.js +2 -2
  73. package/src/sap/ui/commons/PanelRenderer.js +1 -1
  74. package/src/sap/ui/commons/PasswordField.js +2 -2
  75. package/src/sap/ui/commons/PasswordFieldRenderer.js +1 -1
  76. package/src/sap/ui/commons/ProgressIndicator.js +2 -2
  77. package/src/sap/ui/commons/ProgressIndicatorRenderer.js +1 -1
  78. package/src/sap/ui/commons/RadioButton.js +2 -2
  79. package/src/sap/ui/commons/RadioButtonGroup.js +2 -2
  80. package/src/sap/ui/commons/RadioButtonGroupRenderer.js +1 -1
  81. package/src/sap/ui/commons/RadioButtonRenderer.js +1 -1
  82. package/src/sap/ui/commons/RangeSlider.js +2 -2
  83. package/src/sap/ui/commons/RangeSliderRenderer.js +1 -1
  84. package/src/sap/ui/commons/RatingIndicator.js +2 -2
  85. package/src/sap/ui/commons/RatingIndicatorRenderer.js +1 -1
  86. package/src/sap/ui/commons/ResponsiveContainer.js +2 -2
  87. package/src/sap/ui/commons/ResponsiveContainerRange.js +2 -2
  88. package/src/sap/ui/commons/ResponsiveContainerRenderer.js +1 -1
  89. package/src/sap/ui/commons/RichTooltip.js +2 -2
  90. package/src/sap/ui/commons/RichTooltipRenderer.js +1 -1
  91. package/src/sap/ui/commons/RoadMap.js +2 -2
  92. package/src/sap/ui/commons/RoadMapRenderer.js +1 -1
  93. package/src/sap/ui/commons/RoadMapStep.js +2 -2
  94. package/src/sap/ui/commons/RowRepeater.js +2 -2
  95. package/src/sap/ui/commons/RowRepeaterFilter.js +2 -2
  96. package/src/sap/ui/commons/RowRepeaterRenderer.js +1 -1
  97. package/src/sap/ui/commons/RowRepeaterSorter.js +2 -2
  98. package/src/sap/ui/commons/SearchField.js +2 -2
  99. package/src/sap/ui/commons/SearchFieldRenderer.js +1 -1
  100. package/src/sap/ui/commons/SearchProvider.js +2 -2
  101. package/src/sap/ui/commons/SegmentedButton.js +2 -2
  102. package/src/sap/ui/commons/SegmentedButtonRenderer.js +1 -1
  103. package/src/sap/ui/commons/Slider.js +2 -2
  104. package/src/sap/ui/commons/SliderRenderer.js +1 -1
  105. package/src/sap/ui/commons/Splitter.js +2 -2
  106. package/src/sap/ui/commons/SplitterRenderer.js +1 -1
  107. package/src/sap/ui/commons/Tab.js +2 -2
  108. package/src/sap/ui/commons/TabStrip.js +2 -2
  109. package/src/sap/ui/commons/TabStripRenderer.js +1 -1
  110. package/src/sap/ui/commons/TextArea.js +2 -2
  111. package/src/sap/ui/commons/TextAreaRenderer.js +1 -1
  112. package/src/sap/ui/commons/TextField.js +2 -2
  113. package/src/sap/ui/commons/TextFieldRenderer.js +2 -2
  114. package/src/sap/ui/commons/TextView.js +2 -2
  115. package/src/sap/ui/commons/TextViewRenderer.js +1 -1
  116. package/src/sap/ui/commons/Title.js +2 -2
  117. package/src/sap/ui/commons/ToggleButton.js +2 -2
  118. package/src/sap/ui/commons/ToggleButtonRenderer.js +1 -1
  119. package/src/sap/ui/commons/Toolbar.js +2 -2
  120. package/src/sap/ui/commons/ToolbarRenderer.js +1 -1
  121. package/src/sap/ui/commons/ToolbarSeparator.js +2 -2
  122. package/src/sap/ui/commons/Tree.js +2 -2
  123. package/src/sap/ui/commons/TreeNode.js +2 -2
  124. package/src/sap/ui/commons/TreeRenderer.js +1 -1
  125. package/src/sap/ui/commons/TriStateCheckBox.js +2 -2
  126. package/src/sap/ui/commons/TriStateCheckBoxRenderer.js +1 -1
  127. package/src/sap/ui/commons/ValueHelpField.js +2 -2
  128. package/src/sap/ui/commons/ValueHelpFieldRenderer.js +1 -1
  129. package/src/sap/ui/commons/form/Form.js +2 -2
  130. package/src/sap/ui/commons/form/FormContainer.js +2 -2
  131. package/src/sap/ui/commons/form/FormElement.js +2 -2
  132. package/src/sap/ui/commons/form/FormLayout.js +2 -2
  133. package/src/sap/ui/commons/form/FormLayoutRenderer.js +1 -1
  134. package/src/sap/ui/commons/form/FormRenderer.js +1 -1
  135. package/src/sap/ui/commons/form/GridContainerData.js +2 -2
  136. package/src/sap/ui/commons/form/GridElementData.js +2 -2
  137. package/src/sap/ui/commons/form/GridLayout.js +2 -2
  138. package/src/sap/ui/commons/form/GridLayoutRenderer.js +1 -1
  139. package/src/sap/ui/commons/form/ResponsiveLayout.js +2 -2
  140. package/src/sap/ui/commons/form/ResponsiveLayoutRenderer.js +1 -1
  141. package/src/sap/ui/commons/form/SimpleForm.js +2 -2
  142. package/src/sap/ui/commons/form/SimpleFormRenderer.js +1 -1
  143. package/src/sap/ui/commons/layout/AbsoluteLayout.js +2 -2
  144. package/src/sap/ui/commons/layout/AbsoluteLayoutRenderer.js +1 -1
  145. package/src/sap/ui/commons/layout/BorderLayout.js +2 -2
  146. package/src/sap/ui/commons/layout/BorderLayoutArea.js +2 -2
  147. package/src/sap/ui/commons/layout/BorderLayoutRenderer.js +1 -1
  148. package/src/sap/ui/commons/layout/HorizontalLayout.js +2 -2
  149. package/src/sap/ui/commons/layout/HorizontalLayoutRenderer.js +1 -1
  150. package/src/sap/ui/commons/layout/MatrixLayout.js +2 -2
  151. package/src/sap/ui/commons/layout/MatrixLayoutCell.js +2 -2
  152. package/src/sap/ui/commons/layout/MatrixLayoutRenderer.js +1 -1
  153. package/src/sap/ui/commons/layout/MatrixLayoutRow.js +2 -2
  154. package/src/sap/ui/commons/layout/PositionContainer.js +2 -2
  155. package/src/sap/ui/commons/layout/ResponsiveFlowLayout.js +2 -2
  156. package/src/sap/ui/commons/layout/ResponsiveFlowLayoutData.js +2 -2
  157. package/src/sap/ui/commons/layout/ResponsiveFlowLayoutRenderer.js +1 -1
  158. package/src/sap/ui/commons/layout/VerticalLayout.js +2 -2
  159. package/src/sap/ui/commons/layout/VerticalLayoutRenderer.js +1 -1
  160. package/src/sap/ui/commons/library.js +41 -6
  161. package/src/sap/ui/commons/messagebundle.properties +12 -0
  162. package/src/sap/ui/commons/themes/base/AbsoluteLayout.less +2 -1
  163. package/src/sap/ui/commons/themes/base/Accordion.less +8 -7
  164. package/src/sap/ui/commons/themes/base/AccordionSection.less +17 -13
  165. package/src/sap/ui/commons/themes/base/Carousel.less +20 -19
  166. package/src/sap/ui/commons/themes/base/ControlsInUITable.less +12 -36
  167. package/src/sap/ui/commons/themes/base/FileUploader.less +104 -1
  168. package/src/sap/ui/commons/themes/base/FormattedTextView.less +11 -10
  169. package/src/sap/ui/commons/themes/base/library.source.less +1 -1
  170. package/src/sap/ui/commons/themes/sap_hcb/library.source.less +1 -1
@@ -1,19 +1,55 @@
1
1
  /*!
2
2
  * OpenUI5
3
- * (c) Copyright 2025 SAP SE or an SAP affiliate company.
3
+ * (c) Copyright 2026 SAP SE or an SAP affiliate company.
4
4
  * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
5
5
  */
6
6
 
7
7
  // Provides control sap.ui.commons.FileUploader.
8
8
  sap.ui.define([
9
- 'sap/base/Log',
10
- './library',
11
- 'sap/ui/unified/FileUploader',
12
- './FileUploaderRenderer',
13
- 'sap/ui/core/Core' // sap.ui.getCore()
14
- ],
15
- function(Log, library, UnifiedFileUploader, FileUploaderRenderer, Core) {
16
- "use strict";
9
+ 'sap/ui/core/Control',
10
+ './library',
11
+ "sap/ui/core/ControlBehavior",
12
+ "sap/ui/core/Element",
13
+ 'sap/ui/core/LabelEnablement',
14
+ 'sap/ui/core/InvisibleText',
15
+ "sap/ui/core/Lib",
16
+ 'sap/ui/core/library',
17
+ 'sap/ui/core/StaticArea',
18
+ 'sap/ui/Device',
19
+ './FileUploaderRenderer',
20
+ 'sap/ui/dom/containsOrEquals',
21
+ 'sap/ui/events/KeyCodes',
22
+ 'sap/base/Log',
23
+ 'sap/base/security/encodeXML',
24
+ "sap/ui/thirdparty/jquery",
25
+ "sap/ui/commons/Button",
26
+ "sap/ui/commons/TextField",
27
+ // jQuery Plugin "addAriaDescribedBy"
28
+ 'sap/ui/dom/jquery/Aria'
29
+ ], function(
30
+ Control,
31
+ library,
32
+ ControlBehavior,
33
+ Element,
34
+ LabelEnablement,
35
+ InvisibleText,
36
+ Library,
37
+ coreLibrary,
38
+ StaticArea,
39
+ Device,
40
+ FileUploaderRenderer,
41
+ containsOrEquals,
42
+ KeyCodes,
43
+ Log,
44
+ encodeXML,
45
+ jQuery,
46
+ Button,
47
+ TextField
48
+ ) {
49
+
50
+ // shortcut for sap.ui.core.ValueState
51
+ var ValueState = coreLibrary.ValueState;
52
+ var HttpRequestMethod = library.FileUploaderHttpRequestMethod;
17
53
 
18
54
  /**
19
55
  * Constructor for a new FileUploader.
@@ -23,10 +59,9 @@ sap.ui.define([
23
59
  *
24
60
  * @class
25
61
  * The framework generates an input field and a button with text "Browse ...". The API supports features such as on change uploads (the upload starts immediately after a file has been selected), file uploads with explicit calls, adjustable control sizes, text display after uploads, or tooltips containing complete file paths.
26
- * @extends sap.ui.unified.FileUploader
27
62
  *
28
63
  * @author SAP SE
29
- * @version 1.143.0
64
+ * @version 1.144.0
30
65
  *
31
66
  * @constructor
32
67
  * @public
@@ -34,18 +69,2111 @@ sap.ui.define([
34
69
  * Please use the control sap.ui.unified.FileUploader of the library sap.ui.unified instead.
35
70
  * @alias sap.ui.commons.FileUploader
36
71
  */
37
- var FileUploader = UnifiedFileUploader.extend("sap.ui.commons.FileUploader", /** @lends sap.ui.commons.FileUploader.prototype */ { metadata : {
38
-
72
+ var FileUploader = Control.extend("sap.ui.commons.FileUploader", /** @lends sap.ui.commons.FileUploader.prototype */ { metadata : {
39
73
  deprecated : true,
40
- library : "sap.ui.commons"
41
- }});
42
-
43
- try {
44
- sap.ui.getCore().loadLibrary("sap.ui.unified");
45
- } catch (e) {
46
- Log.error("The control 'sap.ui.commons.FileUploader' needs library 'sap.ui.unified'.");
47
- throw (e);
48
- }
74
+ library : "sap.ui.commons",
75
+ interfaces : ["sap.ui.core.IFormContent", "sap.ui.commons.IProcessableBlobs"],
76
+ properties : {
77
+
78
+ /**
79
+ * Value of the path for file upload.
80
+ */
81
+ value : {type : "string", group : "Data", defaultValue : ''},
82
+
83
+ /**
84
+ * Disabled controls have different colors, depending on customer settings.
85
+ */
86
+ enabled : {type : "boolean", group : "Behavior", defaultValue : true},
87
+
88
+ /**
89
+ * Used when URL address is on a remote server.
90
+ */
91
+ uploadUrl : {type : "sap.ui.core.URI", group : "Data", defaultValue : ''},
92
+
93
+ /**
94
+ * Unique control name for identification on the server side after sending data to the server.
95
+ */
96
+ name : {type : "string", group : "Data", defaultValue : null},
97
+
98
+ /**
99
+ * Specifies the displayed control width.
100
+ */
101
+ width : {type : "sap.ui.core.CSSSize", group : "Misc", defaultValue : ''},
102
+
103
+ /**
104
+ * If set to "true", the upload immediately starts after file selection.
105
+ * With the default setting, the upload needs to be explicitly triggered.
106
+ */
107
+ uploadOnChange : {type : "boolean", group : "Behavior", defaultValue : false},
108
+
109
+ /**
110
+ * Additional data that is sent to the back end service.
111
+ *
112
+ * Data will be transmitted as value of a hidden input where the name is derived from the
113
+ * <code>name</code> property with suffix "-data".
114
+ */
115
+ additionalData : {type : "string", group : "Data", defaultValue : null},
116
+
117
+ /**
118
+ * If the FileUploader is configured to upload the file directly after the file is selected,
119
+ * it is not allowed to upload a file with the same name again. If a user should be allowed
120
+ * to upload a file with the same name again this parameter has to be "true".
121
+ *
122
+ * A typical use case would be if the files have different paths.
123
+ */
124
+ sameFilenameAllowed : {type : "boolean", group : "Behavior", defaultValue : false},
125
+
126
+ /**
127
+ * The button's text can be overwritten using this property.
128
+ */
129
+ buttonText : {type : "string", group : "Misc", defaultValue : null},
130
+
131
+ /**
132
+ * The chosen files will be checked against an array of file types.
133
+ *
134
+ * If at least one file does not fit the file type restriction, the upload is prevented.
135
+ * <b>Note:</b> This property is not supported by Microsoft Edge.
136
+ *
137
+ * Example: <code>["jpg", "png", "bmp"]</code>.
138
+ */
139
+ fileType : {type : "string[]", group : "Data", defaultValue : null},
140
+
141
+ /**
142
+ * Allows multiple files to be chosen and uploaded from the same folder.
143
+ *
144
+ * This property is not supported by Internet Explorer 9.
145
+ *
146
+ * <b>Note:</b> Keep in mind that the various operating systems for mobile devices
147
+ * can react differently to the property so that fewer upload functions may be
148
+ * available in some cases.
149
+ */
150
+ multiple : {type : "boolean", group : "Behavior", defaultValue : false},
151
+
152
+ /**
153
+ * A file size limit in megabytes which prevents the upload if at least one file exceeds it.
154
+ *
155
+ * This property is not supported by Internet Explorer 9.
156
+ */
157
+ maximumFileSize : {type : "float", group : "Data", defaultValue : null},
158
+
159
+ /**
160
+ * The chosen files will be checked against an array of MIME types defined in this property.
161
+ *
162
+ * If at least one file does not fit the MIME type restriction, the upload is prevented.
163
+ *
164
+ * <b>Note:</b> This property is not supported by Internet Explorer.
165
+ * It is only reliable for common file types like images, audio, video, plain text and HTML documents.
166
+ * File types that are not recognized by the browser result in <code>file.type</code> to be returned
167
+ * as an empty string. In this case the verification could not be performed.
168
+ * The file upload is not prevented and the validation based on file type is left to the receiving backend side.
169
+ *
170
+ *
171
+ * Example: <code>["image/png", "image/jpeg"]</code>.
172
+ */
173
+ mimeType : {type : "string[]", group : "Data", defaultValue : null},
174
+
175
+ /**
176
+ * If set to "true", the request will be sent as XHR request instead of a form submit.
177
+ *
178
+ * This property is not supported by Internet Explorer 9.
179
+ */
180
+ sendXHR : {type : "boolean", group : "Behavior", defaultValue : false},
181
+
182
+ /**
183
+ * Chosen HTTP request method for file upload.
184
+ * @since 1.81.0
185
+ *
186
+ */
187
+ httpRequestMethod : {type: "sap.ui.commons.FileUploaderHttpRequestMethod", group : "Behavior", defaultValue : HttpRequestMethod.Post},
188
+
189
+ /**
190
+ * Placeholder for the text field.
191
+ */
192
+ placeholder : {type : "string", group : "Appearance", defaultValue : null},
193
+
194
+ /**
195
+ * Style of the button.
196
+ *
197
+ * Values "Transparent, "Accept", "Reject", or "Emphasized" are allowed.
198
+ */
199
+ style : {type : "string", group : "Appearance", defaultValue : null},
200
+
201
+ /**
202
+ * If set to "true", the <code>FileUploader</code> will be rendered as Button only,
203
+ * without showing the input field.
204
+ */
205
+ buttonOnly : {type : "boolean", group : "Appearance", defaultValue : false},
206
+
207
+ /**
208
+ * If set to "false", the request will be sent as file only request instead of a multipart/form-data request.
209
+ *
210
+ * Only one file could be uploaded using this type of request. Required for sending such a request is
211
+ * to set the property <code>sendXHR</code> to "true". This property is not supported by Internet Explorer 9.
212
+ */
213
+ useMultipart : {type : "boolean", group : "Behavior", defaultValue : true},
214
+
215
+ /**
216
+ * The maximum length of a filename which the <code>FileUploader</code> will accept.
217
+ *
218
+ * If the maximum filename length is exceeded, the corresponding event <code>filenameLengthExceed</code> is fired.
219
+ * @since 1.24.0
220
+ */
221
+ maximumFilenameLength : {type : "int", group : "Data", defaultValue : null},
222
+
223
+ /**
224
+ * Visualizes warnings or errors related to the text field.
225
+ *
226
+ * Possible values: Warning, Error, Success, None.
227
+ * @since 1.24.0
228
+ */
229
+ valueState : {type : "sap.ui.core.ValueState", group : "Data", defaultValue : ValueState.None},
230
+
231
+ /**
232
+ * Custom text for the value state message pop-up.
233
+ *
234
+ * <b>Note:</b> If not specified, a default text, based on the value state type, will be used instead.
235
+ * @since 1.52
236
+ */
237
+ valueStateText : {type : "string", group : "Misc", defaultValue : null},
238
+
239
+ /**
240
+ * Icon to be displayed as graphical element within the button.
241
+ *
242
+ * This can be a URI to an image or an icon font URI.
243
+ * @since 1.26.0
244
+ */
245
+ icon : {type : "sap.ui.core.URI", group : "Appearance", defaultValue : ''},
246
+
247
+ /**
248
+ * Icon to be displayed as graphical element within the button when it is hovered (only if also a base icon was specified).
249
+ *
250
+ * If not specified, the base icon is used. If an icon font icon is used, this property is ignored.
251
+ * @since 1.26.0
252
+ */
253
+ iconHovered : {type : "sap.ui.core.URI", group : "Appearance", defaultValue : ''},
254
+
255
+ /**
256
+ * Icon to be displayed as graphical element within the button when it is selected (only if also a base icon was specified).
257
+ *
258
+ * If not specified, the base or hovered icon is used. If an icon font icon is used, this property is ignored.
259
+ * @since 1.26.0
260
+ */
261
+ iconSelected : {type : "sap.ui.core.URI", group : "Appearance", defaultValue : ''},
262
+
263
+ /**
264
+ * If set to true (default), the display sequence is 1. icon 2. control text.
265
+ * @since 1.26.0
266
+ */
267
+ iconFirst : {type : "boolean", group : "Appearance", defaultValue : true},
268
+
269
+ /**
270
+ * If set to true, the button is displayed without any text.
271
+ * @since 1.26.0
272
+ */
273
+ iconOnly : {type : "boolean", group : "Appearance", defaultValue : false},
274
+
275
+ /**
276
+ * Allows users to upload all files from a given directory and its corresponding subdirectories.
277
+ * @since 1.105.0
278
+ *
279
+ * <b>Note:</b> This feature is supported on all WebKit-based browsers as well as Microsoft Edge and Firefox after version 50.
280
+ * <b>Note:</b> Multiple directory selection is not supported.
281
+ */
282
+ directory : {type : "boolean", group : "Behavior", defaultValue : false}
283
+ },
284
+ aggregations : {
285
+
286
+ /**
287
+ * The parameters for the <code>FileUploader</code> which are rendered as a hidden input field.
288
+ * @since 1.12.2
289
+ */
290
+ parameters : {type : "sap.ui.commons.FileUploaderParameter", multiple : true, singularName : "parameter"},
291
+
292
+ /**
293
+ * The header parameters for the <code>FileUploader</code> which are only submitted with XHR requests.
294
+ * Header parameters are not supported by Internet Explorer 9.
295
+ */
296
+ headerParameters : {type : "sap.ui.commons.FileUploaderParameter", multiple : true, singularName : "headerParameter"},
297
+
298
+ /**
299
+ * Settings for the <code>XMLHttpRequest</code> object.
300
+ * <b>Note:</b> This aggregation is only used when the <code>sendXHR</code> property is set to <code>true</code>.
301
+ * @since 1.52
302
+ */
303
+ xhrSettings : {type : "sap.ui.commons.FileUploaderXHRSettings", multiple : false}
304
+ },
305
+ associations : {
306
+
307
+ /**
308
+ * Association to controls / IDs which describe this control (see WAI-ARIA attribute <code>aria-describedby</code>).
309
+ */
310
+ ariaDescribedBy: {type: "sap.ui.core.Control", multiple: true, singularName: "ariaDescribedBy"},
311
+
312
+ /**
313
+ * Association to controls / IDs which label this control (see WAI-ARIA attribute <code>aria-labelledby</code>).
314
+ */
315
+ ariaLabelledBy: {type: "sap.ui.core.Control", multiple: true, singularName: "ariaLabelledBy"}
316
+ },
317
+ events : {
318
+
319
+ /**
320
+ * Event is fired when the value of the file path has been changed.
321
+ *
322
+ * <b>Note:</b> Keep in mind that because of the HTML input element of type file, the
323
+ * event is also fired in Chrome browser when the Cancel button of the
324
+ * uploads window is pressed.
325
+ */
326
+ change : {
327
+ parameters : {
328
+
329
+ /**
330
+ * New file path value.
331
+ */
332
+ newValue : {type : "string"},
333
+
334
+ /**
335
+ * Files.
336
+ */
337
+ files : {type : "object[]"}
338
+ }
339
+ },
340
+
341
+ /**
342
+ * Event is fired as soon as the upload request is completed (either successful or unsuccessful).
343
+ *
344
+ * To see if the upload request was successful, check the <code>status</code> parameter for a value 2xx.
345
+ * The actual progress of the upload can be monitored by listening to the <code>uploadProgress</code> event.
346
+ * However, this covers only the client side of the upload process and does not give any success status
347
+ * from the server.
348
+ */
349
+ uploadComplete : {
350
+ parameters : {
351
+
352
+ /**
353
+ * The name of a file to be uploaded.
354
+ */
355
+ fileName : {type : "string"},
356
+
357
+ /**
358
+ * Response message which comes from the server.
359
+ *
360
+ * On the server side this response has to be put within the &quot;body&quot; tags of the response
361
+ * document of the iFrame. It can consist of a return code and an optional message. This does not
362
+ * work in cross-domain scenarios.
363
+ */
364
+ response : {type : "string"},
365
+
366
+ /**
367
+ * ReadyState of the XHR request.
368
+ *
369
+ * Required for receiving a <code>readyStateXHR</code> is to set the property <code>sendXHR</code>
370
+ * to true. This property is not supported by Internet Explorer 9.
371
+ */
372
+ readyStateXHR : {type : "string"},
373
+
374
+ /**
375
+ * Status of the XHR request.
376
+ *
377
+ * Required for receiving a <code>status</code> is to set the property <code>sendXHR</code> to true.
378
+ * This property is not supported by Internet Explorer 9.
379
+ */
380
+ status : {type : "int"},
381
+
382
+ /**
383
+ * Http-Response which comes from the server.
384
+ *
385
+ * Required for receiving <code>responseRaw</code> is to set the property <code>sendXHR</code> to true.
386
+ *
387
+ * This property is not supported by Internet Explorer 9.
388
+ */
389
+ responseRaw : {type : "string"},
390
+
391
+ /**
392
+ * Http-Response-Headers which come from the server.
393
+ *
394
+ * Provided as a JSON-map, i.e. each header-field is reflected by a property in the <code>headers</code>
395
+ * object, with the property value reflecting the header-field's content.
396
+ *
397
+ * Required for receiving <code>headers</code> is to set the property <code>sendXHR</code> to true.
398
+ * This property is not supported by Internet Explorer 9.
399
+ */
400
+ headers : {type : "object"},
401
+
402
+ /**
403
+ * Http-Request-Headers.
404
+ *
405
+ * Required for receiving <code>requestHeaders</code> is to set the property <code>sendXHR</code> to true.
406
+ * This property is not supported by Internet Explorer 9.
407
+ */
408
+ requestHeaders : {type : "object[]"}
409
+ }
410
+ },
411
+
412
+ /**
413
+ * Event is fired when the type of a file does not match the <code>mimeType</code> or <code>fileType</code> property.
414
+ */
415
+ typeMissmatch : {
416
+ parameters : {
417
+
418
+ /**
419
+ * The name of a file to be uploaded.
420
+ */
421
+ fileName : {type : "string"},
422
+
423
+ /**
424
+ * The file ending of a file to be uploaded.
425
+ */
426
+ fileType : {type : "string"},
427
+
428
+ /**
429
+ * The MIME type of a file to be uploaded.
430
+ */
431
+ mimeType : {type : "string"}
432
+ }
433
+ },
434
+
435
+ /**
436
+ * Event is fired when the size of a file is above the <code>maximumFileSize</code> property.
437
+ * This event is not supported by Internet Explorer 9 (same restriction as for the property
438
+ * <code>maximumFileSize</code>).
439
+ */
440
+ fileSizeExceed : {
441
+ parameters : {
442
+
443
+ /**
444
+ * The name of a file to be uploaded.
445
+ */
446
+ fileName : {type : "string"},
447
+
448
+ /**
449
+ * The size in MB of a file to be uploaded.
450
+ */
451
+ fileSize : {type : "string"}
452
+ }
453
+ },
454
+
455
+ /**
456
+ * Event is fired when the size of the file is 0
457
+ */
458
+ fileEmpty : {
459
+ parameters : {
460
+
461
+ /**
462
+ * The name of the file to be uploaded.
463
+ */
464
+ fileName: {type : "string"}
465
+ }
466
+ },
467
+
468
+ /**
469
+ * Event is fired when the file is allowed for upload on client side.
470
+ */
471
+ fileAllowed : {},
472
+
473
+ /**
474
+ * Event is fired after the upload has started and before the upload is completed.
475
+ *
476
+ * It contains progress information related to the running upload. Depending on file size, band width
477
+ * and used browser the event is fired once or multiple times.
478
+ *
479
+ * This event is only supported with property <code>sendXHR</code> set to true, i.e. the event is not
480
+ * supported in Internet Explorer 9.
481
+ *
482
+ * @since 1.24.0
483
+ */
484
+ uploadProgress : {
485
+ parameters : {
486
+
487
+ /**
488
+ * Indicates whether or not the relative upload progress can be calculated out of loaded and total.
489
+ */
490
+ lengthComputable : {type : "boolean"},
491
+
492
+ /**
493
+ * The number of bytes of the file which have been uploaded by the time the event was fired.
494
+ */
495
+ loaded : {type : "float"},
496
+
497
+ /**
498
+ * The total size of the file to be uploaded in bytes.
499
+ */
500
+ total : {type : "float"},
501
+
502
+ /**
503
+ * The name of a file to be uploaded.
504
+ */
505
+ fileName : {type : "string"},
506
+
507
+ /**
508
+ * Http-Request-Headers.
509
+ *
510
+ * Required for receiving <code>requestHeaders</code> is to set the property <code>sendXHR</code> to true.
511
+ * This property is not supported by Internet Explorer 9.
512
+ */
513
+ requestHeaders : {type : "object[]"}
514
+ }
515
+ },
516
+
517
+ /**
518
+ * Event is fired after the current upload has been aborted.
519
+ *
520
+ * This event is only supported with property <code>sendXHR</code> set to true, i.e. the event is not supported
521
+ * in Internet Explorer 9.
522
+ * @since 1.24.0
523
+ */
524
+ uploadAborted : {
525
+ parameters : {
526
+
527
+ /**
528
+ * The name of a file to be uploaded.
529
+ */
530
+ fileName : {type : "string"},
531
+
532
+ /**
533
+ * Http-Request-Headers.
534
+ *
535
+ * Required for receiving <code>requestHeader</code> is to set the property <code>sendXHR</code> to true.
536
+ * This property is not supported by Internet Explorer 9.
537
+ */
538
+ requestHeaders : {type : "object[]"}
539
+ }
540
+ },
541
+
542
+ /**
543
+ * Event is fired, if the filename of a chosen file is longer than the value specified with the
544
+ * <code>maximumFilenameLength</code> property.
545
+ * @since 1.24.0
546
+ */
547
+ filenameLengthExceed : {
548
+ parameters : {
549
+
550
+ /**
551
+ * The filename, which is longer than specified by the value of the property <code>maximumFilenameLength</code>.
552
+ */
553
+ fileName : {type : "string"}
554
+ }
555
+ },
556
+
557
+ /**
558
+ * Event is fired before an upload is started.
559
+ * @since 1.30.0
560
+ */
561
+ uploadStart : {
562
+ parameters : {
563
+
564
+ /**
565
+ * The name of a file to be uploaded.
566
+ */
567
+ fileName : {type : "string"},
568
+
569
+ /**
570
+ * Http-Request-Headers.
571
+ *
572
+ * Required for receiving <code>requestHeaders</code> is to set the property <code>sendXHR</code>
573
+ * to true. This property is not supported by Internet Explorer 9.
574
+ */
575
+ requestHeaders : {type : "object[]"}
576
+ }
577
+ },
578
+ /**
579
+ * Fired before select file dialog opens.
580
+ * @since 1.102.0
581
+ */
582
+ beforeDialogOpen : {},
583
+
584
+ /**
585
+ * Fired after select file dialog closes.
586
+ * @since 1.102.0
587
+ */
588
+ afterDialogClose : {}
589
+ }
590
+ }, renderer: FileUploaderRenderer});
591
+
592
+ /**
593
+ * Initializes the control.
594
+ * It is called from the constructor.
595
+ * @private
596
+ */
597
+ FileUploader.prototype.init = function(){
598
+ var that = this;
599
+ // load the respective UI-Elements from the FileUploaderHelper
600
+ this.oFilePath = this._createTextField(this.getId() + "-fu_input").addEventDelegate({
601
+ onAfterRendering: function () {
602
+ if (that.getWidth()) {
603
+ that._resizeDomElements();
604
+ }
605
+ }
606
+ });
607
+ this.oBrowse = this._createButton(this.getId() + "-fu_button");
608
+ this.oFilePath.setParent(this);
609
+ this.oBrowse.setParent(this);
610
+
611
+ this.oFileUpload = null;
612
+
613
+ if (ControlBehavior.isAccessibilityEnabled()) {
614
+ if (!FileUploader.prototype._sAccText) {
615
+ var rb = Library.getResourceBundleFor("sap.ui.commons");
616
+ FileUploader.prototype._sAccText = rb.getText("FILEUPLOAD_ACC");
617
+ }
618
+ if (this.oBrowse.addAriaDescribedBy) {
619
+ this.oBrowse.addAriaDescribedBy(this.getId() + "-AccDescr");
620
+ }
621
+
622
+ if (this.oFilePath) {
623
+ this.oFilePath.addAriaLabelledBy(InvisibleText.getStaticId("sap.ui.commons", "FILEUPLOAD_FILENAME"));
624
+ }
625
+ }
626
+ this._submitAfterRendering = false;
627
+
628
+ };
629
+
630
+ FileUploader.prototype.setIcon = function(sIcon) {
631
+ this.oBrowse.setIcon(sIcon);
632
+ this.setProperty("icon", sIcon, false);
633
+ return this;
634
+ };
635
+
636
+ FileUploader.prototype.setIconHovered = function(sIconHovered) {
637
+ this.setProperty("iconHovered", sIconHovered, false);
638
+ if (this.oBrowse.setIconHovered) {
639
+ this.oBrowse.setIconHovered(sIconHovered);
640
+ }
641
+ return this;
642
+ };
643
+
644
+ FileUploader.prototype.setIconSelected = function(sIconSelected) {
645
+ this.setProperty("iconSelected", sIconSelected, false);
646
+ if (this.oBrowse.setIconSelected) {
647
+ this.oBrowse.setIconSelected(sIconSelected);
648
+ } else {
649
+ this.oBrowse.setActiveIcon(sIconSelected);
650
+ }
651
+ return this;
652
+ };
653
+
654
+ FileUploader.prototype.setIconFirst = function(bIconFirst) {
655
+ this.oBrowse.setIconFirst(bIconFirst);
656
+ this.setProperty("iconFirst", bIconFirst, false);
657
+ return this;
658
+ };
659
+
660
+ /**
661
+ * Ensures that FileUploader's internal button will have a reference back to the labels, by which
662
+ * the FileUploader is labelled
663
+ *
664
+ * @returns {this} Reference to <code>this</code> for method chaining
665
+ * @private
666
+ */
667
+ FileUploader.prototype._ensureBackwardsReference = function () {
668
+ var oInternalButton = this.oBrowse,
669
+ aInternalButtonAriaLabelledBy = oInternalButton.getAriaLabelledBy(),
670
+ aReferencingLabels = LabelEnablement.getReferencingLabels(this);
671
+
672
+ if (aInternalButtonAriaLabelledBy) {
673
+ aReferencingLabels.forEach(function (sLabelId) {
674
+ if (aInternalButtonAriaLabelledBy.indexOf(sLabelId) === -1) {
675
+ oInternalButton.addAriaLabelledBy(sLabelId);
676
+ }
677
+ });
678
+ }
679
+
680
+ return this;
681
+ };
682
+
683
+ FileUploader.prototype.setName = function (sName) {
684
+ this.setProperty("name", sName, false);
685
+ this._rerenderInputField();
686
+ return this;
687
+ };
688
+
689
+ FileUploader.prototype.setFileType = function(vTypes) {
690
+ // Compatibility issue: converting the given types to an array in case it is a string
691
+ var aTypes = this._convertTypesToArray(vTypes);
692
+ this.setProperty("fileType", aTypes, false);
693
+ this._rerenderInputField();
694
+ return this;
695
+ };
696
+
697
+ FileUploader.prototype.setMimeType = function(vTypes) {
698
+ // Compatibility issue: converting the given types to an array in case it is a string
699
+ var aTypes = this._convertTypesToArray(vTypes);
700
+ this.setProperty("mimeType", aTypes, false);
701
+ this._rerenderInputField();
702
+ return this;
703
+ };
704
+
705
+ FileUploader.prototype.setMultiple = function(bMultiple) {
706
+ this.setProperty("multiple", bMultiple, false);
707
+ this._rerenderInputField();
708
+ return this;
709
+ };
710
+
711
+ FileUploader.prototype.setDirectory = function(bDirectory) {
712
+ this.setProperty("directory", bDirectory, false);
713
+ this._rerenderInputField();
714
+ return this;
715
+ };
716
+
717
+ FileUploader.prototype._rerenderInputField = function() {
718
+ if (this.oFileUpload) {
719
+ var aFiles = this.oFileUpload.files;
720
+ this._clearInputField();
721
+ this._prepareFileUpload();
722
+
723
+ // Register change event listener for the new input field
724
+ jQuery(this.oFileUpload).on("change", this.handlechange.bind(this));
725
+ // Reattach files to the input field if already selected
726
+ /*eslint strict: [2, "never"]*/
727
+ this.oFileUpload.files = aFiles;
728
+ this._cacheDOMEls();
729
+ }
730
+ };
731
+
732
+ FileUploader.prototype.setTooltip = function(oTooltip) {
733
+ var sTooltip;
734
+
735
+ Control.prototype.setTooltip.call(this, oTooltip);
736
+
737
+ if (this.oFileUpload) {
738
+ sTooltip = this.getTooltip_AsString();
739
+
740
+ if (sTooltip) {
741
+ this.oFileUpload.setAttribute("title", sTooltip);
742
+ } else {
743
+ this.oFileUpload.setAttribute("title", this.getValue() ? this.getValue() : this._getNoFileChosenText());
744
+ }
745
+ }
746
+ return this;
747
+ };
748
+
749
+ FileUploader.prototype.addAriaLabelledBy = function(sID) {
750
+ this.addAssociation("ariaLabelledBy", sID);
751
+ this.oBrowse.addAriaLabelledBy(sID);
752
+
753
+ return this;
754
+ };
755
+
756
+ FileUploader.prototype.removeAriaLabelledBy = function(sID) {
757
+ var sLabelId = this.removeAssociation("ariaLabelledBy", sID);
758
+ if (!sLabelId) {
759
+ return;
760
+ }
761
+
762
+ this.oBrowse.removeAriaLabelledBy(sLabelId);
763
+
764
+ return sLabelId;
765
+ };
766
+
767
+ FileUploader.prototype.removeAllAriaLabelledBy = function() {
768
+ var aLabelIds = this.removeAllAssociation("ariaLabelledBy"),
769
+ aButtonLabels = this.oBrowse.getAriaLabelledBy();
770
+
771
+ // We make sure to leave any sap.m.Label in the button's ariaLabelledBy
772
+ aLabelIds.forEach(function(sLabelId) {
773
+ if (aButtonLabels.indexOf(sLabelId) >= 0) {
774
+ this.oBrowse.removeAriaLabelledBy(sLabelId);
775
+ }
776
+ }.bind(this));
777
+
778
+ return aLabelIds;
779
+ };
780
+
781
+ FileUploader.prototype.addAriaDescribedBy = function(sID) {
782
+ this.addAssociation("ariaDescribedBy", sID);
783
+ this.oBrowse.addAriaDescribedBy(sID);
784
+
785
+ return this;
786
+ };
787
+
788
+ FileUploader.prototype.removeAriaDescribedBy = function(sID) {
789
+ var sDescriptionId = this.removeAssociation("ariaDescribedBy", sID);
790
+ if (!sDescriptionId) {
791
+ return;
792
+ }
793
+
794
+ this.oBrowse.removeAriaDescribedBy(sDescriptionId);
795
+
796
+ return sDescriptionId;
797
+ };
798
+
799
+ FileUploader.prototype.removeAllAriaDescribedBy = function() {
800
+ var aDescriptionIds = this.removeAllAssociation("ariaDescribedBy"),
801
+ aButtonDescriptionIds = this.oBrowse.getAriaDescribedBy();
802
+
803
+ // Keep the default accessibility description in the -AccDescr element
804
+ aDescriptionIds.forEach(function(sLabelId) {
805
+ if (aButtonDescriptionIds.indexOf(sLabelId) >= 0) {
806
+ this.oBrowse.removeAriaDescribedBy(sLabelId);
807
+ }
808
+ }.bind(this));
809
+
810
+ return aDescriptionIds;
811
+ };
812
+
813
+
814
+ FileUploader.prototype._createTextField = function(sId) {
815
+ var oTextField = new TextField(sId);
816
+ return oTextField;
817
+ };
818
+ FileUploader.prototype._setTextFieldContent = function(oTextField, sWidth){
819
+ oTextField.setWidth(sWidth);
820
+ };
821
+ FileUploader.prototype._createButton = function(sId){
822
+ var oButton = new Button(sId);
823
+ return oButton;
824
+ };
825
+ FileUploader.prototype._addFormClass = function(){ return "sapUiCFUM"; };
826
+
827
+
828
+ /*
829
+ * Generates the text, which would be placed as an accessibility description,
830
+ * based on the current FileUploader's placeholder, value and tooltip.
831
+ */
832
+ FileUploader.prototype._generateAccDescriptionText = function () {
833
+ var sTooltip = this.getTooltip_AsString(),
834
+ sPlaceholder = this.getPlaceholder(),
835
+ sValue = this.getValue(),
836
+ bIsRequired = LabelEnablement.isRequired(this),
837
+ sAccDescription = "";
838
+
839
+ if (bIsRequired) {
840
+ sAccDescription += Library.getResourceBundleFor("sap.ui.commons").getText("FILEUPLOAD_REQUIRED") + " ";
841
+ }
842
+
843
+ if (sTooltip) {
844
+ sAccDescription += sTooltip + " ";
845
+ }
846
+
847
+ if (sValue) {
848
+ sAccDescription += sValue + " ";
849
+ } else if (sPlaceholder) {
850
+ sAccDescription += sPlaceholder + " ";
851
+ }
852
+
853
+ sAccDescription += this._sAccText;
854
+
855
+ return sAccDescription;
856
+ };
857
+
858
+
859
+ /**
860
+ * Helper to ensure, that the types (file or mime) are inside an array.
861
+ * The FUP also accepts comma-separated strings for its fileType and mimeType property.
862
+ * @private
863
+ */
864
+ FileUploader.prototype._convertTypesToArray = function (vTypes) {
865
+ if (typeof vTypes === "string") {
866
+ if (vTypes === "") {
867
+ return [];
868
+ } else {
869
+ return vTypes.split(",").map(function (sType) {
870
+ return sType.trim();
871
+ });
872
+ }
873
+ }
874
+ return vTypes;
875
+ };
876
+
877
+ /**
878
+ * Terminates the control when it has been destroyed.
879
+ * @private
880
+ */
881
+ FileUploader.prototype.exit = function(){
882
+
883
+ // destroy the nested controls
884
+ this.oFilePath.destroy();
885
+ this.oBrowse.destroy();
886
+
887
+ // remove the IFRAME
888
+ if (this.oIFrameRef) {
889
+ jQuery(this.oIFrameRef).off();
890
+ StaticArea.getDomRef().removeChild(this.oIFrameRef);
891
+ this.oIFrameRef = null;
892
+ }
893
+
894
+ if (this.oFileUpload) {
895
+ this._clearInputField();
896
+ }
897
+
898
+ if (this.FUEl) {
899
+ this.FUEl = null;
900
+ }
901
+
902
+ if (this.FUDataEl) {
903
+ this.FUDataEl = null;
904
+ }
905
+ };
906
+
907
+ FileUploader.prototype._clearInputField = function() {
908
+ jQuery(this.oFileUpload).off();
909
+ this.oFileUpload.parentElement.removeChild(this.oFileUpload);
910
+ this.oFileUpload = null;
911
+ };
912
+
913
+ /**
914
+ * Clean up event listeners before rendering
915
+ * @private
916
+ */
917
+ FileUploader.prototype.onBeforeRendering = function() {
918
+ // store the file uploader outside in the static area
919
+ var oStaticArea = StaticArea.getDomRef();
920
+ jQuery(this.oFileUpload).appendTo(oStaticArea);
921
+
922
+ if (!this.getName()) {
923
+ Log.warning("Name property is not set. It would be used instead to identify the control on the server.", this);
924
+ }
925
+
926
+ // unbind the custom event handlers
927
+ jQuery(this.oFileUpload).off();
928
+
929
+ if (this.getIconOnly() && this.getButtonOnly()) {
930
+ this.oBrowse.setText("");
931
+ this.oBrowse.setTooltip(this.getTooltip_AsString() || this.getBrowseText());
932
+ } else if (this.getIconOnly()) {
933
+ this.oBrowse.setText("");
934
+ this.oBrowse.setTooltip(this.getBrowseText());
935
+ } else {
936
+ this.oBrowse.setText(this.getButtonText() || this.getBrowseText());
937
+ this.oBrowse.setTooltip("");
938
+ }
939
+
940
+ this.oFilePath.setPlaceholder(this.getPlaceholder());
941
+ };
942
+
943
+ /**
944
+ * Prepare the upload processing, establish the change handler for the
945
+ * pure html input object.
946
+ * @private
947
+ */
948
+ FileUploader.prototype.onAfterRendering = function() {
949
+
950
+ // prepare the file upload control and the upload iframe
951
+ this.prepareFileUploadAndIFrame();
952
+
953
+ this._cacheDOMEls();
954
+ this._addLabelFeaturesToBrowse();
955
+
956
+ // event listener registration for change event
957
+ jQuery(this.oFileUpload).on("change", this.handlechange.bind(this));
958
+
959
+ this.oFilePath.$().attr("tabindex", "-1");
960
+
961
+ setTimeout(this._recalculateWidth.bind(this), 0);
962
+
963
+ this.oFilePath.$().find('input').removeAttr("role").attr("aria-live", "polite");
964
+
965
+ if (this._submitAfterRendering) {
966
+ this._submitAndResetValue();
967
+ this._submitAfterRendering = false;
968
+ }
969
+ };
970
+
971
+
972
+ FileUploader.prototype._cacheDOMEls = function() {
973
+ this.FUEl = this.getDomRef("fu");
974
+ this.FUDataEl = this.getDomRef("fu_data");
975
+ };
976
+
977
+ FileUploader.prototype.onfocusin = function(oEvent) {
978
+
979
+ if (!this.oFilePath.shouldValueStateMessageBeOpened || this.oFilePath.shouldValueStateMessageBeOpened()) {
980
+ this.openValueStateMessage();
981
+ }
982
+
983
+ };
984
+
985
+ FileUploader.prototype.onsapfocusleave = function(oEvent) {
986
+
987
+ if (!oEvent.relatedControlId || !containsOrEquals(this.getDomRef(), Element.getElementById(oEvent.relatedControlId).getFocusDomRef())) {
988
+ this.closeValueStateMessage();
989
+ }
990
+
991
+ };
992
+
993
+ FileUploader.prototype._recalculateWidth = function() {
994
+ // calculation of the width of the overlay for the original file upload
995
+ // !Device.browser.msie check: only for non IE browsers since there we need
996
+ // the button in front of the fileuploader
997
+ if (this.getWidth()) {
998
+ if (this.getButtonOnly() && this.oBrowse.getDomRef()) {
999
+ this.oBrowse.getDomRef().style.width = this.getWidth();
1000
+ }
1001
+ // Recalculate the textfield width...
1002
+ this._resizeDomElements();
1003
+ }
1004
+ };
1005
+
1006
+ /**
1007
+ * Returns the DOM element that should be focused, when the focus is set onto the control.
1008
+ * @returns {Element} The DOM element that should be focused
1009
+ */
1010
+ FileUploader.prototype.getFocusDomRef = function() {
1011
+ return this.oBrowse.getDomRef();
1012
+ };
1013
+
1014
+ FileUploader.prototype._resizeDomElements = function() {
1015
+ var sId = this.getId();
1016
+ this._oBrowseDomRef = this.oBrowse.getDomRef();
1017
+ var $b = jQuery(this._oBrowseDomRef);
1018
+ var _buttonWidth = $b.parent().outerWidth(true);
1019
+ this._oFilePathDomRef = this.oFilePath.getDomRef();
1020
+ var oDomRef = this._oFilePathDomRef;
1021
+ var sWidth = this.getWidth();
1022
+
1023
+ if (sWidth.substr( -1) == "%" && oDomRef) {
1024
+ // Special case - if the width is not in px, we only change the top element
1025
+
1026
+ // Resize all elements from the input field up to the control element itself.
1027
+ while (oDomRef.id != sId) {
1028
+ oDomRef.style.width = "100%";
1029
+ oDomRef = oDomRef.parentNode;
1030
+ }
1031
+
1032
+ oDomRef.style.width = sWidth;
1033
+ } else if (oDomRef){
1034
+ oDomRef.style.width = sWidth;
1035
+
1036
+ // Now make sure the field including the button has the correct size
1037
+ var $fp = jQuery(this._oFilePathDomRef);
1038
+ var _newWidth = $fp.outerWidth() - _buttonWidth;
1039
+ if (_newWidth < 0) {
1040
+ this.oFilePath.getDomRef().style.width = "0px";
1041
+ if (this.oFileUpload) {
1042
+ this.oFileUpload.style.width = $b.outerWidth(true);
1043
+ }
1044
+ } else {
1045
+ this.oFilePath.getDomRef().style.width = _newWidth + "px";
1046
+ }
1047
+ }
1048
+ };
1049
+
1050
+ FileUploader.prototype.onresize = function() {
1051
+ this._recalculateWidth();
1052
+ };
1053
+
1054
+ FileUploader.prototype.onThemeChanged = function() {
1055
+ this._recalculateWidth();
1056
+ };
1057
+
1058
+ FileUploader.prototype.setEnabled = function(bEnabled){
1059
+ var $oFileUpload = jQuery(this.oFileUpload);
1060
+
1061
+ this.setProperty("enabled", bEnabled, false);
1062
+ this.oFilePath.setEnabled(bEnabled);
1063
+ this.oBrowse.setEnabled(bEnabled);
1064
+
1065
+ if (this.getEnabled()) {
1066
+ $oFileUpload.removeAttr('disabled');
1067
+ } else {
1068
+ $oFileUpload.attr('disabled', 'disabled');
1069
+ }
1070
+
1071
+ return this;
1072
+ };
1073
+
1074
+ FileUploader.prototype.setValueState = function(sValueState) {
1075
+
1076
+ this.setProperty("valueState", sValueState, false);
1077
+ //as of 1.23.1 oFilePath can be an sap.ui.commons.TextField or an sap.m.Input, which both have a valueState
1078
+ if (this.oFilePath.setValueState) {
1079
+ this.oFilePath.setValueState(sValueState);
1080
+ } else {
1081
+ Log.warning("Setting the valueState property with the combination of libraries used is not supported.", this);
1082
+ }
1083
+
1084
+ var bControlFocused = containsOrEquals(this.getDomRef(), document.activeElement);
1085
+
1086
+ switch (sValueState) {
1087
+ case ValueState.Error:
1088
+ case ValueState.Warning:
1089
+ case ValueState.Success:
1090
+ this.oBrowse.addAssociation("ariaDescribedBy", this.oFilePath.getId() + "-message-sr");
1091
+ if (bControlFocused) {
1092
+ this.openValueStateMessage();
1093
+ }
1094
+ break;
1095
+ default:
1096
+ this.oBrowse.removeAssociation("ariaDescribedBy", this.oFilePath.getId() + "-message-sr");
1097
+ if (bControlFocused) {
1098
+ this.closeValueStateMessage();
1099
+ }
1100
+ }
1101
+
1102
+ return this;
1103
+
1104
+ };
1105
+
1106
+ FileUploader.prototype.setValueStateText = function(sValueStateText) {
1107
+ if (this.oFilePath.setValueStateText) {
1108
+ this.oFilePath.setValueStateText(sValueStateText);
1109
+ } else {
1110
+ Log.warning("Setting the valueStateText property with the combination of libraries used is not supported.", this);
1111
+ }
1112
+
1113
+ return this.setProperty("valueStateText", sValueStateText, false);
1114
+ };
1115
+
1116
+ FileUploader.prototype.setStyle = function(sStyle) {
1117
+ this.setProperty("style", sStyle, true);
1118
+ if (sStyle) {
1119
+ if (sStyle == "Transparent") {
1120
+ if (this.oBrowse.setLite) {
1121
+ this.oBrowse.setLite(true);
1122
+ } else {
1123
+ this.oBrowse.setType("Transparent");
1124
+ }
1125
+ } else if (this.oBrowse.setType) {
1126
+ this.oBrowse.setType(sStyle);
1127
+ } else {
1128
+ if (sStyle == "Emphasized") {
1129
+ sStyle = "Emph";
1130
+ }
1131
+ this.oBrowse.setStyle(sStyle);
1132
+ }
1133
+ }
1134
+ return this;
1135
+ };
1136
+
1137
+ FileUploader.prototype.setValue = function(sValue, bFireEvent, bSupressFocus) {
1138
+ var oldValue = this.getValue();
1139
+ var oFiles;
1140
+ if ((oldValue != sValue) || this.getSameFilenameAllowed()) {
1141
+ // only upload when a valid value is set
1142
+ var bUpload = this.getUploadOnChange() && sValue;
1143
+ // when we do not upload we re-render (cause some browsers don't like
1144
+ // to change the value of file uploader INPUT elements)
1145
+ this.setProperty("value", sValue, bUpload);
1146
+ if (this.oFileUpload && !this.getTooltip_AsString()) {
1147
+ this.oFileUpload.setAttribute("title", sValue ? sValue : this._getNoFileChosenText());
1148
+ }
1149
+ if (this.oFilePath) {
1150
+ this.oFilePath.setValue(sValue);
1151
+ //refocus the Button, except bSupressFocus is set
1152
+ if (this.oBrowse.getDomRef() && !bSupressFocus && containsOrEquals(this.getDomRef(), document.activeElement)) {
1153
+ this.oBrowse.focus();
1154
+ }
1155
+ }
1156
+ var oForm = this.getDomRef("fu_form"),
1157
+ sapMInnerInput = this.getDomRef("fu_input-inner");
1158
+ //reseting the input fields if setValue("") is called, also for undefined and null
1159
+ if (this.oFileUpload && /* is visible: */ oForm && !sValue) {
1160
+ // some browsers do not allow to clear the value of the fileuploader control
1161
+ // therefore we utilize the form and reset the values inside this form and
1162
+ // apply the additionalData again afterwards
1163
+ oForm.reset();
1164
+ this.getDomRef("fu_input").value = "";
1165
+ //if the sap.m library is used, we also need to clear the inner input-field of sap.m.Input
1166
+ if (sapMInnerInput) {
1167
+ sapMInnerInput.value = "";
1168
+ }
1169
+ //keep the additional data on the form
1170
+ jQuery(this.FUDataEl).val(this.getAdditionalData());
1171
+ }
1172
+ // only fire event when triggered by user interaction
1173
+ if (bFireEvent) {
1174
+ if (window.File) {
1175
+ oFiles = this.FUEl.files;
1176
+ }
1177
+ if (!this.getSameFilenameAllowed() || (sValue && oldValue != sValue)) {
1178
+ this.fireChange({id:this.getId(), newValue:sValue, files:oFiles});
1179
+ }
1180
+ }
1181
+ if (bUpload) {
1182
+ this.upload();
1183
+ }
1184
+ }
1185
+ return this;
1186
+ };
1187
+
1188
+
1189
+ /**
1190
+ * Clears the content of the <code>FileUploader</code>.
1191
+ *
1192
+ * <b>Note:</b> The attached additional data however is retained.
1193
+ *
1194
+ * @public
1195
+ * @since 1.25.0
1196
+ * @returns {this} Reference to <code>this</code> for method chaining
1197
+ */
1198
+ FileUploader.prototype.clear = function () {
1199
+ var uploadForm = this.getDomRef("fu_form");
1200
+ if (uploadForm) {
1201
+ uploadForm.reset();
1202
+ } else if (this.oFileUpload) {
1203
+ this.oFileUpload.files = new DataTransfer().files;
1204
+ }
1205
+ //clear the value, don't fire change event, and suppress the refocusing of the file input field
1206
+ return this.setValue("", false, true);
1207
+ };
1208
+
1209
+ /**
1210
+ * Programmatically opens the file picker dialog.
1211
+ *
1212
+ * @since 1.112
1213
+ * @returns {this} Reference to <code>this</code> for method chaining
1214
+ * @private
1215
+ * @ui5-restricted sap.suite.ui.commons.CloudFilePicker
1216
+ */
1217
+ FileUploader.prototype.openFilePicker = function () {
1218
+ if (this.oFileUpload) {
1219
+ this.oFileUpload.click();
1220
+ }
1221
+
1222
+ return this;
1223
+ };
1224
+
1225
+ /**
1226
+ * Provides a reference to the type "file" input field of the control.
1227
+ *
1228
+ * @since 1.112
1229
+ * @returns {HTMLElement|null} The input type "file" DOM representation.
1230
+ * @private
1231
+ * @ui5-restricted sap.suite.ui.commons.CloudFilePicker
1232
+ */
1233
+ FileUploader.prototype.getInputReference = function () {
1234
+ return this.oFileUpload;
1235
+ };
1236
+
1237
+ FileUploader.prototype.onmousedown = function(oEvent) {
1238
+ this.oBrowse.onmousedown(oEvent);
1239
+ };
1240
+
1241
+ FileUploader.prototype.onmouseup = function(oEvent) {
1242
+ this.oBrowse.onmouseup(oEvent);
1243
+ };
1244
+
1245
+ FileUploader.prototype.onmouseover = function (oEvent) {
1246
+ jQuery(this.oBrowse.getDomRef()).addClass('sapUiBtnStdHover');
1247
+ this.oBrowse.onmouseover(oEvent);
1248
+ };
1249
+
1250
+ FileUploader.prototype.onmouseout = function (oEvent) {
1251
+ jQuery(this.oBrowse.getDomRef()).removeClass('sapUiBtnStdHover');
1252
+ this.oBrowse.onmouseout(oEvent);
1253
+ };
1254
+
1255
+ FileUploader.prototype.setAdditionalData = function(sAdditionalData) {
1256
+ // set the additional data in the hidden input
1257
+ this.setProperty("additionalData", sAdditionalData, true);
1258
+ var oAdditionalData = this.FUDataEl;
1259
+ if (oAdditionalData) {
1260
+ sAdditionalData = this.getAdditionalData() || "";
1261
+ oAdditionalData.value = sAdditionalData;
1262
+ }
1263
+ return this;
1264
+ };
1265
+
1266
+ FileUploader.prototype.sendFiles = function(aXhr, iIndex) {
1267
+ var that = this;
1268
+ var bAllPosted = true;
1269
+
1270
+ for (var i = 0; i < aXhr.length; i++) {
1271
+ if (!aXhr[i].bPosted) {
1272
+ bAllPosted = false;
1273
+ break;
1274
+ }
1275
+ }
1276
+
1277
+ if (bAllPosted) {
1278
+ if (this.getSameFilenameAllowed() && this.getUploadOnChange()) {
1279
+ that.setValue("", true);
1280
+ }
1281
+ return;
1282
+ }
1283
+
1284
+ var oXhr = aXhr[iIndex];
1285
+ var sFilename = oXhr.file.name ? oXhr.file.name : "MultipartFile";
1286
+ var oRequestHeaders = oXhr.requestHeaders;
1287
+
1288
+ var fnProgressListener = function(oProgressEvent) {
1289
+ var oProgressData = {
1290
+ lengthComputable: !!oProgressEvent.lengthComputable,
1291
+ loaded: oProgressEvent.loaded,
1292
+ total: oProgressEvent.total
1293
+ };
1294
+ that.fireUploadProgress({
1295
+ "lengthComputable": oProgressData.lengthComputable,
1296
+ "loaded": oProgressData.loaded,
1297
+ "total": oProgressData.total,
1298
+ "fileName": sFilename,
1299
+ "requestHeaders": oRequestHeaders
1300
+ });
1301
+ };
1302
+
1303
+ oXhr.xhr.upload.addEventListener("progress", fnProgressListener);
1304
+
1305
+ oXhr.xhr.onreadystatechange = function() {
1306
+
1307
+ var sResponse;
1308
+ var sResponseRaw;
1309
+ var mHeaders = {};
1310
+ var sPlainHeader;
1311
+ var aHeaderLines;
1312
+ var iHeaderIdx;
1313
+ var sReadyState;
1314
+ sReadyState = oXhr.xhr.readyState;
1315
+ var iStatus = oXhr.xhr.status;
1316
+
1317
+ if (oXhr.xhr.readyState == 4) {
1318
+ //this check is needed, because (according to the xhr spec) the readyState is set to OPEN (4)
1319
+ //as soon as the xhr is aborted. Only after the progress events are fired, the state is set to UNSENT (0)
1320
+ if (oXhr.xhr.responseXML) {
1321
+ sResponse = oXhr.xhr.responseXML.documentElement.textContent;
1322
+ }
1323
+ sResponseRaw = oXhr.xhr.response;
1324
+
1325
+ //Parse the http-header into a map
1326
+ sPlainHeader = oXhr.xhr.getAllResponseHeaders();
1327
+ if (sPlainHeader) {
1328
+ aHeaderLines = sPlainHeader.split("\u000d\u000a");
1329
+ for (var i = 0; i < aHeaderLines.length; i++) {
1330
+ if (aHeaderLines[i]) {
1331
+ iHeaderIdx = aHeaderLines[i].indexOf("\u003a\u0020");
1332
+ mHeaders[aHeaderLines[i].substring(0, iHeaderIdx)] = aHeaderLines[i].substring(iHeaderIdx + 2);
1333
+ }
1334
+ }
1335
+ }
1336
+ that.fireUploadComplete({
1337
+ "fileName": sFilename,
1338
+ "headers": mHeaders,
1339
+ "response": sResponse,
1340
+ "responseRaw": sResponseRaw,
1341
+ "readyStateXHR": sReadyState,
1342
+ "status": iStatus,
1343
+ "requestHeaders": oRequestHeaders
1344
+ });
1345
+ }
1346
+ that._bUploading = false;
1347
+ };
1348
+ if (oXhr.xhr.readyState === 0 || oXhr.bPosted) {
1349
+ iIndex++;
1350
+ that.sendFiles(aXhr, iIndex);
1351
+ } else {
1352
+ oXhr.xhr.send(oXhr.file);
1353
+ oXhr.bPosted = true;
1354
+ iIndex++;
1355
+ that.sendFiles(aXhr, iIndex);
1356
+ }
1357
+ };
1358
+
1359
+
1360
+ /**
1361
+ * Starts the upload (as defined by uploadUrl).
1362
+ *
1363
+ * @param {boolean} [bPreProcessFiles] Set to <code>true</code> to allow pre-processing of the files before sending the request.
1364
+ * As a result, the <code>upload</code> method becomes asynchronous. See {@link sap.ui.commons.IProcessableBlobs} for more information.
1365
+ * <b>Note:</b> This parameter is only taken into account when <code>sendXHR</code> is set to <code>true</code>.
1366
+ *
1367
+ * @type void
1368
+ * @public
1369
+ */
1370
+ FileUploader.prototype.upload = function(bPreProcessFiles) {
1371
+ var uploadForm,
1372
+ sActionAttr;
1373
+
1374
+ //supress Upload if the FileUploader is not enabled
1375
+ if (!this.getEnabled()) {
1376
+ return;
1377
+ }
1378
+
1379
+ uploadForm = this.getDomRef("fu_form");
1380
+
1381
+ try {
1382
+ this._bUploading = true;
1383
+ if (this.getSendXHR() && window.File) {
1384
+ var aFiles = this.FUEl.files;
1385
+ if (bPreProcessFiles) {
1386
+ this._sendProcessedFilesWithXHR(aFiles);
1387
+ } else {
1388
+ this._sendFilesWithXHR(aFiles);
1389
+ }
1390
+ } else if (uploadForm) {
1391
+ // In order to do the submit, the action DOM attribute of the inner form should be accurate.
1392
+ // If there is a change in the passed to the uploadUrl property string, we must ensure that it is
1393
+ // applied in the DOM and the submit is performed after there is new rendering.
1394
+ sActionAttr = uploadForm.getAttribute("action");
1395
+ if (sActionAttr !== this.getUploadUrl()) {
1396
+ this._submitAfterRendering = true;
1397
+ } else {
1398
+ this._submitAndResetValue();
1399
+ }
1400
+ }
1401
+ } catch (oException) {
1402
+ Log.error("File upload failed:\n" + oException.message);
1403
+ }
1404
+ };
1405
+
1406
+ FileUploader.prototype._submitAndResetValue = function() {
1407
+ var uploadForm = this.getDomRef("fu_form");
1408
+
1409
+ uploadForm.submit();
1410
+ this.fireUploadStart();
1411
+ this._resetValueAfterUploadStart();
1412
+ };
1413
+
1414
+ /**
1415
+ * Aborts the currently running upload.
1416
+ *
1417
+ * @param {string} sHeaderParameterName
1418
+ * The name of the parameter within the <code>headerParameters</code> aggregation to be checked.
1419
+ *
1420
+ * <b>Note:</b> aborts the request, sent with a header parameter with the provided name.
1421
+ * The parameter is taken into account if the sHeaderParameterValue parameter is provided too.
1422
+ *
1423
+ * @param {string} sHeaderParameterValue
1424
+ * The value of the parameter within the <code>headerParameters</code> aggregation to be checked.
1425
+ *
1426
+ * <b>Note:</b> aborts the request, sent with a header parameter with the provided value.
1427
+ * The parameter is taken into account if the sHeaderParameterName parameter is provided too.
1428
+ * @public
1429
+ * @since 1.24.0
1430
+ */
1431
+ FileUploader.prototype.abort = function(sHeaderParameterName, sHeaderParameterValue) {
1432
+ if (!this.getUseMultipart()) {
1433
+ var iStart = this._aXhr.length - 1;
1434
+ for (var i = iStart; i > -1; i--) {
1435
+ if (sHeaderParameterName && sHeaderParameterValue) {
1436
+ for (var j = 0; j < this._aXhr[i].requestHeaders.length; j++) {
1437
+ var sHeader = this._aXhr[i].requestHeaders[j].name;
1438
+ var sValue = this._aXhr[i].requestHeaders[j].value;
1439
+ if (sHeader == sHeaderParameterName && sValue == sHeaderParameterValue) {
1440
+ this._aXhr[i].xhr.abort();
1441
+ this.fireUploadAborted({
1442
+ "fileName": this._aXhr[i].fileName,
1443
+ "requestHeaders": this._aXhr[i].requestHeaders
1444
+ });
1445
+ // Remove aborted entry from internal array.
1446
+ this._aXhr.splice(i, 1);
1447
+ Log.info("File upload aborted.");
1448
+ break;
1449
+ }
1450
+ }
1451
+ } else {
1452
+ this._aXhr[i].xhr.abort();
1453
+ this.fireUploadAborted({
1454
+ "fileName": this._aXhr[i].fileName,
1455
+ "requestHeaders": this._aXhr[i].requestHeaders
1456
+ });
1457
+ // Remove aborted entry from internal array.
1458
+ this._aXhr.splice(i, 1);
1459
+ Log.info("File upload aborted.");
1460
+ }
1461
+ }
1462
+ } else if (this._uploadXHR && this._uploadXHR.abort) {
1463
+ // fires a progress event 'abort' on the _uploadXHR
1464
+ this._uploadXHR.abort();
1465
+ this.fireUploadAborted({
1466
+ "fileName": null,
1467
+ "requestHeaders": null
1468
+ });
1469
+ Log.info("File upload aborted.");
1470
+ }
1471
+ };
1472
+
1473
+ FileUploader.prototype.onclick = function(oEvent) {
1474
+ var bFileInput = oEvent.target.getAttribute("type") === "file";
1475
+ if (bFileInput && this.getSameFilenameAllowed() && this.getEnabled()) {
1476
+ this.setValue("", true);
1477
+ }
1478
+ //refocus the Button, except bSupressFocus is set
1479
+ if (this.oBrowse.getDomRef() && (Device.browser.safari || containsOrEquals(this.getDomRef(), document.activeElement))) {
1480
+ this.oBrowse.focus();
1481
+ }
1482
+
1483
+ if (oEvent.target.getAttribute("type") === "file") {
1484
+ this.fireBeforeDialogOpen();
1485
+
1486
+ document.body.onfocus = function () {
1487
+ this.fireAfterDialogClose();
1488
+ document.body.onfocus = null;
1489
+ }.bind(this);
1490
+ }
1491
+ };
1492
+
1493
+ //
1494
+ //Event Handling
1495
+ //
1496
+ FileUploader.prototype.onkeydown = function(oEvent) {
1497
+ if (!this.getEnabled()) {
1498
+ return;
1499
+ }
1500
+ if (this.getSameFilenameAllowed() && this.getUploadOnChange()) {
1501
+ this.setValue("", true);
1502
+ }
1503
+ var iKeyCode = oEvent.keyCode;
1504
+ if (iKeyCode === KeyCodes.ENTER) {
1505
+ // consider to always put the focus on the hidden file uploader
1506
+ // and let the fileuploader manage the keyboard interaction
1507
+ if (this.oFileUpload) {
1508
+ this.oFileUpload.click();
1509
+ oEvent.preventDefault();
1510
+ oEvent.stopPropagation();
1511
+ }
1512
+ }
1513
+
1514
+ this.oBrowse._bPressedSpace = false;
1515
+ };
1516
+
1517
+ FileUploader.prototype.onkeyup = function(oEvent) {
1518
+ if (!this.getEnabled()) {
1519
+ return;
1520
+ }
1521
+ if (this.getSameFilenameAllowed() && this.getUploadOnChange()) {
1522
+ this.setValue("", true);
1523
+ }
1524
+ var iKeyCode = oEvent.keyCode,
1525
+ eKC = KeyCodes;
1526
+ if (iKeyCode === eKC.DELETE || iKeyCode === eKC.BACKSPACE) {
1527
+ if (this.oFileUpload) {
1528
+ this.setValue("", true);
1529
+ }
1530
+ } else if (iKeyCode === eKC.SPACE) {
1531
+ this.oFileUpload.click();
1532
+ oEvent.preventDefault();
1533
+ oEvent.stopPropagation();
1534
+ } else if (iKeyCode !== eKC.TAB &&
1535
+ iKeyCode !== eKC.SHIFT &&
1536
+ iKeyCode !== eKC.F6 &&
1537
+ iKeyCode !== eKC.PAGE_UP &&
1538
+ iKeyCode !== eKC.PAGE_DOWN &&
1539
+ iKeyCode !== eKC.ESCAPE &&
1540
+ iKeyCode !== eKC.END &&
1541
+ iKeyCode !== eKC.HOME &&
1542
+ iKeyCode !== eKC.ARROW_LEFT &&
1543
+ iKeyCode !== eKC.ARROW_UP &&
1544
+ iKeyCode !== eKC.ARROW_RIGHT &&
1545
+ iKeyCode !== eKC.ARROW_DOWN) {
1546
+ oEvent.preventDefault();
1547
+ oEvent.stopPropagation();
1548
+ }
1549
+
1550
+ this.oBrowse._bPressedSpace = false;
1551
+ };
1552
+
1553
+ /**
1554
+ * Helper function to check if the given filename is longer than the specified 'maximumFilenameLength'.
1555
+ * @param {string} [sFilename] the filename which should be tested
1556
+ * @param {boolean} [bFireEvent] if necessary, this flag triggers that a filenameLengthExceed event is fired
1557
+ * @returns {boolean} whether the filename is too long or not
1558
+ * @private
1559
+ */
1560
+ FileUploader.prototype._isFilenameTooLong = function (sFilename) {
1561
+ var iMaxFilenameLength = this.getMaximumFilenameLength();
1562
+ if (iMaxFilenameLength !== 0 && sFilename.length > iMaxFilenameLength) {
1563
+ Log.info("The filename of " + sFilename + " (" + sFilename.length + " characters) is longer than the maximum of " + iMaxFilenameLength + " characters.");
1564
+ return true;
1565
+ }
1566
+
1567
+ return false;
1568
+ };
1569
+
1570
+ FileUploader.prototype.handlechange = function(oEvent) {
1571
+ if (this.oFileUpload && this.getEnabled()) {
1572
+ var aFileTypes = this.getFileType();
1573
+
1574
+ var sFileString = '';
1575
+ var bWrongType, sName, iIdx, sFileEnding;
1576
+ var uploadForm = this.getDomRef("fu_form");
1577
+
1578
+ if (window.File) {
1579
+ var aFiles = oEvent.target.files;
1580
+
1581
+ if (this._areFilesAllowed(aFiles)) {
1582
+ this.fireFileAllowed();
1583
+ sFileString = this._generateInputValue(aFiles);
1584
+ } else {
1585
+ uploadForm.reset();
1586
+ this.setValue("", true, true);
1587
+ return;
1588
+ }
1589
+ } else if (aFileTypes && aFileTypes.length > 0) {
1590
+ // This else case is executed if the File-API is not supported by the browser (especially IE9).
1591
+ // Check if allowed file types match the chosen file from the oFileUpload IFrame Workaround.
1592
+ bWrongType = true;
1593
+ sName = this.oFileUpload.value || "";
1594
+ iIdx = sName.lastIndexOf(".");
1595
+ sFileEnding = (iIdx === -1) ? "" : sName.substring(iIdx + 1);
1596
+ for (var l = 0; l < aFileTypes.length; l++) {
1597
+ if (sFileEnding == aFileTypes[l]) {
1598
+ bWrongType = false;
1599
+ }
1600
+ }
1601
+ if (bWrongType) {
1602
+ Log.info("File: " + sName + " is of type " + sFileEnding + ". Allowed types are: " + aFileTypes + ".");
1603
+ this.fireTypeMissmatch({
1604
+ fileName:sName,
1605
+ fileType:sFileEnding
1606
+ });
1607
+ uploadForm.reset();
1608
+ this.setValue("", true, true);
1609
+ return;
1610
+ }
1611
+ //check if the filename is too long and fire the corresponding event if necessary
1612
+ if (this._isFilenameTooLong(sName)) {
1613
+ this.fireFilenameLengthExceed({
1614
+ fileName: sName
1615
+ });
1616
+ uploadForm.reset();
1617
+ this.setValue("", true, true);
1618
+ return;
1619
+ }
1620
+ if (sName) {
1621
+ this.fireFileAllowed();
1622
+ }
1623
+ }
1624
+
1625
+ // due to new security mechanism modern browsers simply
1626
+ // append a fakepath in front of the filename instead of
1627
+ // returning the filename only - we strip this path now
1628
+ var sValue = this.oFileUpload.value || "";
1629
+ var iIndex = sValue.lastIndexOf("\\");
1630
+
1631
+ if (iIndex >= 0) {
1632
+ sValue = sValue.substring(iIndex + 1);
1633
+ }
1634
+
1635
+ if (this.getMultiple() || this.getDirectory()) {
1636
+ sValue = sFileString;
1637
+ }
1638
+
1639
+ //sValue has to be filled to avoid clearing the FilePath by pressing cancel
1640
+ if (sValue || Device.browser.chrome) { // in Chrome the file path has to be cleared as the upload will be avoided
1641
+ this.setValue(sValue, true);
1642
+ }
1643
+ }
1644
+ };
1645
+
1646
+ //
1647
+ // Private
1648
+ //
1649
+
1650
+ /*
1651
+ * Send passed files as argument trough XHR request.
1652
+ * @param {array} [aFiles] list of files from type window.File, this array is returned from input type="file" or from Drag and Drop
1653
+ * @returns this
1654
+ * @private
1655
+ */
1656
+ FileUploader.prototype._sendFilesWithXHR = function (aFiles) {
1657
+ var iFiles,
1658
+ sHeader,
1659
+ sValue,
1660
+ oXhrEntry,
1661
+ oXHRSettings = this.getXhrSettings();
1662
+
1663
+ if (aFiles.length > 0) {
1664
+ if (this.getUseMultipart()) {
1665
+ //one xhr request for all files
1666
+ iFiles = 1;
1667
+ } else {
1668
+ //several xhr requests for every file
1669
+ iFiles = aFiles.length;
1670
+ }
1671
+ // Save references to already uploading files if a new upload comes between upload and complete or abort
1672
+ this._aXhr = this._aXhr || [];
1673
+ for (var j = 0; j < iFiles; j++) {
1674
+ //keep a reference on the current upload xhr
1675
+ this._uploadXHR = new window.XMLHttpRequest();
1676
+
1677
+ oXhrEntry = {
1678
+ xhr: this._uploadXHR,
1679
+ requestHeaders: []
1680
+ };
1681
+ this._aXhr.push(oXhrEntry);
1682
+ oXhrEntry.xhr.open(this.getHttpRequestMethod(), this.getUploadUrl(), true);
1683
+ if (oXHRSettings) {
1684
+ oXhrEntry.xhr.withCredentials = oXHRSettings.getWithCredentials();
1685
+ }
1686
+ if (this.getHeaderParameters()) {
1687
+ var aHeaderParams = this.getHeaderParameters();
1688
+ for (var i = 0; i < aHeaderParams.length; i++) {
1689
+ sHeader = aHeaderParams[i].getName();
1690
+ sValue = aHeaderParams[i].getValue();
1691
+ oXhrEntry.requestHeaders.push({
1692
+ name: sHeader,
1693
+ value: sValue
1694
+ });
1695
+ }
1696
+ }
1697
+ var sFilename = aFiles[j].name;
1698
+ var aRequestHeaders = oXhrEntry.requestHeaders;
1699
+ oXhrEntry.fileName = sFilename;
1700
+ oXhrEntry.file = aFiles[j];
1701
+ this.fireUploadStart({
1702
+ "fileName": sFilename,
1703
+ "requestHeaders": aRequestHeaders
1704
+ });
1705
+ for (var k = 0; k < aRequestHeaders.length; k++) {
1706
+ // Check if request is still open in case abort() was called.
1707
+ if (oXhrEntry.xhr.readyState === 0) {
1708
+ break;
1709
+ }
1710
+ sHeader = aRequestHeaders[k].name;
1711
+ sValue = aRequestHeaders[k].value;
1712
+ oXhrEntry.xhr.setRequestHeader(sHeader, sValue);
1713
+ }
1714
+ }
1715
+ if (this.getUseMultipart()) {
1716
+ var formData = new window.FormData();
1717
+ var name = this.FUEl.name;
1718
+ for (var l = 0; l < aFiles.length; l++) {
1719
+ this._appendFileToFormData(formData, name, aFiles[l]);
1720
+ }
1721
+ formData.append("_charset_", "UTF-8");
1722
+ var data = this.FUDataEl.name;
1723
+ if (this.getAdditionalData()) {
1724
+ var sData = this.getAdditionalData();
1725
+ formData.append(data, sData);
1726
+ } else {
1727
+ formData.append(data, "");
1728
+ }
1729
+ if (this.getParameters()) {
1730
+ var oParams = this.getParameters();
1731
+ for (var m = 0; m < oParams.length; m++) {
1732
+ var sName = oParams[m].getName();
1733
+ sValue = oParams[m].getValue();
1734
+ formData.append(sName, sValue);
1735
+ }
1736
+ }
1737
+ oXhrEntry.file = formData;
1738
+ this.sendFiles(this._aXhr, 0);
1739
+ } else {
1740
+ this.sendFiles(this._aXhr, 0);
1741
+ }
1742
+ this._bUploading = false;
1743
+ this._resetValueAfterUploadStart();
1744
+ }
1745
+
1746
+ return this;
1747
+ };
1748
+
1749
+ /**
1750
+ * Append a file to passed FormData object handling special case where there is a Blob or window.File with a name
1751
+ * parameter passed.
1752
+ * @param {object} oFormData receiving FormData object
1753
+ * @param {string} sFieldName name of the form field
1754
+ * @param {object} oFile object to be appended
1755
+ * @private
1756
+ */
1757
+ FileUploader.prototype._appendFileToFormData = function (oFormData, sFieldName, oFile) {
1758
+ // BCP: 1770523801 We pass third parameter 'name' only for instance of 'Blob' that has a 'name'
1759
+ // parameter to prevent the append method failing on Safari browser.
1760
+ if (oFile instanceof window.Blob && oFile.name) {
1761
+ oFormData.append(sFieldName, oFile, oFile.name);
1762
+ } else {
1763
+ oFormData.append(sFieldName, oFile);
1764
+ }
1765
+ };
1766
+
1767
+ /**
1768
+ * Processes the passed files and sends them afterwards via XHR request.
1769
+ * @param {window.File[]} [aFiles] list of files from type window.File
1770
+ * @returns {this} Reference to <code>this</code> for method chaining
1771
+ * @private
1772
+ */
1773
+ FileUploader.prototype._sendProcessedFilesWithXHR = function (aFiles) {
1774
+ this.getProcessedBlobsFromArray(aFiles).then(function(aBlobs){
1775
+ this._sendFilesWithXHR(aBlobs);
1776
+ }.bind(this)).catch(function(oResult){
1777
+ Log.error("File upload failed: " + oResult && oResult.message ? oResult.message : "no details available");
1778
+ });
1779
+ return this;
1780
+ };
1781
+
1782
+ /*
1783
+ * Check if passed files complies with the provided file restrictions.
1784
+ * These restrictions are the values of properties like "fileType", "maximumFileSize", "mimeType", "maximumFilenameLength"
1785
+ * @param {array} [aFiles] list of files from type window.File, this array is returned from input type="file" or from Drag and Drop
1786
+ * @returns {boolean}
1787
+ * @private
1788
+ */
1789
+ FileUploader.prototype._areFilesAllowed = function (aFiles) {
1790
+ var sName, bWrongType, iIdx, sFileEnding, sType,
1791
+ fMaxSize = this.getMaximumFileSize(),
1792
+ aMimeTypes = this.getMimeType(),
1793
+ aFileTypes = this.getFileType();
1794
+
1795
+ for (var i = 0; i < aFiles.length; i++) {
1796
+ sName = aFiles[i].name;
1797
+ sType = aFiles[i].type || "unknown";
1798
+
1799
+ var fSize = ((aFiles[i].size / 1024) / 1024);
1800
+ if (fMaxSize && (fSize > fMaxSize)) {
1801
+ Log.info("File: " + sName + " is of size " + fSize + " MB which exceeds the file size limit of " + fMaxSize + " MB.");
1802
+ this.fireFileSizeExceed({
1803
+ fileName: sName,
1804
+ fileSize: fSize
1805
+ });
1806
+
1807
+ return false;
1808
+ }
1809
+ if (fSize === 0){
1810
+ Log.info("File: " + sName + " is empty!");
1811
+ this.fireFileEmpty({
1812
+ fileName: sName
1813
+ });
1814
+ }
1815
+ //check if the filename is too long and fire the corresponding event if necessary
1816
+ if (this._isFilenameTooLong(sName)) {
1817
+ this.fireFilenameLengthExceed({
1818
+ fileName: sName
1819
+ });
1820
+
1821
+ return false;
1822
+ }
1823
+ //check allowed mime-types for potential mismatches
1824
+ if (aMimeTypes && aMimeTypes.length > 0) {
1825
+ var bWrongMime = true;
1826
+ for (var j = 0; j < aMimeTypes.length; j++) {
1827
+ if (sType == aMimeTypes[j] || aMimeTypes[j] == "*/*" || sType.match(aMimeTypes[j])) {
1828
+ bWrongMime = false;
1829
+ }
1830
+ }
1831
+ if (bWrongMime && sType !== "unknown") {
1832
+ Log.info("File: " + sName + " is of type " + sType + ". Allowed types are: " + aMimeTypes + ".");
1833
+ this.fireTypeMissmatch({
1834
+ fileName: sName,
1835
+ mimeType: sType
1836
+ });
1837
+
1838
+ return false;
1839
+ }
1840
+ }
1841
+ //check allowed file-types for potential mismatches
1842
+ if (aFileTypes && aFileTypes.length > 0) {
1843
+ bWrongType = true;
1844
+ iIdx = sName.lastIndexOf(".");
1845
+ sFileEnding = (iIdx === -1) ? "" : sName.substring(iIdx + 1);
1846
+ for (var k = 0; k < aFileTypes.length; k++) {
1847
+ if (sFileEnding.toLowerCase() == aFileTypes[k].toLowerCase()) {
1848
+ bWrongType = false;
1849
+ }
1850
+ }
1851
+ if (bWrongType) {
1852
+ Log.info("File: " + sName + " is of type " + sFileEnding + ". Allowed types are: " + aFileTypes + ".");
1853
+ this.fireTypeMissmatch({
1854
+ fileName:sName,
1855
+ fileType:sFileEnding
1856
+ });
1857
+
1858
+ return false;
1859
+ }
1860
+ }
1861
+ }
1862
+
1863
+ return true;
1864
+ };
1865
+
1866
+ /**
1867
+ * Validate provided files from drag and drop event and send them trough XHR
1868
+ * Be aware that this method is private and is created only for drag and drop enablement inside sap.m.UploadCollection
1869
+ * @param {window.File[]} [aFiles] list of files from type window.File, this array is returned from input type="file" or from Drag and Drop
1870
+ * @returns {this} Reference to <code>this</code> for method chaining
1871
+ * @private
1872
+ */
1873
+ FileUploader.prototype._sendFilesFromDragAndDrop = function (aFiles) {
1874
+ if (this._areFilesAllowed(aFiles)) {
1875
+ this._sendFilesWithXHR(aFiles);
1876
+ }
1877
+ return this;
1878
+ };
1879
+
1880
+ /**
1881
+ * The value in the FileUplader input is generated from this method.
1882
+ * It contains the names of the files in quotes divided by space.
1883
+ * @param {window.File[]} [aFiles] list with files from type window.File, this array is returned from input type="file" or from Drag and Drop
1884
+ * @returns {string} The value of the input
1885
+ */
1886
+ FileUploader.prototype._generateInputValue = function (aFiles) {
1887
+ var sFileString = "";
1888
+
1889
+ for (var i = 0; i < aFiles.length; i++) {
1890
+ sFileString = sFileString + '"' + aFiles[i].name + '" ';
1891
+ }
1892
+
1893
+ return sFileString;
1894
+ };
1895
+
1896
+ /**
1897
+ * Helper to retrieve the I18N texts for a button
1898
+ * @private
1899
+ */
1900
+ FileUploader.prototype.getBrowseText = function() {
1901
+
1902
+ // as the text is the same for all FileUploaders, get it only once
1903
+ if (!FileUploader.prototype._sBrowseText) {
1904
+ var rb = Library.getResourceBundleFor("sap.ui.commons");
1905
+ FileUploader.prototype._sBrowseText = rb.getText("FILEUPLOAD_BROWSE");
1906
+ }
1907
+
1908
+ return FileUploader.prototype._sBrowseText ? FileUploader.prototype._sBrowseText : "Browse...";
1909
+
1910
+ };
1911
+
1912
+ /**
1913
+ * Helper to retrieve the I18N text for the tooltip when there is no file chosen
1914
+ * @private
1915
+ */
1916
+ FileUploader.prototype._getNoFileChosenText = function() {
1917
+
1918
+ // as the text is the same for all FileUploaders, get it only once
1919
+ if (!FileUploader.prototype._sNoFileChosenText) {
1920
+ var rb = Library.getResourceBundleFor("sap.ui.commons");
1921
+ FileUploader.prototype._sNoFileChosenText = rb.getText("FILEUPLOAD_NO_FILE_CHOSEN");
1922
+ }
1923
+
1924
+ return FileUploader.prototype._sNoFileChosenText ? FileUploader.prototype._sNoFileChosenText : "No file chosen";
1925
+
1926
+ };
1927
+
1928
+ /**
1929
+ * Getter for shortened value.
1930
+ * @private
1931
+ * @deprecated the value now is the short value (filename only)!
1932
+ */
1933
+ FileUploader.prototype.getShortenValue = function() {
1934
+ return this.getValue();
1935
+ };
1936
+
1937
+ /**
1938
+ * Prepares the hidden IFrame for uploading the file (in static area).
1939
+ * @private
1940
+ */
1941
+ FileUploader.prototype.prepareFileUploadAndIFrame = function() {
1942
+ this._prepareFileUpload();
1943
+
1944
+ if (!this.oIFrameRef) {
1945
+ // create the upload iframe
1946
+ var oIFrameRef = document.createElement("iframe");
1947
+ oIFrameRef.style.display = "none";
1948
+ /*eslint-enable no-script-url */
1949
+ oIFrameRef.id = this.getId() + "-frame";
1950
+ StaticArea.getDomRef().appendChild(oIFrameRef);
1951
+ oIFrameRef.contentWindow.name = this.getId() + "-frame";
1952
+
1953
+ // sink the load event of the upload iframe
1954
+ this._bUploading = false; // flag for uploading
1955
+ jQuery(oIFrameRef).on("load", function(oEvent) {
1956
+ if (this._bUploading) {
1957
+ Log.info("File uploaded to " + this.getUploadUrl());
1958
+ var sResponse;
1959
+ try {
1960
+ sResponse = this.oIFrameRef.contentWindow.document.body.innerHTML;
1961
+ } catch (ex) {
1962
+ // in case of cross-domain submit we get a permission denied exception
1963
+ // when we try to access the body of the IFrame document
1964
+ }
1965
+ this.fireUploadComplete({"response": sResponse});
1966
+ this._bUploading = false;
1967
+ }
1968
+ }.bind(this));
1969
+
1970
+ // keep the reference
1971
+ this.oIFrameRef = oIFrameRef;
1972
+
1973
+ }
1974
+ };
1975
+
1976
+ FileUploader.prototype._prepareFileUpload = function() {
1977
+ if (!this.oFileUpload) {
1978
+ // create the file uploader markup
1979
+ var aFileUpload = [];
1980
+ aFileUpload.push('<input ');
1981
+ aFileUpload.push('type="file" ');
1982
+ aFileUpload.push('aria-hidden="true" ');
1983
+ if (this.getName()) {
1984
+ if (this.getMultiple() || this.getDirectory()) {
1985
+ aFileUpload.push('name="' + encodeXML(this.getName()) + '[]" ');
1986
+ } else {
1987
+ aFileUpload.push('name="' + encodeXML(this.getName()) + '" ');
1988
+ }
1989
+ } else if (this.getMultiple() || this.getDirectory()) {
1990
+ aFileUpload.push('name="' + this.getId() + '[]" ');
1991
+ } else {
1992
+ aFileUpload.push('name="' + this.getId() + '" ');
1993
+ }
1994
+
1995
+ aFileUpload.push('id="' + this.getId() + '-fu" ');
1996
+ // for IE9 the file uploader itself gets the focus to make sure that the
1997
+ // keyboard interaction works and there is no security issue - unfortunately
1998
+ // this has the negative side effect that 2 tabs are required.
1999
+ aFileUpload.push('tabindex="-1" ');
2000
+ aFileUpload.push('size="1" ');
2001
+
2002
+ if (this.getTooltip_AsString() ) {
2003
+ aFileUpload.push('title="' + encodeXML(this.getTooltip_AsString()) + '" ');
2004
+ //} else if (this.getTooltip() ) {
2005
+ // object tooltip, do nothing - tooltip will be displayed
2006
+ } else {
2007
+ // only if there is no tooltip, then set value or default tooltip as fallback
2008
+ aFileUpload.push('title="' + encodeXML(this.getValue() ? this.getValue() : this._getNoFileChosenText()) + '" ');
2009
+ }
2010
+
2011
+ if (!this.getEnabled()) {
2012
+ aFileUpload.push('disabled="disabled" ');
2013
+ }
2014
+
2015
+ if (this.getDirectory()) {
2016
+ aFileUpload.push('webkitdirectory ');
2017
+ }
2018
+
2019
+ if (this.getMultiple()) {
2020
+ aFileUpload.push('multiple ');
2021
+ }
2022
+
2023
+ if ((this.getMimeType() || this.getFileType()) && window.File) {
2024
+ var sAcceptedTypes = this._getAcceptedTypes();
2025
+ aFileUpload.push('accept="' + encodeXML(sAcceptedTypes) + '" ');
2026
+ }
2027
+ aFileUpload.push('>');
2028
+
2029
+ // add it into the control markup
2030
+ this.oFileUpload = jQuery(aFileUpload.join("")).prependTo(this.$().find(".sapUiFupInputMask")).get(0);
2031
+ } else {
2032
+
2033
+ // move the file uploader from the static area to the control markup
2034
+ jQuery(this.oFileUpload).prependTo(this.$().find(".sapUiFupInputMask"));
2035
+
2036
+ }
2037
+ };
2038
+
2039
+ FileUploader.prototype.openValueStateMessage = function() {
2040
+
2041
+ if (this.oFilePath.openValueStateMessage) {
2042
+ this.oFilePath.openValueStateMessage();
2043
+ }
2044
+
2045
+ };
2046
+
2047
+ FileUploader.prototype.closeValueStateMessage = function() {
2048
+
2049
+ if (this.oFilePath.closeValueStateMessage) {
2050
+ this.oFilePath.closeValueStateMessage();
2051
+ }
2052
+
2053
+ };
2054
+
2055
+ FileUploader.prototype._getAcceptedTypes = function() {
2056
+ var aMimeTypes = this.getMimeType() || [],
2057
+ aFileTypes = this.getFileType() || [];
2058
+ aFileTypes = aFileTypes.map(function(item) {
2059
+ return item.indexOf(".") === 0 ? item : "." + item;
2060
+ });
2061
+ return aFileTypes.concat(aMimeTypes).join(",");
2062
+ };
2063
+
2064
+ FileUploader.prototype._resetValueAfterUploadStart = function () {
2065
+ Log.info("File uploading to " + this.getUploadUrl());
2066
+ if (this.getSameFilenameAllowed() && this.getUploadOnChange() && this.getUseMultipart()) {
2067
+ this.setValue("", true);
2068
+ }
2069
+ };
2070
+ /*
2071
+ * Add default input type=file and label behaviour to file uploader.
2072
+ */
2073
+ FileUploader.prototype._addLabelFeaturesToBrowse = function () {
2074
+ let $browse;
2075
+ const fnBrowseClickHandler = (oEvent) => {
2076
+ oEvent.preventDefault();
2077
+ oEvent.stopPropagation();
2078
+ this.FUEl.click(); // The default behaviour on click on label is to open "open file" dialog. The only way to attach click event that is transferred from the label to the button is this way. AttachPress and attachTap don't work in this case.
2079
+ };
2080
+
2081
+ if (this.oBrowse && this.oBrowse.$().length) {
2082
+ $browse = this.oBrowse.$();
2083
+
2084
+ if (this.oBrowse.getAriaLabelledBy()) {
2085
+ LabelEnablement.getReferencingLabels(this).forEach(function (sLabelId) {
2086
+ const $externalLabel = Element.getElementById(sLabelId).$();
2087
+ $externalLabel.off("click").on("click", fnBrowseClickHandler);
2088
+ }, this);
2089
+ }
2090
+
2091
+ $browse.off("click").on("click", fnBrowseClickHandler);
2092
+
2093
+ // The event propagation needs to be stopped so composing controls, which also react on
2094
+ // drag and drop events like the sap.m.UploadCollection or sap.m.upload.UploadSet aren't affected.
2095
+ $browse.off("dragover").on("dragover", (oEvent) => {
2096
+ oEvent.preventDefault();
2097
+ oEvent.stopPropagation();
2098
+ });
2099
+ $browse.off("dragenter").on("dragenter", (oEvent) => {
2100
+ oEvent.preventDefault();
2101
+ oEvent.stopPropagation();
2102
+ });
2103
+ $browse.off("drop").on("drop", (oEvent) => {
2104
+ oEvent.preventDefault();
2105
+ oEvent.stopPropagation();
2106
+ var aFileList = oEvent.originalEvent.dataTransfer.files;
2107
+ // TODO: enable directory drag and drop
2108
+ if ((!this.getMultiple() && aFileList.length > 1) || this.getDirectory()) {
2109
+ return;
2110
+ }
2111
+
2112
+ this.oFileUpload.files = aFileList;
2113
+ var oChangeEvent = {
2114
+ target: {
2115
+ files: aFileList
2116
+ }
2117
+ };
2118
+ this.handlechange(oChangeEvent);
2119
+ });
2120
+ }
2121
+ };
2122
+
2123
+ /**
2124
+ * Allows to process Blobs before they get uploaded. This API can be used to create custom Blobs
2125
+ * and upload these custom Blobs instead of the received/initials Blobs in the parameter <code>aBlobs</code>.
2126
+ * One use case could be to create and upload zip archives based on the passed Blobs.
2127
+ * The default implementation of this API should simply resolve with the received Blobs (parameter <code>aBlobs</code>).
2128
+ *
2129
+ * This API is only supported in case <code>sendXHR</code> is <code>true</code>. This means only IE10+ is supported, while IE9 and below is not.
2130
+ *
2131
+ * This is a default implementation of the interface <code>sap.ui.commons.IProcessableBlobs</code>.
2132
+ *
2133
+ * @public
2134
+ * @since 1.52
2135
+ * @param {Blob[]} aBlobs The initial Blobs which can be used to determine/calculate a new array of Blobs for further processing.
2136
+ * @returns {Promise<Blob[]>} A Promise that resolves with an array of Blobs which is used for the final uploading.
2137
+ */
2138
+ FileUploader.prototype.getProcessedBlobsFromArray = function (aBlobs){
2139
+ return new Promise(function(resolve){
2140
+ resolve(aBlobs);
2141
+ });
2142
+ };
2143
+
2144
+ // If the file has been edited after it has been chosen,
2145
+ // Chrome 85 fails silently on submit, so we could
2146
+ // check if it is readable first.
2147
+ // https://stackoverflow.com/questions/61916331
2148
+ // BCP: 2070313680
2149
+
2150
+ /**
2151
+ * Checks if the chosen file is readable.
2152
+ *
2153
+ * @returns {Promise} A promise that resolves successfully
2154
+ * if the chosen file can be read and fails with an error message if it cannot
2155
+ * @public
2156
+ */
2157
+ FileUploader.prototype.checkFileReadable = function() {
2158
+ return new Promise(function(resolve, reject) {
2159
+ var oReader;
2160
+
2161
+ if (window.File && this.FUEl && this.FUEl.files.length) {
2162
+ oReader = new FileReader();
2163
+ oReader.readAsArrayBuffer(this.FUEl.files[0].slice(0, 1));
2164
+
2165
+ oReader.onload = function() {
2166
+ resolve();
2167
+ };
2168
+
2169
+ oReader.onerror = function() {
2170
+ reject(oReader.error);
2171
+ };
2172
+ } else {
2173
+ resolve();
2174
+ }
2175
+ }.bind(this));
2176
+ };
49
2177
 
50
2178
  return FileUploader;
51
2179