@syncfusion/ej2-inputs 31.1.17 → 31.1.20
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.
- package/dist/ej2-inputs.min.js +2 -2
- package/dist/ej2-inputs.umd.min.js +2 -2
- package/dist/ej2-inputs.umd.min.js.map +1 -1
- package/dist/es6/ej2-inputs.es2015.js +4 -3
- package/dist/es6/ej2-inputs.es2015.js.map +1 -1
- package/dist/es6/ej2-inputs.es5.js +4 -3
- package/dist/es6/ej2-inputs.es5.js.map +1 -1
- package/dist/global/ej2-inputs.min.js +2 -2
- package/dist/global/ej2-inputs.min.js.map +1 -1
- package/dist/global/index.d.ts +1 -1
- package/package.json +10 -60
- package/src/color-picker/color-picker.js +4 -3
- package/styles/bootstrap4-lite.css +2 -2
- package/styles/bootstrap4.css +2 -2
- package/styles/bootstrap5-dark-lite.css +2 -2
- package/styles/bootstrap5-dark.css +2 -2
- package/styles/bootstrap5-lite.css +2 -2
- package/styles/bootstrap5.css +2 -2
- package/styles/input/_bootstrap4-definition.scss +1 -1
- package/styles/input/_bootstrap5-definition.scss +1 -1
- package/styles/input/bootstrap4.css +2 -2
- package/styles/input/bootstrap5-dark.css +2 -2
- package/styles/input/bootstrap5.css +2 -2
- package/dist/ts/color-picker/color-picker-model.d.ts +0 -186
- package/dist/ts/color-picker/color-picker.d.ts +0 -398
- package/dist/ts/color-picker/color-picker.ts +0 -2209
- package/dist/ts/color-picker/index.d.ts +0 -5
- package/dist/ts/color-picker/index.ts +0 -5
- package/dist/ts/common/index.d.ts +0 -4
- package/dist/ts/common/index.ts +0 -4
- package/dist/ts/common/signature-base.d.ts +0 -340
- package/dist/ts/common/signature-base.ts +0 -1170
- package/dist/ts/form-validator/form-validator-model.d.ts +0 -121
- package/dist/ts/form-validator/form-validator.d.ts +0 -312
- package/dist/ts/form-validator/form-validator.ts +0 -1068
- package/dist/ts/form-validator/index.d.ts +0 -5
- package/dist/ts/form-validator/index.ts +0 -5
- package/dist/ts/index.d.ts +0 -18
- package/dist/ts/index.ts +0 -18
- package/dist/ts/input/index.d.ts +0 -4
- package/dist/ts/input/index.ts +0 -4
- package/dist/ts/input/input.d.ts +0 -345
- package/dist/ts/input/input.ts +0 -1277
- package/dist/ts/maskedtextbox/base/index.d.ts +0 -4
- package/dist/ts/maskedtextbox/base/index.ts +0 -4
- package/dist/ts/maskedtextbox/base/mask-base.d.ts +0 -134
- package/dist/ts/maskedtextbox/base/mask-base.ts +0 -1207
- package/dist/ts/maskedtextbox/index.d.ts +0 -5
- package/dist/ts/maskedtextbox/index.ts +0 -5
- package/dist/ts/maskedtextbox/maskedtextbox/index.d.ts +0 -5
- package/dist/ts/maskedtextbox/maskedtextbox/index.ts +0 -5
- package/dist/ts/maskedtextbox/maskedtextbox/maskedtextbox-model.d.ts +0 -167
- package/dist/ts/maskedtextbox/maskedtextbox/maskedtextbox.d.ts +0 -307
- package/dist/ts/maskedtextbox/maskedtextbox/maskedtextbox.ts +0 -709
- package/dist/ts/numerictextbox/index.d.ts +0 -5
- package/dist/ts/numerictextbox/index.ts +0 -5
- package/dist/ts/numerictextbox/numerictextbox-model.d.ts +0 -228
- package/dist/ts/numerictextbox/numerictextbox.d.ts +0 -431
- package/dist/ts/numerictextbox/numerictextbox.ts +0 -1672
- package/dist/ts/otp-input/index.d.ts +0 -5
- package/dist/ts/otp-input/index.ts +0 -5
- package/dist/ts/otp-input/otp-input-model.d.ts +0 -165
- package/dist/ts/otp-input/otp-input.d.ts +0 -365
- package/dist/ts/otp-input/otp-input.ts +0 -924
- package/dist/ts/rating/index.d.ts +0 -5
- package/dist/ts/rating/index.ts +0 -5
- package/dist/ts/rating/rating-model.d.ts +0 -239
- package/dist/ts/rating/rating.d.ts +0 -416
- package/dist/ts/rating/rating.ts +0 -1101
- package/dist/ts/signature/index.d.ts +0 -5
- package/dist/ts/signature/index.ts +0 -5
- package/dist/ts/signature/signature-model.d.ts +0 -131
- package/dist/ts/signature/signature.d.ts +0 -167
- package/dist/ts/signature/signature.ts +0 -266
- package/dist/ts/slider/index.d.ts +0 -5
- package/dist/ts/slider/index.ts +0 -5
- package/dist/ts/slider/slider-model.d.ts +0 -401
- package/dist/ts/slider/slider.d.ts +0 -721
- package/dist/ts/slider/slider.ts +0 -3497
- package/dist/ts/smart-textarea/caret-helper.d.ts +0 -17
- package/dist/ts/smart-textarea/caret-helper.ts +0 -95
- package/dist/ts/smart-textarea/index.d.ts +0 -5
- package/dist/ts/smart-textarea/index.ts +0 -5
- package/dist/ts/smart-textarea/smart-textarea-model.d.ts +0 -44
- package/dist/ts/smart-textarea/smart-textarea.d.ts +0 -80
- package/dist/ts/smart-textarea/smart-textarea.ts +0 -518
- package/dist/ts/speech-to-text/index.d.ts +0 -5
- package/dist/ts/speech-to-text/index.ts +0 -5
- package/dist/ts/speech-to-text/speech-to-text-model.d.ts +0 -270
- package/dist/ts/speech-to-text/speech-to-text.d.ts +0 -487
- package/dist/ts/speech-to-text/speech-to-text.ts +0 -1008
- package/dist/ts/textarea/index.d.ts +0 -5
- package/dist/ts/textarea/index.ts +0 -5
- package/dist/ts/textarea/textarea-model.d.ts +0 -161
- package/dist/ts/textarea/textarea.d.ts +0 -237
- package/dist/ts/textarea/textarea.ts +0 -812
- package/dist/ts/textbox/index.d.ts +0 -5
- package/dist/ts/textbox/index.ts +0 -5
- package/dist/ts/textbox/textbox-model.d.ts +0 -155
- package/dist/ts/textbox/textbox.d.ts +0 -288
- package/dist/ts/textbox/textbox.ts +0 -872
- package/dist/ts/uploader/index.d.ts +0 -5
- package/dist/ts/uploader/index.ts +0 -5
- package/dist/ts/uploader/uploader-model.d.ts +0 -555
- package/dist/ts/uploader/uploader.d.ts +0 -1216
- package/dist/ts/uploader/uploader.ts +0 -4391
|
@@ -1,4391 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { Component, Property, Event, EmitType, EventHandler, L10n, compile, isNullOrUndefined, SanitizeHtmlHelper} from '@syncfusion/ej2-base';
|
|
3
|
-
import { NotifyPropertyChanges, INotifyPropertyChanged, detach, append, Animation } from '@syncfusion/ej2-base';
|
|
4
|
-
import { addClass, removeClass, KeyboardEvents, KeyboardEventArgs, setValue, getValue, ChildProperty } from '@syncfusion/ej2-base';
|
|
5
|
-
import { Collection, Complex, Browser, Ajax, BeforeSendEventArgs, getUniqueID, closest, remove } from '@syncfusion/ej2-base';
|
|
6
|
-
import { createSpinner, showSpinner, hideSpinner } from '@syncfusion/ej2-popups';
|
|
7
|
-
import { UploaderModel, AsyncSettingsModel, ButtonsPropsModel, FilesPropModel } from './uploader-model';
|
|
8
|
-
import { select, selectAll } from '@syncfusion/ej2-base';
|
|
9
|
-
|
|
10
|
-
const CONTROL_WRAPPER: string = 'e-upload e-control-wrapper';
|
|
11
|
-
const INPUT_WRAPPER: string = 'e-file-select';
|
|
12
|
-
const DROP_AREA: string = 'e-file-drop';
|
|
13
|
-
const DROP_WRAPPER: string = 'e-file-select-wrap';
|
|
14
|
-
const LIST_PARENT: string = 'e-upload-files';
|
|
15
|
-
const FILE: string = 'e-upload-file-list';
|
|
16
|
-
const STATUS: string = 'e-file-status';
|
|
17
|
-
const ACTION_BUTTONS: string = 'e-upload-actions';
|
|
18
|
-
const UPLOAD_BUTTONS: string = 'e-file-upload-btn e-css e-btn e-flat e-primary';
|
|
19
|
-
const CLEAR_BUTTONS: string = 'e-file-clear-btn e-css e-btn e-flat';
|
|
20
|
-
const FILE_NAME: string = 'e-file-name';
|
|
21
|
-
const FILE_TYPE: string = 'e-file-type';
|
|
22
|
-
const FILE_SIZE: string = 'e-file-size';
|
|
23
|
-
const REMOVE_ICON: string = 'e-file-remove-btn';
|
|
24
|
-
const DELETE_ICON: string = 'e-file-delete-btn';
|
|
25
|
-
const SPINNER_PANE: string = 'e-spinner-pane';
|
|
26
|
-
const ABORT_ICON: string = 'e-file-abort-btn';
|
|
27
|
-
const RETRY_ICON: string = 'e-file-reload-btn';
|
|
28
|
-
const DRAG_HOVER: string = 'e-upload-drag-hover';
|
|
29
|
-
const PROGRESS_WRAPPER: string = 'e-upload-progress-wrap';
|
|
30
|
-
const PROGRESSBAR: string = 'e-upload-progress-bar';
|
|
31
|
-
const PROGRESSBAR_TEXT: string = 'e-progress-bar-text';
|
|
32
|
-
const UPLOAD_INPROGRESS: string = 'e-upload-progress';
|
|
33
|
-
const UPLOAD_SUCCESS: string = 'e-upload-success';
|
|
34
|
-
const UPLOAD_FAILED: string = 'e-upload-fails';
|
|
35
|
-
const TEXT_CONTAINER: string = 'e-file-container';
|
|
36
|
-
const VALIDATION_FAILS: string = 'e-validation-fails';
|
|
37
|
-
const RTL: string = 'e-rtl';
|
|
38
|
-
const DISABLED : string = 'e-disabled';
|
|
39
|
-
const RTL_CONTAINER : string = 'e-rtl-container';
|
|
40
|
-
const ICON_FOCUSED : string = 'e-clear-icon-focus';
|
|
41
|
-
const PROGRESS_INNER_WRAPPER: string = 'e-progress-inner-wrap';
|
|
42
|
-
const PAUSE_UPLOAD: string = 'e-file-pause-btn';
|
|
43
|
-
const RESUME_UPLOAD: string = 'e-file-play-btn';
|
|
44
|
-
const RESTRICT_RETRY: string = 'e-restrict-retry';
|
|
45
|
-
const wrapperAttr: string[] = ['title', 'style', 'class'];
|
|
46
|
-
const FORM_UPLOAD: string = 'e-form-upload';
|
|
47
|
-
const HIDDEN_INPUT: string = 'e-hidden-file-input';
|
|
48
|
-
const INVALID_FILE: string = 'e-file-invalid';
|
|
49
|
-
const INFORMATION: string = 'e-file-information';
|
|
50
|
-
|
|
51
|
-
export type DropEffect = 'Copy' | 'Move' | 'Link' | 'None'| 'Default';
|
|
52
|
-
export class FilesProp extends ChildProperty<FilesProp> {
|
|
53
|
-
/**
|
|
54
|
-
* Specifies the name of the file
|
|
55
|
-
*
|
|
56
|
-
* @default ''
|
|
57
|
-
*/
|
|
58
|
-
@Property('')
|
|
59
|
-
public name: string;
|
|
60
|
-
/**
|
|
61
|
-
* Specifies the size of the file
|
|
62
|
-
*
|
|
63
|
-
* @default null
|
|
64
|
-
*/
|
|
65
|
-
@Property(null)
|
|
66
|
-
public size: number;
|
|
67
|
-
/**
|
|
68
|
-
* Specifies the type of the file
|
|
69
|
-
*
|
|
70
|
-
* @default ''
|
|
71
|
-
*/
|
|
72
|
-
@Property('')
|
|
73
|
-
public type: string;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export class ButtonsProps extends ChildProperty<ButtonsProps> {
|
|
77
|
-
/**
|
|
78
|
-
* Specifies the text or html content to browse button
|
|
79
|
-
*
|
|
80
|
-
* @default 'Browse...'
|
|
81
|
-
*/
|
|
82
|
-
@Property('Browse...')
|
|
83
|
-
public browse: string | HTMLElement;
|
|
84
|
-
/**
|
|
85
|
-
* Specifies the text or html content to upload button
|
|
86
|
-
*
|
|
87
|
-
* @default 'Upload'
|
|
88
|
-
*/
|
|
89
|
-
@Property('Upload')
|
|
90
|
-
public upload: string | HTMLElement;
|
|
91
|
-
/**
|
|
92
|
-
* Specifies the text or html content to clear button
|
|
93
|
-
*
|
|
94
|
-
* @default 'Clear'
|
|
95
|
-
*/
|
|
96
|
-
@Property('Clear')
|
|
97
|
-
public clear: string | HTMLElement;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export class AsyncSettings extends ChildProperty<AsyncSettings> {
|
|
101
|
-
/**
|
|
102
|
-
* Specifies the URL of save action that will receive the upload files and save in the server.
|
|
103
|
-
* The save action type must be POST request and define the argument as same input name used to render the component.
|
|
104
|
-
* The upload operations could not perform without this property.
|
|
105
|
-
*
|
|
106
|
-
* @default ''
|
|
107
|
-
*/
|
|
108
|
-
@Property('')
|
|
109
|
-
public saveUrl: string;
|
|
110
|
-
/**
|
|
111
|
-
* Specifies the URL of remove action that receives the file information and handle the remove operation in server.
|
|
112
|
-
* The remove action type must be POST request and define “removeFileNames” attribute to get file information that will be removed.
|
|
113
|
-
* This property is optional.
|
|
114
|
-
*
|
|
115
|
-
* @default ''
|
|
116
|
-
*/
|
|
117
|
-
@Property('')
|
|
118
|
-
public removeUrl: string;
|
|
119
|
-
/**
|
|
120
|
-
* Specifies the chunk size to split the large file into chunks, and upload it to the server in a sequential order.
|
|
121
|
-
* If the chunk size property has value, the uploader enables the chunk upload by default.
|
|
122
|
-
* It must be specified in bytes value.
|
|
123
|
-
*
|
|
124
|
-
* > For more information, refer to the [chunk upload](../../uploader/chunk-upload/) section from the documentation.
|
|
125
|
-
*
|
|
126
|
-
* @default 0
|
|
127
|
-
*/
|
|
128
|
-
@Property(0)
|
|
129
|
-
public chunkSize: number;
|
|
130
|
-
/**
|
|
131
|
-
* Specifies the number of retries that the uploader can perform on the file failed to upload.
|
|
132
|
-
* By default, the uploader set 3 as maximum retries. This property must be specified to prevent infinity looping.
|
|
133
|
-
*
|
|
134
|
-
* @default 3
|
|
135
|
-
*/
|
|
136
|
-
@Property(3)
|
|
137
|
-
public retryCount: number;
|
|
138
|
-
/**
|
|
139
|
-
* Specifies the delay time in milliseconds that the automatic retry happens after the delay.
|
|
140
|
-
*
|
|
141
|
-
* @default 500
|
|
142
|
-
*/
|
|
143
|
-
@Property(500)
|
|
144
|
-
public retryAfterDelay: number;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export interface FileInfo {
|
|
148
|
-
/**
|
|
149
|
-
* Returns the upload file name.
|
|
150
|
-
*/
|
|
151
|
-
name: string
|
|
152
|
-
/**
|
|
153
|
-
* Returns the details about upload file.
|
|
154
|
-
*
|
|
155
|
-
*/
|
|
156
|
-
rawFile: string | Blob
|
|
157
|
-
/**
|
|
158
|
-
* Returns the size of file in bytes.
|
|
159
|
-
*/
|
|
160
|
-
size: number
|
|
161
|
-
/**
|
|
162
|
-
* Returns the status of the file.
|
|
163
|
-
*/
|
|
164
|
-
status: string
|
|
165
|
-
/**
|
|
166
|
-
* Returns the MIME type of file as a string. Returns empty string if the file’s type is not determined.
|
|
167
|
-
*/
|
|
168
|
-
type: string
|
|
169
|
-
/**
|
|
170
|
-
* Returns the list of validation errors (if any).
|
|
171
|
-
*/
|
|
172
|
-
validationMessages: ValidationMessages
|
|
173
|
-
/**
|
|
174
|
-
* Returns the current state of the file such as Failed, Canceled, Selected, Uploaded, or Uploading.
|
|
175
|
-
*/
|
|
176
|
-
statusCode: string
|
|
177
|
-
/**
|
|
178
|
-
* Returns where the file selected from, to upload.
|
|
179
|
-
*/
|
|
180
|
-
fileSource?: string
|
|
181
|
-
/**
|
|
182
|
-
* Returns the respective file list item.
|
|
183
|
-
*/
|
|
184
|
-
list ?: HTMLElement
|
|
185
|
-
/**
|
|
186
|
-
* Returns the input element mapped with file list item.
|
|
187
|
-
*/
|
|
188
|
-
input ?: HTMLInputElement
|
|
189
|
-
/**
|
|
190
|
-
* Returns the unique upload file name ID.
|
|
191
|
-
*/
|
|
192
|
-
id?: string
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
export interface MetaData {
|
|
196
|
-
chunkIndex: number
|
|
197
|
-
blob: Blob | string
|
|
198
|
-
file: FileInfo
|
|
199
|
-
start: number
|
|
200
|
-
end: number
|
|
201
|
-
retryCount: number
|
|
202
|
-
request: Ajax
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export interface ValidationMessages {
|
|
206
|
-
/**
|
|
207
|
-
* Returns the minimum file size validation message, if selected file size is less than specified minFileSize property.
|
|
208
|
-
*/
|
|
209
|
-
minSize? : string
|
|
210
|
-
/**
|
|
211
|
-
* Returns the maximum file size validation message, if selected file size is less than specified maxFileSize property.
|
|
212
|
-
*/
|
|
213
|
-
maxSize? : string
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export interface SelectedEventArgs {
|
|
217
|
-
/**
|
|
218
|
-
* Returns the original event arguments.
|
|
219
|
-
*/
|
|
220
|
-
event: MouseEvent | TouchEvent | DragEvent | ClipboardEvent
|
|
221
|
-
/**
|
|
222
|
-
* Defines whether the current action can be prevented.
|
|
223
|
-
*/
|
|
224
|
-
cancel: boolean
|
|
225
|
-
/**
|
|
226
|
-
* Returns the list of selected files.
|
|
227
|
-
*/
|
|
228
|
-
filesData: FileInfo[]
|
|
229
|
-
/**
|
|
230
|
-
* Determines whether the file list generates based on the modified data.
|
|
231
|
-
*/
|
|
232
|
-
isModified: boolean
|
|
233
|
-
/**
|
|
234
|
-
* Specifies the modified files data to generate the file items. The argument depends on `isModified` argument.
|
|
235
|
-
*/
|
|
236
|
-
modifiedFilesData: FileInfo[]
|
|
237
|
-
/**
|
|
238
|
-
* Specifies the step value to the progress bar.
|
|
239
|
-
*/
|
|
240
|
-
progressInterval: string
|
|
241
|
-
/**
|
|
242
|
-
* Specifies whether the file selection has been canceled
|
|
243
|
-
*/
|
|
244
|
-
isCanceled?: boolean
|
|
245
|
-
/**
|
|
246
|
-
* Set the current request header to the XMLHttpRequest instance.
|
|
247
|
-
*
|
|
248
|
-
*/
|
|
249
|
-
currentRequest?: { [key: string]: string }[]
|
|
250
|
-
/**
|
|
251
|
-
* Defines the additional data in key and value pair format that will be submitted to the upload action.
|
|
252
|
-
*/
|
|
253
|
-
customFormData: { [key: string]: Object }[]
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
export interface BeforeRemoveEventArgs {
|
|
257
|
-
/**
|
|
258
|
-
* Defines whether the current action can be prevented.
|
|
259
|
-
*/
|
|
260
|
-
cancel: boolean
|
|
261
|
-
/**
|
|
262
|
-
* Defines the additional data with key and value pair format that will be submitted to the remove action.
|
|
263
|
-
*
|
|
264
|
-
*/
|
|
265
|
-
customFormData: { [key: string]: Object }[]
|
|
266
|
-
/**
|
|
267
|
-
* Returns the XMLHttpRequest instance that is associated with remove action.
|
|
268
|
-
*
|
|
269
|
-
*/
|
|
270
|
-
currentRequest?: { [key: string]: string }[]
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
export interface RemovingEventArgs {
|
|
274
|
-
/**
|
|
275
|
-
* Defines whether the current action can be prevented.
|
|
276
|
-
*/
|
|
277
|
-
cancel: boolean
|
|
278
|
-
/**
|
|
279
|
-
* Defines the additional data with key and value pair format that will be submitted to the remove action.
|
|
280
|
-
*
|
|
281
|
-
*/
|
|
282
|
-
customFormData: { [key: string]: Object }[]
|
|
283
|
-
/**
|
|
284
|
-
* Returns the original event arguments.
|
|
285
|
-
*/
|
|
286
|
-
event: MouseEvent | TouchEvent | KeyboardEventArgs
|
|
287
|
-
/**
|
|
288
|
-
* Returns the list of files’ details that will be removed.
|
|
289
|
-
*/
|
|
290
|
-
filesData: FileInfo[]
|
|
291
|
-
/**
|
|
292
|
-
* Returns the XMLHttpRequest instance that is associated with remove action.
|
|
293
|
-
*
|
|
294
|
-
*/
|
|
295
|
-
currentRequest?: XMLHttpRequest
|
|
296
|
-
/**
|
|
297
|
-
* Defines whether the selected raw file send to server remove action.
|
|
298
|
-
* Set true to send raw file.
|
|
299
|
-
* Set false to send file name only.
|
|
300
|
-
*/
|
|
301
|
-
postRawFile?: boolean
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
export interface ClearingEventArgs {
|
|
305
|
-
/**
|
|
306
|
-
* Defines whether the current action can be prevented.
|
|
307
|
-
*/
|
|
308
|
-
cancel: boolean
|
|
309
|
-
/**
|
|
310
|
-
* Returns the list of files that will be cleared from the FileList.
|
|
311
|
-
*/
|
|
312
|
-
filesData: FileInfo[]
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
export interface BeforeUploadEventArgs {
|
|
316
|
-
/**
|
|
317
|
-
* Defines whether the current action can be prevented.
|
|
318
|
-
*/
|
|
319
|
-
cancel: boolean
|
|
320
|
-
/**
|
|
321
|
-
* Defines the additional data in key and value pair format that will be submitted to the upload action.
|
|
322
|
-
*
|
|
323
|
-
*/
|
|
324
|
-
customFormData: { [key: string]: Object }[]
|
|
325
|
-
/**
|
|
326
|
-
* Returns the XMLHttpRequest instance that is associated with upload action.
|
|
327
|
-
*
|
|
328
|
-
*/
|
|
329
|
-
currentRequest?: { [key: string]: string }[]
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
export interface UploadingEventArgs {
|
|
333
|
-
/**
|
|
334
|
-
* Returns the list of files that will be uploaded.
|
|
335
|
-
*/
|
|
336
|
-
fileData: FileInfo
|
|
337
|
-
/**
|
|
338
|
-
* Defines the additional data in key and value pair format that will be submitted to the upload action.
|
|
339
|
-
*
|
|
340
|
-
* @deprecated
|
|
341
|
-
*/
|
|
342
|
-
customFormData: { [key: string]: Object }[]
|
|
343
|
-
/**
|
|
344
|
-
* Defines whether the current action can be prevented.
|
|
345
|
-
*/
|
|
346
|
-
cancel: boolean
|
|
347
|
-
/**
|
|
348
|
-
* Returns the chunk size in bytes if the chunk upload is enabled.
|
|
349
|
-
*/
|
|
350
|
-
chunkSize?: number
|
|
351
|
-
/**
|
|
352
|
-
* Returns the index of current chunk if the chunk upload is enabled.
|
|
353
|
-
*/
|
|
354
|
-
currentChunkIndex?: number
|
|
355
|
-
/**
|
|
356
|
-
* Returns the XMLHttpRequest instance that is associated with upload action.
|
|
357
|
-
*
|
|
358
|
-
* @deprecated
|
|
359
|
-
*/
|
|
360
|
-
currentRequest?: XMLHttpRequest
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
export interface ProgressEventArgs {
|
|
364
|
-
/**
|
|
365
|
-
* Returns the original event arguments.
|
|
366
|
-
*/
|
|
367
|
-
e?: object
|
|
368
|
-
/**
|
|
369
|
-
* Returns the details about upload file.
|
|
370
|
-
*/
|
|
371
|
-
file?: FileInfo
|
|
372
|
-
/**
|
|
373
|
-
* Returns the upload event operation.
|
|
374
|
-
*/
|
|
375
|
-
operation?: string
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
export interface UploadChangeEventArgs {
|
|
379
|
-
/**
|
|
380
|
-
* Returns the list of files that will be cleared from the FileList.
|
|
381
|
-
*
|
|
382
|
-
*/
|
|
383
|
-
files?: FileInfo[]
|
|
384
|
-
}
|
|
385
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
386
|
-
export interface FailureEventArgs extends SuccessEventArgs { }
|
|
387
|
-
export interface SuccessEventArgs {
|
|
388
|
-
/**
|
|
389
|
-
* Returns the original event arguments.
|
|
390
|
-
*/
|
|
391
|
-
e?: object
|
|
392
|
-
/**
|
|
393
|
-
* Returns the details about upload file.
|
|
394
|
-
*/
|
|
395
|
-
file?: FileInfo
|
|
396
|
-
/**
|
|
397
|
-
* Returns the upload status.
|
|
398
|
-
*/
|
|
399
|
-
statusText?: string
|
|
400
|
-
/**
|
|
401
|
-
* Returns the upload event operation.
|
|
402
|
-
*/
|
|
403
|
-
operation: string
|
|
404
|
-
/**
|
|
405
|
-
* Returns the upload event operation.
|
|
406
|
-
*/
|
|
407
|
-
response?: ResponseEventArgs
|
|
408
|
-
/**
|
|
409
|
-
* Returns the upload chunk index.
|
|
410
|
-
*/
|
|
411
|
-
chunkIndex?: number
|
|
412
|
-
/**
|
|
413
|
-
* Returns the upload chunk size.
|
|
414
|
-
*/
|
|
415
|
-
chunkSize?: number
|
|
416
|
-
/**
|
|
417
|
-
* Returns the total chunk size.
|
|
418
|
-
*/
|
|
419
|
-
totalChunk?: number
|
|
420
|
-
/**
|
|
421
|
-
* Returns the original event arguments.
|
|
422
|
-
*/
|
|
423
|
-
event?: object
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
export interface ResponseEventArgs {
|
|
427
|
-
headers?: string
|
|
428
|
-
readyState?: object
|
|
429
|
-
statusCode?: object
|
|
430
|
-
statusText?: string
|
|
431
|
-
withCredentials?: boolean
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
export interface CancelEventArgs {
|
|
435
|
-
/**
|
|
436
|
-
* Defines whether the current action can be prevented.
|
|
437
|
-
*/
|
|
438
|
-
cancel: boolean
|
|
439
|
-
/**
|
|
440
|
-
* Returns the original event arguments.
|
|
441
|
-
*/
|
|
442
|
-
event: ProgressEventInit
|
|
443
|
-
/**
|
|
444
|
-
* Returns the file details that will be canceled.
|
|
445
|
-
*/
|
|
446
|
-
fileData: FileInfo
|
|
447
|
-
/**
|
|
448
|
-
* Defines the additional data in key and value pair format that will be submitted when the upload action is canceled.
|
|
449
|
-
*
|
|
450
|
-
*/
|
|
451
|
-
customFormData: { [key: string]: Object }[]
|
|
452
|
-
/**
|
|
453
|
-
* Defines the additional data in key and value pair format that will be submitted on the header when the upload action is canceled.
|
|
454
|
-
*
|
|
455
|
-
*/
|
|
456
|
-
currentRequest?: { [key: string]: string }[]
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
export interface PauseResumeEventArgs {
|
|
460
|
-
/**
|
|
461
|
-
* Returns the original event arguments.
|
|
462
|
-
*/
|
|
463
|
-
event: Event
|
|
464
|
-
/**
|
|
465
|
-
* Returns the file data that is Paused or Resumed.
|
|
466
|
-
*/
|
|
467
|
-
file: FileInfo
|
|
468
|
-
/**
|
|
469
|
-
* Returns the total number of chunks.
|
|
470
|
-
*/
|
|
471
|
-
chunkCount: number
|
|
472
|
-
/**
|
|
473
|
-
* Returns the index of chunk that is Paused or Resumed.
|
|
474
|
-
*/
|
|
475
|
-
chunkIndex: number
|
|
476
|
-
/**
|
|
477
|
-
* Returns the chunk size value in bytes.
|
|
478
|
-
*/
|
|
479
|
-
chunkSize: number
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
export interface ActionCompleteEventArgs {
|
|
483
|
-
/**
|
|
484
|
-
* Return the selected file details.
|
|
485
|
-
*/
|
|
486
|
-
fileData: FileInfo[]
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
export interface RenderingEventArgs {
|
|
490
|
-
/**
|
|
491
|
-
* Return the current file item element.
|
|
492
|
-
*/
|
|
493
|
-
element: HTMLElement
|
|
494
|
-
/**
|
|
495
|
-
* Return the current rendering file item data as File object.
|
|
496
|
-
*/
|
|
497
|
-
fileInfo: FileInfo
|
|
498
|
-
/**
|
|
499
|
-
* Return the index of the file item in the file list.
|
|
500
|
-
*/
|
|
501
|
-
index: number
|
|
502
|
-
/**
|
|
503
|
-
* Return whether the file is preloaded
|
|
504
|
-
*/
|
|
505
|
-
isPreload: boolean
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
export interface FileListRenderingEventArgs {
|
|
509
|
-
/**
|
|
510
|
-
* Return the current file item element.
|
|
511
|
-
*/
|
|
512
|
-
element: HTMLElement
|
|
513
|
-
/**
|
|
514
|
-
* Return the current rendering file item data as File object.
|
|
515
|
-
*/
|
|
516
|
-
fileInfo: FileInfo
|
|
517
|
-
/**
|
|
518
|
-
* Return the index of the file item in the file list.
|
|
519
|
-
*/
|
|
520
|
-
index: number
|
|
521
|
-
/**
|
|
522
|
-
* Return whether the file is preloaded
|
|
523
|
-
*/
|
|
524
|
-
isPreload: boolean
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
interface InitialAttr {
|
|
528
|
-
accept: string
|
|
529
|
-
multiple: boolean
|
|
530
|
-
disabled: boolean
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
/**
|
|
534
|
-
* The uploader component allows to upload images, documents, and other files from local to server.
|
|
535
|
-
* ```html
|
|
536
|
-
* <input type='file' name='images[]' id='upload'/>
|
|
537
|
-
* ```
|
|
538
|
-
* ```typescript
|
|
539
|
-
* <script>
|
|
540
|
-
* var uploadObj = new Uploader();
|
|
541
|
-
* uploadObj.appendTo('#upload');
|
|
542
|
-
* </script>
|
|
543
|
-
* ```
|
|
544
|
-
*/
|
|
545
|
-
|
|
546
|
-
@NotifyPropertyChanges
|
|
547
|
-
export class Uploader extends Component<HTMLInputElement> implements INotifyPropertyChanged {
|
|
548
|
-
private initialAttr: InitialAttr = { accept: null, multiple: false, disabled: false };
|
|
549
|
-
private uploadWrapper: HTMLElement;
|
|
550
|
-
private browseButton: HTMLElement;
|
|
551
|
-
private listParent: HTMLElement;
|
|
552
|
-
private sortFilesList: FileList;
|
|
553
|
-
private actionButtons: HTMLElement;
|
|
554
|
-
private uploadButton: HTMLElement;
|
|
555
|
-
private clearButton: HTMLElement;
|
|
556
|
-
private pauseButton: HTMLElement;
|
|
557
|
-
private formElement: HTMLElement;
|
|
558
|
-
private dropAreaWrapper: HTMLElement;
|
|
559
|
-
private filesEntries: any[];
|
|
560
|
-
private uploadedFilesData: FileInfo[] = [];
|
|
561
|
-
private base64String: string[] = [];
|
|
562
|
-
private currentRequestHeader: { [key: string]: string }[];
|
|
563
|
-
private customFormDatas: { [key: string]: object }[];
|
|
564
|
-
private dropZoneElement: HTMLElement;
|
|
565
|
-
private l10n: L10n;
|
|
566
|
-
private preLocaleObj: { [key: string]: Object };
|
|
567
|
-
private uploadTemplateFn: Function;
|
|
568
|
-
private keyboardModule: KeyboardEvents;
|
|
569
|
-
private progressInterval: string;
|
|
570
|
-
private progressAnimation: Animation;
|
|
571
|
-
private isForm: boolean = false;
|
|
572
|
-
private allTypes: boolean = false;
|
|
573
|
-
private keyConfigs: { [key: string]: string };
|
|
574
|
-
private localeText: { [key: string]: Object };
|
|
575
|
-
private pausedData: MetaData[] = [];
|
|
576
|
-
private uploadMetaData: MetaData[] = [];
|
|
577
|
-
private tabIndex: string = '0';
|
|
578
|
-
private btnTabIndex: string = '0';
|
|
579
|
-
private disableKeyboardNavigation: boolean = false;
|
|
580
|
-
private count: number = -1;
|
|
581
|
-
private actionCompleteCount: number = 0;
|
|
582
|
-
private flag: boolean = true;
|
|
583
|
-
private selectedFiles: FileInfo[] = [];
|
|
584
|
-
private browserName: string;
|
|
585
|
-
private uploaderOptions: UploaderModel;
|
|
586
|
-
private uploaderName: string = 'UploadFiles';
|
|
587
|
-
private fileStreams: FileInfo[] = [];
|
|
588
|
-
private newFileRef: number = 0;
|
|
589
|
-
private isFirstFileOnSelection: boolean = false;
|
|
590
|
-
private dragCounter : number = 0;
|
|
591
|
-
private isPreloadFiles: boolean;
|
|
592
|
-
/**
|
|
593
|
-
* Get the file item(li) which are shown in file list.
|
|
594
|
-
*
|
|
595
|
-
* @private
|
|
596
|
-
*/
|
|
597
|
-
public fileList: HTMLElement[] = [];
|
|
598
|
-
/**
|
|
599
|
-
* Get the data of files which are shown in file list.
|
|
600
|
-
*
|
|
601
|
-
* @private
|
|
602
|
-
*/
|
|
603
|
-
public filesData: FileInfo[] = [];
|
|
604
|
-
/**
|
|
605
|
-
* Configures the save and remove URL to perform the upload operations in the server asynchronously.
|
|
606
|
-
*
|
|
607
|
-
* @default { saveUrl: '', removeUrl: '' }
|
|
608
|
-
*/
|
|
609
|
-
@Complex<AsyncSettingsModel>({ saveUrl: '', removeUrl: '' }, AsyncSettings)
|
|
610
|
-
public asyncSettings: AsyncSettingsModel;
|
|
611
|
-
|
|
612
|
-
/**
|
|
613
|
-
* By default, the file uploader component is processing the multiple files simultaneously.
|
|
614
|
-
* If sequentialUpload property is enabled, the file upload component performs the upload one after the other.
|
|
615
|
-
*
|
|
616
|
-
* @default false
|
|
617
|
-
*/
|
|
618
|
-
@Property(false)
|
|
619
|
-
public sequentialUpload: boolean;
|
|
620
|
-
|
|
621
|
-
/**
|
|
622
|
-
* You can add the additional html attributes such as disabled, value etc., to the element.
|
|
623
|
-
* If you configured both property and equivalent html attribute then the component considers the property value.
|
|
624
|
-
*
|
|
625
|
-
* {% codeBlock src='uploader/htmlAttributes/index.md' %}{% endcodeBlock %}
|
|
626
|
-
*
|
|
627
|
-
* @default {}
|
|
628
|
-
*/
|
|
629
|
-
@Property({})
|
|
630
|
-
public htmlAttributes: { [key: string]: string };
|
|
631
|
-
|
|
632
|
-
/**
|
|
633
|
-
* Specifies the CSS class name that can be appended with root element of the uploader.
|
|
634
|
-
* One or more custom CSS classes can be added to a uploader.
|
|
635
|
-
*
|
|
636
|
-
* @default ''
|
|
637
|
-
*/
|
|
638
|
-
@Property('')
|
|
639
|
-
public cssClass: string;
|
|
640
|
-
/**
|
|
641
|
-
* Specifies Boolean value that indicates whether the component is enabled or disabled.
|
|
642
|
-
* The uploader component does not allow to interact when this property is disabled.
|
|
643
|
-
*
|
|
644
|
-
* @default true
|
|
645
|
-
*/
|
|
646
|
-
@Property(true)
|
|
647
|
-
public enabled: boolean;
|
|
648
|
-
|
|
649
|
-
/**
|
|
650
|
-
* Specifies the HTML string that used to customize the content of each file in the list.
|
|
651
|
-
*
|
|
652
|
-
* > For more information, refer to the [template](../../uploader/template/) section from the documentation.
|
|
653
|
-
*
|
|
654
|
-
* @default null
|
|
655
|
-
* @aspType string
|
|
656
|
-
*/
|
|
657
|
-
@Property(null)
|
|
658
|
-
public template: string | Function;
|
|
659
|
-
|
|
660
|
-
/**
|
|
661
|
-
* Specifies a Boolean value that indicates whether the multiple files can be browsed or
|
|
662
|
-
* dropped simultaneously in the uploader component.
|
|
663
|
-
*
|
|
664
|
-
* @default true
|
|
665
|
-
*/
|
|
666
|
-
@Property(true)
|
|
667
|
-
public multiple: boolean;
|
|
668
|
-
|
|
669
|
-
/**
|
|
670
|
-
* By default, the uploader component initiates automatic upload when the files are added in upload queue.
|
|
671
|
-
* If you want to manipulate the files before uploading to server, disable the autoUpload property.
|
|
672
|
-
* The buttons “upload” and “clear” will be hided from file list when autoUpload property is true.
|
|
673
|
-
*
|
|
674
|
-
* @default true
|
|
675
|
-
*/
|
|
676
|
-
@Property(true)
|
|
677
|
-
public autoUpload: boolean;
|
|
678
|
-
|
|
679
|
-
/**
|
|
680
|
-
* Specifies Boolean value that indicates whether to prevent the cross site scripting code in filename or not.
|
|
681
|
-
* The uploader component removes the cross-site scripting code or functions from the filename and shows the validation error message to the user when enableHtmlSanitizer is true.
|
|
682
|
-
*
|
|
683
|
-
* @default true
|
|
684
|
-
*/
|
|
685
|
-
@Property(true)
|
|
686
|
-
public enableHtmlSanitizer: boolean;
|
|
687
|
-
|
|
688
|
-
/**
|
|
689
|
-
* You can customize the default text of “browse, clear, and upload” buttons with plain text or HTML elements.
|
|
690
|
-
* The buttons’ text can be customized from localization also. If you configured both locale and buttons property,
|
|
691
|
-
* the uploader component considers the buttons property value.
|
|
692
|
-
* {% codeBlock src='uploader/buttons/index.md' %}{% endcodeBlock %}
|
|
693
|
-
*
|
|
694
|
-
* @default { browse : 'Browse...', clear: 'Clear', upload: 'Upload' }
|
|
695
|
-
*/
|
|
696
|
-
@Complex<ButtonsPropsModel>({}, ButtonsProps)
|
|
697
|
-
public buttons: ButtonsPropsModel;
|
|
698
|
-
|
|
699
|
-
/**
|
|
700
|
-
* Specifies the extensions of the file types allowed in the uploader component and pass the extensions
|
|
701
|
-
* with comma separators. For example,
|
|
702
|
-
* if you want to upload specific image files, pass allowedExtensions as “.jpg,.png”.
|
|
703
|
-
*
|
|
704
|
-
* @default ''
|
|
705
|
-
*/
|
|
706
|
-
@Property('')
|
|
707
|
-
public allowedExtensions: string;
|
|
708
|
-
|
|
709
|
-
/**
|
|
710
|
-
* Specifies the minimum file size to be uploaded in bytes.
|
|
711
|
-
* The property used to make sure that you cannot upload empty files and small files.
|
|
712
|
-
*
|
|
713
|
-
* @default 0
|
|
714
|
-
*/
|
|
715
|
-
@Property(0)
|
|
716
|
-
public minFileSize: number;
|
|
717
|
-
|
|
718
|
-
/**
|
|
719
|
-
* Specifies the maximum allowed file size to be uploaded in bytes.
|
|
720
|
-
* The property used to make sure that you cannot upload too large files.
|
|
721
|
-
*
|
|
722
|
-
* @default 30000000
|
|
723
|
-
*/
|
|
724
|
-
@Property(30000000)
|
|
725
|
-
public maxFileSize: number;
|
|
726
|
-
|
|
727
|
-
/**
|
|
728
|
-
* Specifies the drop target to handle the drag-and-drop upload.
|
|
729
|
-
* By default, the component creates wrapper around file input that will act as drop target.
|
|
730
|
-
*
|
|
731
|
-
* > For more information, refer to the [drag-and-drop](../../uploader/file-source/#drag-and-drop) section from the documentation.
|
|
732
|
-
*
|
|
733
|
-
* @default null
|
|
734
|
-
*/
|
|
735
|
-
@Property(null)
|
|
736
|
-
public dropArea: string | HTMLElement;
|
|
737
|
-
|
|
738
|
-
/**
|
|
739
|
-
* Specifies the list of files that will be preloaded on rendering of uploader component.
|
|
740
|
-
* The property used to view and remove the uploaded files from server. By default, the files are configured with
|
|
741
|
-
* uploaded successfully state. The following properties are mandatory to configure the preload files:
|
|
742
|
-
* * Name
|
|
743
|
-
* * Size
|
|
744
|
-
* * Type
|
|
745
|
-
*
|
|
746
|
-
* {% codeBlock src='uploader/files/index.md' %}{% endcodeBlock %}
|
|
747
|
-
*
|
|
748
|
-
* @default { name: '', size: null, type: '' }
|
|
749
|
-
*/
|
|
750
|
-
@Collection<FilesPropModel>([{}], FilesProp)
|
|
751
|
-
public files: FilesPropModel[];
|
|
752
|
-
|
|
753
|
-
/**
|
|
754
|
-
* Specifies a Boolean value that indicates whether the default file list can be rendered.
|
|
755
|
-
* The property used to prevent default file list and design own template for file list.
|
|
756
|
-
*
|
|
757
|
-
* @default true
|
|
758
|
-
*/
|
|
759
|
-
@Property(true)
|
|
760
|
-
public showFileList: boolean;
|
|
761
|
-
|
|
762
|
-
/**
|
|
763
|
-
* Specifies a Boolean value that indicates whether the folder of files can be browsed in the uploader component.
|
|
764
|
-
*
|
|
765
|
-
* > When enabled this property, it allows only files of folder to select or drop to upload and
|
|
766
|
-
* it cannot be allowed to select or drop files.
|
|
767
|
-
*
|
|
768
|
-
* @default false
|
|
769
|
-
*/
|
|
770
|
-
@Property(false)
|
|
771
|
-
public directoryUpload: boolean;
|
|
772
|
-
|
|
773
|
-
/**
|
|
774
|
-
* Specifies the drag operation effect to the uploader component. Possible values are Copy , Move, Link and None.
|
|
775
|
-
*
|
|
776
|
-
* By default, the uploader component works based on the browser drag operation effect.
|
|
777
|
-
*
|
|
778
|
-
* @default 'Default'
|
|
779
|
-
*/
|
|
780
|
-
@Property('Default')
|
|
781
|
-
public dropEffect: DropEffect;
|
|
782
|
-
|
|
783
|
-
/**
|
|
784
|
-
* Triggers when the component is created.
|
|
785
|
-
*
|
|
786
|
-
* @event created
|
|
787
|
-
*/
|
|
788
|
-
@Event()
|
|
789
|
-
public created: EmitType<Object>;
|
|
790
|
-
|
|
791
|
-
/**
|
|
792
|
-
* Triggers after all the selected files has processed to upload successfully or failed to server.
|
|
793
|
-
*
|
|
794
|
-
* @event actionComplete
|
|
795
|
-
*/
|
|
796
|
-
@Event()
|
|
797
|
-
public actionComplete: EmitType<ActionCompleteEventArgs>;
|
|
798
|
-
|
|
799
|
-
/**
|
|
800
|
-
* DEPRECATED-Triggers before rendering each file item from the file list in a page.
|
|
801
|
-
* It helps to customize specific file item structure.
|
|
802
|
-
*
|
|
803
|
-
* @event rendering
|
|
804
|
-
*/
|
|
805
|
-
@Event()
|
|
806
|
-
public rendering: EmitType<RenderingEventArgs>;
|
|
807
|
-
|
|
808
|
-
/**
|
|
809
|
-
* Triggers when the upload process before. This event is used to add additional parameter with upload request.
|
|
810
|
-
*
|
|
811
|
-
* @event beforeUpload
|
|
812
|
-
*/
|
|
813
|
-
@Event()
|
|
814
|
-
public beforeUpload: EmitType<BeforeUploadEventArgs>;
|
|
815
|
-
|
|
816
|
-
/**
|
|
817
|
-
* Triggers before rendering each file item from the file list in a page.
|
|
818
|
-
* It helps to customize specific file item structure.
|
|
819
|
-
*
|
|
820
|
-
* @event fileListRendering
|
|
821
|
-
*/
|
|
822
|
-
@Event()
|
|
823
|
-
public fileListRendering: EmitType<FileListRenderingEventArgs>;
|
|
824
|
-
|
|
825
|
-
/**
|
|
826
|
-
* Triggers after selecting or dropping the files by adding the files in upload queue.
|
|
827
|
-
*
|
|
828
|
-
* @event selected
|
|
829
|
-
*/
|
|
830
|
-
@Event()
|
|
831
|
-
public selected: EmitType<SelectedEventArgs>;
|
|
832
|
-
|
|
833
|
-
/**
|
|
834
|
-
* Triggers when the upload process gets started. This event is used to add additional parameter with upload request.
|
|
835
|
-
*
|
|
836
|
-
* @event uploading
|
|
837
|
-
*/
|
|
838
|
-
@Event()
|
|
839
|
-
public uploading: EmitType<UploadingEventArgs>;
|
|
840
|
-
|
|
841
|
-
/**
|
|
842
|
-
* Triggers when the AJAX request gets success on uploading files or removing files.
|
|
843
|
-
*
|
|
844
|
-
* <table>
|
|
845
|
-
* <tr>
|
|
846
|
-
* <td colSpan=1 rowSpan=1>
|
|
847
|
-
* Event arguments<br/></td><td colSpan=1 rowSpan=1>
|
|
848
|
-
* Description<br/></td></tr>
|
|
849
|
-
* <tr>
|
|
850
|
-
* <td colSpan=1 rowSpan=1>
|
|
851
|
-
* event<br/></td><td colSpan=1 rowSpan=1>
|
|
852
|
-
* Ajax progress event arguments.<br/></td></tr>
|
|
853
|
-
* <tr>
|
|
854
|
-
* <td colSpan=1 rowSpan=1>
|
|
855
|
-
* file<br/></td><td colSpan=1 rowSpan=1>
|
|
856
|
-
* File information which is uploaded/removed.<br/></td></tr>
|
|
857
|
-
* <tr>
|
|
858
|
-
* <td colSpan=1 rowSpan=1>
|
|
859
|
-
* name<br/></td><td colSpan=1 rowSpan=1>
|
|
860
|
-
* Name of the event<br/></td></tr>
|
|
861
|
-
* <tr>
|
|
862
|
-
* <td colSpan=1 rowSpan=1>
|
|
863
|
-
* operation<br/></td><td colSpan=1 rowSpan=1>
|
|
864
|
-
* It indicates the success of the operation whether its uploaded or removed<br/></td></tr>
|
|
865
|
-
* </table>
|
|
866
|
-
*
|
|
867
|
-
* @event success
|
|
868
|
-
*/
|
|
869
|
-
@Event()
|
|
870
|
-
public success: EmitType<Object>;
|
|
871
|
-
|
|
872
|
-
/**
|
|
873
|
-
* Triggers when the AJAX request fails on uploading or removing files.
|
|
874
|
-
*
|
|
875
|
-
* <table>
|
|
876
|
-
* <tr>
|
|
877
|
-
* <td colSpan=1 rowSpan=1>
|
|
878
|
-
* Event arguments<br/></td><td colSpan=1 rowSpan=1>
|
|
879
|
-
* Description<br/></td></tr>
|
|
880
|
-
* <tr>
|
|
881
|
-
* <td colSpan=1 rowSpan=1>
|
|
882
|
-
* event<br/></td><td colSpan=1 rowSpan=1>
|
|
883
|
-
* Ajax progress event arguments.<br/></td></tr>
|
|
884
|
-
* <tr>
|
|
885
|
-
* <td colSpan=1 rowSpan=1>
|
|
886
|
-
* file<br/></td><td colSpan=1 rowSpan=1>
|
|
887
|
-
* File information which is failed from upload/remove.<br/></td></tr>
|
|
888
|
-
* <tr>
|
|
889
|
-
* <td colSpan=1 rowSpan=1>
|
|
890
|
-
* name<br/></td><td colSpan=1 rowSpan=1>
|
|
891
|
-
* Name of the event<br/></td></tr>
|
|
892
|
-
* <tr>
|
|
893
|
-
* <td colSpan=1 rowSpan=1>
|
|
894
|
-
* operation<br/></td><td colSpan=1 rowSpan=1>
|
|
895
|
-
* It indicates the failure of the operation whether its upload or remove<br/></td></tr>
|
|
896
|
-
* </table>
|
|
897
|
-
*
|
|
898
|
-
* @event failure
|
|
899
|
-
*/
|
|
900
|
-
@Event()
|
|
901
|
-
public failure: EmitType<Object>;
|
|
902
|
-
|
|
903
|
-
/**
|
|
904
|
-
* Triggers on removing the uploaded file. The event used to get confirm before removing the file from server.
|
|
905
|
-
*
|
|
906
|
-
* @event removing
|
|
907
|
-
*/
|
|
908
|
-
@Event()
|
|
909
|
-
public removing: EmitType<RemovingEventArgs>;
|
|
910
|
-
|
|
911
|
-
/**
|
|
912
|
-
* Triggers on remove the uploaded file. The event used to get confirm before remove the file from server.
|
|
913
|
-
*
|
|
914
|
-
* @event beforeRemove
|
|
915
|
-
*/
|
|
916
|
-
@Event()
|
|
917
|
-
public beforeRemove: EmitType<BeforeRemoveEventArgs>;
|
|
918
|
-
|
|
919
|
-
/**
|
|
920
|
-
* Triggers before clearing the items in file list when clicking “clear”.
|
|
921
|
-
*
|
|
922
|
-
* @event clearing
|
|
923
|
-
*/
|
|
924
|
-
@Event()
|
|
925
|
-
public clearing: EmitType<ClearingEventArgs>;
|
|
926
|
-
|
|
927
|
-
/**
|
|
928
|
-
* Triggers when uploading a file to the server using the AJAX request.
|
|
929
|
-
*
|
|
930
|
-
* <table>
|
|
931
|
-
* <tr>
|
|
932
|
-
* <td colSpan=1 rowSpan=1>
|
|
933
|
-
* Event arguments<br/></td><td colSpan=1 rowSpan=1>
|
|
934
|
-
* Description<br/></td></tr>
|
|
935
|
-
* <tr>
|
|
936
|
-
* <td colSpan=1 rowSpan=1>
|
|
937
|
-
* event<br/></td><td colSpan=1 rowSpan=1>
|
|
938
|
-
* Ajax progress event arguments.<br/></td></tr>
|
|
939
|
-
* <tr>
|
|
940
|
-
* <td colSpan=1 rowSpan=1>
|
|
941
|
-
* file<br/></td><td colSpan=1 rowSpan=1>
|
|
942
|
-
* File information which is uploading to server.<br/></td></tr>
|
|
943
|
-
* <tr>
|
|
944
|
-
* <td colSpan=1 rowSpan=1>
|
|
945
|
-
* name<br/></td><td colSpan=1 rowSpan=1>
|
|
946
|
-
* Name of the event<br/></td></tr>
|
|
947
|
-
* </table>
|
|
948
|
-
*
|
|
949
|
-
* @event progress
|
|
950
|
-
*/
|
|
951
|
-
@Event()
|
|
952
|
-
public progress: EmitType<Object>;
|
|
953
|
-
|
|
954
|
-
/**
|
|
955
|
-
* Triggers when changes occur in uploaded file list by selecting or dropping files.
|
|
956
|
-
*
|
|
957
|
-
* <table>
|
|
958
|
-
* <tr>
|
|
959
|
-
* <td colSpan=1 rowSpan=1>
|
|
960
|
-
* Event arguments<br/></td><td colSpan=1 rowSpan=1>
|
|
961
|
-
* Description<br/></td></tr>
|
|
962
|
-
* <tr>
|
|
963
|
-
* <td colSpan=1 rowSpan=1>
|
|
964
|
-
* file<br/></td><td colSpan=1 rowSpan=1>
|
|
965
|
-
* File information which is successfully uploaded to server or removed in server.<br/></td></tr>
|
|
966
|
-
* <tr>
|
|
967
|
-
* <td colSpan=1 rowSpan=1>
|
|
968
|
-
* name<br/></td><td colSpan=1 rowSpan=1>
|
|
969
|
-
* Name of the event<br/></td></tr>
|
|
970
|
-
* </table>
|
|
971
|
-
*
|
|
972
|
-
* @event change
|
|
973
|
-
*/
|
|
974
|
-
@Event()
|
|
975
|
-
public change: EmitType<Object>;
|
|
976
|
-
|
|
977
|
-
/**
|
|
978
|
-
* Fires when the chunk file uploaded successfully.
|
|
979
|
-
*
|
|
980
|
-
* <table>
|
|
981
|
-
* <tr>
|
|
982
|
-
* <td colSpan=1 rowSpan=1>
|
|
983
|
-
* Event arguments<br/></td><td colSpan=1 rowSpan=1>
|
|
984
|
-
* Description<br/></td></tr>
|
|
985
|
-
* <tr>
|
|
986
|
-
* <td colSpan=1 rowSpan=1>
|
|
987
|
-
* chunkIndex<br/></td><td colSpan=1 rowSpan=1>
|
|
988
|
-
* Returns current chunk index.<br/></td></tr>
|
|
989
|
-
* <tr>
|
|
990
|
-
* <td colSpan=1 rowSpan=1>
|
|
991
|
-
* chunkSize<br/></td><td colSpan=1 rowSpan=1>
|
|
992
|
-
* Returns the size of the chunk file.<br/></td></tr>
|
|
993
|
-
* <tr>
|
|
994
|
-
* <td colSpan=1 rowSpan=1>
|
|
995
|
-
* file<br/></td><td colSpan=1 rowSpan=1>
|
|
996
|
-
* File information which is uploading to server.<br/></td></tr>
|
|
997
|
-
* <tr>
|
|
998
|
-
* <td colSpan=1 rowSpan=1>
|
|
999
|
-
* name<br/></td><td colSpan=1 rowSpan=1>
|
|
1000
|
-
* Name of the event<br/></td></tr>
|
|
1001
|
-
* </table>
|
|
1002
|
-
*
|
|
1003
|
-
* @event chunkSuccess
|
|
1004
|
-
*/
|
|
1005
|
-
@Event()
|
|
1006
|
-
public chunkSuccess: EmitType<Object>;
|
|
1007
|
-
|
|
1008
|
-
/**
|
|
1009
|
-
* Fires if the chunk file failed to upload.
|
|
1010
|
-
*
|
|
1011
|
-
* <table>
|
|
1012
|
-
* <tr>
|
|
1013
|
-
* <td colSpan=1 rowSpan=1>
|
|
1014
|
-
* Event arguments<br/></td><td colSpan=1 rowSpan=1>
|
|
1015
|
-
* Description<br/></td></tr>
|
|
1016
|
-
* <tr>
|
|
1017
|
-
* <td colSpan=1 rowSpan=1>
|
|
1018
|
-
* chunkIndex<br/></td><td colSpan=1 rowSpan=1>
|
|
1019
|
-
* Returns current chunk index.<br/></td></tr>
|
|
1020
|
-
* <tr>
|
|
1021
|
-
* <td colSpan=1 rowSpan=1>
|
|
1022
|
-
* chunkSize<br/></td><td colSpan=1 rowSpan=1>
|
|
1023
|
-
* Returns the size of the chunk file.<br/></td></tr>
|
|
1024
|
-
* <tr>
|
|
1025
|
-
* <td colSpan=1 rowSpan=1>
|
|
1026
|
-
* file<br/></td><td colSpan=1 rowSpan=1>
|
|
1027
|
-
* File information which is uploading to server.<br/></td></tr>
|
|
1028
|
-
* <tr>
|
|
1029
|
-
* <td colSpan=1 rowSpan=1>
|
|
1030
|
-
* name<br/></td><td colSpan=1 rowSpan=1>
|
|
1031
|
-
* Name of the event<br/></td></tr>
|
|
1032
|
-
* <tr>
|
|
1033
|
-
* <td colSpan=1 rowSpan=1>
|
|
1034
|
-
* totalChunk<br/></td><td colSpan=1 rowSpan=1>
|
|
1035
|
-
* Returns the total chunk count<br/></td></tr>
|
|
1036
|
-
* <tr>
|
|
1037
|
-
* <td colSpan=1 rowSpan=1>
|
|
1038
|
-
* cancel<br/></td><td colSpan=1 rowSpan=1>
|
|
1039
|
-
* Prevent triggering of failure event when we pass true to this attribute<br/></td></tr>
|
|
1040
|
-
* </table>
|
|
1041
|
-
*
|
|
1042
|
-
* @event chunkFailure
|
|
1043
|
-
*/
|
|
1044
|
-
@Event()
|
|
1045
|
-
public chunkFailure: EmitType<Object>;
|
|
1046
|
-
|
|
1047
|
-
/**
|
|
1048
|
-
* Fires when every chunk upload process gets started. This event is used to add additional parameter with upload request.
|
|
1049
|
-
*
|
|
1050
|
-
* @event chunkUploading
|
|
1051
|
-
*/
|
|
1052
|
-
@Event()
|
|
1053
|
-
public chunkUploading: EmitType<UploadingEventArgs>;
|
|
1054
|
-
|
|
1055
|
-
/**
|
|
1056
|
-
* Fires if cancel the chunk file uploading.
|
|
1057
|
-
*
|
|
1058
|
-
* @event canceling
|
|
1059
|
-
*/
|
|
1060
|
-
@Event()
|
|
1061
|
-
public canceling: EmitType<CancelEventArgs>;
|
|
1062
|
-
|
|
1063
|
-
/**
|
|
1064
|
-
* Fires if pause the chunk file uploading.
|
|
1065
|
-
*
|
|
1066
|
-
* @event pausing
|
|
1067
|
-
*/
|
|
1068
|
-
@Event()
|
|
1069
|
-
public pausing: EmitType<PauseResumeEventArgs>;
|
|
1070
|
-
|
|
1071
|
-
/**
|
|
1072
|
-
* Fires if resume the paused chunk file upload.
|
|
1073
|
-
*
|
|
1074
|
-
* @event resuming
|
|
1075
|
-
*/
|
|
1076
|
-
@Event()
|
|
1077
|
-
public resuming: EmitType<PauseResumeEventArgs>;
|
|
1078
|
-
/**
|
|
1079
|
-
* Triggers when change the Uploader value.
|
|
1080
|
-
*
|
|
1081
|
-
* @param {UploaderModel} options - Specifies the Uploader model.
|
|
1082
|
-
* @param {string | HTMLInputElement} element - Specifies the element to render as component.
|
|
1083
|
-
* @private
|
|
1084
|
-
*/
|
|
1085
|
-
public constructor(options?: UploaderModel, element?: string | HTMLInputElement) {
|
|
1086
|
-
super(options, element);
|
|
1087
|
-
this.uploaderOptions = options;
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
/**
|
|
1091
|
-
* Calls internally if any of the property value is changed.
|
|
1092
|
-
*
|
|
1093
|
-
* @param {UploaderModel} newProp - Returns the dynamic property value of the component.
|
|
1094
|
-
* @param {UploaderModel} oldProp - Returns the previous property value of the component.
|
|
1095
|
-
* @returns {void}
|
|
1096
|
-
* @private
|
|
1097
|
-
*/
|
|
1098
|
-
public onPropertyChanged(newProp: UploaderModel, oldProp: UploaderModel): void {
|
|
1099
|
-
for (const prop of Object.keys(newProp)) {
|
|
1100
|
-
switch (prop) {
|
|
1101
|
-
case 'allowedExtensions':
|
|
1102
|
-
this.setExtensions(this.allowedExtensions);
|
|
1103
|
-
this.clearAll();
|
|
1104
|
-
break;
|
|
1105
|
-
case 'enabled':
|
|
1106
|
-
this.setControlStatus();
|
|
1107
|
-
break;
|
|
1108
|
-
case 'multiple':
|
|
1109
|
-
this.setMultipleSelection();
|
|
1110
|
-
break;
|
|
1111
|
-
case 'enableRtl':
|
|
1112
|
-
this.setRTL();
|
|
1113
|
-
this.reRenderFileList();
|
|
1114
|
-
break;
|
|
1115
|
-
case 'buttons':
|
|
1116
|
-
this.buttons.browse = isNullOrUndefined(this.buttons.browse) ? '' : this.buttons.browse;
|
|
1117
|
-
this.buttons.clear = isNullOrUndefined(this.buttons.clear) ? '' : this.buttons.clear;
|
|
1118
|
-
this.buttons.upload = isNullOrUndefined(this.buttons.upload) ? '' : this.buttons.upload;
|
|
1119
|
-
this.renderButtonTemplates();
|
|
1120
|
-
break;
|
|
1121
|
-
case 'dropArea':
|
|
1122
|
-
this.unBindDropEvents();
|
|
1123
|
-
this.updateDropArea();
|
|
1124
|
-
break;
|
|
1125
|
-
case 'htmlAttributes':
|
|
1126
|
-
this.updateHTMLAttrToElement();
|
|
1127
|
-
this.updateHTMLAttrToWrapper();
|
|
1128
|
-
this.checkHTMLAttributes(true);
|
|
1129
|
-
break;
|
|
1130
|
-
case 'files':
|
|
1131
|
-
this.renderPreLoadFiles();
|
|
1132
|
-
break;
|
|
1133
|
-
case 'directoryUpload':
|
|
1134
|
-
this.updateDirectoryAttributes();
|
|
1135
|
-
break;
|
|
1136
|
-
case 'template':
|
|
1137
|
-
if ((this as any).isReact){
|
|
1138
|
-
this.reRenderFileList();
|
|
1139
|
-
}else{
|
|
1140
|
-
this.clearAll();
|
|
1141
|
-
}
|
|
1142
|
-
break;
|
|
1143
|
-
case 'minFileSize':
|
|
1144
|
-
case 'maxFileSize':
|
|
1145
|
-
case 'autoUpload':
|
|
1146
|
-
this.clearAll();
|
|
1147
|
-
break;
|
|
1148
|
-
case 'sequentialUpload':
|
|
1149
|
-
this.clearAll();
|
|
1150
|
-
break;
|
|
1151
|
-
case 'locale':
|
|
1152
|
-
this.l10n.setLocale(this.locale);
|
|
1153
|
-
this.setLocalizedTexts();
|
|
1154
|
-
this.preLocaleObj = getValue('currentLocale', this.l10n);
|
|
1155
|
-
break;
|
|
1156
|
-
case 'cssClass':
|
|
1157
|
-
this.setCSSClass(oldProp.cssClass);
|
|
1158
|
-
break;
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
private setLocalizedTexts() : void {
|
|
1164
|
-
if (isNullOrUndefined(this.template)) {
|
|
1165
|
-
if (typeof (this.buttons.browse) === 'string') {
|
|
1166
|
-
this.browseButton.innerText = (this.buttons.browse === 'Browse...') ?
|
|
1167
|
-
this.localizedTexts('Browse') : this.buttons.browse;
|
|
1168
|
-
this.browseButton.setAttribute('title', this.browseButton.innerText);
|
|
1169
|
-
if (this.uploadWrapper && !isNullOrUndefined(this.uploadWrapper.querySelector('.' + DROP_AREA))) {
|
|
1170
|
-
this.uploadWrapper.querySelector('.' + DROP_AREA).innerHTML = this.localizedTexts('dropFilesHint');
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
this.updateFileList();
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
private getKeyValue(val : string): string {
|
|
1178
|
-
let keyValue: string;
|
|
1179
|
-
for (const key of Object.keys(this.preLocaleObj)) {
|
|
1180
|
-
if (this.preLocaleObj[`${key}`] === val) {
|
|
1181
|
-
keyValue = key;
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
return keyValue;
|
|
1185
|
-
}
|
|
1186
|
-
|
|
1187
|
-
private updateFileList () : void {
|
|
1188
|
-
let element : HTMLElement;
|
|
1189
|
-
/* istanbul ignore next */
|
|
1190
|
-
if (this.fileList.length > 0 && !isNullOrUndefined(this.uploadWrapper.querySelector('.' + LIST_PARENT ))) {
|
|
1191
|
-
for (let i: number = 0; i < this.fileList.length; i++) {
|
|
1192
|
-
element = this.fileList[i as number].querySelector('.e-file-status') as HTMLElement;
|
|
1193
|
-
element.innerHTML = this.localizedTexts(this.getKeyValue(this.filesData[i as number].status));
|
|
1194
|
-
this.filesData[i as number].status = this.localizedTexts(this.getKeyValue(this.filesData[i as number].status));
|
|
1195
|
-
if (this.fileList[i as number].classList.contains(UPLOAD_SUCCESS)) {
|
|
1196
|
-
this.fileList[i as number].querySelector('.e-icons').setAttribute('title', this.localizedTexts('delete'));
|
|
1197
|
-
}
|
|
1198
|
-
if (this.fileList[i as number].querySelector('.e-file-play-btn')) {
|
|
1199
|
-
this.fileList[i as number].querySelector('.e-icons').setAttribute('title', this.localizedTexts('resume'));
|
|
1200
|
-
}
|
|
1201
|
-
if (this.fileList[i as number].querySelector('.e-file-remove-btn')) {
|
|
1202
|
-
this.fileList[i as number].querySelector('.e-icons').setAttribute('title', this.localizedTexts('remove'));
|
|
1203
|
-
}
|
|
1204
|
-
if (this.fileList[i as number].querySelector('.e-file-reload-btn')) {
|
|
1205
|
-
this.fileList[i as number].querySelector('.e-icons').setAttribute('title', this.localizedTexts('retry'));
|
|
1206
|
-
}
|
|
1207
|
-
if (!this.autoUpload) {
|
|
1208
|
-
this.uploadButton.innerText = (this.buttons.upload === 'Upload') ?
|
|
1209
|
-
this.localizedTexts('Upload') : <string>this.buttons.upload;
|
|
1210
|
-
this.uploadButton.setAttribute('title', this.localizedTexts('Upload'));
|
|
1211
|
-
this.clearButton.innerText = (this.buttons.clear === 'Clear') ?
|
|
1212
|
-
this.localizedTexts('Clear') : <string>this.buttons.clear;
|
|
1213
|
-
this.clearButton.setAttribute('title', this.localizedTexts('Clear'));
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
|
-
private reRenderFileList(): void {
|
|
1220
|
-
if (this.listParent) {
|
|
1221
|
-
detach(this.listParent);
|
|
1222
|
-
this.listParent = null;
|
|
1223
|
-
this.fileList = [];
|
|
1224
|
-
this.internalCreateFileList(this.filesData);
|
|
1225
|
-
if (this.actionButtons) {
|
|
1226
|
-
this.removeActionButtons();
|
|
1227
|
-
this.renderActionButtons();
|
|
1228
|
-
this.checkActionButtonStatus();
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
|
-
protected preRender(): void {
|
|
1234
|
-
this.localeText = { Browse : 'Browse...', Clear : 'Clear', Upload : 'Upload', invalidFileName : 'File Name is not allowed',
|
|
1235
|
-
dropFilesHint : 'Or drop files here', invalidMaxFileSize : 'File size is too large',
|
|
1236
|
-
invalidMinFileSize : 'File size is too small', invalidFileType: 'File type is not allowed',
|
|
1237
|
-
uploadFailedMessage : 'File failed to upload', uploadSuccessMessage : 'File uploaded successfully',
|
|
1238
|
-
removedSuccessMessage: 'File removed successfully', removedFailedMessage: 'Unable to remove file', inProgress: 'Uploading',
|
|
1239
|
-
readyToUploadMessage: 'Ready to upload', abort: 'Abort', remove: 'Remove', cancel: 'Cancel', delete: 'Delete file',
|
|
1240
|
-
pauseUpload: 'File upload paused', pause: 'Pause', resume: 'Resume', retry: 'Retry',
|
|
1241
|
-
fileUploadCancel: 'File upload canceled', invalidFileSelection: 'Invalid files selected', totalFiles: 'Total files',
|
|
1242
|
-
size: 'Size'
|
|
1243
|
-
};
|
|
1244
|
-
this.l10n = new L10n('uploader', this.localeText, this.locale);
|
|
1245
|
-
this.preLocaleObj = getValue('currentLocale', this.l10n);
|
|
1246
|
-
this.formRendered();
|
|
1247
|
-
this.updateHTMLAttrToElement();
|
|
1248
|
-
this.checkHTMLAttributes(false);
|
|
1249
|
-
const ejInstance: any = getValue('ej2_instances', this.element);
|
|
1250
|
-
/* istanbul ignore next */
|
|
1251
|
-
if (this.element.tagName === 'EJS-UPLOADER') {
|
|
1252
|
-
const inputElement: HTMLInputElement = <HTMLInputElement>this.createElement('input', { attrs: { type: 'file' }});
|
|
1253
|
-
let index: number = 0;
|
|
1254
|
-
for (index; index < this.element.attributes.length; index++) {
|
|
1255
|
-
if (this.element.attributes[index as number].nodeName !== 'id'){
|
|
1256
|
-
inputElement.setAttribute(this.element.attributes[index as number].nodeName,
|
|
1257
|
-
this.element.attributes[index as number].nodeValue);
|
|
1258
|
-
}
|
|
1259
|
-
else if (this.element.attributes[index as number].nodeName === 'id'){
|
|
1260
|
-
inputElement.setAttribute(this.element.attributes[index as number].nodeName, getUniqueID('uploader'));
|
|
1261
|
-
}
|
|
1262
|
-
inputElement.innerHTML = this.element.innerHTML;
|
|
1263
|
-
}
|
|
1264
|
-
if (!inputElement.hasAttribute('name')) {
|
|
1265
|
-
inputElement.setAttribute('name', 'UploadFiles');
|
|
1266
|
-
}
|
|
1267
|
-
this.element.appendChild(inputElement);
|
|
1268
|
-
this.element = inputElement;
|
|
1269
|
-
setValue('ej2_instances', ejInstance, this.element);
|
|
1270
|
-
}
|
|
1271
|
-
/* istanbul ignore next */
|
|
1272
|
-
if (ejInstance[0].isPureReactComponent) {
|
|
1273
|
-
if (!isNullOrUndefined(ejInstance[0].props.name)) {
|
|
1274
|
-
this.element.setAttribute('name', ejInstance[0].props.name);
|
|
1275
|
-
} else if (!isNullOrUndefined(ejInstance[0].props.id) && isNullOrUndefined(ejInstance[0].props.name)) {
|
|
1276
|
-
this.element.setAttribute('name', ejInstance[0].props.id);
|
|
1277
|
-
} else {
|
|
1278
|
-
this.element.setAttribute('name', 'UploadFiles');
|
|
1279
|
-
}
|
|
1280
|
-
}
|
|
1281
|
-
if (isNullOrUndefined(this.element.getAttribute('name'))) {
|
|
1282
|
-
this.element.setAttribute('name', this.element.getAttribute('id'));
|
|
1283
|
-
}
|
|
1284
|
-
if (!this.element.hasAttribute('type')) {
|
|
1285
|
-
this.element.setAttribute('type', 'file');
|
|
1286
|
-
}
|
|
1287
|
-
this.updateDirectoryAttributes();
|
|
1288
|
-
this.keyConfigs = {
|
|
1289
|
-
enter: 'enter'
|
|
1290
|
-
};
|
|
1291
|
-
if (this.element.hasAttribute('tabindex')) {
|
|
1292
|
-
this.tabIndex = this.element.getAttribute('tabindex');
|
|
1293
|
-
}
|
|
1294
|
-
this.browserName = Browser.info.name;
|
|
1295
|
-
this.uploaderName = this.element.getAttribute('name');
|
|
1296
|
-
}
|
|
1297
|
-
|
|
1298
|
-
private formRendered(): void {
|
|
1299
|
-
let parentEle: HTMLElement = closest(this.element, 'form') as HTMLElement;
|
|
1300
|
-
if (!isNullOrUndefined(parentEle)) {
|
|
1301
|
-
for (; parentEle && parentEle !== document.documentElement; parentEle = parentEle.parentElement) {
|
|
1302
|
-
if (parentEle.tagName === 'FORM') {
|
|
1303
|
-
this.isForm = true;
|
|
1304
|
-
this.formElement = parentEle;
|
|
1305
|
-
parentEle.setAttribute('enctype', 'multipart/form-data');
|
|
1306
|
-
parentEle.setAttribute('encoding', 'multipart/form-data');
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
protected getPersistData(): string {
|
|
1313
|
-
return this.addOnPersist(['filesData']);
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
/**
|
|
1317
|
-
* Return the module name of the component.
|
|
1318
|
-
*
|
|
1319
|
-
* @returns {string} Returns the component name.
|
|
1320
|
-
*/
|
|
1321
|
-
public getModuleName(): string {
|
|
1322
|
-
return 'uploader';
|
|
1323
|
-
}
|
|
1324
|
-
|
|
1325
|
-
private updateDirectoryAttributes(): void {
|
|
1326
|
-
if (this.directoryUpload) {
|
|
1327
|
-
this.element.setAttribute('directory', 'true');
|
|
1328
|
-
this.element.setAttribute('webkitdirectory', 'true');
|
|
1329
|
-
} else {
|
|
1330
|
-
this.element.removeAttribute('directory');
|
|
1331
|
-
this.element.removeAttribute('webkitdirectory');
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
|
|
1335
|
-
/**
|
|
1336
|
-
* To Initialize the control rendering
|
|
1337
|
-
*
|
|
1338
|
-
* @private
|
|
1339
|
-
* @returns {void}
|
|
1340
|
-
*/
|
|
1341
|
-
public render(): void {
|
|
1342
|
-
this.renderBrowseButton();
|
|
1343
|
-
this.initializeUpload();
|
|
1344
|
-
this.updateHTMLAttrToWrapper();
|
|
1345
|
-
this.wireEvents();
|
|
1346
|
-
this.setMultipleSelection();
|
|
1347
|
-
this.setExtensions(this.allowedExtensions);
|
|
1348
|
-
this.setRTL();
|
|
1349
|
-
this.renderPreLoadFiles();
|
|
1350
|
-
this.setControlStatus();
|
|
1351
|
-
this.setCSSClass();
|
|
1352
|
-
}
|
|
1353
|
-
|
|
1354
|
-
private renderBrowseButton(): void {
|
|
1355
|
-
this.browseButton = this.createElement('button', { className: 'e-css e-btn', attrs: {'type': 'button'}});
|
|
1356
|
-
this.browseButton.setAttribute('tabindex', this.tabIndex);
|
|
1357
|
-
if (typeof(this.buttons.browse) === 'string') {
|
|
1358
|
-
this.browseButton.textContent = (this.buttons.browse === 'Browse...') ?
|
|
1359
|
-
this.localizedTexts('Browse') : this.buttons.browse;
|
|
1360
|
-
this.browseButton.setAttribute('title', this.browseButton.innerText);
|
|
1361
|
-
} else {
|
|
1362
|
-
this.browseButton.appendChild(this.buttons.browse);
|
|
1363
|
-
}
|
|
1364
|
-
this.element.setAttribute('aria-label', 'Uploader');
|
|
1365
|
-
}
|
|
1366
|
-
|
|
1367
|
-
private renderActionButtons(): void {
|
|
1368
|
-
this.element.setAttribute('tabindex', '-1');
|
|
1369
|
-
this.actionButtons = this.createElement('div', { className: ACTION_BUTTONS });
|
|
1370
|
-
this.uploadButton = this.createElement('button', { className: UPLOAD_BUTTONS ,
|
|
1371
|
-
attrs: {'type': 'button', 'tabindex': this.btnTabIndex , 'aria-label': this.localizedTexts('Upload')} });
|
|
1372
|
-
this.clearButton = this.createElement('button', { className: CLEAR_BUTTONS,
|
|
1373
|
-
attrs: {'type': 'button', 'tabindex': this.btnTabIndex, 'aria-label': this.localizedTexts('Clear') } });
|
|
1374
|
-
this.actionButtons.appendChild(this.clearButton);
|
|
1375
|
-
this.actionButtons.appendChild(this.uploadButton);
|
|
1376
|
-
this.renderButtonTemplates();
|
|
1377
|
-
this.uploadWrapper.appendChild(this.actionButtons);
|
|
1378
|
-
this.browseButton.blur();
|
|
1379
|
-
if (!this.isPreloadFiles) {
|
|
1380
|
-
this.uploadButton.focus();
|
|
1381
|
-
}
|
|
1382
|
-
this.wireActionButtonEvents();
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
|
-
/* istanbul ignore next */
|
|
1386
|
-
private serverActionButtonsEventBind(element: HTMLElement): void {
|
|
1387
|
-
if (element && !this.isForm) {
|
|
1388
|
-
this.browseButton.blur();
|
|
1389
|
-
this.actionButtons = element;
|
|
1390
|
-
this.uploadButton = this.actionButtons.querySelector('.e-file-upload-btn');
|
|
1391
|
-
this.clearButton = this.actionButtons.querySelector('.e-file-clear-btn');
|
|
1392
|
-
this.uploadButton.focus();
|
|
1393
|
-
this.unwireActionButtonEvents();
|
|
1394
|
-
this.wireActionButtonEvents();
|
|
1395
|
-
this.checkActionButtonStatus();
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
private wireActionButtonEvents(): void {
|
|
1400
|
-
EventHandler.add(this.uploadButton, 'click', this.uploadButtonClick, this);
|
|
1401
|
-
EventHandler.add(this.clearButton, 'click', this.clearButtonClick, this);
|
|
1402
|
-
}
|
|
1403
|
-
|
|
1404
|
-
private unwireActionButtonEvents(): void {
|
|
1405
|
-
EventHandler.remove(this.uploadButton, 'click', this.uploadButtonClick);
|
|
1406
|
-
EventHandler.remove(this.clearButton, 'click', this.clearButtonClick);
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1409
|
-
private removeActionButtons(): void {
|
|
1410
|
-
if (this.actionButtons) {
|
|
1411
|
-
this.unwireActionButtonEvents();
|
|
1412
|
-
detach(this.actionButtons);
|
|
1413
|
-
this.actionButtons = null;
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
|
|
1417
|
-
private renderButtonTemplates(): void {
|
|
1418
|
-
if (typeof (this.buttons.browse) === 'string') {
|
|
1419
|
-
this.browseButton.textContent = (this.buttons.browse === 'Browse...') ?
|
|
1420
|
-
this.localizedTexts('Browse') : this.buttons.browse;
|
|
1421
|
-
this.browseButton.setAttribute('title', this.browseButton.textContent);
|
|
1422
|
-
} else {
|
|
1423
|
-
this.browseButton.innerHTML = '';
|
|
1424
|
-
this.browseButton.appendChild(this.buttons.browse);
|
|
1425
|
-
}
|
|
1426
|
-
if (this.uploadButton) {
|
|
1427
|
-
const uploadText: string | HTMLElement = isNullOrUndefined(this.buttons.upload) ? 'Upload' : this.buttons.upload;
|
|
1428
|
-
this.buttons.upload = uploadText;
|
|
1429
|
-
if (typeof (this.buttons.upload) === 'string') {
|
|
1430
|
-
this.uploadButton.textContent = (this.buttons.upload === 'Upload') ?
|
|
1431
|
-
this.localizedTexts('Upload') : this.buttons.upload;
|
|
1432
|
-
this.uploadButton.setAttribute('title', this.uploadButton.textContent);
|
|
1433
|
-
} else {
|
|
1434
|
-
this.uploadButton.innerHTML = '';
|
|
1435
|
-
this.uploadButton.appendChild(this.buttons.upload);
|
|
1436
|
-
}
|
|
1437
|
-
}
|
|
1438
|
-
if (this.clearButton) {
|
|
1439
|
-
const clearText: string | HTMLElement = isNullOrUndefined(this.buttons.clear) ? 'Clear' : this.buttons.clear;
|
|
1440
|
-
this.buttons.clear = clearText;
|
|
1441
|
-
if (typeof (this.buttons.clear) === 'string') {
|
|
1442
|
-
this.clearButton.textContent = (this.buttons.clear === 'Clear') ?
|
|
1443
|
-
this.localizedTexts('Clear') : this.buttons.clear;
|
|
1444
|
-
this.clearButton.setAttribute('title', this.clearButton.textContent);
|
|
1445
|
-
} else {
|
|
1446
|
-
this.clearButton.innerHTML = '';
|
|
1447
|
-
this.clearButton.appendChild(this.buttons.clear);
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1451
|
-
|
|
1452
|
-
private initializeUpload(): void {
|
|
1453
|
-
this.element.setAttribute('tabindex', '-1');
|
|
1454
|
-
const inputWrapper: HTMLElement = this.createElement('span', { className: INPUT_WRAPPER });
|
|
1455
|
-
this.element.parentElement.insertBefore(inputWrapper, this.element);
|
|
1456
|
-
this.dropAreaWrapper = this.createElement('div', { className: DROP_WRAPPER });
|
|
1457
|
-
this.element.parentElement.insertBefore(this.dropAreaWrapper, this.element);
|
|
1458
|
-
inputWrapper.appendChild(this.element);
|
|
1459
|
-
this.dropAreaWrapper.appendChild(this.browseButton);
|
|
1460
|
-
this.dropAreaWrapper.appendChild(inputWrapper);
|
|
1461
|
-
this.uploadWrapper = this.createElement('div', { className: CONTROL_WRAPPER });
|
|
1462
|
-
this.dropAreaWrapper.parentElement.insertBefore(this.uploadWrapper, this.dropAreaWrapper);
|
|
1463
|
-
this.uploadWrapper.appendChild(this.dropAreaWrapper);
|
|
1464
|
-
this.setDropArea();
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
private renderPreLoadFiles(): void {
|
|
1468
|
-
if (this.files.length) {
|
|
1469
|
-
if (this.enablePersistence && this.filesData.length) {
|
|
1470
|
-
this.internalCreateFileList(this.filesData);
|
|
1471
|
-
return;
|
|
1472
|
-
}
|
|
1473
|
-
if (isNullOrUndefined(this.files[0].size)) {
|
|
1474
|
-
return;
|
|
1475
|
-
}
|
|
1476
|
-
this.isPreloadFiles = true;
|
|
1477
|
-
let files: FilesPropModel[] = [].slice.call(this.files);
|
|
1478
|
-
const filesData: FileInfo[] = [];
|
|
1479
|
-
if (!this.multiple) {
|
|
1480
|
-
this.clearData();
|
|
1481
|
-
files = [files[0]];
|
|
1482
|
-
}
|
|
1483
|
-
for (const data of files) {
|
|
1484
|
-
const fileData: FileInfo = {
|
|
1485
|
-
name: data.name + '.' + data.type.split('.')[data.type.split('.').length - 1],
|
|
1486
|
-
rawFile: '',
|
|
1487
|
-
size: data.size,
|
|
1488
|
-
status: this.localizedTexts('uploadSuccessMessage'),
|
|
1489
|
-
type: data.type,
|
|
1490
|
-
validationMessages: {minSize: '', maxSize: ''},
|
|
1491
|
-
statusCode: '2'
|
|
1492
|
-
};
|
|
1493
|
-
filesData.push(fileData);
|
|
1494
|
-
this.filesData.push(fileData);
|
|
1495
|
-
}
|
|
1496
|
-
this.internalCreateFileList(filesData);
|
|
1497
|
-
if (!this.autoUpload && this.listParent && !this.actionButtons && (!this.isForm || this.allowUpload()) && this.showFileList) {
|
|
1498
|
-
this.renderActionButtons();
|
|
1499
|
-
}
|
|
1500
|
-
this.checkActionButtonStatus();
|
|
1501
|
-
if (this.sequentialUpload) {
|
|
1502
|
-
this.count = this.filesData.length - 1;
|
|
1503
|
-
}
|
|
1504
|
-
this.isPreloadFiles = false;
|
|
1505
|
-
}
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
private checkActionButtonStatus(): void {
|
|
1509
|
-
if (this.actionButtons) {
|
|
1510
|
-
const length: number = this.uploadWrapper.querySelectorAll('.' + VALIDATION_FAILS).length +
|
|
1511
|
-
this.uploadWrapper.querySelectorAll('.e-upload-fails:not(.e-upload-progress)').length +
|
|
1512
|
-
this.uploadWrapper.querySelectorAll('span.' + UPLOAD_SUCCESS).length +
|
|
1513
|
-
this.uploadWrapper.querySelectorAll('span.' + UPLOAD_INPROGRESS).length;
|
|
1514
|
-
if (length > 0 && length === this.uploadWrapper.querySelectorAll('li').length) {
|
|
1515
|
-
this.uploadButton.setAttribute('disabled', 'disabled');
|
|
1516
|
-
} else {
|
|
1517
|
-
this.uploadButton.removeAttribute('disabled');
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
|
|
1522
|
-
private setDropArea(): void {
|
|
1523
|
-
const dropTextArea: HTMLElement = <HTMLElement>this.dropAreaWrapper.querySelector('.e-file-drop');
|
|
1524
|
-
if (this.dropArea) {
|
|
1525
|
-
this.dropZoneElement = (typeof(this.dropArea) !== 'string') ? this.dropArea :
|
|
1526
|
-
select(this.dropArea, document) as HTMLElement;
|
|
1527
|
-
let element: HTMLElement = this.element;
|
|
1528
|
-
let enableDropText: boolean = false;
|
|
1529
|
-
while (element.parentNode) {
|
|
1530
|
-
element = element.parentNode as HTMLElement;
|
|
1531
|
-
if (element === this.dropZoneElement) {
|
|
1532
|
-
enableDropText = true;
|
|
1533
|
-
if (!dropTextArea) {
|
|
1534
|
-
this.createDropTextHint();
|
|
1535
|
-
} else {
|
|
1536
|
-
dropTextArea.innerHTML = this.localizedTexts('dropFilesHint');
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1539
|
-
}
|
|
1540
|
-
if (!enableDropText && dropTextArea) {
|
|
1541
|
-
remove(dropTextArea);
|
|
1542
|
-
}
|
|
1543
|
-
} else if (!isNullOrUndefined(this.uploaderOptions) && this.uploaderOptions.dropArea === undefined) {
|
|
1544
|
-
this.createDropTextHint();
|
|
1545
|
-
this.dropZoneElement = this.uploadWrapper;
|
|
1546
|
-
this.setProperties({dropArea: this.uploadWrapper }, true);
|
|
1547
|
-
}
|
|
1548
|
-
this.bindDropEvents();
|
|
1549
|
-
}
|
|
1550
|
-
|
|
1551
|
-
private updateDropArea() : void {
|
|
1552
|
-
if (this.dropArea) {
|
|
1553
|
-
this.setDropArea();
|
|
1554
|
-
} else {
|
|
1555
|
-
this.dropZoneElement = null;
|
|
1556
|
-
const dropTextArea: HTMLElement = <HTMLElement>this.dropAreaWrapper.querySelector('.e-file-drop');
|
|
1557
|
-
if (dropTextArea) {
|
|
1558
|
-
remove(dropTextArea);
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
|
|
1563
|
-
private createDropTextHint () : void {
|
|
1564
|
-
const fileDropArea: HTMLElement = this.createElement('span', { className: DROP_AREA});
|
|
1565
|
-
fileDropArea.innerHTML = this.localizedTexts('dropFilesHint');
|
|
1566
|
-
this.dropAreaWrapper.appendChild(fileDropArea);
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
|
-
private updateHTMLAttrToElement(): void {
|
|
1570
|
-
if ( !isNullOrUndefined(this.htmlAttributes)) {
|
|
1571
|
-
for (const pro of Object.keys(this.htmlAttributes)) {
|
|
1572
|
-
if (wrapperAttr.indexOf(pro) < 0 ) {
|
|
1573
|
-
this.element.setAttribute(pro, this.htmlAttributes[`${pro}`]);
|
|
1574
|
-
}
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
private updateHTMLAttrToWrapper(): void {
|
|
1579
|
-
if ( !isNullOrUndefined(this.htmlAttributes)) {
|
|
1580
|
-
for (const pro of Object.keys(this.htmlAttributes)) {
|
|
1581
|
-
if (wrapperAttr.indexOf(pro) > -1 ) {
|
|
1582
|
-
if (pro === 'class') {
|
|
1583
|
-
const updatedClassValues : string = (this.htmlAttributes[`${pro}`].replace(/\s+/g, ' ')).trim();
|
|
1584
|
-
if (updatedClassValues !== '') {
|
|
1585
|
-
addClass([this.uploadWrapper], updatedClassValues.split(' '));
|
|
1586
|
-
}
|
|
1587
|
-
} else if (pro === 'style') {
|
|
1588
|
-
let uploadStyle: string = this.uploadWrapper.getAttribute(pro);
|
|
1589
|
-
uploadStyle = !isNullOrUndefined(uploadStyle) ? (uploadStyle + this.htmlAttributes[`${pro}`]) :
|
|
1590
|
-
this.htmlAttributes[`${pro}`];
|
|
1591
|
-
this.uploadWrapper.setAttribute(pro, uploadStyle);
|
|
1592
|
-
} else {
|
|
1593
|
-
this.uploadWrapper.setAttribute(pro, this.htmlAttributes[`${pro}`]);
|
|
1594
|
-
}
|
|
1595
|
-
}
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
}
|
|
1599
|
-
|
|
1600
|
-
private setMultipleSelection(): void {
|
|
1601
|
-
if (this.multiple && !this.element.hasAttribute('multiple')) {
|
|
1602
|
-
const newAttr: Attr = document.createAttribute('multiple');
|
|
1603
|
-
newAttr.value = 'multiple';
|
|
1604
|
-
this.element.setAttributeNode(newAttr);
|
|
1605
|
-
} else if (!this.multiple) {
|
|
1606
|
-
this.element.removeAttribute('multiple');
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
|
-
|
|
1610
|
-
private checkAutoUpload(fileData: FileInfo[]): void {
|
|
1611
|
-
if (this.autoUpload) {
|
|
1612
|
-
if (this.sequentialUpload) {
|
|
1613
|
-
/* istanbul ignore next */
|
|
1614
|
-
this.sequenceUpload(fileData);
|
|
1615
|
-
} else {
|
|
1616
|
-
this.upload(fileData);
|
|
1617
|
-
}
|
|
1618
|
-
this.removeActionButtons();
|
|
1619
|
-
} else if (!this.actionButtons) {
|
|
1620
|
-
this.renderActionButtons();
|
|
1621
|
-
}
|
|
1622
|
-
this.checkActionButtonStatus();
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1625
|
-
private sequenceUpload(fileData: FileInfo[]): void {
|
|
1626
|
-
if ( this.filesData.length - fileData.length === 0 ||
|
|
1627
|
-
this.filesData[(this.filesData.length - fileData.length - 1)].statusCode !== '1' ) {
|
|
1628
|
-
if (this.multiple || this.count < 0){
|
|
1629
|
-
++this.count;
|
|
1630
|
-
}
|
|
1631
|
-
const isFileListCreated: boolean = this.showFileList ? false : true;
|
|
1632
|
-
if (typeof this.filesData[this.count] === 'object') {
|
|
1633
|
-
this.isFirstFileOnSelection = false;
|
|
1634
|
-
this.upload(this.filesData[this.count], isFileListCreated);
|
|
1635
|
-
if (this.filesData[this.count].statusCode === '0') {
|
|
1636
|
-
this.sequenceUpload(fileData);
|
|
1637
|
-
}
|
|
1638
|
-
} else {
|
|
1639
|
-
--this.count;
|
|
1640
|
-
}
|
|
1641
|
-
}
|
|
1642
|
-
}
|
|
1643
|
-
private setCSSClass(oldCSSClass?: string): void {
|
|
1644
|
-
let updatedOldCssClass: string = oldCSSClass;
|
|
1645
|
-
if (!isNullOrUndefined(oldCSSClass)) {
|
|
1646
|
-
updatedOldCssClass = (oldCSSClass.replace(/\s+/g, ' ')).trim();
|
|
1647
|
-
}
|
|
1648
|
-
if (!isNullOrUndefined(oldCSSClass) && updatedOldCssClass !== '') {
|
|
1649
|
-
removeClass([this.uploadWrapper], updatedOldCssClass.split(' '));
|
|
1650
|
-
}
|
|
1651
|
-
let updatedCssClassValue: string = this.cssClass;
|
|
1652
|
-
if (!isNullOrUndefined(this.cssClass) && this.cssClass !== '') {
|
|
1653
|
-
updatedCssClassValue = (this.cssClass.replace(/\s+/g, ' ')).trim();
|
|
1654
|
-
}
|
|
1655
|
-
if (!isNullOrUndefined(this.cssClass) && updatedCssClassValue !== '') {
|
|
1656
|
-
addClass([this.uploadWrapper], updatedCssClassValue.split(updatedCssClassValue.indexOf(',') > -1 ? ',' : ' '));
|
|
1657
|
-
}
|
|
1658
|
-
}
|
|
1659
|
-
private wireEvents(): void {
|
|
1660
|
-
EventHandler.add(this.browseButton, 'click', this.browseButtonClick, this);
|
|
1661
|
-
EventHandler.add(this.element, 'change', this.onSelectFiles, this);
|
|
1662
|
-
EventHandler.add(document, 'click', this.removeFocus, this);
|
|
1663
|
-
this.keyboardModule = new KeyboardEvents( this.uploadWrapper, {
|
|
1664
|
-
keyAction: this.keyActionHandler.bind(this),
|
|
1665
|
-
keyConfigs: this.keyConfigs,
|
|
1666
|
-
eventName: 'keydown'
|
|
1667
|
-
});
|
|
1668
|
-
if (this.isForm) {
|
|
1669
|
-
EventHandler.add(this.formElement, 'reset', this.resetForm, this);
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
private unWireEvents(): void {
|
|
1674
|
-
EventHandler.remove(this.browseButton, 'click', this.browseButtonClick);
|
|
1675
|
-
EventHandler.remove(this.element, 'change', this.onSelectFiles);
|
|
1676
|
-
EventHandler.remove(document, 'click', this.removeFocus);
|
|
1677
|
-
if (this.isForm) {
|
|
1678
|
-
EventHandler.remove(this.formElement, 'reset', this.resetForm);
|
|
1679
|
-
}
|
|
1680
|
-
if (this.keyboardModule) {
|
|
1681
|
-
this.keyboardModule.destroy();
|
|
1682
|
-
}
|
|
1683
|
-
}
|
|
1684
|
-
|
|
1685
|
-
private resetForm() : void {
|
|
1686
|
-
this.clearAll();
|
|
1687
|
-
}
|
|
1688
|
-
|
|
1689
|
-
private keyActionHandler(e: KeyboardEventArgs): void {
|
|
1690
|
-
const targetElement: HTMLElement = e.target as HTMLElement;
|
|
1691
|
-
switch (e.action) {
|
|
1692
|
-
case 'enter':
|
|
1693
|
-
if (e.target === this.clearButton) {
|
|
1694
|
-
this.clearButtonClick();
|
|
1695
|
-
} else if (e.target === this.uploadButton) {
|
|
1696
|
-
this.uploadButtonClick();
|
|
1697
|
-
} else if (e.target === this.browseButton) {
|
|
1698
|
-
this.browseButtonClick();
|
|
1699
|
-
} else if (targetElement.classList.contains(PAUSE_UPLOAD)) {
|
|
1700
|
-
const metaData: MetaData = this.getCurrentMetaData(null, e);
|
|
1701
|
-
metaData.file.statusCode = '4';
|
|
1702
|
-
metaData.file.status = this.localizedTexts('pauseUpload');
|
|
1703
|
-
this.abortUpload(metaData, false);
|
|
1704
|
-
} else if (targetElement.classList.contains(RESUME_UPLOAD)) {
|
|
1705
|
-
this.resumeUpload(this.getCurrentMetaData(null, e), e);
|
|
1706
|
-
} else if (targetElement.classList.contains(RETRY_ICON)) {
|
|
1707
|
-
const metaData: MetaData = this.getCurrentMetaData(null, e);
|
|
1708
|
-
if (!isNullOrUndefined(metaData)) {
|
|
1709
|
-
metaData.file.statusCode = '1';
|
|
1710
|
-
metaData.file.status = this.localizedTexts('readyToUploadMessage');
|
|
1711
|
-
this.chunkUpload(metaData.file);
|
|
1712
|
-
} else {
|
|
1713
|
-
const target: HTMLElement = (<HTMLElement>e.target).parentElement;
|
|
1714
|
-
const fileData: FileInfo = this.filesData[this.fileList.indexOf(target)];
|
|
1715
|
-
this.retry(fileData);
|
|
1716
|
-
}
|
|
1717
|
-
} else {
|
|
1718
|
-
this.removeFiles(e);
|
|
1719
|
-
if (!targetElement.classList.contains(ABORT_ICON)) {
|
|
1720
|
-
this.browseButton.focus();
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
e.preventDefault();
|
|
1724
|
-
e.stopPropagation();
|
|
1725
|
-
break;
|
|
1726
|
-
}
|
|
1727
|
-
}
|
|
1728
|
-
|
|
1729
|
-
private getCurrentMetaData(fileInfo?: FileInfo, e?: KeyboardEventArgs) : MetaData {
|
|
1730
|
-
let fileData: FileInfo; let targetMetaData : MetaData;
|
|
1731
|
-
if (isNullOrUndefined(fileInfo)) {
|
|
1732
|
-
const target: HTMLElement = (<HTMLElement>e.target).parentElement;
|
|
1733
|
-
fileData = this.filesData[this.fileList.indexOf(target)];
|
|
1734
|
-
} else {
|
|
1735
|
-
fileData = fileInfo;
|
|
1736
|
-
}
|
|
1737
|
-
for (let i: number = 0; i < this.uploadMetaData.length; i++) {
|
|
1738
|
-
if (this.uploadMetaData[i as number].file.name === fileData.name) {
|
|
1739
|
-
targetMetaData = this.uploadMetaData[i as number];
|
|
1740
|
-
}
|
|
1741
|
-
}
|
|
1742
|
-
return targetMetaData;
|
|
1743
|
-
}
|
|
1744
|
-
|
|
1745
|
-
private removeFocus() : void {
|
|
1746
|
-
if (this.uploadWrapper && this.listParent && this.listParent.querySelector('.' + ICON_FOCUSED)) {
|
|
1747
|
-
(<HTMLElement>document.activeElement).blur();
|
|
1748
|
-
this.listParent.querySelector('.' + ICON_FOCUSED).classList.remove(ICON_FOCUSED);
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
|
|
1752
|
-
private browseButtonClick(): void {
|
|
1753
|
-
this.element.click();
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
|
-
private uploadButtonClick(): void {
|
|
1757
|
-
if (this.sequentialUpload) {
|
|
1758
|
-
this.sequenceUpload(this.filesData);
|
|
1759
|
-
} else {
|
|
1760
|
-
this.upload(this.filesData);
|
|
1761
|
-
}
|
|
1762
|
-
}
|
|
1763
|
-
|
|
1764
|
-
private clearButtonClick(): void {
|
|
1765
|
-
this.clearAll();
|
|
1766
|
-
/* istanbul ignore next */
|
|
1767
|
-
if (this.sequentialUpload) {
|
|
1768
|
-
this.count = -1;
|
|
1769
|
-
}
|
|
1770
|
-
this.actionCompleteCount = 0;
|
|
1771
|
-
}
|
|
1772
|
-
|
|
1773
|
-
private bindDropEvents(): void {
|
|
1774
|
-
if (this.dropZoneElement) {
|
|
1775
|
-
EventHandler.add(this.dropZoneElement, 'drop', this.dropElement, this);
|
|
1776
|
-
EventHandler.add(this.dropZoneElement, 'dragover', this.dragHover, this);
|
|
1777
|
-
EventHandler.add(this.dropZoneElement, 'dragleave', this.onDragLeave, this);
|
|
1778
|
-
EventHandler.add(this.dropZoneElement, 'paste', this.onPasteFile, this);
|
|
1779
|
-
EventHandler.add(this.dropZoneElement, 'dragenter', this.onDragEnter, this);
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
|
|
1783
|
-
private unBindDropEvents(): void {
|
|
1784
|
-
if (this.dropZoneElement) {
|
|
1785
|
-
EventHandler.remove(this.dropZoneElement, 'drop', this.dropElement);
|
|
1786
|
-
EventHandler.remove(this.dropZoneElement, 'dragover', this.dragHover);
|
|
1787
|
-
EventHandler.remove(this.dropZoneElement, 'dragleave', this.onDragLeave);
|
|
1788
|
-
EventHandler.remove(this.dropZoneElement, 'dragenter', this.onDragEnter);
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
|
|
1792
|
-
private onDragEnter( e : DragEvent) : void {
|
|
1793
|
-
if (!this.enabled) {
|
|
1794
|
-
return;
|
|
1795
|
-
}
|
|
1796
|
-
this.dropZoneElement.classList.add(DRAG_HOVER);
|
|
1797
|
-
this.dragCounter = this.dragCounter + 1;
|
|
1798
|
-
e.preventDefault();
|
|
1799
|
-
e.stopPropagation();
|
|
1800
|
-
}
|
|
1801
|
-
private onDragLeave(): void {
|
|
1802
|
-
if (!this.enabled) {
|
|
1803
|
-
return;
|
|
1804
|
-
}
|
|
1805
|
-
this.dragCounter = this.dragCounter - 1;
|
|
1806
|
-
if (!this.dragCounter) {
|
|
1807
|
-
this.dropZoneElement.classList.remove(DRAG_HOVER);
|
|
1808
|
-
}
|
|
1809
|
-
}
|
|
1810
|
-
|
|
1811
|
-
private dragHover(e: DragEvent): void {
|
|
1812
|
-
if (!this.enabled) {
|
|
1813
|
-
return;
|
|
1814
|
-
}
|
|
1815
|
-
if (this.dropEffect !== 'Default') {
|
|
1816
|
-
e.dataTransfer.dropEffect = this.dropEffect.toLowerCase();
|
|
1817
|
-
}
|
|
1818
|
-
e.preventDefault();
|
|
1819
|
-
e.stopPropagation();
|
|
1820
|
-
}
|
|
1821
|
-
|
|
1822
|
-
/* istanbul ignore next */
|
|
1823
|
-
private dropElement(e: DragEvent): void {
|
|
1824
|
-
this.dragCounter = 0;
|
|
1825
|
-
this.dropZoneElement.classList.remove(DRAG_HOVER);
|
|
1826
|
-
this.onSelectFiles(e);
|
|
1827
|
-
e.preventDefault();
|
|
1828
|
-
e.stopPropagation();
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
/* istanbul ignore next */
|
|
1832
|
-
private onPasteFile(event: ClipboardEvent): void {
|
|
1833
|
-
const item: DataTransferItemList = event.clipboardData.items;
|
|
1834
|
-
if (event.type === 'paste' && this.browserName !== 'msie' && this.browserName !== 'edge' && this.browserName !== 'safari') {
|
|
1835
|
-
this.element.files = event.clipboardData.files;
|
|
1836
|
-
}
|
|
1837
|
-
if (item.length !== 1 && !this.multiple) {
|
|
1838
|
-
return;
|
|
1839
|
-
}
|
|
1840
|
-
for (let file: number = 0; file < item.length; file++){
|
|
1841
|
-
const pasteFile: DataTransferItem = [].slice.call(item)[file as number];
|
|
1842
|
-
if (!isNullOrUndefined(pasteFile.getAsFile()) && ((pasteFile.kind === 'file') || pasteFile.type.match('^image/'))) {
|
|
1843
|
-
this.renderSelectedFiles(event, [pasteFile.getAsFile()], false, true);
|
|
1844
|
-
}
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
|
-
private getSelectedFiles(index: number): FileInfo[] {
|
|
1849
|
-
const data: FileInfo[] = [];
|
|
1850
|
-
const liElement: HTMLElement = this.fileList[index as number];
|
|
1851
|
-
const allFiles: FileInfo[] = this.getFilesData();
|
|
1852
|
-
const nameElements: number = +liElement.getAttribute('data-files-count');
|
|
1853
|
-
let startIndex: number = 0 ;
|
|
1854
|
-
for (let i: number = 0; i < index; i++ ) {
|
|
1855
|
-
startIndex += (+this.fileList[i as number].getAttribute('data-files-count'));
|
|
1856
|
-
}
|
|
1857
|
-
for (let j: number = startIndex; j < (startIndex + nameElements); j++) {
|
|
1858
|
-
data.push(allFiles[j as number]);
|
|
1859
|
-
}
|
|
1860
|
-
return data;
|
|
1861
|
-
}
|
|
1862
|
-
|
|
1863
|
-
private removeFiles(args: MouseEvent | TouchEvent | KeyboardEventArgs): void {
|
|
1864
|
-
if (!this.enabled) {
|
|
1865
|
-
return;
|
|
1866
|
-
}
|
|
1867
|
-
const selectedElement: HTMLElement = (<HTMLInputElement>args.target).parentElement;
|
|
1868
|
-
const index: number = this.fileList.indexOf(selectedElement);
|
|
1869
|
-
const liElement: HTMLElement = this.fileList[index as number];
|
|
1870
|
-
const formUpload: boolean = this.isFormUpload();
|
|
1871
|
-
const fileData: FileInfo[] = formUpload ? this.getSelectedFiles(index) : this.getFilesInArray(this.filesData[index as number]);
|
|
1872
|
-
if (isNullOrUndefined(fileData)) {
|
|
1873
|
-
return;
|
|
1874
|
-
}
|
|
1875
|
-
if ((<HTMLInputElement>args.target).classList.contains(ABORT_ICON) && !formUpload) {
|
|
1876
|
-
fileData[0].statusCode = '5';
|
|
1877
|
-
if (!isNullOrUndefined(liElement)) {
|
|
1878
|
-
const spinnerTarget: HTMLElement = liElement.querySelector('.' + ABORT_ICON) as HTMLElement;
|
|
1879
|
-
createSpinner({ target: spinnerTarget , width: '20px' });
|
|
1880
|
-
showSpinner(spinnerTarget);
|
|
1881
|
-
}
|
|
1882
|
-
if (this.sequentialUpload) {
|
|
1883
|
-
/* istanbul ignore next */
|
|
1884
|
-
this.uploadSequential();
|
|
1885
|
-
}
|
|
1886
|
-
if (!(liElement.classList.contains(RESTRICT_RETRY))) {
|
|
1887
|
-
this.checkActionComplete(true);
|
|
1888
|
-
}
|
|
1889
|
-
} else if (!closest(args.target as Element, '.' + SPINNER_PANE)) {
|
|
1890
|
-
this.remove(fileData, false, false, true, args);
|
|
1891
|
-
}
|
|
1892
|
-
if (this.isForm && liElement && liElement.classList.contains(INVALID_FILE)){
|
|
1893
|
-
this.element.value = '';
|
|
1894
|
-
}
|
|
1895
|
-
this.checkActionButtonStatus();
|
|
1896
|
-
if (this.actionButtons && this.clearButton && this.uploadWrapper) {
|
|
1897
|
-
const progressBarElements: NodeListOf<Element> = this.uploadWrapper.querySelectorAll(
|
|
1898
|
-
'.e-upload-progress-bar.e-upload-progress:not(.e-upload-success):not(.e-upload-fails)');
|
|
1899
|
-
if (progressBarElements.length === 1 && selectedElement.contains(progressBarElements[0])
|
|
1900
|
-
&& this.clearButton.hasAttribute('disabled')) {
|
|
1901
|
-
this.clearButton.removeAttribute('disabled');
|
|
1902
|
-
}
|
|
1903
|
-
}
|
|
1904
|
-
}
|
|
1905
|
-
|
|
1906
|
-
private removeFilesData(file: FileInfo, customTemplate: boolean): void {
|
|
1907
|
-
let index: number ;
|
|
1908
|
-
if (customTemplate) {
|
|
1909
|
-
if (!this.showFileList) {
|
|
1910
|
-
index = this.filesData.indexOf(file);
|
|
1911
|
-
this.filesData.splice(index, 1);
|
|
1912
|
-
}
|
|
1913
|
-
return;
|
|
1914
|
-
}
|
|
1915
|
-
const selectedElement: HTMLElement = this.getLiElement(file);
|
|
1916
|
-
if (isNullOrUndefined(selectedElement)) {
|
|
1917
|
-
return;
|
|
1918
|
-
}
|
|
1919
|
-
this.element.value = '';
|
|
1920
|
-
detach(selectedElement);
|
|
1921
|
-
index = this.fileList.indexOf(selectedElement);
|
|
1922
|
-
this.fileList.splice(index, 1);
|
|
1923
|
-
this.filesData.splice(index, 1);
|
|
1924
|
-
if (this.fileList.length === 0 && !isNullOrUndefined(this.listParent)) {
|
|
1925
|
-
detach(this.listParent);
|
|
1926
|
-
this.listParent = null;
|
|
1927
|
-
this.removeActionButtons();
|
|
1928
|
-
}
|
|
1929
|
-
if (this.sequentialUpload) {
|
|
1930
|
-
/* istanbul ignore next */
|
|
1931
|
-
if (index <= this.count) {
|
|
1932
|
-
--this.count;
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1935
|
-
}
|
|
1936
|
-
|
|
1937
|
-
private removeUploadedFile(
|
|
1938
|
-
file: FileInfo, eventArgs: RemovingEventArgs,
|
|
1939
|
-
removeDirectly: boolean, custom: boolean): void {
|
|
1940
|
-
const selectedFiles: FileInfo = file;
|
|
1941
|
-
const ajax: Ajax = new Ajax(this.asyncSettings.removeUrl, 'POST', true, null);
|
|
1942
|
-
ajax.emitError = false;
|
|
1943
|
-
const formData: FormData = new FormData();
|
|
1944
|
-
ajax.beforeSend = (e: BeforeSendEventArgs) => {
|
|
1945
|
-
eventArgs.currentRequest = ajax.httpRequest;
|
|
1946
|
-
if (!removeDirectly) {
|
|
1947
|
-
this.trigger('removing', eventArgs, (eventArgs: RemovingEventArgs) => {
|
|
1948
|
-
if (eventArgs.cancel) {
|
|
1949
|
-
e.cancel = true;
|
|
1950
|
-
} else {
|
|
1951
|
-
this.removingEventCallback(eventArgs, formData, selectedFiles, file);
|
|
1952
|
-
}
|
|
1953
|
-
});
|
|
1954
|
-
} else {
|
|
1955
|
-
this.removingEventCallback(eventArgs, formData, selectedFiles, file);
|
|
1956
|
-
}
|
|
1957
|
-
};
|
|
1958
|
-
ajax.onLoad = (e: Event): object => {
|
|
1959
|
-
this.removeCompleted(e, selectedFiles, custom); return {};
|
|
1960
|
-
};
|
|
1961
|
-
/* istanbul ignore next */
|
|
1962
|
-
ajax.onError = (e: Event): object => {
|
|
1963
|
-
this.removeFailed(e, selectedFiles, custom); return {};
|
|
1964
|
-
};
|
|
1965
|
-
ajax.send(formData);
|
|
1966
|
-
}
|
|
1967
|
-
|
|
1968
|
-
private removingEventCallback(eventArgs: RemovingEventArgs, formData: FormData, selectedFiles: FileInfo, file: FileInfo): void {
|
|
1969
|
-
/* istanbul ignore next */
|
|
1970
|
-
const name: string = this.element.getAttribute('name');
|
|
1971
|
-
const liElement: HTMLElement = this.getLiElement(file);
|
|
1972
|
-
if (!isNullOrUndefined(liElement) && (!isNullOrUndefined(liElement.querySelector('.' + DELETE_ICON)) ||
|
|
1973
|
-
!isNullOrUndefined(liElement.querySelector('.' + REMOVE_ICON)))) {
|
|
1974
|
-
const spinnerTarget: HTMLElement = liElement.querySelector('.' + DELETE_ICON) ?
|
|
1975
|
-
liElement.querySelector('.' + DELETE_ICON) as HTMLElement :
|
|
1976
|
-
liElement.querySelector('.' + REMOVE_ICON) as HTMLElement;
|
|
1977
|
-
createSpinner({ target: spinnerTarget , width: '20px' });
|
|
1978
|
-
showSpinner(spinnerTarget);
|
|
1979
|
-
}
|
|
1980
|
-
if (eventArgs.postRawFile && !isNullOrUndefined(selectedFiles.rawFile) && selectedFiles.rawFile !== '') {
|
|
1981
|
-
formData.append(name, selectedFiles.rawFile, selectedFiles.name);
|
|
1982
|
-
} else {
|
|
1983
|
-
formData.append(name, selectedFiles.name);
|
|
1984
|
-
}
|
|
1985
|
-
this.updateFormData(formData, eventArgs.customFormData);
|
|
1986
|
-
}
|
|
1987
|
-
|
|
1988
|
-
/* istanbul ignore next */
|
|
1989
|
-
private updateFormData(formData: FormData, customData: { [key: string]: Object }[]): void {
|
|
1990
|
-
if (customData.length > 0 && customData[0]) {
|
|
1991
|
-
for (let i: number = 0; i < customData.length; i++) {
|
|
1992
|
-
const data: { [key: string]: Object } = customData[i as number];
|
|
1993
|
-
// eslint-disable-next-line @typescript-eslint/tslint/config
|
|
1994
|
-
const value: any = Object.keys(data).map(function(e) {
|
|
1995
|
-
return data[`${e}`];
|
|
1996
|
-
});
|
|
1997
|
-
formData.append(Object.keys(data)[0], value);
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
|
|
2002
|
-
/* istanbul ignore next */
|
|
2003
|
-
private updateCustomheader(request: XMLHttpRequest, currentRequest: { [key: string]: string }[]): void {
|
|
2004
|
-
if (currentRequest.length > 0 && currentRequest[0]) {
|
|
2005
|
-
for (let i: number = 0; i < currentRequest.length; i++) {
|
|
2006
|
-
const data: { [key: string]: string } = currentRequest[i as number];
|
|
2007
|
-
// eslint-disable-next-line @typescript-eslint/tslint/config
|
|
2008
|
-
const value: any = Object.keys(data).map(function (e) {
|
|
2009
|
-
return data[`${e}`];
|
|
2010
|
-
});
|
|
2011
|
-
request.setRequestHeader(Object.keys(data)[0], value);
|
|
2012
|
-
}
|
|
2013
|
-
}
|
|
2014
|
-
}
|
|
2015
|
-
|
|
2016
|
-
private removeCompleted(e: Event, files: FileInfo, customTemplate: boolean): void {
|
|
2017
|
-
const response: Object = e && e.currentTarget ? this.getResponse(e) : null;
|
|
2018
|
-
const status : XMLHttpRequest = e.target as XMLHttpRequest;
|
|
2019
|
-
if (status.readyState === 4 && status.status >= 200 && status.status <= 299 ) {
|
|
2020
|
-
const args : Object = {
|
|
2021
|
-
e, response: response, operation: 'remove', file: this.updateStatus(
|
|
2022
|
-
files, this.localizedTexts('removedSuccessMessage'), '2')
|
|
2023
|
-
};
|
|
2024
|
-
this.trigger('success', args);
|
|
2025
|
-
this.removeFilesData(files, customTemplate);
|
|
2026
|
-
const index: number = this.uploadedFilesData.indexOf(files);
|
|
2027
|
-
this.uploadedFilesData.splice(index, 1);
|
|
2028
|
-
this.trigger('change', { files: this.uploadedFilesData });
|
|
2029
|
-
} else {
|
|
2030
|
-
this.removeFailed(e, files, customTemplate);
|
|
2031
|
-
}
|
|
2032
|
-
}
|
|
2033
|
-
|
|
2034
|
-
private removeFailed(e: Event, files: FileInfo, customTemplate: boolean): void {
|
|
2035
|
-
const response: Object = e && e.currentTarget ? this.getResponse(e) : null;
|
|
2036
|
-
const args : Object = {
|
|
2037
|
-
e, response: response, operation: 'remove', file: this.updateStatus(files, this.localizedTexts('removedFailedMessage'), '0')
|
|
2038
|
-
};
|
|
2039
|
-
if (!customTemplate) {
|
|
2040
|
-
const index: number = this.filesData.indexOf(files);
|
|
2041
|
-
const rootElement: HTMLElement = this.fileList[index as number];
|
|
2042
|
-
if (rootElement) {
|
|
2043
|
-
rootElement.classList.remove(UPLOAD_SUCCESS);
|
|
2044
|
-
rootElement.classList.add(UPLOAD_FAILED);
|
|
2045
|
-
const statusElement: HTMLElement = rootElement.querySelector('.' + STATUS) as HTMLElement;
|
|
2046
|
-
if (statusElement) {
|
|
2047
|
-
statusElement.classList.remove(UPLOAD_SUCCESS);
|
|
2048
|
-
statusElement.classList.add(UPLOAD_FAILED);
|
|
2049
|
-
}
|
|
2050
|
-
}
|
|
2051
|
-
this.checkActionButtonStatus();
|
|
2052
|
-
}
|
|
2053
|
-
this.trigger('failure', args);
|
|
2054
|
-
const liElement: HTMLElement = this.getLiElement(files);
|
|
2055
|
-
/* istanbul ignore next */
|
|
2056
|
-
if (!isNullOrUndefined(liElement) && !isNullOrUndefined(liElement.querySelector('.' + DELETE_ICON))) {
|
|
2057
|
-
const spinnerTarget: HTMLElement = liElement.querySelector('.' + DELETE_ICON) as HTMLElement;
|
|
2058
|
-
hideSpinner(spinnerTarget);
|
|
2059
|
-
detach(liElement.querySelector('.e-spinner-pane'));
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
|
|
2063
|
-
/* istanbul ignore next */
|
|
2064
|
-
private getFilesFromFolder(event: MouseEvent | TouchEvent | DragEvent | ClipboardEvent): void {
|
|
2065
|
-
this.filesEntries = [];
|
|
2066
|
-
const items: DataTransferItem[] | DataTransferItemList = this.multiple ?
|
|
2067
|
-
(<DragEvent>event).dataTransfer.items : [(<DragEvent>event).dataTransfer.items[0]];
|
|
2068
|
-
const validDirectoryUpload: boolean = this.checkDirectoryUpload(items);
|
|
2069
|
-
if (!validDirectoryUpload) {
|
|
2070
|
-
return;
|
|
2071
|
-
}
|
|
2072
|
-
for (let i: number = 0; i < items.length; i++) {
|
|
2073
|
-
const item: any = items[i as number].webkitGetAsEntry();
|
|
2074
|
-
if (item.isFile) {
|
|
2075
|
-
const files: { [key: string]: Object }[] = [];
|
|
2076
|
-
(item).file( (fileObj: any) => {
|
|
2077
|
-
const path: string = item.fullPath;
|
|
2078
|
-
files.push({'path': path, 'file': fileObj});
|
|
2079
|
-
});
|
|
2080
|
-
this.renderSelectedFiles(event, files, true);
|
|
2081
|
-
} else if (item.isDirectory) {
|
|
2082
|
-
this.traverseFileTree(item, event);
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
}
|
|
2086
|
-
|
|
2087
|
-
/* istanbul ignore next */
|
|
2088
|
-
private checkDirectoryUpload(items: DataTransferItem[] | DataTransferItemList): boolean {
|
|
2089
|
-
for (let i: number = 0; items && i < items.length; i++) {
|
|
2090
|
-
const item : any = items[i as number].webkitGetAsEntry();
|
|
2091
|
-
if (item.isDirectory) {
|
|
2092
|
-
return true;
|
|
2093
|
-
}
|
|
2094
|
-
}
|
|
2095
|
-
return false;
|
|
2096
|
-
}
|
|
2097
|
-
/* istanbul ignore next */
|
|
2098
|
-
public traverseFileTree(item: any, event?: MouseEvent | TouchEvent | DragEvent | ClipboardEvent): void {
|
|
2099
|
-
if (item.isFile) {
|
|
2100
|
-
this.filesEntries.push(item);
|
|
2101
|
-
} else if (item.isDirectory) {
|
|
2102
|
-
const directoryReader: any = item.createReader();
|
|
2103
|
-
this.readFileFromDirectory(directoryReader, event);
|
|
2104
|
-
}
|
|
2105
|
-
}
|
|
2106
|
-
|
|
2107
|
-
/* istanbul ignore next */
|
|
2108
|
-
private readFileFromDirectory(directoryReader: any, event?: MouseEvent | TouchEvent | DragEvent | ClipboardEvent): void {
|
|
2109
|
-
directoryReader.readEntries( (entries: any) => {
|
|
2110
|
-
for (let i: number = 0; i < entries.length; i++) {
|
|
2111
|
-
this.traverseFileTree(entries[i as number], event);
|
|
2112
|
-
}
|
|
2113
|
-
this.pushFilesEntries(event);
|
|
2114
|
-
if (entries.length) {
|
|
2115
|
-
this.readFileFromDirectory(directoryReader);
|
|
2116
|
-
}
|
|
2117
|
-
});
|
|
2118
|
-
}
|
|
2119
|
-
|
|
2120
|
-
private pushFilesEntries(event?: MouseEvent | TouchEvent | DragEvent | ClipboardEvent): void {
|
|
2121
|
-
const files: { [key: string]: Object }[] = [];
|
|
2122
|
-
for (let i: number = 0; i < this.filesEntries.length; i++) {
|
|
2123
|
-
this.filesEntries[i as number].file( (fileObj: any) => {
|
|
2124
|
-
if (this.filesEntries.length) {
|
|
2125
|
-
const path: string = this.filesEntries[i as number].fullPath;
|
|
2126
|
-
files.push({'path': path, 'file': fileObj});
|
|
2127
|
-
if (i === this.filesEntries.length - 1) {
|
|
2128
|
-
this.filesEntries = [];
|
|
2129
|
-
this.renderSelectedFiles(event, files, true);
|
|
2130
|
-
}
|
|
2131
|
-
}
|
|
2132
|
-
});
|
|
2133
|
-
}
|
|
2134
|
-
}
|
|
2135
|
-
|
|
2136
|
-
private onSelectFiles(args: MouseEvent | TouchEvent | DragEvent | ClipboardEvent): void {
|
|
2137
|
-
if (!this.enabled) {
|
|
2138
|
-
return;
|
|
2139
|
-
}
|
|
2140
|
-
let targetFiles: File[];
|
|
2141
|
-
/* istanbul ignore next */
|
|
2142
|
-
if (args.type === 'drop') {
|
|
2143
|
-
if (this.directoryUpload) {
|
|
2144
|
-
this.getFilesFromFolder(args);
|
|
2145
|
-
} else {
|
|
2146
|
-
const files: FileList = this.sortFilesList = (<DragEvent>args).dataTransfer.files;
|
|
2147
|
-
if (this.browserName !== 'msie' && this.browserName !== 'edge' && this.browserName !== 'safari') {
|
|
2148
|
-
this.element.files = files;
|
|
2149
|
-
}
|
|
2150
|
-
if (files.length > 0) {
|
|
2151
|
-
targetFiles = this.multiple ? this.sortFileList(files) : [files[0]];
|
|
2152
|
-
this.renderSelectedFiles(args, targetFiles);
|
|
2153
|
-
}
|
|
2154
|
-
}
|
|
2155
|
-
} else {
|
|
2156
|
-
targetFiles = [].slice.call((<HTMLInputElement>args.target).files);
|
|
2157
|
-
this.renderSelectedFiles(args, targetFiles);
|
|
2158
|
-
}
|
|
2159
|
-
if (this.isAngular || (this as any).isReact) {
|
|
2160
|
-
args.stopPropagation();
|
|
2161
|
-
}
|
|
2162
|
-
|
|
2163
|
-
}
|
|
2164
|
-
/* istanbul ignore next */
|
|
2165
|
-
private getBase64(file: File): Promise<void> {
|
|
2166
|
-
return new Promise((resolve: Function, reject: Function) => {
|
|
2167
|
-
const fileReader: FileReader = new FileReader();
|
|
2168
|
-
fileReader.readAsDataURL(file);
|
|
2169
|
-
fileReader.onload = () => resolve(fileReader.result as string);
|
|
2170
|
-
fileReader.onerror = (error: ProgressEvent) => reject(error);
|
|
2171
|
-
});
|
|
2172
|
-
}
|
|
2173
|
-
|
|
2174
|
-
/* istanbul ignore next */
|
|
2175
|
-
/* tslint:ignore */
|
|
2176
|
-
private renderSelectedFiles(
|
|
2177
|
-
args: MouseEvent | TouchEvent | DragEvent | ClipboardEvent,
|
|
2178
|
-
targetFiles: any, directory?: boolean, paste?: boolean): void {
|
|
2179
|
-
this.base64String = [];
|
|
2180
|
-
const eventArgs: SelectedEventArgs = {
|
|
2181
|
-
event: args,
|
|
2182
|
-
cancel: false,
|
|
2183
|
-
filesData: [],
|
|
2184
|
-
isModified: false,
|
|
2185
|
-
modifiedFilesData: [],
|
|
2186
|
-
progressInterval: '',
|
|
2187
|
-
isCanceled: false,
|
|
2188
|
-
currentRequest: null,
|
|
2189
|
-
customFormData: null
|
|
2190
|
-
};
|
|
2191
|
-
/* istanbul ignore next */
|
|
2192
|
-
if (targetFiles.length < 1) {
|
|
2193
|
-
eventArgs.isCanceled = true;
|
|
2194
|
-
this.trigger('selected', eventArgs);
|
|
2195
|
-
return;
|
|
2196
|
-
}
|
|
2197
|
-
this.flag = true;
|
|
2198
|
-
let fileData: FileInfo[] = [];
|
|
2199
|
-
if (!this.multiple) {
|
|
2200
|
-
this.clearData(true);
|
|
2201
|
-
this.actionCompleteCount = 0;
|
|
2202
|
-
targetFiles = [targetFiles[0]];
|
|
2203
|
-
}
|
|
2204
|
-
for (let i: number = 0; i < targetFiles.length; i++) {
|
|
2205
|
-
const file: File = directory ? targetFiles[i as number].file : targetFiles[i as number];
|
|
2206
|
-
this.updateInitialFileDetails(args, targetFiles, file, i, fileData, directory, paste);
|
|
2207
|
-
}
|
|
2208
|
-
eventArgs.filesData = fileData;
|
|
2209
|
-
if (!isNullOrUndefined(this.allowedExtensions) && this.allowedExtensions.indexOf('*') > -1) {
|
|
2210
|
-
this.allTypes = true;
|
|
2211
|
-
}
|
|
2212
|
-
if (this.enableHtmlSanitizer){
|
|
2213
|
-
for (let i: number = 0; i < fileData.length; i++) {
|
|
2214
|
-
const sanitizeFile: any = SanitizeHtmlHelper.beforeSanitize();
|
|
2215
|
-
const sanitizeFileName: string = SanitizeHtmlHelper.serializeValue(sanitizeFile, fileData[parseInt(i.toString(), 10)].name);
|
|
2216
|
-
const currentFileName: string = fileData[parseInt(i.toString(), 10)].name;
|
|
2217
|
-
let isUTF8: boolean = false;
|
|
2218
|
-
for (let i: number = 0; i < currentFileName.length; i++) {
|
|
2219
|
-
if (currentFileName.charCodeAt(i) > 127) {
|
|
2220
|
-
isUTF8 = true;
|
|
2221
|
-
break;
|
|
2222
|
-
}
|
|
2223
|
-
}
|
|
2224
|
-
const htmlTagRegex: RegExp = /<([a-z][a-z0-9]*)\b[^>]*>(.*?)<\/\1>/i;
|
|
2225
|
-
const hasHTMLString: boolean = htmlTagRegex.test(currentFileName);
|
|
2226
|
-
if ((sanitizeFileName !== fileData[parseInt(i.toString(), 10)].name) && !(isUTF8 && !hasHTMLString)) {
|
|
2227
|
-
const encodedFileName: any = targetFiles[parseInt(i.toString(), 10)].name.replace(/[\u00A0-\u9999<>\\&]/g, function (i: any): string {
|
|
2228
|
-
return '&#' + i.charCodeAt(0) + ';';
|
|
2229
|
-
});
|
|
2230
|
-
fileData[parseInt(i.toString(), 10)].name = encodedFileName;
|
|
2231
|
-
fileData[parseInt(i.toString(), 10)].status = this.localizedTexts('invalidFileName');
|
|
2232
|
-
fileData[parseInt(i.toString(), 10)].statusCode = '0';
|
|
2233
|
-
}
|
|
2234
|
-
}
|
|
2235
|
-
}
|
|
2236
|
-
if (!this.allTypes) {
|
|
2237
|
-
fileData = this.checkExtension(fileData);
|
|
2238
|
-
}
|
|
2239
|
-
this.trigger('selected', eventArgs, (eventArgs: SelectedEventArgs) => {
|
|
2240
|
-
this._internalRenderSelect(eventArgs, fileData);
|
|
2241
|
-
});
|
|
2242
|
-
}
|
|
2243
|
-
|
|
2244
|
-
private updateInitialFileDetails(args: MouseEvent | TouchEvent | DragEvent | ClipboardEvent,
|
|
2245
|
-
targetFiles: any, file: File, i: number, fileData: FileInfo[],
|
|
2246
|
-
directory?: boolean, paste?: boolean): void {
|
|
2247
|
-
const fileName: string = directory ? targetFiles[i as number].path.substring(1, targetFiles[i as number].path.length) : paste ?
|
|
2248
|
-
getUniqueID(file.name.substring(0, file.name.lastIndexOf('.'))) + '.' + this.getFileType(file.name) :
|
|
2249
|
-
this.directoryUpload ? targetFiles[i as number].webkitRelativePath : file.name;
|
|
2250
|
-
const fileDetails: FileInfo = {
|
|
2251
|
-
name: fileName,
|
|
2252
|
-
rawFile: file,
|
|
2253
|
-
size: file.size,
|
|
2254
|
-
status: this.localizedTexts('readyToUploadMessage'),
|
|
2255
|
-
type: this.getFileType(file.name),
|
|
2256
|
-
validationMessages: this.validatedFileSize(file.size),
|
|
2257
|
-
statusCode: '1',
|
|
2258
|
-
id: getUniqueID(file.name.substring(0, file.name.lastIndexOf('.'))) + '.' + this.getFileType(file.name)
|
|
2259
|
-
};
|
|
2260
|
-
/* istanbul ignore next */
|
|
2261
|
-
if (paste) {
|
|
2262
|
-
fileDetails.fileSource = 'paste';
|
|
2263
|
-
}
|
|
2264
|
-
fileDetails.status = fileDetails.validationMessages.minSize !== '' ? this.localizedTexts('invalidMinFileSize') :
|
|
2265
|
-
fileDetails.validationMessages.maxSize !== '' ? this.localizedTexts('invalidMaxFileSize') : fileDetails.status;
|
|
2266
|
-
if (fileDetails.validationMessages.minSize !== '' || fileDetails.validationMessages.maxSize !== '') {
|
|
2267
|
-
fileDetails.statusCode = '0';
|
|
2268
|
-
this.checkActionComplete(true);
|
|
2269
|
-
}
|
|
2270
|
-
fileData.push(fileDetails);
|
|
2271
|
-
}
|
|
2272
|
-
|
|
2273
|
-
private _internalRenderSelect(eventArgs: SelectedEventArgs, fileData: FileInfo[]): void {
|
|
2274
|
-
if (!eventArgs.cancel) {
|
|
2275
|
-
/* istanbul ignore next */
|
|
2276
|
-
this.selectedFiles = this.selectedFiles.concat(fileData);
|
|
2277
|
-
this.btnTabIndex = this.disableKeyboardNavigation ? '-1' : '0';
|
|
2278
|
-
if (this.showFileList) {
|
|
2279
|
-
if (eventArgs.isModified && eventArgs.modifiedFilesData.length > 0) {
|
|
2280
|
-
for (let j: number = 0; j < eventArgs.modifiedFilesData.length; j++) {
|
|
2281
|
-
for (let k: number = 0; k < fileData.length; k++) {
|
|
2282
|
-
if (eventArgs.modifiedFilesData[j as number].id === fileData[k as number].id) {
|
|
2283
|
-
eventArgs.modifiedFilesData[j as number].rawFile = fileData[k as number].rawFile;
|
|
2284
|
-
}
|
|
2285
|
-
}
|
|
2286
|
-
}
|
|
2287
|
-
const dataFiles: FileInfo[] = this.allTypes ? eventArgs.modifiedFilesData :
|
|
2288
|
-
this.checkExtension(eventArgs.modifiedFilesData);
|
|
2289
|
-
this.updateSortedFileList(dataFiles);
|
|
2290
|
-
this.filesData = this.filesData.concat(dataFiles);
|
|
2291
|
-
if (!this.isForm || this.allowUpload()) {
|
|
2292
|
-
this.checkAutoUpload(dataFiles);
|
|
2293
|
-
}
|
|
2294
|
-
} else {
|
|
2295
|
-
this.internalCreateFileList(fileData);
|
|
2296
|
-
if (this.autoUpload && this.sequenceUpload && this.sequentialUpload && this.filesData.length > 0 && this.filesData[this.filesData.length - 1 as number].statusCode !== '2' && this.filesData[this.filesData.length - 1 as number].statusCode !== '0') {
|
|
2297
|
-
this.filesData = this.filesData.concat(fileData);
|
|
2298
|
-
return;
|
|
2299
|
-
}
|
|
2300
|
-
this.filesData = this.filesData.concat(fileData);
|
|
2301
|
-
if (!this.isForm || this.allowUpload()) {
|
|
2302
|
-
this.checkAutoUpload(fileData);
|
|
2303
|
-
}
|
|
2304
|
-
}
|
|
2305
|
-
if (!isNullOrUndefined(eventArgs.progressInterval) && eventArgs.progressInterval !== '') {
|
|
2306
|
-
this.progressInterval = eventArgs.progressInterval;
|
|
2307
|
-
}
|
|
2308
|
-
} else {
|
|
2309
|
-
this.filesData = this.filesData.concat(fileData);
|
|
2310
|
-
if (this.autoUpload) {
|
|
2311
|
-
this.upload(this.filesData, true);
|
|
2312
|
-
}
|
|
2313
|
-
}
|
|
2314
|
-
this.raiseActionComplete();
|
|
2315
|
-
this.isFirstFileOnSelection = true;
|
|
2316
|
-
}
|
|
2317
|
-
}
|
|
2318
|
-
|
|
2319
|
-
private allowUpload(): boolean {
|
|
2320
|
-
let allowFormUpload: boolean = false;
|
|
2321
|
-
if (this.isForm && (!isNullOrUndefined(this.asyncSettings.saveUrl) && this.asyncSettings.saveUrl !== '' )) {
|
|
2322
|
-
allowFormUpload = true;
|
|
2323
|
-
}
|
|
2324
|
-
return allowFormUpload;
|
|
2325
|
-
}
|
|
2326
|
-
|
|
2327
|
-
private isFormUpload(): boolean {
|
|
2328
|
-
let isFormUpload: boolean = false;
|
|
2329
|
-
if (this.isForm && ((isNullOrUndefined(this.asyncSettings.saveUrl) || this.asyncSettings.saveUrl === '' )
|
|
2330
|
-
&& (isNullOrUndefined(this.asyncSettings.removeUrl) || this.asyncSettings.removeUrl === '' ))) {
|
|
2331
|
-
isFormUpload = true;
|
|
2332
|
-
}
|
|
2333
|
-
return isFormUpload;
|
|
2334
|
-
}
|
|
2335
|
-
|
|
2336
|
-
private clearData(singleUpload?: boolean) : void {
|
|
2337
|
-
if (!isNullOrUndefined(this.listParent)) {
|
|
2338
|
-
detach(this.listParent);
|
|
2339
|
-
this.listParent = null;
|
|
2340
|
-
}
|
|
2341
|
-
if (this.browserName !== 'msie' && !singleUpload) {
|
|
2342
|
-
this.element.value = '';
|
|
2343
|
-
}
|
|
2344
|
-
this.fileList = [];
|
|
2345
|
-
this.filesData = [];
|
|
2346
|
-
this.removeActionButtons();
|
|
2347
|
-
}
|
|
2348
|
-
|
|
2349
|
-
private updateSortedFileList(filesData: FileInfo[]): void {
|
|
2350
|
-
const previousListClone: HTMLElement = this.createElement('div', {id: 'clonewrapper'});
|
|
2351
|
-
let added: number = -1;
|
|
2352
|
-
if (this.listParent) {
|
|
2353
|
-
for (let i: number = 0; i < this.listParent.querySelectorAll('li').length; i++) {
|
|
2354
|
-
const liElement: HTMLElement = this.listParent.querySelectorAll('li')[i as number];
|
|
2355
|
-
previousListClone.appendChild(liElement.cloneNode(true));
|
|
2356
|
-
}
|
|
2357
|
-
this.removeActionButtons();
|
|
2358
|
-
const oldList: HTMLElement[] = [].slice.call(previousListClone.childNodes);
|
|
2359
|
-
this.createParentUL();
|
|
2360
|
-
for (let index: number = 0; index < filesData.length; index++) {
|
|
2361
|
-
for (let j: number = 0; j < this.filesData.length; j++) {
|
|
2362
|
-
if (this.filesData[j as number].name === filesData[index as number].name) {
|
|
2363
|
-
this.listParent.appendChild(oldList[j as number]);
|
|
2364
|
-
EventHandler.add(oldList[j as number].querySelector('.e-icons'), 'click', this.removeFiles, this);
|
|
2365
|
-
this.fileList.push(oldList[j as number]);
|
|
2366
|
-
added = index;
|
|
2367
|
-
}
|
|
2368
|
-
}
|
|
2369
|
-
if (added !== index) {
|
|
2370
|
-
this.internalCreateFileList([filesData[index as number]]);
|
|
2371
|
-
}
|
|
2372
|
-
}
|
|
2373
|
-
} else {
|
|
2374
|
-
this.internalCreateFileList(filesData);
|
|
2375
|
-
}
|
|
2376
|
-
}
|
|
2377
|
-
|
|
2378
|
-
private isBlank(str: string): boolean {
|
|
2379
|
-
return (!str || /^\s*$/.test(str));
|
|
2380
|
-
}
|
|
2381
|
-
|
|
2382
|
-
private checkGenericExtension(genericType: string, fileExtension: string): boolean {
|
|
2383
|
-
const validExtensions: string[] = [];
|
|
2384
|
-
|
|
2385
|
-
switch (genericType.toLowerCase()) {
|
|
2386
|
-
case 'image/*':
|
|
2387
|
-
validExtensions.push('jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'svg', 'webp', 'heic');
|
|
2388
|
-
break;
|
|
2389
|
-
case 'audio/*':
|
|
2390
|
-
validExtensions.push('mp3', 'wav', 'aac', 'flac', 'ogg', 'm4a');
|
|
2391
|
-
break;
|
|
2392
|
-
case 'video/*':
|
|
2393
|
-
validExtensions.push('mp4', 'mov', 'avi', 'mkv', 'flv', 'wmv', 'webm', 'mpeg');
|
|
2394
|
-
break;
|
|
2395
|
-
case 'application/*':
|
|
2396
|
-
validExtensions.push('doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'zip', 'rar', '7z', 'tar', 'pdf');
|
|
2397
|
-
break;
|
|
2398
|
-
case 'text/*':
|
|
2399
|
-
validExtensions.push('txt', 'csv', 'html', 'css', 'js', 'json', 'xml', 'md');
|
|
2400
|
-
break;
|
|
2401
|
-
default:
|
|
2402
|
-
break;
|
|
2403
|
-
}
|
|
2404
|
-
|
|
2405
|
-
return (validExtensions as any).includes(fileExtension.toLowerCase());
|
|
2406
|
-
}
|
|
2407
|
-
|
|
2408
|
-
private checkExtension(files: FileInfo[]): FileInfo[] {
|
|
2409
|
-
const dropFiles: FileInfo[] = files;
|
|
2410
|
-
if (!this.isBlank(this.allowedExtensions)) {
|
|
2411
|
-
const allowedExtensions: string[] = [];
|
|
2412
|
-
const extensions: string[] = !isNullOrUndefined(allowedExtensions) ? this.allowedExtensions.split(',') : [''];
|
|
2413
|
-
for (const extension of extensions) {
|
|
2414
|
-
allowedExtensions.push(extension.trim().toLocaleLowerCase());
|
|
2415
|
-
}
|
|
2416
|
-
for (let i: number = 0; i < files.length; i++) {
|
|
2417
|
-
const checkFileType: string = files[i as number].type.indexOf('.') !== -1 ?
|
|
2418
|
-
files[i as number].type.replace('.', '') : files[i as number].type;
|
|
2419
|
-
if (allowedExtensions[0].indexOf('/*') !== -1) {
|
|
2420
|
-
const isValidExtension : boolean = this.checkGenericExtension(allowedExtensions[0], checkFileType);
|
|
2421
|
-
if (!isValidExtension)
|
|
2422
|
-
{
|
|
2423
|
-
files[i as number].status = this.localizedTexts('invalidFileType');
|
|
2424
|
-
files[i as number].statusCode = '0';
|
|
2425
|
-
}
|
|
2426
|
-
}
|
|
2427
|
-
else if ((allowedExtensions.indexOf(('.' + checkFileType).toLocaleLowerCase()) === -1)) {
|
|
2428
|
-
files[i as number].status = this.localizedTexts('invalidFileType');
|
|
2429
|
-
files[i as number].statusCode = '0';
|
|
2430
|
-
}
|
|
2431
|
-
}
|
|
2432
|
-
}
|
|
2433
|
-
return dropFiles;
|
|
2434
|
-
}
|
|
2435
|
-
|
|
2436
|
-
private validatedFileSize(fileSize: number): Object {
|
|
2437
|
-
let minSizeError: string = '';
|
|
2438
|
-
let maxSizeError: string = '';
|
|
2439
|
-
if (fileSize < this.minFileSize) {
|
|
2440
|
-
minSizeError = this.localizedTexts('invalidMinFileSize');
|
|
2441
|
-
} else if (fileSize > this.maxFileSize) {
|
|
2442
|
-
maxSizeError = this.localizedTexts('invalidMaxFileSize');
|
|
2443
|
-
} else {
|
|
2444
|
-
minSizeError = '';
|
|
2445
|
-
maxSizeError = '';
|
|
2446
|
-
}
|
|
2447
|
-
const errorMessage: Object = { minSize: minSizeError, maxSize: maxSizeError };
|
|
2448
|
-
return errorMessage;
|
|
2449
|
-
}
|
|
2450
|
-
|
|
2451
|
-
private isPreLoadFile(fileData: FileInfo) : boolean {
|
|
2452
|
-
let isPreload: boolean = false;
|
|
2453
|
-
for (let i : number = 0; i < this.files.length; i++) {
|
|
2454
|
-
if (this.files[i as number].name === fileData.name.slice(0, fileData.name.lastIndexOf('.')) &&
|
|
2455
|
-
this.files[i as number].type === fileData.type) {
|
|
2456
|
-
isPreload = true;
|
|
2457
|
-
}
|
|
2458
|
-
}
|
|
2459
|
-
return isPreload;
|
|
2460
|
-
}
|
|
2461
|
-
|
|
2462
|
-
private createCustomfileList(fileData: FileInfo[]): void {
|
|
2463
|
-
this.createParentUL();
|
|
2464
|
-
for (const listItem of fileData) {
|
|
2465
|
-
const listElement: HTMLElement = this.createElement('li', { className: FILE, attrs: { 'data-file-name': listItem.name } });
|
|
2466
|
-
this.uploadTemplateFn = this.templateComplier(this.template);
|
|
2467
|
-
const liTempCompiler: any = this.uploadTemplateFn(
|
|
2468
|
-
listItem, this, 'template', this.element.id + 'Template', this.isStringTemplate, null, listElement);
|
|
2469
|
-
if (liTempCompiler) {
|
|
2470
|
-
const fromElements: HTMLElement[] = [].slice.call(liTempCompiler);
|
|
2471
|
-
append(fromElements, listElement);
|
|
2472
|
-
}
|
|
2473
|
-
const index: number = fileData.indexOf(listItem);
|
|
2474
|
-
const eventArgs: RenderingEventArgs = {
|
|
2475
|
-
element: listElement,
|
|
2476
|
-
fileInfo: listItem,
|
|
2477
|
-
index: index,
|
|
2478
|
-
isPreload: this.isPreLoadFile(listItem)
|
|
2479
|
-
};
|
|
2480
|
-
const eventsArgs: FileListRenderingEventArgs = {
|
|
2481
|
-
element: listElement,
|
|
2482
|
-
fileInfo: listItem,
|
|
2483
|
-
index: index,
|
|
2484
|
-
isPreload: this.isPreLoadFile(listItem)
|
|
2485
|
-
};
|
|
2486
|
-
this.trigger('rendering', eventArgs);
|
|
2487
|
-
this.trigger('fileListRendering', eventsArgs);
|
|
2488
|
-
this.listParent.appendChild(listElement);
|
|
2489
|
-
this.fileList.push(listElement);
|
|
2490
|
-
}
|
|
2491
|
-
this.renderReactTemplates();
|
|
2492
|
-
}
|
|
2493
|
-
|
|
2494
|
-
private createParentUL() : void {
|
|
2495
|
-
if (isNullOrUndefined(this.listParent)) {
|
|
2496
|
-
this.listParent = this.createElement('ul', { className: LIST_PARENT });
|
|
2497
|
-
this.uploadWrapper.appendChild(this.listParent);
|
|
2498
|
-
}
|
|
2499
|
-
}
|
|
2500
|
-
|
|
2501
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2502
|
-
private formFileList(fileData: FileInfo[], files: FileList): void {
|
|
2503
|
-
const fileList: HTMLElement = this.createElement('li', { className: FILE });
|
|
2504
|
-
fileList.setAttribute('data-files-count', fileData.length + '');
|
|
2505
|
-
const fileContainer: HTMLElement = this.createElement('span', { className: TEXT_CONTAINER });
|
|
2506
|
-
let statusMessage: string;
|
|
2507
|
-
for (const listItem of fileData) {
|
|
2508
|
-
const fileNameEle: HTMLElement = this.createElement('span', { className: FILE_NAME });
|
|
2509
|
-
fileNameEle.innerHTML = this.getFileNameOnly(listItem.name);
|
|
2510
|
-
const fileTypeEle: HTMLElement = this.createElement('span', { className: FILE_TYPE });
|
|
2511
|
-
const fileType: string = this.getFileType(listItem.name);
|
|
2512
|
-
fileTypeEle.innerHTML = '.' + fileType;
|
|
2513
|
-
if (!fileType) {
|
|
2514
|
-
fileTypeEle.classList.add('e-hidden');
|
|
2515
|
-
}
|
|
2516
|
-
if (!this.enableRtl) {
|
|
2517
|
-
fileContainer.appendChild(fileNameEle);
|
|
2518
|
-
fileContainer.appendChild(fileTypeEle);
|
|
2519
|
-
} else {
|
|
2520
|
-
const rtlContainer: Element = this.createElement('span', { className: RTL_CONTAINER });
|
|
2521
|
-
rtlContainer.appendChild(fileTypeEle);
|
|
2522
|
-
rtlContainer.appendChild(fileNameEle);
|
|
2523
|
-
fileContainer.appendChild(rtlContainer);
|
|
2524
|
-
}
|
|
2525
|
-
this.truncateName(fileNameEle);
|
|
2526
|
-
statusMessage = this.formValidateFileInfo(listItem, fileList);
|
|
2527
|
-
}
|
|
2528
|
-
fileList.appendChild(fileContainer);
|
|
2529
|
-
this.setListToFileInfo(fileData, fileList);
|
|
2530
|
-
const index: number = this.listParent.querySelectorAll('li').length;
|
|
2531
|
-
const infoEle: HTMLElement = this.createElement('span');
|
|
2532
|
-
if (fileList.classList.contains(INVALID_FILE)) {
|
|
2533
|
-
infoEle.classList.add(STATUS);
|
|
2534
|
-
infoEle.classList.add(INVALID_FILE);
|
|
2535
|
-
infoEle.innerText = fileData.length > 1 ? this.localizedTexts('invalidFileSelection') : statusMessage;
|
|
2536
|
-
} else {
|
|
2537
|
-
infoEle.classList.add( fileData.length > 1 ? INFORMATION : FILE_SIZE);
|
|
2538
|
-
infoEle.innerText = fileData.length > 1 ? this.localizedTexts('totalFiles') + ': ' + fileData.length + ' , '
|
|
2539
|
-
+ this.localizedTexts('size') + ': ' +
|
|
2540
|
-
this.bytesToSize(this.getFileSize(fileData)) : this.bytesToSize(fileData[0].size);
|
|
2541
|
-
this.createFormInput(fileData);
|
|
2542
|
-
}
|
|
2543
|
-
fileContainer.appendChild(infoEle);
|
|
2544
|
-
|
|
2545
|
-
if (isNullOrUndefined(fileList.querySelector('.e-icons'))) {
|
|
2546
|
-
const iconElement: HTMLElement = this.createElement('span', {className: 'e-icons', attrs: { 'tabindex': this.btnTabIndex}});
|
|
2547
|
-
/* istanbul ignore next */
|
|
2548
|
-
if (this.browserName === 'msie') {
|
|
2549
|
-
iconElement.classList.add('e-msie');
|
|
2550
|
-
}
|
|
2551
|
-
iconElement.setAttribute('title', this.localizedTexts('remove'));
|
|
2552
|
-
fileList.appendChild(fileContainer);
|
|
2553
|
-
fileList.appendChild(iconElement);
|
|
2554
|
-
EventHandler.add(iconElement, 'click', this.removeFiles, this);
|
|
2555
|
-
iconElement.classList.add(REMOVE_ICON);
|
|
2556
|
-
}
|
|
2557
|
-
|
|
2558
|
-
const eventArgs: RenderingEventArgs = {
|
|
2559
|
-
element: fileList,
|
|
2560
|
-
fileInfo: this.mergeFileInfo(fileData, fileList),
|
|
2561
|
-
index: index,
|
|
2562
|
-
isPreload: this.isPreLoadFile(this.mergeFileInfo(fileData, fileList))
|
|
2563
|
-
};
|
|
2564
|
-
const eventsArgs: FileListRenderingEventArgs = {
|
|
2565
|
-
element: fileList,
|
|
2566
|
-
fileInfo: this.mergeFileInfo(fileData, fileList),
|
|
2567
|
-
index: index,
|
|
2568
|
-
isPreload: this.isPreLoadFile(this.mergeFileInfo(fileData, fileList))
|
|
2569
|
-
};
|
|
2570
|
-
this.trigger('rendering', eventArgs);
|
|
2571
|
-
this.trigger('fileListRendering', eventsArgs);
|
|
2572
|
-
this.listParent.appendChild(fileList);
|
|
2573
|
-
this.fileList.push(fileList);
|
|
2574
|
-
}
|
|
2575
|
-
|
|
2576
|
-
private formValidateFileInfo(listItem: FileInfo, fileList: HTMLElement): string {
|
|
2577
|
-
let statusMessage: string = listItem.status;
|
|
2578
|
-
const validationMessages: ValidationMessages = this.validatedFileSize(listItem.size);
|
|
2579
|
-
if (validationMessages.minSize !== '' || validationMessages.maxSize !== '') {
|
|
2580
|
-
this.addInvalidClass(fileList);
|
|
2581
|
-
statusMessage = validationMessages.minSize !== '' ? this.localizedTexts('invalidMinFileSize') :
|
|
2582
|
-
validationMessages.maxSize !== '' ? this.localizedTexts('invalidMaxFileSize') : statusMessage;
|
|
2583
|
-
}
|
|
2584
|
-
const typeValidationMessage: string = this.checkExtension(this.getFilesInArray(listItem))[0].status;
|
|
2585
|
-
if ( typeValidationMessage === this.localizedTexts('invalidFileType')) {
|
|
2586
|
-
this.addInvalidClass(fileList);
|
|
2587
|
-
statusMessage = typeValidationMessage;
|
|
2588
|
-
}
|
|
2589
|
-
return statusMessage;
|
|
2590
|
-
}
|
|
2591
|
-
|
|
2592
|
-
private addInvalidClass(fileList: HTMLElement): void {
|
|
2593
|
-
fileList.classList.add(INVALID_FILE);
|
|
2594
|
-
}
|
|
2595
|
-
|
|
2596
|
-
private createFormInput(fileData: FileInfo[]): void {
|
|
2597
|
-
if (this.browserName !== 'safari') {
|
|
2598
|
-
const inputElement: HTMLInputElement = this.element.cloneNode(true) as HTMLInputElement;
|
|
2599
|
-
inputElement.classList.add(HIDDEN_INPUT);
|
|
2600
|
-
for (const listItem of fileData) {
|
|
2601
|
-
listItem.input = inputElement;
|
|
2602
|
-
}
|
|
2603
|
-
inputElement.setAttribute('id', getUniqueID('hiddenUploader'));
|
|
2604
|
-
inputElement.setAttribute('name', this.uploaderName);
|
|
2605
|
-
this.uploadWrapper.querySelector('.' + INPUT_WRAPPER).appendChild(inputElement);
|
|
2606
|
-
if (this.browserName !== 'msie' && this.browserName !== 'edge') {
|
|
2607
|
-
this.element.value = ''; }
|
|
2608
|
-
}
|
|
2609
|
-
}
|
|
2610
|
-
|
|
2611
|
-
private getFileSize(fileData: FileInfo[]): number {
|
|
2612
|
-
let fileSize: number = 0;
|
|
2613
|
-
for (const file of fileData) {
|
|
2614
|
-
fileSize += file.size;
|
|
2615
|
-
}
|
|
2616
|
-
return fileSize;
|
|
2617
|
-
}
|
|
2618
|
-
|
|
2619
|
-
private mergeFileInfo(fileData: FileInfo[], fileList: HTMLElement): FileInfo {
|
|
2620
|
-
const result: FileInfo = {
|
|
2621
|
-
name: '',
|
|
2622
|
-
rawFile: '',
|
|
2623
|
-
size: 0,
|
|
2624
|
-
status: '',
|
|
2625
|
-
type: '',
|
|
2626
|
-
validationMessages: { minSize: '', maxSize: ''},
|
|
2627
|
-
statusCode: '1',
|
|
2628
|
-
list: fileList
|
|
2629
|
-
};
|
|
2630
|
-
const fileNames: string [] = [];
|
|
2631
|
-
let type: string = '';
|
|
2632
|
-
for (const listItem of fileData) {
|
|
2633
|
-
fileNames.push(listItem.name);
|
|
2634
|
-
type = listItem.type;
|
|
2635
|
-
}
|
|
2636
|
-
result.name = fileNames.join(', ');
|
|
2637
|
-
result.size = this.getFileSize(fileData);
|
|
2638
|
-
result.type = type;
|
|
2639
|
-
result.status = this.statusForFormUpload(fileData, fileList);
|
|
2640
|
-
return result;
|
|
2641
|
-
}
|
|
2642
|
-
|
|
2643
|
-
private statusForFormUpload(fileData: FileInfo[], fileList: HTMLElement): string {
|
|
2644
|
-
let isValid: boolean = true;
|
|
2645
|
-
let statusMessage: string ;
|
|
2646
|
-
for (const listItem of fileData) {
|
|
2647
|
-
statusMessage = listItem.status;
|
|
2648
|
-
const validationMessages: ValidationMessages = this.validatedFileSize(listItem.size);
|
|
2649
|
-
if (validationMessages.minSize !== '' || validationMessages.maxSize !== '') {
|
|
2650
|
-
isValid = false;
|
|
2651
|
-
statusMessage = validationMessages.minSize !== '' ? this.localizedTexts('invalidMinFileSize') :
|
|
2652
|
-
validationMessages.maxSize !== '' ? this.localizedTexts('invalidMaxFileSize') : statusMessage;
|
|
2653
|
-
}
|
|
2654
|
-
const typeValidationMessage: string = this.checkExtension(this.getFilesInArray(listItem))[0].status;
|
|
2655
|
-
if ( typeValidationMessage === this.localizedTexts('invalidFileType')) {
|
|
2656
|
-
isValid = false;
|
|
2657
|
-
statusMessage = typeValidationMessage;
|
|
2658
|
-
}
|
|
2659
|
-
}
|
|
2660
|
-
|
|
2661
|
-
if (!isValid) {
|
|
2662
|
-
fileList.classList.add(INVALID_FILE);
|
|
2663
|
-
statusMessage = fileData.length > 1 ? this.localizedTexts('invalidFileSelection') : statusMessage;
|
|
2664
|
-
} else {
|
|
2665
|
-
statusMessage = this.localizedTexts('totalFiles') + ': ' + fileData.length + ' , '
|
|
2666
|
-
+ this.localizedTexts('size') + ': ' +
|
|
2667
|
-
this.bytesToSize(this.getFileSize(fileData));
|
|
2668
|
-
}
|
|
2669
|
-
return statusMessage;
|
|
2670
|
-
}
|
|
2671
|
-
|
|
2672
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2673
|
-
private formCustomFileList(fileData: FileInfo[], files: FileList): void {
|
|
2674
|
-
this.createParentUL();
|
|
2675
|
-
const fileList: HTMLElement = this.createElement('li', { className: FILE });
|
|
2676
|
-
fileList.setAttribute('data-files-count', fileData.length + '');
|
|
2677
|
-
this.setListToFileInfo(fileData, fileList);
|
|
2678
|
-
const result: FileInfo = this.mergeFileInfo(fileData, fileList);
|
|
2679
|
-
fileList.setAttribute('data-file-name', result.name);
|
|
2680
|
-
this.uploadTemplateFn = this.templateComplier(this.template);
|
|
2681
|
-
const liTempCompiler: any = this.uploadTemplateFn(result, this, 'template', this.element.id + 'Template', this.isStringTemplate, null, fileList);
|
|
2682
|
-
if (liTempCompiler) {
|
|
2683
|
-
const fromElements: HTMLElement[] = [].slice.call(liTempCompiler);
|
|
2684
|
-
append(fromElements, fileList);
|
|
2685
|
-
}
|
|
2686
|
-
const index: number = this.listParent.querySelectorAll('li').length;
|
|
2687
|
-
if (!fileList.classList.contains(INVALID_FILE)) {
|
|
2688
|
-
this.createFormInput(fileData);
|
|
2689
|
-
}
|
|
2690
|
-
const eventArgs: RenderingEventArgs = {
|
|
2691
|
-
element: fileList,
|
|
2692
|
-
fileInfo: result,
|
|
2693
|
-
index: index,
|
|
2694
|
-
isPreload: this.isPreLoadFile(result)
|
|
2695
|
-
};
|
|
2696
|
-
const eventsArgs: FileListRenderingEventArgs = {
|
|
2697
|
-
element: fileList,
|
|
2698
|
-
fileInfo: result,
|
|
2699
|
-
index: index,
|
|
2700
|
-
isPreload: this.isPreLoadFile(result)
|
|
2701
|
-
};
|
|
2702
|
-
this.trigger('rendering', eventArgs);
|
|
2703
|
-
this.trigger('fileListRendering', eventsArgs);
|
|
2704
|
-
this.listParent.appendChild(fileList);
|
|
2705
|
-
this.fileList.push(fileList);
|
|
2706
|
-
this.renderReactTemplates();
|
|
2707
|
-
}
|
|
2708
|
-
/**
|
|
2709
|
-
* Create the file list for specified files data.
|
|
2710
|
-
*
|
|
2711
|
-
* @param { FileInfo[] } fileData - Specifies the files data for file list creation.
|
|
2712
|
-
* @returns {void}
|
|
2713
|
-
*/
|
|
2714
|
-
public createFileList(fileData: FileInfo[]): void {
|
|
2715
|
-
this.filesData = this.filesData && this.filesData.length > 0 ? this.filesData.concat(fileData) : fileData;
|
|
2716
|
-
this.internalCreateFileList(fileData);
|
|
2717
|
-
}
|
|
2718
|
-
|
|
2719
|
-
private internalCreateFileList(fileData: FileInfo[]): void {
|
|
2720
|
-
this.createParentUL();
|
|
2721
|
-
if (this.template !== '' && !isNullOrUndefined(this.template)) {
|
|
2722
|
-
if (this.isFormUpload()) {
|
|
2723
|
-
this.uploadWrapper.classList.add(FORM_UPLOAD);
|
|
2724
|
-
this.formCustomFileList(fileData, this.element.files);
|
|
2725
|
-
} else {
|
|
2726
|
-
this.createCustomfileList(fileData);
|
|
2727
|
-
}
|
|
2728
|
-
} else if (this.isFormUpload()) {
|
|
2729
|
-
this.uploadWrapper.classList.add(FORM_UPLOAD);
|
|
2730
|
-
this.formFileList(fileData, this.element.files);
|
|
2731
|
-
} else {
|
|
2732
|
-
for (const listItem of fileData) {
|
|
2733
|
-
const liElement: HTMLElement = this.createElement('li', {
|
|
2734
|
-
className: FILE,
|
|
2735
|
-
attrs: { 'data-file-name': listItem.name, 'data-files-count': '1' }
|
|
2736
|
-
});
|
|
2737
|
-
const textContainer: Element = this.createElement('span', { className: TEXT_CONTAINER });
|
|
2738
|
-
const textElement: HTMLElement = this.createElement(
|
|
2739
|
-
'span', { className: FILE_NAME, attrs: { 'title': listItem.name } });
|
|
2740
|
-
textElement.innerHTML = this.getFileNameOnly(listItem.name);
|
|
2741
|
-
const fileExtension: Element = this.createElement('span', { className: FILE_TYPE });
|
|
2742
|
-
const fileType: string = this.getFileType(listItem.name);
|
|
2743
|
-
fileExtension.innerHTML = '.' + fileType;
|
|
2744
|
-
if (!fileType) {
|
|
2745
|
-
fileExtension.classList.add('e-hidden');
|
|
2746
|
-
}
|
|
2747
|
-
if (!this.enableRtl) {
|
|
2748
|
-
textContainer.appendChild(textElement);
|
|
2749
|
-
textContainer.appendChild(fileExtension);
|
|
2750
|
-
} else {
|
|
2751
|
-
const rtlContainer: Element = this.createElement('span', { className: RTL_CONTAINER });
|
|
2752
|
-
rtlContainer.appendChild(fileExtension);
|
|
2753
|
-
rtlContainer.appendChild(textElement);
|
|
2754
|
-
textContainer.appendChild(rtlContainer);
|
|
2755
|
-
}
|
|
2756
|
-
const fileSize: Element = this.createElement('span', { className: FILE_SIZE });
|
|
2757
|
-
fileSize.innerHTML = this.bytesToSize(listItem.size);
|
|
2758
|
-
textContainer.appendChild(fileSize);
|
|
2759
|
-
const statusElement: HTMLElement = this.createElement('span', { className: STATUS });
|
|
2760
|
-
textContainer.appendChild(statusElement);
|
|
2761
|
-
statusElement.innerHTML = listItem.status;
|
|
2762
|
-
liElement.appendChild(textContainer);
|
|
2763
|
-
const iconElement: HTMLElement = this.createElement('span', { className: ' e-icons',
|
|
2764
|
-
attrs: { 'tabindex': this.btnTabIndex } });
|
|
2765
|
-
/* istanbul ignore next */
|
|
2766
|
-
if (this.browserName === 'msie') {
|
|
2767
|
-
iconElement.classList.add('e-msie');
|
|
2768
|
-
}
|
|
2769
|
-
iconElement.setAttribute('title', this.localizedTexts('remove'));
|
|
2770
|
-
liElement.appendChild(iconElement);
|
|
2771
|
-
EventHandler.add(iconElement, 'click', this.removeFiles, this);
|
|
2772
|
-
if (listItem.statusCode === '2') {
|
|
2773
|
-
statusElement.classList.add(UPLOAD_SUCCESS);
|
|
2774
|
-
iconElement.classList.add(DELETE_ICON);
|
|
2775
|
-
iconElement.setAttribute('title', this.localizedTexts('delete'));
|
|
2776
|
-
iconElement.setAttribute('aria-label', this.localizedTexts('delete'));
|
|
2777
|
-
} else if (listItem.statusCode !== '1') {
|
|
2778
|
-
statusElement.classList.remove(UPLOAD_SUCCESS);
|
|
2779
|
-
statusElement.classList.add(VALIDATION_FAILS);
|
|
2780
|
-
}
|
|
2781
|
-
if (this.autoUpload && listItem.statusCode === '1' && this.asyncSettings.saveUrl !== '') {
|
|
2782
|
-
statusElement.innerHTML = '';
|
|
2783
|
-
}
|
|
2784
|
-
if (!iconElement.classList.contains(DELETE_ICON)) {
|
|
2785
|
-
iconElement.classList.add(REMOVE_ICON);
|
|
2786
|
-
iconElement.setAttribute('aria-label', this.localizedTexts('remove'));
|
|
2787
|
-
}
|
|
2788
|
-
const index: number = fileData.indexOf(listItem);
|
|
2789
|
-
const eventArgs: RenderingEventArgs = {
|
|
2790
|
-
element: liElement,
|
|
2791
|
-
fileInfo: listItem,
|
|
2792
|
-
index: index,
|
|
2793
|
-
isPreload: this.isPreLoadFile(listItem)
|
|
2794
|
-
};
|
|
2795
|
-
const eventsArgs: FileListRenderingEventArgs = {
|
|
2796
|
-
element: liElement,
|
|
2797
|
-
fileInfo: listItem,
|
|
2798
|
-
index: index,
|
|
2799
|
-
isPreload: this.isPreLoadFile(listItem)
|
|
2800
|
-
};
|
|
2801
|
-
this.trigger('rendering', eventArgs);
|
|
2802
|
-
this.trigger('fileListRendering', eventsArgs);
|
|
2803
|
-
this.listParent.appendChild(liElement);
|
|
2804
|
-
this.fileList.push(liElement);
|
|
2805
|
-
this.truncateName(textElement);
|
|
2806
|
-
const preventActionComplete: boolean = this.flag;
|
|
2807
|
-
if (this.isPreLoadFile(listItem)) {
|
|
2808
|
-
this.flag = false;
|
|
2809
|
-
this.checkActionComplete(true);
|
|
2810
|
-
this.flag = preventActionComplete;
|
|
2811
|
-
}
|
|
2812
|
-
}
|
|
2813
|
-
}
|
|
2814
|
-
}
|
|
2815
|
-
|
|
2816
|
-
private getSlicedName(nameElement: HTMLElement): void {
|
|
2817
|
-
const text: string = nameElement.textContent;
|
|
2818
|
-
nameElement.dataset.tail = text.slice(text.length - 10);
|
|
2819
|
-
}
|
|
2820
|
-
|
|
2821
|
-
private setListToFileInfo(fileData: FileInfo[], fileList: HTMLElement): void {
|
|
2822
|
-
for (const listItem of fileData) {
|
|
2823
|
-
listItem.list = fileList;
|
|
2824
|
-
}
|
|
2825
|
-
}
|
|
2826
|
-
|
|
2827
|
-
private truncateName(name: HTMLElement): void {
|
|
2828
|
-
const nameElement: HTMLElement = name;
|
|
2829
|
-
if (this.browserName !== 'edge' && nameElement.offsetWidth < nameElement.scrollWidth) {
|
|
2830
|
-
this.getSlicedName(nameElement);
|
|
2831
|
-
/* istanbul ignore next */
|
|
2832
|
-
} else if (nameElement.offsetWidth + 1 < nameElement.scrollWidth) {
|
|
2833
|
-
this.getSlicedName(nameElement);
|
|
2834
|
-
}
|
|
2835
|
-
}
|
|
2836
|
-
|
|
2837
|
-
private getFileType(name: string): string {
|
|
2838
|
-
let extension: string;
|
|
2839
|
-
const index: number = name.lastIndexOf('.');
|
|
2840
|
-
if (index >= 0) {
|
|
2841
|
-
extension = name.substring(index + 1);
|
|
2842
|
-
}
|
|
2843
|
-
return extension ? extension : '';
|
|
2844
|
-
}
|
|
2845
|
-
|
|
2846
|
-
private getFileNameOnly(name: string): string {
|
|
2847
|
-
let type: string = this.getFileType(name);
|
|
2848
|
-
const names: string[] = name.split('.' + type);
|
|
2849
|
-
return type = names[0];
|
|
2850
|
-
}
|
|
2851
|
-
|
|
2852
|
-
private setInitialAttributes(): void {
|
|
2853
|
-
if (this.initialAttr.accept) {
|
|
2854
|
-
this.element.setAttribute('accept', this.initialAttr.accept);
|
|
2855
|
-
}
|
|
2856
|
-
if (this.initialAttr.disabled) {
|
|
2857
|
-
this.element.setAttribute('disabled', 'disabled');
|
|
2858
|
-
}
|
|
2859
|
-
if (this.initialAttr.multiple) {
|
|
2860
|
-
const newAttr: Attr = document.createAttribute('multiple');
|
|
2861
|
-
this.element.setAttributeNode(newAttr);
|
|
2862
|
-
}
|
|
2863
|
-
}
|
|
2864
|
-
|
|
2865
|
-
private filterfileList(files : FileInfo[]) : FileInfo[] {
|
|
2866
|
-
const filterFiles : FileInfo[] = [];
|
|
2867
|
-
let li : HTMLElement;
|
|
2868
|
-
for (let i : number = 0; i < files.length; i++) {
|
|
2869
|
-
li = this.getLiElement(files[i as number]);
|
|
2870
|
-
if (!isNullOrUndefined(li) && !li.classList.contains(UPLOAD_SUCCESS)) {
|
|
2871
|
-
filterFiles.push(files[i as number]);
|
|
2872
|
-
}
|
|
2873
|
-
else if (!this.showFileList && files[i as number].status !== 'File uploaded successfully') {
|
|
2874
|
-
filterFiles.push(files[i as number]);
|
|
2875
|
-
}
|
|
2876
|
-
}
|
|
2877
|
-
return filterFiles;
|
|
2878
|
-
}
|
|
2879
|
-
|
|
2880
|
-
private updateStatus(files : FileInfo, status ? : string, statusCode? : string, updateLiStatus : boolean = true ) : FileInfo {
|
|
2881
|
-
if (!(status === '' || isNullOrUndefined(status)) && !(statusCode === '' || isNullOrUndefined(statusCode))) {
|
|
2882
|
-
files.status = status;
|
|
2883
|
-
files.statusCode = statusCode;
|
|
2884
|
-
}
|
|
2885
|
-
if (updateLiStatus) {
|
|
2886
|
-
const li : HTMLElement = this.getLiElement(files);
|
|
2887
|
-
if (!isNullOrUndefined(li)) {
|
|
2888
|
-
if (!isNullOrUndefined(li.querySelector('.' + STATUS)) && !((status === '' || isNullOrUndefined(status)))) {
|
|
2889
|
-
li.querySelector('.' + STATUS).textContent = status;
|
|
2890
|
-
}
|
|
2891
|
-
}
|
|
2892
|
-
}
|
|
2893
|
-
return files;
|
|
2894
|
-
}
|
|
2895
|
-
|
|
2896
|
-
private getLiElement(files : FileInfo) : HTMLElement {
|
|
2897
|
-
let index: number;
|
|
2898
|
-
for (let i: number = 0; i < this.filesData.length; i++) {
|
|
2899
|
-
if (!isNullOrUndefined(files) && ((!isNullOrUndefined(this.filesData[i as number].id) &&
|
|
2900
|
-
!isNullOrUndefined(files.id)) ? (this.filesData[i as number].name === files.name &&
|
|
2901
|
-
this.filesData[i as number].id === files.id) : this.filesData[i as number].name === files.name)) {
|
|
2902
|
-
index = i;
|
|
2903
|
-
}
|
|
2904
|
-
}
|
|
2905
|
-
return this.fileList[index as number];
|
|
2906
|
-
}
|
|
2907
|
-
|
|
2908
|
-
private createProgressBar(liElement : Element) : void {
|
|
2909
|
-
const progressbarWrapper : Element = this.createElement('span', {className: PROGRESS_WRAPPER});
|
|
2910
|
-
const progressBar : Element = this.createElement('progressbar', {className: PROGRESSBAR, attrs: {value : '0', max : '100'}});
|
|
2911
|
-
const progressbarInnerWrapper : Element = this.createElement('span', {className: PROGRESS_INNER_WRAPPER});
|
|
2912
|
-
progressBar.setAttribute('style', 'width: 0%');
|
|
2913
|
-
const progressbarText : Element = this.createElement('span', {className: PROGRESSBAR_TEXT});
|
|
2914
|
-
progressbarText.textContent = '0%';
|
|
2915
|
-
progressbarInnerWrapper.appendChild(progressBar);
|
|
2916
|
-
progressbarWrapper.appendChild(progressbarInnerWrapper);
|
|
2917
|
-
progressbarWrapper.appendChild(progressbarText);
|
|
2918
|
-
liElement.querySelector('.' + TEXT_CONTAINER).appendChild(progressbarWrapper);
|
|
2919
|
-
}
|
|
2920
|
-
|
|
2921
|
-
/* istanbul ignore next */
|
|
2922
|
-
private updateProgressbar(e : ProgressEventInit, li : Element) : void {
|
|
2923
|
-
if (!isNaN(Math.round((e.loaded / e.total) * 100)) && !isNullOrUndefined(li.querySelector('.' + PROGRESSBAR))) {
|
|
2924
|
-
if (!isNullOrUndefined(this.progressInterval) && this.progressInterval !== '') {
|
|
2925
|
-
const value : number = (Math.round((e.loaded / e.total) * 100)) % parseInt(this.progressInterval, 10);
|
|
2926
|
-
if (value === 0 || value === 100 ) {
|
|
2927
|
-
this.changeProgressValue(li, Math.round((e.loaded / e.total) * 100).toString() + '%');
|
|
2928
|
-
}
|
|
2929
|
-
} else {
|
|
2930
|
-
this.changeProgressValue(li, Math.round((e.loaded / e.total) * 100).toString() + '%');
|
|
2931
|
-
}
|
|
2932
|
-
}
|
|
2933
|
-
}
|
|
2934
|
-
|
|
2935
|
-
private changeProgressValue(li : Element, progressValue : string) : void {
|
|
2936
|
-
li.querySelector('.' + PROGRESSBAR).setAttribute('style', 'width:' + progressValue );
|
|
2937
|
-
li.querySelector('.' + PROGRESSBAR_TEXT).textContent = progressValue;
|
|
2938
|
-
}
|
|
2939
|
-
|
|
2940
|
-
private uploadInProgress (e: ProgressEventInit , files : FileInfo, customUI?: boolean, request?: Ajax) : void {
|
|
2941
|
-
const li : HTMLElement = this.getLiElement(files);
|
|
2942
|
-
if (isNullOrUndefined(li) && (!customUI)) {
|
|
2943
|
-
return;
|
|
2944
|
-
}
|
|
2945
|
-
if (!isNullOrUndefined(li)) {
|
|
2946
|
-
/* istanbul ignore next */
|
|
2947
|
-
if (files.statusCode === '5') {
|
|
2948
|
-
this.cancelUploadingFile(files, e, request, li);
|
|
2949
|
-
}
|
|
2950
|
-
if (!(li.querySelectorAll('.' + PROGRESS_WRAPPER).length > 0) && li.querySelector('.' + STATUS)) {
|
|
2951
|
-
li.querySelector('.' + STATUS).classList.add(UPLOAD_INPROGRESS);
|
|
2952
|
-
this.createProgressBar(li);
|
|
2953
|
-
this.updateProgressBarClasses(li, UPLOAD_INPROGRESS);
|
|
2954
|
-
li.querySelector('.' + STATUS).classList.remove(UPLOAD_FAILED);
|
|
2955
|
-
}
|
|
2956
|
-
this.updateProgressbar(e, <Element>li);
|
|
2957
|
-
const iconEle: HTMLElement = li.querySelector('.' + REMOVE_ICON) as HTMLElement;
|
|
2958
|
-
if (!isNullOrUndefined(iconEle)) {
|
|
2959
|
-
iconEle.classList.add(ABORT_ICON, UPLOAD_INPROGRESS);
|
|
2960
|
-
iconEle.setAttribute('title', this.localizedTexts('abort'));
|
|
2961
|
-
iconEle.classList.remove(REMOVE_ICON);
|
|
2962
|
-
}
|
|
2963
|
-
} else {
|
|
2964
|
-
this.cancelUploadingFile(files, e, request);
|
|
2965
|
-
}
|
|
2966
|
-
const args : object = {e, operation: 'upload', file: this.updateStatus(files, this.localizedTexts('inProgress'), '3')};
|
|
2967
|
-
this.trigger('progress', args);
|
|
2968
|
-
}
|
|
2969
|
-
|
|
2970
|
-
/* istanbul ignore next */
|
|
2971
|
-
private cancelUploadingFile(files: FileInfo, e: ProgressEventInit, request?: Ajax, li?: HTMLElement): void {
|
|
2972
|
-
if (files.statusCode === '5') {
|
|
2973
|
-
const eventArgs: CancelEventArgs = {
|
|
2974
|
-
event: e,
|
|
2975
|
-
fileData: files,
|
|
2976
|
-
cancel: false,
|
|
2977
|
-
customFormData : [],
|
|
2978
|
-
currentRequest : null
|
|
2979
|
-
};
|
|
2980
|
-
this.trigger('canceling', eventArgs, (eventArgs: CancelEventArgs) => {
|
|
2981
|
-
if (eventArgs.cancel) {
|
|
2982
|
-
files.statusCode = '3';
|
|
2983
|
-
if (!isNullOrUndefined(li)) {
|
|
2984
|
-
const spinnerTarget: HTMLElement = li.querySelector('.' + ABORT_ICON) as HTMLElement;
|
|
2985
|
-
if (!isNullOrUndefined(spinnerTarget)) {
|
|
2986
|
-
hideSpinner(spinnerTarget);
|
|
2987
|
-
detach(li.querySelector('.e-spinner-pane'));
|
|
2988
|
-
}
|
|
2989
|
-
}
|
|
2990
|
-
} else {
|
|
2991
|
-
request.emitError = false;
|
|
2992
|
-
request.httpRequest.abort();
|
|
2993
|
-
const formData: FormData = new FormData();
|
|
2994
|
-
if (files.statusCode === '5') {
|
|
2995
|
-
const name: string = this.element.getAttribute('name');
|
|
2996
|
-
formData.append(name, files.name);
|
|
2997
|
-
formData.append('cancel-uploading', files.name);
|
|
2998
|
-
this.updateFormData(formData, eventArgs.customFormData);
|
|
2999
|
-
const ajax: Ajax = new Ajax(this.asyncSettings.removeUrl, 'POST', true, null);
|
|
3000
|
-
ajax.emitError = false;
|
|
3001
|
-
ajax.beforeSend = (e: BeforeSendEventArgs) => {
|
|
3002
|
-
if (eventArgs.currentRequest) {
|
|
3003
|
-
this.updateCustomheader(ajax.httpRequest, eventArgs.currentRequest);
|
|
3004
|
-
}
|
|
3005
|
-
};
|
|
3006
|
-
ajax.onLoad = (e: Event): object => {
|
|
3007
|
-
this.removecanceledFile(e, files); return {};
|
|
3008
|
-
};
|
|
3009
|
-
ajax.send(formData);
|
|
3010
|
-
}
|
|
3011
|
-
}
|
|
3012
|
-
});
|
|
3013
|
-
}
|
|
3014
|
-
}
|
|
3015
|
-
|
|
3016
|
-
private removecanceledFile(e: Event, file: FileInfo): void {
|
|
3017
|
-
const liElement: HTMLElement = this.getLiElement(file);
|
|
3018
|
-
if (isNullOrUndefined(liElement) || liElement.querySelector('.' + RETRY_ICON) || isNullOrUndefined(liElement.querySelector('.' + ABORT_ICON))) {
|
|
3019
|
-
return;
|
|
3020
|
-
}
|
|
3021
|
-
this.updateStatus(file, this.localizedTexts('fileUploadCancel'), '5');
|
|
3022
|
-
this.renderFailureState(e, file, liElement);
|
|
3023
|
-
const spinnerTarget: HTMLElement = liElement.querySelector('.' + REMOVE_ICON ) as HTMLElement;
|
|
3024
|
-
if (!isNullOrUndefined(liElement)) {
|
|
3025
|
-
hideSpinner(spinnerTarget);
|
|
3026
|
-
if (!isNullOrUndefined(liElement.querySelector('.e-spinner-pane'))) {
|
|
3027
|
-
detach(liElement.querySelector('.e-spinner-pane'));
|
|
3028
|
-
}
|
|
3029
|
-
}
|
|
3030
|
-
const requestResponse: Object = e && e.currentTarget ? this.getResponse(e) : null;
|
|
3031
|
-
const args: Object = { event: e, response: requestResponse, operation: 'cancel', file: file };
|
|
3032
|
-
this.trigger('success', args);
|
|
3033
|
-
}
|
|
3034
|
-
|
|
3035
|
-
private renderFailureState(e: Event, file: FileInfo, liElement: HTMLElement): void {
|
|
3036
|
-
this.updateProgressBarClasses(liElement, UPLOAD_FAILED);
|
|
3037
|
-
this.removeProgressbar(liElement, 'failure');
|
|
3038
|
-
if (!isNullOrUndefined(liElement.querySelector('.e-file-status'))) {
|
|
3039
|
-
liElement.querySelector('.e-file-status').classList.add(UPLOAD_FAILED);
|
|
3040
|
-
}
|
|
3041
|
-
const deleteIcon: Element = liElement.querySelector('.' + ABORT_ICON);
|
|
3042
|
-
if (isNullOrUndefined(deleteIcon)) {
|
|
3043
|
-
return;
|
|
3044
|
-
}
|
|
3045
|
-
deleteIcon.classList.remove(ABORT_ICON, UPLOAD_INPROGRESS);
|
|
3046
|
-
deleteIcon.classList.add(REMOVE_ICON);
|
|
3047
|
-
deleteIcon.setAttribute('title', this.localizedTexts('remove'));
|
|
3048
|
-
this.pauseButton = this.createElement('span', {className: 'e-icons e-file-reload-btn', attrs: { 'tabindex': this.btnTabIndex}});
|
|
3049
|
-
deleteIcon.parentElement.insertBefore(this.pauseButton, deleteIcon);
|
|
3050
|
-
this.pauseButton.setAttribute('title', this.localizedTexts('retry'));
|
|
3051
|
-
this.pauseButton.setAttribute('aria-label', this.localizedTexts('retry'));
|
|
3052
|
-
const retryElement: HTMLElement = liElement.querySelector('.' + RETRY_ICON) as HTMLElement;
|
|
3053
|
-
/* istanbul ignore next */
|
|
3054
|
-
retryElement.addEventListener('click', (e: Event) => {
|
|
3055
|
-
this.reloadcanceledFile(e, file, liElement, false);
|
|
3056
|
-
}, false);
|
|
3057
|
-
}
|
|
3058
|
-
|
|
3059
|
-
private reloadcanceledFile(e: Event, file: FileInfo, liElement?: HTMLElement, custom?: boolean): void {
|
|
3060
|
-
file.statusCode = '1';
|
|
3061
|
-
file.status = this.localizedTexts('readyToUploadMessage');
|
|
3062
|
-
if (!custom) {
|
|
3063
|
-
if (!isNullOrUndefined(liElement.querySelector('.' + STATUS))) {
|
|
3064
|
-
liElement.querySelector('.' + STATUS).classList.remove(UPLOAD_FAILED);
|
|
3065
|
-
}
|
|
3066
|
-
if (!isNullOrUndefined(liElement.querySelector('.' + RETRY_ICON))) {
|
|
3067
|
-
detach(liElement.querySelector('.' + RETRY_ICON));
|
|
3068
|
-
}
|
|
3069
|
-
this.pauseButton = null;
|
|
3070
|
-
}
|
|
3071
|
-
/* istanbul ignore next */
|
|
3072
|
-
if (!isNullOrUndefined(liElement)) {
|
|
3073
|
-
liElement.classList.add(RESTRICT_RETRY);
|
|
3074
|
-
}
|
|
3075
|
-
this.upload([file]);
|
|
3076
|
-
}
|
|
3077
|
-
|
|
3078
|
-
/* istanbul ignore next */
|
|
3079
|
-
private uploadComplete(e: Event, file: FileInfo, customUI ?: boolean) : void {
|
|
3080
|
-
const status : XMLHttpRequest = e.target as XMLHttpRequest;
|
|
3081
|
-
if (status.readyState === 4 && status.status >= 200 && status.status <= 299 ) {
|
|
3082
|
-
const li : HTMLElement = this.getLiElement(file);
|
|
3083
|
-
if (isNullOrUndefined(li) && (!customUI || isNullOrUndefined(customUI)) && this.showFileList ) {
|
|
3084
|
-
return;
|
|
3085
|
-
}
|
|
3086
|
-
if (!isNullOrUndefined(li)) {
|
|
3087
|
-
this.updateProgressBarClasses(li, UPLOAD_SUCCESS);
|
|
3088
|
-
this.removeProgressbar(li, 'success');
|
|
3089
|
-
const iconEle: Element = li.querySelector('.' + ABORT_ICON);
|
|
3090
|
-
if (!isNullOrUndefined(iconEle)) {
|
|
3091
|
-
iconEle.classList.add(DELETE_ICON);
|
|
3092
|
-
iconEle.setAttribute('title', this.localizedTexts('delete'));
|
|
3093
|
-
iconEle.setAttribute('aria-label', this.localizedTexts('delete'));
|
|
3094
|
-
iconEle.classList.remove(ABORT_ICON);
|
|
3095
|
-
iconEle.classList.remove(UPLOAD_INPROGRESS);
|
|
3096
|
-
}
|
|
3097
|
-
}
|
|
3098
|
-
this.raiseSuccessEvent(e, file);
|
|
3099
|
-
} else {
|
|
3100
|
-
this.uploadFailed(e, file);
|
|
3101
|
-
}
|
|
3102
|
-
}
|
|
3103
|
-
|
|
3104
|
-
private getResponse(e: Event): Object {
|
|
3105
|
-
const target: any = e.currentTarget;
|
|
3106
|
-
const response: Object = {
|
|
3107
|
-
readyState: target.readyState,
|
|
3108
|
-
statusCode: target.status,
|
|
3109
|
-
statusText: target.statusText,
|
|
3110
|
-
headers: target.getAllResponseHeaders(),
|
|
3111
|
-
withCredentials: target.withCredentials
|
|
3112
|
-
};
|
|
3113
|
-
return response;
|
|
3114
|
-
}
|
|
3115
|
-
|
|
3116
|
-
private raiseSuccessEvent(e: Event, file: FileInfo): void {
|
|
3117
|
-
const response: Object = e && e.currentTarget ? this.getResponse(e) : null;
|
|
3118
|
-
const statusMessage: string = this.localizedTexts('uploadSuccessMessage');
|
|
3119
|
-
const args: Object = {
|
|
3120
|
-
e, response: response, operation: 'upload', file: this.updateStatus(file, statusMessage, '2', false), statusText: statusMessage
|
|
3121
|
-
};
|
|
3122
|
-
const liElement: HTMLElement = this.getLiElement(file);
|
|
3123
|
-
if (!isNullOrUndefined(liElement)) {
|
|
3124
|
-
const spinnerEle: HTMLElement = liElement.querySelector('.' + SPINNER_PANE) as HTMLElement;
|
|
3125
|
-
if (!isNullOrUndefined(spinnerEle)) {
|
|
3126
|
-
hideSpinner(liElement);
|
|
3127
|
-
detach(spinnerEle);
|
|
3128
|
-
}
|
|
3129
|
-
}
|
|
3130
|
-
this.trigger('success', args, (args: Object) => {
|
|
3131
|
-
this.updateStatus(file, (args as any).statusText, '2');
|
|
3132
|
-
if (this.multiple) {
|
|
3133
|
-
this.uploadedFilesData.push(file);
|
|
3134
|
-
}
|
|
3135
|
-
else {
|
|
3136
|
-
this.uploadedFilesData = [file];
|
|
3137
|
-
}
|
|
3138
|
-
this.trigger('change', { file: this.uploadedFilesData });
|
|
3139
|
-
this.checkActionButtonStatus();
|
|
3140
|
-
if (this.fileList.length > 0) {
|
|
3141
|
-
if ((!(this.getLiElement(file)).classList.contains(RESTRICT_RETRY))) {
|
|
3142
|
-
this.uploadSequential();
|
|
3143
|
-
this.checkActionComplete(true);
|
|
3144
|
-
} else {
|
|
3145
|
-
/* istanbul ignore next */
|
|
3146
|
-
(this.getLiElement(file)).classList.remove(RESTRICT_RETRY);
|
|
3147
|
-
}
|
|
3148
|
-
}
|
|
3149
|
-
else if (!this.showFileList) {
|
|
3150
|
-
this.checkActionComplete(true);
|
|
3151
|
-
}
|
|
3152
|
-
});
|
|
3153
|
-
}
|
|
3154
|
-
|
|
3155
|
-
private uploadFailed(e: Event, file: FileInfo): void {
|
|
3156
|
-
const li: HTMLElement = this.getLiElement(file);
|
|
3157
|
-
const response: Object = e && e.currentTarget ? this.getResponse(e) : null;
|
|
3158
|
-
const statusMessage: string = this.localizedTexts('uploadFailedMessage');
|
|
3159
|
-
const args: Object = {
|
|
3160
|
-
e, response: response, operation: 'upload', file: this.updateStatus(file, statusMessage, '0', false), statusText: statusMessage
|
|
3161
|
-
};
|
|
3162
|
-
if (!isNullOrUndefined(li)) {
|
|
3163
|
-
this.renderFailureState(e, file, li);
|
|
3164
|
-
}
|
|
3165
|
-
this.trigger('failure', args, (args: Object) => {
|
|
3166
|
-
this.updateStatus(file, (args as any).statusText, '0');
|
|
3167
|
-
this.checkActionButtonStatus();
|
|
3168
|
-
this.uploadSequential();
|
|
3169
|
-
this.checkActionComplete(true);
|
|
3170
|
-
});
|
|
3171
|
-
}
|
|
3172
|
-
|
|
3173
|
-
private uploadSequential() : void {
|
|
3174
|
-
if (this.sequentialUpload) {
|
|
3175
|
-
if (this.autoUpload) {
|
|
3176
|
-
/* istanbul ignore next */
|
|
3177
|
-
this.checkAutoUpload(this.filesData);
|
|
3178
|
-
} else {
|
|
3179
|
-
this.uploadButtonClick();
|
|
3180
|
-
}
|
|
3181
|
-
}
|
|
3182
|
-
}
|
|
3183
|
-
|
|
3184
|
-
private checkActionComplete(increment: boolean): void {
|
|
3185
|
-
if (increment) {
|
|
3186
|
-
++this.actionCompleteCount;
|
|
3187
|
-
} else {
|
|
3188
|
-
--this.actionCompleteCount;
|
|
3189
|
-
}
|
|
3190
|
-
this.raiseActionComplete();
|
|
3191
|
-
}
|
|
3192
|
-
|
|
3193
|
-
private raiseActionComplete(): void {
|
|
3194
|
-
if ((this.filesData.length === this.actionCompleteCount) && this.flag) {
|
|
3195
|
-
this.flag = false;
|
|
3196
|
-
const eventArgs: ActionCompleteEventArgs = {
|
|
3197
|
-
fileData: []
|
|
3198
|
-
};
|
|
3199
|
-
eventArgs.fileData = this.getSelectedFileStatus(this.selectedFiles);
|
|
3200
|
-
this.trigger('actionComplete', eventArgs);
|
|
3201
|
-
}
|
|
3202
|
-
}
|
|
3203
|
-
|
|
3204
|
-
private getSelectedFileStatus(selectedFiles: FileInfo[]): FileInfo[] {
|
|
3205
|
-
const matchFiles: FileInfo [] = [];
|
|
3206
|
-
let matchFilesIndex: number = 0;
|
|
3207
|
-
for ( let selectFileIndex: number = 0 ; selectFileIndex < selectedFiles.length; selectFileIndex++ ) {
|
|
3208
|
-
const selectedFileData: FileInfo = selectedFiles[selectFileIndex as number];
|
|
3209
|
-
for ( let fileDataIndex: number = 0 ; fileDataIndex < this.filesData.length; fileDataIndex++ ) {
|
|
3210
|
-
if ( this.filesData[fileDataIndex as number].name === selectedFileData.name &&
|
|
3211
|
-
this.filesData[fileDataIndex as number].status === selectedFileData.status ) {
|
|
3212
|
-
matchFiles[matchFilesIndex as number] = this.filesData[fileDataIndex as number];
|
|
3213
|
-
++matchFilesIndex;
|
|
3214
|
-
break;
|
|
3215
|
-
}
|
|
3216
|
-
}
|
|
3217
|
-
}
|
|
3218
|
-
return matchFiles;
|
|
3219
|
-
}
|
|
3220
|
-
|
|
3221
|
-
private updateProgressBarClasses (li : HTMLElement, className : string) : void {
|
|
3222
|
-
const progressBar: HTMLElement = <HTMLElement>li.querySelector('.' + PROGRESSBAR);
|
|
3223
|
-
if (!isNullOrUndefined(progressBar)) {
|
|
3224
|
-
progressBar.classList.add(className);
|
|
3225
|
-
if (this.actionButtons && this.clearButton && this.uploadWrapper) {
|
|
3226
|
-
if (className === 'e-upload-progress' && !this.clearButton.hasAttribute('disabled')) {
|
|
3227
|
-
this.clearButton.setAttribute('disabled', 'disabled');
|
|
3228
|
-
} else if ((className === 'e-upload-success' || className === 'e-upload-fails') && this.uploadWrapper.querySelectorAll(
|
|
3229
|
-
'.e-upload-progress-bar.e-upload-progress:not(.e-upload-success):not(.e-upload-fails)').length === 0 &&
|
|
3230
|
-
this.clearButton.hasAttribute('disabled')) {
|
|
3231
|
-
this.clearButton.removeAttribute('disabled');
|
|
3232
|
-
}
|
|
3233
|
-
}
|
|
3234
|
-
}
|
|
3235
|
-
}
|
|
3236
|
-
|
|
3237
|
-
private removeProgressbar(li : HTMLElement, callType : string) : void {
|
|
3238
|
-
if (!isNullOrUndefined(li.querySelector('.' + PROGRESS_WRAPPER))) {
|
|
3239
|
-
this.progressAnimation = new Animation({ duration: 1250 });
|
|
3240
|
-
this.progressAnimation.animate(<HTMLElement>li.querySelector('.' + PROGRESS_WRAPPER), {name: 'FadeOut'});
|
|
3241
|
-
this.progressAnimation.animate(<HTMLElement>li.querySelector('.' + PROGRESSBAR_TEXT), {name: 'FadeOut'});
|
|
3242
|
-
setTimeout(() => {
|
|
3243
|
-
this.animateProgressBar(li, callType);
|
|
3244
|
-
}, 750);
|
|
3245
|
-
}
|
|
3246
|
-
}
|
|
3247
|
-
|
|
3248
|
-
/* istanbul ignore next */
|
|
3249
|
-
private animateProgressBar(li: Element, callType: string) : void {
|
|
3250
|
-
if (callType === 'success') {
|
|
3251
|
-
li.classList.add(UPLOAD_SUCCESS);
|
|
3252
|
-
if (!isNullOrUndefined(li.querySelector('.' + STATUS))) {
|
|
3253
|
-
li.querySelector('.' + STATUS).classList.remove(UPLOAD_INPROGRESS);
|
|
3254
|
-
this.progressAnimation.animate(<HTMLElement>li.querySelector('.' + STATUS), {name: 'FadeIn'});
|
|
3255
|
-
li.querySelector('.' + STATUS).classList.add(UPLOAD_SUCCESS);
|
|
3256
|
-
}
|
|
3257
|
-
} else {
|
|
3258
|
-
if (!isNullOrUndefined(li.querySelector('.' + STATUS))) {
|
|
3259
|
-
li.querySelector('.' + STATUS).classList.remove(UPLOAD_INPROGRESS);
|
|
3260
|
-
this.progressAnimation.animate(<HTMLElement>li.querySelector('.' + STATUS), {name: 'FadeIn'});
|
|
3261
|
-
li.querySelector('.' + STATUS).classList.add(UPLOAD_FAILED);
|
|
3262
|
-
}
|
|
3263
|
-
}
|
|
3264
|
-
if (li.querySelector('.' + PROGRESS_WRAPPER)) {
|
|
3265
|
-
detach(li.querySelector('.' + PROGRESS_WRAPPER));
|
|
3266
|
-
}
|
|
3267
|
-
}
|
|
3268
|
-
|
|
3269
|
-
private setExtensions(extensions : string): void {
|
|
3270
|
-
if (extensions !== '' && !isNullOrUndefined(extensions)) {
|
|
3271
|
-
this.element.setAttribute('accept', extensions);
|
|
3272
|
-
} else {
|
|
3273
|
-
this.element.removeAttribute('accept');
|
|
3274
|
-
}
|
|
3275
|
-
}
|
|
3276
|
-
|
|
3277
|
-
private templateComplier(uploadTemplate: string | Function): Function {
|
|
3278
|
-
if (uploadTemplate) {
|
|
3279
|
-
try {
|
|
3280
|
-
if (typeof uploadTemplate !== 'function' && selectAll(uploadTemplate, document).length) {
|
|
3281
|
-
return compile(select(uploadTemplate, document).innerHTML.trim());
|
|
3282
|
-
} else {
|
|
3283
|
-
return compile(uploadTemplate);
|
|
3284
|
-
}
|
|
3285
|
-
} catch (exception) {
|
|
3286
|
-
return compile(uploadTemplate);
|
|
3287
|
-
}
|
|
3288
|
-
}
|
|
3289
|
-
return undefined;
|
|
3290
|
-
}
|
|
3291
|
-
|
|
3292
|
-
private setRTL() : void {
|
|
3293
|
-
if (this.enableRtl) {
|
|
3294
|
-
addClass([this.uploadWrapper], RTL);
|
|
3295
|
-
} else {
|
|
3296
|
-
removeClass([this.uploadWrapper], RTL);
|
|
3297
|
-
}
|
|
3298
|
-
}
|
|
3299
|
-
|
|
3300
|
-
private localizedTexts(localeText : string): string {
|
|
3301
|
-
this.l10n.setLocale(this.locale);
|
|
3302
|
-
return this.l10n.getConstant(localeText);
|
|
3303
|
-
}
|
|
3304
|
-
|
|
3305
|
-
private setControlStatus() : void {
|
|
3306
|
-
if (!this.enabled) {
|
|
3307
|
-
this.uploadWrapper.classList.add(DISABLED);
|
|
3308
|
-
this.element.setAttribute('disabled', 'disabled');
|
|
3309
|
-
this.browseButton.setAttribute('disabled', 'disabled');
|
|
3310
|
-
if (!isNullOrUndefined(this.clearButton)) {
|
|
3311
|
-
this.clearButton.setAttribute('disabled', 'disabled');
|
|
3312
|
-
}
|
|
3313
|
-
if (!isNullOrUndefined(this.uploadButton)) {
|
|
3314
|
-
this.uploadButton.setAttribute('disabled', 'disabled');
|
|
3315
|
-
}
|
|
3316
|
-
} else {
|
|
3317
|
-
if (this.uploadWrapper.classList.contains(DISABLED)) {
|
|
3318
|
-
this.uploadWrapper.classList.remove(DISABLED);
|
|
3319
|
-
}
|
|
3320
|
-
if (!isNullOrUndefined(this.browseButton) && this.element.hasAttribute('disabled')) {
|
|
3321
|
-
this.element.removeAttribute('disabled');
|
|
3322
|
-
this.browseButton.removeAttribute('disabled');
|
|
3323
|
-
}
|
|
3324
|
-
if (!isNullOrUndefined(this.clearButton) && this.clearButton.hasAttribute('disabled')) {
|
|
3325
|
-
this.clearButton.removeAttribute('disabled');
|
|
3326
|
-
}
|
|
3327
|
-
if (!isNullOrUndefined(this.uploadButton) && this.uploadButton.hasAttribute('disabled')) {
|
|
3328
|
-
this.uploadButton.hasAttribute('disabled');
|
|
3329
|
-
}
|
|
3330
|
-
}
|
|
3331
|
-
}
|
|
3332
|
-
|
|
3333
|
-
private checkHTMLAttributes(isDynamic: boolean) : void {
|
|
3334
|
-
const attributes: string[] = isDynamic ? isNullOrUndefined(this.htmlAttributes) ? [] : Object.keys(this.htmlAttributes) :
|
|
3335
|
-
['accept', 'multiple', 'disabled'];
|
|
3336
|
-
for (const prop of attributes) {
|
|
3337
|
-
if (!isNullOrUndefined(this.element.getAttribute(prop))) {
|
|
3338
|
-
switch (prop) {
|
|
3339
|
-
case 'accept':
|
|
3340
|
-
if ((isNullOrUndefined(this.uploaderOptions) || (this.uploaderOptions['allowedExtensions'] === undefined))
|
|
3341
|
-
|| isDynamic) {
|
|
3342
|
-
this.setProperties({allowedExtensions: this.element.getAttribute('accept')}, !isDynamic);
|
|
3343
|
-
this.initialAttr.accept = this.allowedExtensions;
|
|
3344
|
-
}
|
|
3345
|
-
break;
|
|
3346
|
-
case 'multiple':
|
|
3347
|
-
if ((isNullOrUndefined(this.uploaderOptions) || (this.uploaderOptions['multiple'] === undefined)) || isDynamic) {
|
|
3348
|
-
const isMutiple: boolean = this.element.getAttribute(prop) === 'multiple' ||
|
|
3349
|
-
this.element.getAttribute(prop) === '' || this.element.getAttribute(prop) === 'true' ? true : false;
|
|
3350
|
-
this.setProperties({multiple: isMutiple}, !isDynamic);
|
|
3351
|
-
this.initialAttr.multiple = true;
|
|
3352
|
-
}
|
|
3353
|
-
break;
|
|
3354
|
-
case 'disabled':
|
|
3355
|
-
if ((isNullOrUndefined(this.uploaderOptions) || (this.uploaderOptions['enabled'] === undefined)) || isDynamic) {
|
|
3356
|
-
const isDisabled: boolean = this.element.getAttribute(prop) === 'disabled' ||
|
|
3357
|
-
this.element.getAttribute(prop) === '' || this.element.getAttribute(prop) === 'true' ? false : true;
|
|
3358
|
-
this.setProperties({enabled: isDisabled}, !isDynamic);
|
|
3359
|
-
this.initialAttr.disabled = true;
|
|
3360
|
-
}
|
|
3361
|
-
}
|
|
3362
|
-
}
|
|
3363
|
-
}
|
|
3364
|
-
}
|
|
3365
|
-
|
|
3366
|
-
private chunkUpload(file: FileInfo, custom?: boolean, fileIndex?: number): void {
|
|
3367
|
-
const start: number = 0;
|
|
3368
|
-
const end: number = Math.min(this.asyncSettings.chunkSize, file.size);
|
|
3369
|
-
const index: number = 0;
|
|
3370
|
-
const blob: string | Blob = file.rawFile.slice(start, end);
|
|
3371
|
-
const metaData: MetaData = { chunkIndex: index, blob: blob, file: file, start: start, end: end, retryCount: 0, request: null };
|
|
3372
|
-
this.sendRequest(file, metaData, custom, fileIndex);
|
|
3373
|
-
}
|
|
3374
|
-
|
|
3375
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3376
|
-
private sendRequest(file: FileInfo, metaData: MetaData, custom?: boolean, fileIndex?: number): void {
|
|
3377
|
-
const formData: FormData = new FormData();
|
|
3378
|
-
const blob: string | Blob = file.rawFile.slice(metaData.start, metaData.end);
|
|
3379
|
-
formData.append(this.uploaderName, blob, file.name);
|
|
3380
|
-
formData.append('chunk-index', metaData.chunkIndex.toString());
|
|
3381
|
-
formData.append('chunkIndex', metaData.chunkIndex.toString());
|
|
3382
|
-
const totalChunk: number = Math.max(Math.ceil(file.size / this.asyncSettings.chunkSize), 1);
|
|
3383
|
-
formData.append('total-chunk', totalChunk.toString());
|
|
3384
|
-
formData.append('totalChunk', totalChunk.toString());
|
|
3385
|
-
const ajax: Ajax = new Ajax({ url: this.asyncSettings.saveUrl, type: 'POST', async: true, contentType: null });
|
|
3386
|
-
ajax.emitError = false;
|
|
3387
|
-
ajax.onLoad = (e: Event): object => {
|
|
3388
|
-
this.chunkUploadComplete(e, metaData, custom); return {};
|
|
3389
|
-
};
|
|
3390
|
-
ajax.onUploadProgress = (e: Event) => {
|
|
3391
|
-
this.chunkUploadInProgress(e, metaData, custom);
|
|
3392
|
-
return {};
|
|
3393
|
-
};
|
|
3394
|
-
const eventArgs: UploadingEventArgs = {
|
|
3395
|
-
fileData: file,
|
|
3396
|
-
customFormData: [],
|
|
3397
|
-
cancel: false,
|
|
3398
|
-
chunkSize: this.asyncSettings.chunkSize === 0 ? null : this.asyncSettings.chunkSize
|
|
3399
|
-
};
|
|
3400
|
-
ajax.beforeSend = (e: BeforeSendEventArgs) => {
|
|
3401
|
-
eventArgs.currentRequest = ajax.httpRequest;
|
|
3402
|
-
eventArgs.currentChunkIndex = metaData.chunkIndex;
|
|
3403
|
-
if (eventArgs.currentChunkIndex === 0) {
|
|
3404
|
-
// This event is currently not required but to avoid breaking changes for previous customer, we have included.
|
|
3405
|
-
this.trigger('uploading', eventArgs, (eventArgs: UploadingEventArgs) => {
|
|
3406
|
-
this.uploadingEventCallback(formData, eventArgs, e, file);
|
|
3407
|
-
});
|
|
3408
|
-
} else {
|
|
3409
|
-
this.trigger('chunkUploading', eventArgs, (eventArgs: UploadingEventArgs) => {
|
|
3410
|
-
this.uploadingEventCallback(formData, eventArgs, e, file);
|
|
3411
|
-
});
|
|
3412
|
-
}
|
|
3413
|
-
};
|
|
3414
|
-
/* istanbul ignore next */
|
|
3415
|
-
ajax.onError = (e: Event) => {
|
|
3416
|
-
this.chunkUploadFailed(e, metaData, custom); return {};
|
|
3417
|
-
};
|
|
3418
|
-
ajax.send(formData);
|
|
3419
|
-
metaData.request = ajax;
|
|
3420
|
-
}
|
|
3421
|
-
|
|
3422
|
-
private uploadingEventCallback(formData: FormData, eventArgs: UploadingEventArgs, e: BeforeSendEventArgs, file: FileInfo): void {
|
|
3423
|
-
if (eventArgs.cancel) {
|
|
3424
|
-
this.eventCancelByArgs(e, eventArgs, file);
|
|
3425
|
-
} else {
|
|
3426
|
-
this.updateFormData(formData, eventArgs.customFormData);
|
|
3427
|
-
}
|
|
3428
|
-
}
|
|
3429
|
-
|
|
3430
|
-
private eventCancelByArgs(e: BeforeSendEventArgs, eventArgs: UploadingEventArgs, file: FileInfo): void {
|
|
3431
|
-
e.cancel = true;
|
|
3432
|
-
if (eventArgs.fileData.statusCode === '5') {
|
|
3433
|
-
return;
|
|
3434
|
-
}
|
|
3435
|
-
eventArgs.fileData.statusCode = '5';
|
|
3436
|
-
eventArgs.fileData.status = this.localizedTexts('fileUploadCancel');
|
|
3437
|
-
const liElement: HTMLElement = this.getLiElement(eventArgs.fileData);
|
|
3438
|
-
if (liElement) {
|
|
3439
|
-
if (!isNullOrUndefined(liElement.querySelector('.' + STATUS))) {
|
|
3440
|
-
liElement.querySelector('.' + STATUS).innerHTML = this.localizedTexts('fileUploadCancel');
|
|
3441
|
-
liElement.querySelector('.' + STATUS).classList.add(UPLOAD_FAILED);
|
|
3442
|
-
}
|
|
3443
|
-
this.pauseButton = this.createElement('span',
|
|
3444
|
-
{className: 'e-icons e-file-reload-btn', attrs: { 'tabindex': this.btnTabIndex}});
|
|
3445
|
-
const removeIcon: Element = liElement.querySelector('.' + REMOVE_ICON);
|
|
3446
|
-
if (removeIcon) {
|
|
3447
|
-
removeIcon.parentElement.insertBefore(this.pauseButton, removeIcon);
|
|
3448
|
-
}
|
|
3449
|
-
this.pauseButton.setAttribute('title', this.localizedTexts('retry'));
|
|
3450
|
-
/* istanbul ignore next */
|
|
3451
|
-
this.pauseButton.addEventListener('click', (e: Event) => {
|
|
3452
|
-
this.reloadcanceledFile(e, file, liElement);
|
|
3453
|
-
}, false);
|
|
3454
|
-
this.checkActionButtonStatus();
|
|
3455
|
-
}
|
|
3456
|
-
}
|
|
3457
|
-
|
|
3458
|
-
private checkChunkUpload(): boolean {
|
|
3459
|
-
return (this.asyncSettings.chunkSize <= 0 || isNullOrUndefined(this.asyncSettings.chunkSize)) ? false : true;
|
|
3460
|
-
}
|
|
3461
|
-
|
|
3462
|
-
private chunkUploadComplete(e: Event, metaData: MetaData, custom?: boolean): void {
|
|
3463
|
-
const response: XMLHttpRequest = e.target as XMLHttpRequest;
|
|
3464
|
-
let liElement: HTMLElement;
|
|
3465
|
-
if (response.readyState === 4 && response.status >= 200 && response.status < 300) {
|
|
3466
|
-
const requestResponse: Object = e && e.currentTarget ? this.getResponse(e) : null;
|
|
3467
|
-
const totalChunk: number = Math.max(Math.ceil(metaData.file.size / this.asyncSettings.chunkSize), 1);
|
|
3468
|
-
const eventArgs: Object = {
|
|
3469
|
-
event: e,
|
|
3470
|
-
file: metaData.file,
|
|
3471
|
-
chunkIndex: metaData.chunkIndex,
|
|
3472
|
-
totalChunk: totalChunk,
|
|
3473
|
-
chunkSize: this.asyncSettings.chunkSize,
|
|
3474
|
-
response: requestResponse
|
|
3475
|
-
};
|
|
3476
|
-
this.trigger('chunkSuccess', eventArgs);
|
|
3477
|
-
if (isNullOrUndefined(custom) || !custom) {
|
|
3478
|
-
liElement = this.getLiElement(metaData.file);
|
|
3479
|
-
}
|
|
3480
|
-
this.updateMetaData(metaData);
|
|
3481
|
-
if (metaData.end === metaData.file.size) {
|
|
3482
|
-
metaData.file.statusCode = '3';
|
|
3483
|
-
}
|
|
3484
|
-
if (metaData.file.statusCode === '5') {
|
|
3485
|
-
const eventArgs: CancelEventArgs = { event: e, fileData: metaData.file, cancel: false, customFormData: [] };
|
|
3486
|
-
this.trigger('canceling', eventArgs, (eventArgs: CancelEventArgs) => {
|
|
3487
|
-
/* istanbul ignore next */
|
|
3488
|
-
if (eventArgs.cancel) {
|
|
3489
|
-
metaData.file.statusCode = '3';
|
|
3490
|
-
const spinnerTarget: HTMLElement = liElement.querySelector('.' + ABORT_ICON) as HTMLElement;
|
|
3491
|
-
if (!isNullOrUndefined(liElement) && !isNullOrUndefined(spinnerTarget)) {
|
|
3492
|
-
hideSpinner(spinnerTarget);
|
|
3493
|
-
detach(liElement.querySelector('.e-spinner-pane'));
|
|
3494
|
-
}
|
|
3495
|
-
this.sendNextRequest(metaData);
|
|
3496
|
-
} else {
|
|
3497
|
-
metaData.request.emitError = false;
|
|
3498
|
-
response.abort();
|
|
3499
|
-
const formData: FormData = new FormData();
|
|
3500
|
-
const name: string = this.element.getAttribute('name');
|
|
3501
|
-
formData.append(name, metaData.file.name);
|
|
3502
|
-
formData.append('cancel-uploading', metaData.file.name);
|
|
3503
|
-
formData.append('cancelUploading', metaData.file.name);
|
|
3504
|
-
this.updateFormData(formData, eventArgs.customFormData);
|
|
3505
|
-
const ajax: Ajax = new Ajax(this.asyncSettings.removeUrl, 'POST', true, null);
|
|
3506
|
-
ajax.emitError = false;
|
|
3507
|
-
ajax.onLoad = (e: Event): object => {
|
|
3508
|
-
this.removeChunkFile(e, metaData, custom); return {};
|
|
3509
|
-
};
|
|
3510
|
-
ajax.send(formData);
|
|
3511
|
-
}
|
|
3512
|
-
});
|
|
3513
|
-
} else {
|
|
3514
|
-
if ((totalChunk - 1) === metaData.chunkIndex && totalChunk > metaData.chunkIndex) {
|
|
3515
|
-
const index: number = this.pausedData.indexOf(metaData);
|
|
3516
|
-
if (index >= 0) {
|
|
3517
|
-
this.pausedData.splice(index, 1);
|
|
3518
|
-
}
|
|
3519
|
-
if (isNullOrUndefined(this.template) && (isNullOrUndefined(custom) || !custom) && liElement) {
|
|
3520
|
-
if (liElement && !isNullOrUndefined(liElement.querySelector('.' + PAUSE_UPLOAD))) {
|
|
3521
|
-
detach(liElement.querySelector('.' + PAUSE_UPLOAD));
|
|
3522
|
-
}
|
|
3523
|
-
this.removeChunkProgressBar(metaData);
|
|
3524
|
-
}
|
|
3525
|
-
this.raiseSuccessEvent(e, metaData.file);
|
|
3526
|
-
return;
|
|
3527
|
-
}
|
|
3528
|
-
if (metaData.file.statusCode !== '4') {
|
|
3529
|
-
this.sendNextRequest(metaData);
|
|
3530
|
-
}
|
|
3531
|
-
}
|
|
3532
|
-
} else {
|
|
3533
|
-
this.chunkUploadFailed(e, metaData);
|
|
3534
|
-
}
|
|
3535
|
-
}
|
|
3536
|
-
|
|
3537
|
-
private sendNextRequest(metaData: MetaData): void {
|
|
3538
|
-
metaData.start = metaData.end;
|
|
3539
|
-
metaData.end += this.asyncSettings.chunkSize;
|
|
3540
|
-
metaData.end = Math.min(metaData.end, metaData.file.size);
|
|
3541
|
-
metaData.chunkIndex += 1;
|
|
3542
|
-
this.sendRequest(metaData.file, metaData);
|
|
3543
|
-
}
|
|
3544
|
-
|
|
3545
|
-
private removeChunkFile(e: Event, metaData: MetaData, custom: boolean): void {
|
|
3546
|
-
if (isNullOrUndefined(this.template) && (isNullOrUndefined(custom) && !custom)) {
|
|
3547
|
-
const liElement: HTMLElement = this.getLiElement(metaData.file);
|
|
3548
|
-
const deleteIcon: Element = liElement.querySelector('.' + ABORT_ICON);
|
|
3549
|
-
const spinnerTarget: HTMLElement = deleteIcon as HTMLElement;
|
|
3550
|
-
this.updateStatus(metaData.file, this.localizedTexts('fileUploadCancel'), '5');
|
|
3551
|
-
this.updateProgressBarClasses(liElement, UPLOAD_FAILED);
|
|
3552
|
-
this.removeProgressbar(liElement, 'failure');
|
|
3553
|
-
if (deleteIcon) {
|
|
3554
|
-
deleteIcon.classList.remove(ABORT_ICON);
|
|
3555
|
-
deleteIcon.classList.add(REMOVE_ICON);
|
|
3556
|
-
deleteIcon.setAttribute('title', this.localizedTexts('remove'));
|
|
3557
|
-
}
|
|
3558
|
-
const pauseIcon: Element = liElement.querySelector('.' + PAUSE_UPLOAD);
|
|
3559
|
-
if (pauseIcon) {
|
|
3560
|
-
pauseIcon.classList.add(RETRY_ICON);
|
|
3561
|
-
pauseIcon.classList.remove(PAUSE_UPLOAD);
|
|
3562
|
-
pauseIcon.setAttribute('title', this.localizedTexts('retry'));
|
|
3563
|
-
}
|
|
3564
|
-
if (!isNullOrUndefined(liElement) && !isNullOrUndefined(deleteIcon)
|
|
3565
|
-
&& !isNullOrUndefined(liElement.querySelector('.e-spinner-pane'))) {
|
|
3566
|
-
hideSpinner(spinnerTarget);
|
|
3567
|
-
detach(liElement.querySelector('.e-spinner-pane'));
|
|
3568
|
-
}
|
|
3569
|
-
}
|
|
3570
|
-
}
|
|
3571
|
-
|
|
3572
|
-
private pauseUpload(metaData: MetaData, e?: Event, custom?: boolean): void {
|
|
3573
|
-
metaData.file.statusCode = '4';
|
|
3574
|
-
metaData.file.status = this.localizedTexts('pause');
|
|
3575
|
-
this.updateMetaData(metaData);
|
|
3576
|
-
const eventArgs: PauseResumeEventArgs = {
|
|
3577
|
-
event: e ? e : null,
|
|
3578
|
-
file: metaData.file,
|
|
3579
|
-
chunkIndex: metaData.chunkIndex,
|
|
3580
|
-
chunkCount: Math.round(metaData.file.size / this.asyncSettings.chunkSize),
|
|
3581
|
-
chunkSize: this.asyncSettings.chunkSize
|
|
3582
|
-
};
|
|
3583
|
-
this.abortUpload(metaData, custom, eventArgs);
|
|
3584
|
-
if (this.sequentialUpload) {
|
|
3585
|
-
this.uploadSequential();
|
|
3586
|
-
}
|
|
3587
|
-
}
|
|
3588
|
-
|
|
3589
|
-
private abortUpload(metaData: MetaData, custom: boolean, eventArgs?: PauseResumeEventArgs): void {
|
|
3590
|
-
if (metaData.file.statusCode !== '4') {
|
|
3591
|
-
metaData.request.emitError = false;
|
|
3592
|
-
metaData.request.httpRequest.abort();
|
|
3593
|
-
}
|
|
3594
|
-
const liElement: HTMLElement = this.getLiElement(metaData.file);
|
|
3595
|
-
if (isNullOrUndefined(this.template) && (isNullOrUndefined(custom) || !custom) && liElement) {
|
|
3596
|
-
const targetElement: HTMLElement = liElement.querySelector('.' + PAUSE_UPLOAD) as HTMLElement;
|
|
3597
|
-
targetElement.classList.remove(PAUSE_UPLOAD);
|
|
3598
|
-
targetElement.classList.add(RESUME_UPLOAD);
|
|
3599
|
-
targetElement.setAttribute('title', this.localizedTexts('resume'));
|
|
3600
|
-
targetElement.nextElementSibling.classList.add(REMOVE_ICON);
|
|
3601
|
-
targetElement.nextElementSibling.classList.remove(ABORT_ICON);
|
|
3602
|
-
targetElement.nextElementSibling.setAttribute('title', this.localizedTexts('remove'));
|
|
3603
|
-
}
|
|
3604
|
-
for (let i: number = 0; i < this.pausedData.length; i++) {
|
|
3605
|
-
if (this.pausedData[i as number].file.name === metaData.file.name) {
|
|
3606
|
-
this.pausedData.splice(i, 1);
|
|
3607
|
-
}
|
|
3608
|
-
}
|
|
3609
|
-
this.pausedData.push(metaData);
|
|
3610
|
-
this.trigger('pausing', eventArgs);
|
|
3611
|
-
}
|
|
3612
|
-
private resumeUpload(metaData: MetaData, e?: Event, custom?: boolean): void {
|
|
3613
|
-
const liElement: HTMLElement = this.getLiElement(metaData.file);
|
|
3614
|
-
let targetElement: Element;
|
|
3615
|
-
if (!isNullOrUndefined(liElement)) {
|
|
3616
|
-
targetElement = liElement.querySelector('.' + RESUME_UPLOAD);
|
|
3617
|
-
}
|
|
3618
|
-
if (!isNullOrUndefined(targetElement) && (isNullOrUndefined(custom) || !custom)) {
|
|
3619
|
-
targetElement.classList.remove(RESUME_UPLOAD);
|
|
3620
|
-
targetElement.classList.add(PAUSE_UPLOAD);
|
|
3621
|
-
targetElement.setAttribute('title', this.localizedTexts('pause'));
|
|
3622
|
-
targetElement.nextElementSibling.classList.remove(REMOVE_ICON);
|
|
3623
|
-
targetElement.nextElementSibling.classList.add(ABORT_ICON);
|
|
3624
|
-
targetElement.nextElementSibling.setAttribute('title', this.localizedTexts('abort'));
|
|
3625
|
-
}
|
|
3626
|
-
metaData.file.status = this.localizedTexts('inProgress');
|
|
3627
|
-
metaData.file.statusCode = '3';
|
|
3628
|
-
this.updateMetaData(metaData);
|
|
3629
|
-
const eventArgs: PauseResumeEventArgs = {
|
|
3630
|
-
event: e ? e : null,
|
|
3631
|
-
file: metaData.file,
|
|
3632
|
-
chunkIndex: metaData.chunkIndex,
|
|
3633
|
-
chunkCount: Math.round(metaData.file.size / this.asyncSettings.chunkSize),
|
|
3634
|
-
chunkSize: this.asyncSettings.chunkSize
|
|
3635
|
-
};
|
|
3636
|
-
this.trigger('resuming', eventArgs);
|
|
3637
|
-
for (let i: number = 0; i < this.pausedData.length; i++ ) {
|
|
3638
|
-
if (this.pausedData[i as number].end === this.pausedData[i as number].file.size ) {
|
|
3639
|
-
this.chunkUploadComplete(e, metaData, custom);
|
|
3640
|
-
} else {
|
|
3641
|
-
if (this.pausedData[i as number].file.name === metaData.file.name) {
|
|
3642
|
-
this.pausedData[i as number].start = this.pausedData[i as number].end;
|
|
3643
|
-
this.pausedData[i as number].end = this.pausedData[i as number].end + this.asyncSettings.chunkSize;
|
|
3644
|
-
this.pausedData[i as number].end = Math.min(this.pausedData[i as number].end, this.pausedData[i as number].file.size);
|
|
3645
|
-
this.pausedData[i as number].chunkIndex = this.pausedData[i as number].chunkIndex + 1;
|
|
3646
|
-
this.sendRequest(this.pausedData[i as number].file, this.pausedData[i as number], custom);
|
|
3647
|
-
}
|
|
3648
|
-
}
|
|
3649
|
-
}
|
|
3650
|
-
}
|
|
3651
|
-
|
|
3652
|
-
private updateMetaData(metaData : MetaData): void {
|
|
3653
|
-
if (this.uploadMetaData.indexOf(metaData) === -1) {
|
|
3654
|
-
this.uploadMetaData.push(metaData);
|
|
3655
|
-
} else {
|
|
3656
|
-
this.uploadMetaData.splice(this.uploadMetaData.indexOf(metaData), 1);
|
|
3657
|
-
this.uploadMetaData.push(metaData);
|
|
3658
|
-
}
|
|
3659
|
-
}
|
|
3660
|
-
|
|
3661
|
-
private removeChunkProgressBar(metaData: MetaData): void {
|
|
3662
|
-
const liElement: HTMLElement = this.getLiElement(metaData.file);
|
|
3663
|
-
if (!isNullOrUndefined(liElement)) {
|
|
3664
|
-
this.updateProgressBarClasses(liElement, UPLOAD_SUCCESS);
|
|
3665
|
-
this.removeProgressbar(liElement, 'success');
|
|
3666
|
-
const cancelButton: Element = liElement.querySelector('.' + ABORT_ICON);
|
|
3667
|
-
if (!isNullOrUndefined(cancelButton)) {
|
|
3668
|
-
cancelButton.classList.add(DELETE_ICON);
|
|
3669
|
-
cancelButton.setAttribute('title', this.localizedTexts('delete'));
|
|
3670
|
-
cancelButton.classList.remove(ABORT_ICON, UPLOAD_INPROGRESS);
|
|
3671
|
-
}
|
|
3672
|
-
}
|
|
3673
|
-
}
|
|
3674
|
-
|
|
3675
|
-
private chunkUploadFailed(e: Event, metaData: MetaData, custom?: boolean): void {
|
|
3676
|
-
const chunkCount: number = Math.max(Math.ceil(metaData.file.size / this.asyncSettings.chunkSize), 1);
|
|
3677
|
-
let liElement : HTMLElement;
|
|
3678
|
-
if (isNullOrUndefined(this.template) && (isNullOrUndefined(custom) || !custom)) {
|
|
3679
|
-
liElement = this.getLiElement(metaData.file);
|
|
3680
|
-
}
|
|
3681
|
-
const requestResponse: Object = e && e.currentTarget ? this.getResponse(e) : null;
|
|
3682
|
-
const eventArgs: Object = {
|
|
3683
|
-
event: e,
|
|
3684
|
-
file: metaData.file,
|
|
3685
|
-
chunkIndex: metaData.chunkIndex,
|
|
3686
|
-
totalChunk: chunkCount,
|
|
3687
|
-
chunkSize: this.asyncSettings.chunkSize,
|
|
3688
|
-
cancel: false,
|
|
3689
|
-
response: requestResponse
|
|
3690
|
-
};
|
|
3691
|
-
this.trigger('chunkFailure', eventArgs, (eventArgs: Object) => {
|
|
3692
|
-
// To prevent triggering of failure event
|
|
3693
|
-
if (!(<any>eventArgs).cancel) {
|
|
3694
|
-
if (metaData.retryCount < this.asyncSettings.retryCount) {
|
|
3695
|
-
setTimeout(() => {
|
|
3696
|
-
this.retryRequest(liElement, metaData, custom);
|
|
3697
|
-
}, this.asyncSettings.retryAfterDelay);
|
|
3698
|
-
} else {
|
|
3699
|
-
if (!isNullOrUndefined(liElement)) {
|
|
3700
|
-
const pauseButton: Element = liElement.querySelector('.' + PAUSE_UPLOAD) ?
|
|
3701
|
-
liElement.querySelector('.' + PAUSE_UPLOAD) : liElement.querySelector('.' + RESUME_UPLOAD);
|
|
3702
|
-
if (!isNullOrUndefined(pauseButton)) {
|
|
3703
|
-
pauseButton.classList.add(RETRY_ICON);
|
|
3704
|
-
pauseButton.classList.remove(PAUSE_UPLOAD, RESUME_UPLOAD);
|
|
3705
|
-
}
|
|
3706
|
-
this.updateProgressBarClasses(liElement, UPLOAD_FAILED);
|
|
3707
|
-
this.removeProgressbar(liElement, 'failure');
|
|
3708
|
-
liElement.querySelector('.e-icons').classList.remove(UPLOAD_INPROGRESS);
|
|
3709
|
-
const iconElement: Element = liElement.querySelector('.' + ABORT_ICON) ?
|
|
3710
|
-
liElement.querySelector('.' + ABORT_ICON) : liElement.querySelector('.' + REMOVE_ICON);
|
|
3711
|
-
iconElement.classList.remove(ABORT_ICON);
|
|
3712
|
-
if (!isNullOrUndefined(liElement.querySelector('.' + PAUSE_UPLOAD))) {
|
|
3713
|
-
detach(liElement.querySelector('.' + PAUSE_UPLOAD));
|
|
3714
|
-
}
|
|
3715
|
-
if (metaData.start > 0) {
|
|
3716
|
-
iconElement.classList.add(DELETE_ICON);
|
|
3717
|
-
iconElement.setAttribute('title', this.localizedTexts('delete'));
|
|
3718
|
-
} else {
|
|
3719
|
-
iconElement.classList.add(REMOVE_ICON);
|
|
3720
|
-
iconElement.setAttribute('title', this.localizedTexts('remove'));
|
|
3721
|
-
}
|
|
3722
|
-
}
|
|
3723
|
-
metaData.retryCount = 0;
|
|
3724
|
-
const file: FileInfo = metaData.file;
|
|
3725
|
-
const failureMessage: string = this.localizedTexts('uploadFailedMessage');
|
|
3726
|
-
const args: Object = {
|
|
3727
|
-
e, response: requestResponse,
|
|
3728
|
-
operation: 'upload',
|
|
3729
|
-
file: this.updateStatus(file, failureMessage, '0', false),
|
|
3730
|
-
statusText: failureMessage
|
|
3731
|
-
};
|
|
3732
|
-
this.trigger('failure', args, (args: Object) => {
|
|
3733
|
-
this.updateStatus(file, (args as any).statusText, '0');
|
|
3734
|
-
this.uploadSequential();
|
|
3735
|
-
this.checkActionComplete(true);
|
|
3736
|
-
});
|
|
3737
|
-
}
|
|
3738
|
-
}
|
|
3739
|
-
});
|
|
3740
|
-
}
|
|
3741
|
-
|
|
3742
|
-
private retryRequest(liElement: HTMLElement, metaData: MetaData, custom?: boolean): void {
|
|
3743
|
-
if (isNullOrUndefined(this.template) && (isNullOrUndefined(custom) || !custom) && liElement) {
|
|
3744
|
-
this.updateProgressBarClasses(liElement, UPLOAD_FAILED);
|
|
3745
|
-
}
|
|
3746
|
-
if (metaData) {
|
|
3747
|
-
metaData.retryCount += 1;
|
|
3748
|
-
this.sendRequest(metaData.file, metaData);
|
|
3749
|
-
}
|
|
3750
|
-
}
|
|
3751
|
-
|
|
3752
|
-
private checkPausePlayAction(e: Event): void {
|
|
3753
|
-
const targetElement: HTMLElement = e.target as HTMLElement;
|
|
3754
|
-
const selectedElement: HTMLElement = (<HTMLInputElement>e.target).parentElement;
|
|
3755
|
-
const index: number = this.fileList.indexOf(selectedElement);
|
|
3756
|
-
const fileData: FileInfo = this.filesData[index as number];
|
|
3757
|
-
const metaData: MetaData = this.getCurrentMetaData(fileData);
|
|
3758
|
-
if (targetElement.classList.contains(PAUSE_UPLOAD)) {
|
|
3759
|
-
/* istanbul ignore next */
|
|
3760
|
-
this.pauseUpload(metaData, e);
|
|
3761
|
-
} else if (targetElement.classList.contains(RESUME_UPLOAD)) {
|
|
3762
|
-
/* istanbul ignore next */
|
|
3763
|
-
this.resumeUpload(metaData, e);
|
|
3764
|
-
} else if (targetElement.classList.contains(RETRY_ICON)) {
|
|
3765
|
-
if (metaData.file.status === this.localizedTexts('fileUploadCancel')) {
|
|
3766
|
-
this.retryUpload(metaData, false);
|
|
3767
|
-
} else {
|
|
3768
|
-
this.retryUpload(metaData, true);
|
|
3769
|
-
}
|
|
3770
|
-
}
|
|
3771
|
-
}
|
|
3772
|
-
|
|
3773
|
-
private retryUpload(metaData: MetaData, fromcanceledStage: boolean): void {
|
|
3774
|
-
if (fromcanceledStage) {
|
|
3775
|
-
metaData.end = metaData.end + this.asyncSettings.chunkSize;
|
|
3776
|
-
metaData.start = metaData.start + this.asyncSettings.chunkSize;
|
|
3777
|
-
this.sendRequest(metaData.file, metaData);
|
|
3778
|
-
} else {
|
|
3779
|
-
metaData.file.statusCode = '1';
|
|
3780
|
-
metaData.file.status = this.localizedTexts('readyToUploadMessage');
|
|
3781
|
-
this.chunkUpload(metaData.file);
|
|
3782
|
-
}
|
|
3783
|
-
/* istanbul ignore next */
|
|
3784
|
-
(this.getLiElement(metaData.file)).classList.add(RESTRICT_RETRY);
|
|
3785
|
-
}
|
|
3786
|
-
|
|
3787
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3788
|
-
private chunkUploadInProgress(e: ProgressEventInit, metaData: MetaData, custom?: boolean): void {
|
|
3789
|
-
if (metaData.file.statusCode === '4') {
|
|
3790
|
-
return;
|
|
3791
|
-
}
|
|
3792
|
-
if (metaData.file.statusCode !== '4' && metaData.file.statusCode !== '5') {
|
|
3793
|
-
metaData.file.statusCode = '3';
|
|
3794
|
-
metaData.file.status = this.localizedTexts('inProgress');
|
|
3795
|
-
}
|
|
3796
|
-
this.updateMetaData(metaData);
|
|
3797
|
-
const liElement: HTMLElement = this.getLiElement(metaData.file);
|
|
3798
|
-
if (isNullOrUndefined(liElement)) {
|
|
3799
|
-
return;
|
|
3800
|
-
}
|
|
3801
|
-
const retryElement: Element = liElement.querySelector('.' + RETRY_ICON);
|
|
3802
|
-
if (!isNullOrUndefined(retryElement)) {
|
|
3803
|
-
retryElement.classList.add(PAUSE_UPLOAD);
|
|
3804
|
-
retryElement.setAttribute('title', this.localizedTexts('pause'));
|
|
3805
|
-
retryElement.classList.remove(RETRY_ICON);
|
|
3806
|
-
}
|
|
3807
|
-
if (!isNullOrUndefined(liElement)) {
|
|
3808
|
-
if (!(liElement.querySelectorAll('.' + PROGRESS_WRAPPER).length > 0)) {
|
|
3809
|
-
const statusElement: Element = liElement.querySelector('.' + STATUS);
|
|
3810
|
-
if ( isNullOrUndefined(this.template)) {
|
|
3811
|
-
statusElement.classList.add(UPLOAD_INPROGRESS);
|
|
3812
|
-
statusElement.classList.remove(UPLOAD_FAILED);
|
|
3813
|
-
this.createProgressBar(liElement);
|
|
3814
|
-
this.updateProgressBarClasses(liElement, UPLOAD_INPROGRESS);
|
|
3815
|
-
}
|
|
3816
|
-
const clearIcon: Element = liElement.querySelector('.' + REMOVE_ICON) ? liElement.querySelector('.' + REMOVE_ICON) :
|
|
3817
|
-
liElement.querySelector('.' + DELETE_ICON);
|
|
3818
|
-
if (!isNullOrUndefined(clearIcon)) {
|
|
3819
|
-
clearIcon.classList.add(ABORT_ICON);
|
|
3820
|
-
clearIcon.setAttribute('title', this.localizedTexts('abort'));
|
|
3821
|
-
clearIcon.classList.remove(REMOVE_ICON);
|
|
3822
|
-
}
|
|
3823
|
-
}
|
|
3824
|
-
if (!isNaN(Math.round((e.loaded / e.total) * 100)) && isNullOrUndefined(this.template) && metaData.file.statusCode !== '4' ) {
|
|
3825
|
-
let progressVal: number;
|
|
3826
|
-
const totalChunks: number = Math.ceil(metaData.file.size / this.asyncSettings.chunkSize) - 1;
|
|
3827
|
-
if (this.asyncSettings.chunkSize && totalChunks) {
|
|
3828
|
-
progressVal = Math.round(metaData.chunkIndex / totalChunks * 100);
|
|
3829
|
-
this.changeProgressValue(liElement, progressVal.toString() + '%');
|
|
3830
|
-
}
|
|
3831
|
-
}
|
|
3832
|
-
if (metaData.chunkIndex === 0) {
|
|
3833
|
-
this.checkActionButtonStatus();
|
|
3834
|
-
}
|
|
3835
|
-
}
|
|
3836
|
-
if (isNullOrUndefined(liElement.querySelector('.' + PAUSE_UPLOAD)) && isNullOrUndefined(this.template)
|
|
3837
|
-
&& isNullOrUndefined(liElement.querySelector('.' + DELETE_ICON)) ) {
|
|
3838
|
-
this.pauseButton = this.createElement('span', {className: 'e-icons e-file-pause-btn', attrs: { 'tabindex': this.btnTabIndex }});
|
|
3839
|
-
if (this.browserName === 'msie') {
|
|
3840
|
-
this.pauseButton.classList.add('e-msie');
|
|
3841
|
-
}
|
|
3842
|
-
const abortIcon: Element = liElement.querySelector('.' + ABORT_ICON);
|
|
3843
|
-
abortIcon.parentElement.insertBefore(this.pauseButton, abortIcon);
|
|
3844
|
-
this.pauseButton.setAttribute('title', this.localizedTexts('pause'));
|
|
3845
|
-
this.pauseButton.addEventListener('click', (e: Event) => {
|
|
3846
|
-
this.checkPausePlayAction(e);
|
|
3847
|
-
}, false);
|
|
3848
|
-
}
|
|
3849
|
-
}
|
|
3850
|
-
|
|
3851
|
-
/**
|
|
3852
|
-
* It is used to convert bytes value into kilobytes or megabytes depending on the size based
|
|
3853
|
-
* on [binary prefix](https://en.wikipedia.org/wiki/Binary_prefix).
|
|
3854
|
-
*
|
|
3855
|
-
* @param { number } bytes - Specifies the file size in bytes.
|
|
3856
|
-
* @returns {string} - Returns the file size.
|
|
3857
|
-
*/
|
|
3858
|
-
public bytesToSize(bytes : number) : string {
|
|
3859
|
-
let i : number = -1;
|
|
3860
|
-
if (!bytes) {
|
|
3861
|
-
return '0.0 KB';
|
|
3862
|
-
}
|
|
3863
|
-
do {
|
|
3864
|
-
bytes = bytes / 1024;
|
|
3865
|
-
i++;
|
|
3866
|
-
} while (bytes > 99);
|
|
3867
|
-
if (i >= 2) {
|
|
3868
|
-
bytes = bytes * 1024;
|
|
3869
|
-
i = 1;
|
|
3870
|
-
}
|
|
3871
|
-
return Math.max(bytes, 0).toFixed(1) + ' ' + ['KB', 'MB'][i as number];
|
|
3872
|
-
}
|
|
3873
|
-
/**
|
|
3874
|
-
* Allows you to sort the file data alphabetically based on its file name clearly.
|
|
3875
|
-
*
|
|
3876
|
-
* @param { FileList } filesData - specifies the files data for upload.
|
|
3877
|
-
* @returns {File[]}
|
|
3878
|
-
*/
|
|
3879
|
-
/* istanbul ignore next */
|
|
3880
|
-
public sortFileList(filesData?: FileList): File[] {
|
|
3881
|
-
filesData = filesData ? filesData : this.sortFilesList;
|
|
3882
|
-
const files: FileList = filesData;
|
|
3883
|
-
const fileNames: string[] = [];
|
|
3884
|
-
for (let i: number = 0; i < files.length; i++) {
|
|
3885
|
-
fileNames.push(files[i as number].name);
|
|
3886
|
-
}
|
|
3887
|
-
const sortedFileNames: string[] = fileNames.sort();
|
|
3888
|
-
const sortedFilesData: File[] = [];
|
|
3889
|
-
for (const name of sortedFileNames) {
|
|
3890
|
-
for (let i: number = 0; i < files.length; i++) {
|
|
3891
|
-
if (name === files[i as number].name) {
|
|
3892
|
-
sortedFilesData.push(files[i as number]);
|
|
3893
|
-
}
|
|
3894
|
-
}
|
|
3895
|
-
}
|
|
3896
|
-
return sortedFilesData;
|
|
3897
|
-
}
|
|
3898
|
-
|
|
3899
|
-
/**
|
|
3900
|
-
* Removes the component from the DOM and detaches all its related event handlers. Also it removes the attributes and classes.
|
|
3901
|
-
*
|
|
3902
|
-
* @method destroy
|
|
3903
|
-
* @returns {void}
|
|
3904
|
-
*/
|
|
3905
|
-
public destroy(): void {
|
|
3906
|
-
this.element.value = null;
|
|
3907
|
-
this.clearTemplate();
|
|
3908
|
-
this.clearAll();
|
|
3909
|
-
this.unWireEvents();
|
|
3910
|
-
this.unBindDropEvents();
|
|
3911
|
-
if (this.multiple) {
|
|
3912
|
-
this.element.removeAttribute('multiple');
|
|
3913
|
-
}
|
|
3914
|
-
if (!this.enabled) {
|
|
3915
|
-
this.element.removeAttribute('disabled');
|
|
3916
|
-
}
|
|
3917
|
-
this.element.removeAttribute('accept');
|
|
3918
|
-
this.setInitialAttributes();
|
|
3919
|
-
const attributes: string[] = ['aria-label', 'directory', 'webkitdirectory', 'tabindex'];
|
|
3920
|
-
for (const key of attributes) {
|
|
3921
|
-
this.element.removeAttribute(key);
|
|
3922
|
-
}
|
|
3923
|
-
if (!isNullOrUndefined(this.uploadWrapper)) {
|
|
3924
|
-
this.uploadWrapper.parentElement.appendChild(this.element);
|
|
3925
|
-
detach(this.uploadWrapper);
|
|
3926
|
-
}
|
|
3927
|
-
this.uploadWrapper = null;
|
|
3928
|
-
this.uploadWrapper = null;
|
|
3929
|
-
this.browseButton = null;
|
|
3930
|
-
this.dropAreaWrapper = null;
|
|
3931
|
-
this.dropZoneElement = null;
|
|
3932
|
-
this.dropArea = null;
|
|
3933
|
-
this.keyboardModule = null;
|
|
3934
|
-
this.clearButton = null;
|
|
3935
|
-
this.uploadButton = null;
|
|
3936
|
-
super.destroy();
|
|
3937
|
-
}
|
|
3938
|
-
|
|
3939
|
-
/**
|
|
3940
|
-
* Allows you to call the upload process manually by calling save URL action.
|
|
3941
|
-
* To process the selected files (added in upload queue), pass an empty argument otherwise
|
|
3942
|
-
* upload the specific file based on its argument.
|
|
3943
|
-
*
|
|
3944
|
-
* @param { FileInfo | FileInfo[] } files - Specifies the files data for upload.
|
|
3945
|
-
* @param {boolean} custom - Specifies whether the uploader is rendered with custom file list.
|
|
3946
|
-
* @returns {void}
|
|
3947
|
-
*/
|
|
3948
|
-
public upload(files?: FileInfo | FileInfo[], custom?: boolean): void {
|
|
3949
|
-
files = files ? files : this.filesData;
|
|
3950
|
-
if (this.sequentialUpload && (this.isFirstFileOnSelection || custom)) {
|
|
3951
|
-
this.sequenceUpload(files as FileInfo[]);
|
|
3952
|
-
} else {
|
|
3953
|
-
const uploadFiles: FileInfo[] = this.getFilesInArray(files);
|
|
3954
|
-
const eventArgs: BeforeUploadEventArgs = {
|
|
3955
|
-
customFormData: [],
|
|
3956
|
-
currentRequest: null,
|
|
3957
|
-
cancel: false
|
|
3958
|
-
};
|
|
3959
|
-
this.trigger('beforeUpload', eventArgs, (eventArgs: BeforeUploadEventArgs) => {
|
|
3960
|
-
if (!eventArgs.cancel) {
|
|
3961
|
-
this.customFormDatas = (eventArgs.customFormData && eventArgs.customFormData.length > 0) ?
|
|
3962
|
-
eventArgs.customFormData : this.customFormDatas;
|
|
3963
|
-
this.uploadFiles(uploadFiles, custom);
|
|
3964
|
-
}
|
|
3965
|
-
});
|
|
3966
|
-
}
|
|
3967
|
-
}
|
|
3968
|
-
private getFilesInArray(files: FileInfo | FileInfo[]): FileInfo[] {
|
|
3969
|
-
let uploadFiles: FileInfo[] = [];
|
|
3970
|
-
if (files) {
|
|
3971
|
-
if (files instanceof Array) {
|
|
3972
|
-
uploadFiles = files;
|
|
3973
|
-
} else {
|
|
3974
|
-
uploadFiles.push(files);
|
|
3975
|
-
}
|
|
3976
|
-
}
|
|
3977
|
-
return uploadFiles;
|
|
3978
|
-
}
|
|
3979
|
-
|
|
3980
|
-
/* istanbul ignore next */
|
|
3981
|
-
private serverReadFileBase64(fileIndex: number, position: number, totalCount: number) : Promise<string> {
|
|
3982
|
-
return new Promise((resolve: Function, reject: Function) => {
|
|
3983
|
-
const file: Blob = this.fileStreams[fileIndex as number].rawFile as Blob;
|
|
3984
|
-
try {
|
|
3985
|
-
const reader: FileReader = new FileReader();
|
|
3986
|
-
reader.onload = ((args: any) => {
|
|
3987
|
-
return () => {
|
|
3988
|
-
try {
|
|
3989
|
-
const contents: string = args.result as string;
|
|
3990
|
-
const data: string = contents ? contents.split(';base64,')[1] : null;
|
|
3991
|
-
resolve(data);
|
|
3992
|
-
} catch (e) {
|
|
3993
|
-
reject(e);
|
|
3994
|
-
}
|
|
3995
|
-
};
|
|
3996
|
-
})(reader);
|
|
3997
|
-
reader.readAsDataURL(file.slice(position, position + totalCount));
|
|
3998
|
-
} catch (e) {
|
|
3999
|
-
reject(e);
|
|
4000
|
-
}
|
|
4001
|
-
});
|
|
4002
|
-
}
|
|
4003
|
-
|
|
4004
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
4005
|
-
/* istanbul ignore next */
|
|
4006
|
-
private uploadFileCount(ele: Element): number {
|
|
4007
|
-
/* eslint-enable @typescript-eslint/no-unused-vars */
|
|
4008
|
-
const files: FileInfo[] = this.filesData;
|
|
4009
|
-
if (!files || files.length === 0) {
|
|
4010
|
-
return -1;
|
|
4011
|
-
}
|
|
4012
|
-
const result: number = files.length;
|
|
4013
|
-
return result;
|
|
4014
|
-
}
|
|
4015
|
-
|
|
4016
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
4017
|
-
/* istanbul ignore next */
|
|
4018
|
-
private getFileRead(index: number, ele: Element): number {
|
|
4019
|
-
/* eslint-enable @typescript-eslint/no-unused-vars */
|
|
4020
|
-
const files: FileInfo[] = this.filesData;
|
|
4021
|
-
if (!files || files.length === 0) {
|
|
4022
|
-
return -1;
|
|
4023
|
-
}
|
|
4024
|
-
const file: FileInfo = files[index as number];
|
|
4025
|
-
const fileCount: number = this.newFileRef++;
|
|
4026
|
-
this.fileStreams[fileCount as number] = file;
|
|
4027
|
-
return fileCount;
|
|
4028
|
-
}
|
|
4029
|
-
|
|
4030
|
-
private uploadFiles(files: FileInfo[], custom?: boolean): void {
|
|
4031
|
-
let selectedFiles: FileInfo[] = [];
|
|
4032
|
-
if (this.asyncSettings.saveUrl === '' || isNullOrUndefined(this.asyncSettings.saveUrl)) {
|
|
4033
|
-
return;
|
|
4034
|
-
}
|
|
4035
|
-
if (!custom || isNullOrUndefined(custom)) {
|
|
4036
|
-
if (!this.multiple) {
|
|
4037
|
-
const file: FileInfo[] = [];
|
|
4038
|
-
file.push(files[0]);
|
|
4039
|
-
selectedFiles = this.filterfileList(file);
|
|
4040
|
-
} else {
|
|
4041
|
-
selectedFiles = this.filterfileList(files);
|
|
4042
|
-
}
|
|
4043
|
-
} else {
|
|
4044
|
-
selectedFiles = files;
|
|
4045
|
-
}
|
|
4046
|
-
for (let i: number = 0; i < selectedFiles.length; i++) {
|
|
4047
|
-
this.uploadFilesRequest(selectedFiles, i, custom);
|
|
4048
|
-
}
|
|
4049
|
-
}
|
|
4050
|
-
|
|
4051
|
-
private uploadFilesRequest(selectedFiles: FileInfo[], i: number, custom?: boolean): void {
|
|
4052
|
-
const chunkEnabled: boolean = this.checkChunkUpload();
|
|
4053
|
-
const ajax: Ajax = new Ajax(this.asyncSettings.saveUrl, 'POST', true, null);
|
|
4054
|
-
ajax.emitError = false;
|
|
4055
|
-
const eventArgs: UploadingEventArgs = {
|
|
4056
|
-
fileData: selectedFiles[i as number],
|
|
4057
|
-
customFormData: [],
|
|
4058
|
-
cancel: false
|
|
4059
|
-
};
|
|
4060
|
-
const formData: FormData = new FormData();
|
|
4061
|
-
ajax.beforeSend = (e: BeforeSendEventArgs) => {
|
|
4062
|
-
eventArgs.currentRequest = ajax.httpRequest;
|
|
4063
|
-
this.trigger('uploading', eventArgs, (eventArgs: UploadingEventArgs) => {
|
|
4064
|
-
/* istanbul ignore next */
|
|
4065
|
-
if (eventArgs.cancel) {
|
|
4066
|
-
this.eventCancelByArgs(e, eventArgs, selectedFiles[i as number]);
|
|
4067
|
-
}
|
|
4068
|
-
if (this.customFormDatas && this.customFormDatas.length > 0) {
|
|
4069
|
-
this.updateFormData(formData, this.customFormDatas);
|
|
4070
|
-
}
|
|
4071
|
-
this.updateFormData(formData, eventArgs.customFormData);
|
|
4072
|
-
});
|
|
4073
|
-
};
|
|
4074
|
-
if (selectedFiles[i as number].statusCode === '1') {
|
|
4075
|
-
const name: string = this.element.getAttribute('name');
|
|
4076
|
-
formData.append(name, selectedFiles[i as number].rawFile, selectedFiles[i as number].name);
|
|
4077
|
-
if (chunkEnabled && selectedFiles[i as number].size > this.asyncSettings.chunkSize) {
|
|
4078
|
-
this.chunkUpload(selectedFiles[i as number], custom, i);
|
|
4079
|
-
} else {
|
|
4080
|
-
ajax.onLoad = (e: Event): object => {
|
|
4081
|
-
if (eventArgs.cancel) {
|
|
4082
|
-
return {};
|
|
4083
|
-
} else {
|
|
4084
|
-
this.uploadComplete(e, selectedFiles[i as number], custom);
|
|
4085
|
-
return {};
|
|
4086
|
-
}
|
|
4087
|
-
};
|
|
4088
|
-
ajax.onUploadProgress = (e: Event): object => {
|
|
4089
|
-
if (eventArgs.cancel) {
|
|
4090
|
-
return {};
|
|
4091
|
-
} else {
|
|
4092
|
-
this.uploadInProgress(e, selectedFiles[i as number], custom, ajax);
|
|
4093
|
-
return {};
|
|
4094
|
-
}
|
|
4095
|
-
};
|
|
4096
|
-
/* istanbul ignore next */
|
|
4097
|
-
ajax.onError = (e: Event) => {
|
|
4098
|
-
this.uploadFailed(e, selectedFiles[i as number]); return {};
|
|
4099
|
-
};
|
|
4100
|
-
ajax.send(formData);
|
|
4101
|
-
}
|
|
4102
|
-
}
|
|
4103
|
-
}
|
|
4104
|
-
|
|
4105
|
-
private spliceFiles(liIndex: number): void {
|
|
4106
|
-
const liElement: HTMLElement = this.fileList[liIndex as number];
|
|
4107
|
-
const allFiles: FileInfo[] = this.getFilesData();
|
|
4108
|
-
const nameElements: number = +liElement.getAttribute('data-files-count');
|
|
4109
|
-
let startIndex: number = 0 ;
|
|
4110
|
-
for (let i: number = 0; i < liIndex; i++ ) {
|
|
4111
|
-
startIndex += (+this.fileList[i as number].getAttribute('data-files-count'));
|
|
4112
|
-
}
|
|
4113
|
-
const endIndex: number = (startIndex + nameElements) - 1;
|
|
4114
|
-
for (let j: number = endIndex; j >= startIndex; j--) {
|
|
4115
|
-
allFiles.splice(j, 1);
|
|
4116
|
-
}
|
|
4117
|
-
}
|
|
4118
|
-
/* eslint-disable valid-jsdoc, jsdoc/require-param */
|
|
4119
|
-
/**
|
|
4120
|
-
* Remove the uploaded file from server manually by calling the remove URL action.
|
|
4121
|
-
* If you pass an empty argument to this method, the complete file list can be cleared,
|
|
4122
|
-
* otherwise remove the specific file based on its argument (“file_data”).
|
|
4123
|
-
*
|
|
4124
|
-
* @param { FileInfo | FileInfo[] } fileData - specifies the files data to remove from file list/server.
|
|
4125
|
-
* @param { boolean } customTemplate - Set true if the component rendering with customize template.
|
|
4126
|
-
* @param { boolean } removeDirectly - Set true if files remove without removing event.
|
|
4127
|
-
* @param { boolean } postRawFile - Set false, to post file name only to the remove action.
|
|
4128
|
-
* @returns {void}
|
|
4129
|
-
*/
|
|
4130
|
-
public remove(
|
|
4131
|
-
fileData?: FileInfo | FileInfo[], customTemplate?: boolean, removeDirectly?: boolean,
|
|
4132
|
-
postRawFile?: boolean, args?: MouseEvent | TouchEvent | KeyboardEventArgs): void {
|
|
4133
|
-
if (isNullOrUndefined(postRawFile)) {
|
|
4134
|
-
postRawFile = true;
|
|
4135
|
-
}
|
|
4136
|
-
const eventArgs: RemovingEventArgs = {
|
|
4137
|
-
event: args,
|
|
4138
|
-
cancel: false,
|
|
4139
|
-
filesData: [],
|
|
4140
|
-
customFormData: [],
|
|
4141
|
-
postRawFile: postRawFile,
|
|
4142
|
-
currentRequest: null
|
|
4143
|
-
};
|
|
4144
|
-
const beforeEventArgs: BeforeRemoveEventArgs = {
|
|
4145
|
-
cancel: false,
|
|
4146
|
-
customFormData: [],
|
|
4147
|
-
currentRequest: null
|
|
4148
|
-
};
|
|
4149
|
-
this.trigger('beforeRemove', beforeEventArgs, (beforeEventArgs: BeforeRemoveEventArgs) => {
|
|
4150
|
-
if (!beforeEventArgs.cancel) {
|
|
4151
|
-
if (this.isFormUpload()) {
|
|
4152
|
-
eventArgs.filesData = fileData as FileInfo[];
|
|
4153
|
-
this.trigger('removing', eventArgs, (eventArgs: RemovingEventArgs) => {
|
|
4154
|
-
if (!eventArgs.cancel) {
|
|
4155
|
-
const removingFiles: FileInfo[] = this.getFilesInArray(fileData);
|
|
4156
|
-
let isLiRemoved: boolean = false;
|
|
4157
|
-
let liIndex: number;
|
|
4158
|
-
for (const data of removingFiles) {
|
|
4159
|
-
if (!isLiRemoved) {
|
|
4160
|
-
liIndex = this.fileList.indexOf(data.list);
|
|
4161
|
-
}
|
|
4162
|
-
if (liIndex > -1) {
|
|
4163
|
-
const inputElement: HTMLElement = !isNullOrUndefined(data.input) ? data.input : null;
|
|
4164
|
-
if (inputElement) {
|
|
4165
|
-
detach(inputElement);
|
|
4166
|
-
}
|
|
4167
|
-
this.spliceFiles(liIndex);
|
|
4168
|
-
detach(this.fileList[liIndex as number]);
|
|
4169
|
-
this.fileList.splice(liIndex, 1);
|
|
4170
|
-
isLiRemoved = true;
|
|
4171
|
-
liIndex = -1;
|
|
4172
|
-
}
|
|
4173
|
-
}
|
|
4174
|
-
}
|
|
4175
|
-
});
|
|
4176
|
-
} else if (this.isForm && (isNullOrUndefined(this.asyncSettings.removeUrl) || this.asyncSettings.removeUrl === '')) {
|
|
4177
|
-
eventArgs.filesData = this.getFilesData();
|
|
4178
|
-
this.trigger('removing', eventArgs, (eventArgs: RemovingEventArgs) => {
|
|
4179
|
-
if (!eventArgs.cancel) {
|
|
4180
|
-
this.clearAll();
|
|
4181
|
-
}
|
|
4182
|
-
});
|
|
4183
|
-
} else {
|
|
4184
|
-
let removeFiles: FileInfo[] = [];
|
|
4185
|
-
fileData = !isNullOrUndefined(fileData) ? fileData : this.filesData;
|
|
4186
|
-
if (fileData instanceof Array) {
|
|
4187
|
-
removeFiles = fileData;
|
|
4188
|
-
} else {
|
|
4189
|
-
removeFiles.push(fileData);
|
|
4190
|
-
}
|
|
4191
|
-
eventArgs.filesData = removeFiles;
|
|
4192
|
-
const removeUrl: string = this.asyncSettings.removeUrl;
|
|
4193
|
-
const validUrl: boolean = (removeUrl === '' || isNullOrUndefined(removeUrl)) ? false : true;
|
|
4194
|
-
for (const files of removeFiles) {
|
|
4195
|
-
const fileUploadedIndex : number = this.uploadedFilesData.indexOf(files);
|
|
4196
|
-
if ((files.statusCode === '2' || files.statusCode === '4' || (files.statusCode === '0' &&
|
|
4197
|
-
fileUploadedIndex !== -1)) && validUrl) {
|
|
4198
|
-
this.removeUploadedFile(files, eventArgs, removeDirectly, customTemplate);
|
|
4199
|
-
} else {
|
|
4200
|
-
if (!removeDirectly) {
|
|
4201
|
-
this.trigger('removing', eventArgs, (eventArgs: RemovingEventArgs) => {
|
|
4202
|
-
if (!eventArgs.cancel) {
|
|
4203
|
-
this.removeFilesData(files, customTemplate);
|
|
4204
|
-
}
|
|
4205
|
-
});
|
|
4206
|
-
} else {
|
|
4207
|
-
this.removeFilesData(files, customTemplate);
|
|
4208
|
-
}
|
|
4209
|
-
}
|
|
4210
|
-
if (args && !(args.target as Element).classList.contains(REMOVE_ICON)) {
|
|
4211
|
-
this.checkActionComplete(false);
|
|
4212
|
-
}
|
|
4213
|
-
}
|
|
4214
|
-
}
|
|
4215
|
-
}
|
|
4216
|
-
});
|
|
4217
|
-
}
|
|
4218
|
-
/* eslint-enable valid-jsdoc, jsdoc/require-param */
|
|
4219
|
-
/**
|
|
4220
|
-
* Clear all the file entries from list that can be uploaded files or added in upload queue.
|
|
4221
|
-
*
|
|
4222
|
-
* @returns {void}
|
|
4223
|
-
*/
|
|
4224
|
-
public clearAll(): void {
|
|
4225
|
-
if (isNullOrUndefined(this.listParent)) {
|
|
4226
|
-
if (this.browserName !== 'msie') {
|
|
4227
|
-
this.element.value = '';
|
|
4228
|
-
}
|
|
4229
|
-
this.filesData = [];
|
|
4230
|
-
return;
|
|
4231
|
-
}
|
|
4232
|
-
const eventArgs: ClearingEventArgs = {
|
|
4233
|
-
cancel: false,
|
|
4234
|
-
filesData: this.filesData
|
|
4235
|
-
};
|
|
4236
|
-
this.trigger('clearing', eventArgs, (eventArgs: ClearingEventArgs) => {
|
|
4237
|
-
if (!eventArgs.cancel) {
|
|
4238
|
-
this.clearData();
|
|
4239
|
-
this.actionCompleteCount = 0;
|
|
4240
|
-
this.count = -1;
|
|
4241
|
-
}
|
|
4242
|
-
});
|
|
4243
|
-
}
|
|
4244
|
-
/* eslint-disable valid-jsdoc, jsdoc/require-returns-description */
|
|
4245
|
-
/**
|
|
4246
|
-
* Get the data of files which are shown in file list.
|
|
4247
|
-
*
|
|
4248
|
-
* @param { number } index - specifies the file list item(li) index.
|
|
4249
|
-
* @returns {FileInfo[]}
|
|
4250
|
-
*/
|
|
4251
|
-
public getFilesData(index?: number): FileInfo[] {
|
|
4252
|
-
if (isNullOrUndefined(index)) {
|
|
4253
|
-
return this.filesData;
|
|
4254
|
-
} else {
|
|
4255
|
-
return this.getSelectedFiles(index);
|
|
4256
|
-
}
|
|
4257
|
-
}
|
|
4258
|
-
/* eslint-enable valid-jsdoc, jsdoc/require-returns-description */
|
|
4259
|
-
/**
|
|
4260
|
-
* Pauses the in-progress chunked upload based on the file data.
|
|
4261
|
-
*
|
|
4262
|
-
* @param { FileInfo | FileInfo[] } fileData - specifies the files data to pause from uploading.
|
|
4263
|
-
* @param { boolean } custom - Set true if used custom UI.
|
|
4264
|
-
* @returns {void}
|
|
4265
|
-
*/
|
|
4266
|
-
public pause(fileData?: FileInfo | FileInfo[], custom?: boolean): void {
|
|
4267
|
-
fileData = fileData ? fileData : this.filesData;
|
|
4268
|
-
const fileDataFiles: FileInfo[] = this.getFilesInArray(fileData);
|
|
4269
|
-
this.pauseUploading(fileDataFiles, custom);
|
|
4270
|
-
}
|
|
4271
|
-
private pauseUploading(fileData: FileInfo[], custom?: boolean): void {
|
|
4272
|
-
const files: FileInfo[] = this.getFiles(fileData);
|
|
4273
|
-
for (let i: number = 0; i < files.length; i++) {
|
|
4274
|
-
if (files[i as number].statusCode === '3') {
|
|
4275
|
-
this.pauseUpload(this.getCurrentMetaData(files[i as number], null), null, custom);
|
|
4276
|
-
}
|
|
4277
|
-
}
|
|
4278
|
-
}
|
|
4279
|
-
|
|
4280
|
-
private getFiles (fileData: FileInfo[]) : FileInfo[] {
|
|
4281
|
-
let files: FileInfo[] = [];
|
|
4282
|
-
if (!isNullOrUndefined(fileData) && !(fileData instanceof Array)) {
|
|
4283
|
-
files.push(fileData);
|
|
4284
|
-
} else {
|
|
4285
|
-
files = fileData;
|
|
4286
|
-
}
|
|
4287
|
-
return files;
|
|
4288
|
-
}
|
|
4289
|
-
|
|
4290
|
-
/**
|
|
4291
|
-
* Resumes the chunked upload that is previously paused based on the file data.
|
|
4292
|
-
*
|
|
4293
|
-
* @param { FileInfo | FileInfo[] } fileData - specifies the files data to resume the paused file.
|
|
4294
|
-
* @param { boolean } custom - Set true if used custom UI.
|
|
4295
|
-
* @returns {void}
|
|
4296
|
-
*/
|
|
4297
|
-
public resume(fileData?: FileInfo | FileInfo[], custom?: boolean): void {
|
|
4298
|
-
fileData = fileData ? fileData : this.filesData;
|
|
4299
|
-
const fileDataFiles: FileInfo[] = this.getFilesInArray(fileData);
|
|
4300
|
-
this.resumeFiles(fileDataFiles, custom);
|
|
4301
|
-
}
|
|
4302
|
-
|
|
4303
|
-
private resumeFiles(fileData: FileInfo[], custom?: boolean): void {
|
|
4304
|
-
const files: FileInfo[] = this.getFiles(fileData);
|
|
4305
|
-
for (let i: number = 0; i < files.length; i++) {
|
|
4306
|
-
if (files[i as number].statusCode === '4') {
|
|
4307
|
-
this.resumeUpload(this.getCurrentMetaData(files[i as number], null), null, custom);
|
|
4308
|
-
}
|
|
4309
|
-
}
|
|
4310
|
-
}
|
|
4311
|
-
|
|
4312
|
-
/**
|
|
4313
|
-
* Retries the canceled or failed file upload based on the file data.
|
|
4314
|
-
*
|
|
4315
|
-
* @param { FileInfo | FileInfo[] } fileData - specifies the files data to retry the canceled or failed file.
|
|
4316
|
-
* @param { boolean } fromcanceledStage - Set true to retry from canceled stage and set false to retry from initial stage.
|
|
4317
|
-
* @param {boolean} custom -Specifies whether the uploader is rendered with custom file list.
|
|
4318
|
-
* @returns {void}
|
|
4319
|
-
*/
|
|
4320
|
-
public retry(fileData?: FileInfo | FileInfo[], fromcanceledStage?: boolean, custom?: boolean): void {
|
|
4321
|
-
fileData = fileData ? fileData : this.filesData;
|
|
4322
|
-
const fileDataFiles: FileInfo[] = this.getFilesInArray(fileData);
|
|
4323
|
-
if (this.sequentialUpload && this.isFirstFileOnSelection) {
|
|
4324
|
-
this.isFirstFileOnSelection = false;
|
|
4325
|
-
}
|
|
4326
|
-
this.retryFailedFiles(fileDataFiles, fromcanceledStage, custom);
|
|
4327
|
-
}
|
|
4328
|
-
|
|
4329
|
-
private retryFailedFiles(fileData: FileInfo[], fromcanceledStage: boolean, custom: boolean): void {
|
|
4330
|
-
const files: FileInfo[] = this.getFiles(fileData);
|
|
4331
|
-
for (let i: number = 0; i < files.length; i++) {
|
|
4332
|
-
if (files[i as number].statusCode === '5' || files[i as number].statusCode === '0') {
|
|
4333
|
-
if (this.asyncSettings.chunkSize > 0 && this.getCurrentMetaData(files[i as number], null)) {
|
|
4334
|
-
this.retryUpload(this.getCurrentMetaData(files[i as number], null), fromcanceledStage);
|
|
4335
|
-
} else {
|
|
4336
|
-
let liElement: HTMLElement;
|
|
4337
|
-
if (!custom) {
|
|
4338
|
-
liElement = this.fileList[this.filesData.indexOf(files[i as number])];
|
|
4339
|
-
}
|
|
4340
|
-
this.reloadcanceledFile(null, files[i as number], liElement, custom);
|
|
4341
|
-
}
|
|
4342
|
-
}
|
|
4343
|
-
}
|
|
4344
|
-
}
|
|
4345
|
-
|
|
4346
|
-
/**
|
|
4347
|
-
* Stops the in-progress chunked upload based on the file data.
|
|
4348
|
-
* When the file upload is canceled, the partially uploaded file is removed from server.
|
|
4349
|
-
*
|
|
4350
|
-
* @param { FileInfo | FileInfo[] } fileData - specifies the files data to cancel the progressing file.
|
|
4351
|
-
* @returns {void}
|
|
4352
|
-
*/
|
|
4353
|
-
public cancel(fileData?: FileInfo[]): void {
|
|
4354
|
-
fileData = fileData ? fileData : this.filesData;
|
|
4355
|
-
const cancelingFiles: FileInfo[] = this.getFilesInArray(fileData);
|
|
4356
|
-
this.cancelUpload(cancelingFiles);
|
|
4357
|
-
}
|
|
4358
|
-
|
|
4359
|
-
private cancelUpload(fileData: FileInfo[]): void {
|
|
4360
|
-
const files: FileInfo[] = this.getFiles(fileData);
|
|
4361
|
-
if (this.asyncSettings.chunkSize > 0) {
|
|
4362
|
-
for (let i: number = 0; i < files.length; i++) {
|
|
4363
|
-
if (files[i as number].statusCode === '3') {
|
|
4364
|
-
const metaData: MetaData = this.getCurrentMetaData(files[i as number], null);
|
|
4365
|
-
metaData.file.statusCode = '5';
|
|
4366
|
-
metaData.file.status = this.localizedTexts('fileUploadCancel');
|
|
4367
|
-
this.updateMetaData(metaData);
|
|
4368
|
-
this.showHideUploadSpinner(files[i as number]);
|
|
4369
|
-
}
|
|
4370
|
-
}
|
|
4371
|
-
} else {
|
|
4372
|
-
for (let i: number = 0; i < files.length; i++) {
|
|
4373
|
-
if (files[i as number].statusCode === '3') {
|
|
4374
|
-
files[i as number].statusCode = '5';
|
|
4375
|
-
files[i as number].status = this.localizedTexts('fileUploadCancel');
|
|
4376
|
-
this.showHideUploadSpinner(files[i as number]);
|
|
4377
|
-
}
|
|
4378
|
-
}
|
|
4379
|
-
}
|
|
4380
|
-
}
|
|
4381
|
-
|
|
4382
|
-
private showHideUploadSpinner(files: FileInfo): void {
|
|
4383
|
-
const liElement: HTMLElement = this.getLiElement(files);
|
|
4384
|
-
if (!isNullOrUndefined(liElement) && isNullOrUndefined(this.template)) {
|
|
4385
|
-
const spinnerTarget: HTMLElement = liElement.querySelector('.' + ABORT_ICON) as HTMLElement;
|
|
4386
|
-
createSpinner({ target: spinnerTarget , width: '20px' });
|
|
4387
|
-
showSpinner(spinnerTarget);
|
|
4388
|
-
}
|
|
4389
|
-
}
|
|
4390
|
-
}
|
|
4391
|
-
/* eslint-enable @typescript-eslint/no-explicit-any */
|