@@ -7,6 +7,14 @@ export class FileInput extends Component {
7
7
/** @type {string } Use this as selector to instantiate the file input. */
8
8
static selector = '.file-input'
9
9
10
+ /**
11
+ * Get configured maximum filesize from 'data-max-size' and use in node.
12
+ * @returns {number } Maximum file size.
13
+ */
14
+ getLimit ( ) {
15
+ return parseInt ( this . getInput ( ) . dataset . maxSize )
16
+ }
17
+
10
18
/**
11
19
* Returns the card (drop zone) associated with the file input.
12
20
* @return {HTMLDivElement }
@@ -23,6 +31,22 @@ export class FileInput extends Component {
23
31
return this . node . querySelector ( `${ FileInput . selector } __input` )
24
32
}
25
33
34
+ /**
35
+ * Return the label when zero files are selected.
36
+ * @return HTMLInputElement
37
+ */
38
+ getLabelEmpty ( ) {
39
+ return this . node . querySelector ( `${ FileInput . selector } __label-empty` )
40
+ }
41
+
42
+ /**
43
+ * Return the label if more than 0 files are selected.
44
+ * @return HTMLInputElement
45
+ */
46
+ getLabelSelected ( ) {
47
+ return this . node . querySelector ( `${ FileInput . selector } __label-selected` )
48
+ }
49
+
26
50
/**
27
51
* Return the element associated with the files section.
28
52
* @return {HTMLDivElement }
@@ -39,6 +63,14 @@ export class FileInput extends Component {
39
63
return this . node . querySelector ( `${ FileInput . selector } .file-list__list` )
40
64
}
41
65
66
+ /**
67
+ * Returns the element outside of this component, which prompts the user to delete file-items that exceed the limit.
68
+ * @return {HTMLDivElement }
69
+ */
70
+ getFormNonFieldError ( ) {
71
+ return document . querySelector ( '.form__non-field-error' )
72
+ }
73
+
42
74
/**
43
75
* Binds events to callbacks.
44
76
* Callbacks should trigger `setState` which in turn triggers `render`.
@@ -90,13 +122,15 @@ export class FileInput extends Component {
90
122
91
123
/**
92
124
* Gets called when dragging starts on the card (drop zone).
125
+ * @param {Event } e
93
126
*/
94
- onDragEnter ( e ) {
127
+ onDragEnter ( ) {
95
128
this . node . classList . add ( 'file-input--drag-active' )
96
129
}
97
130
98
131
/**
99
132
* Gets called when dragging ends on the card (drop zone).
133
+ * @param {Event } e
100
134
*/
101
135
onDragLeave ( e ) {
102
136
if ( e . target !== this . getCard ( ) ) {
@@ -106,8 +140,7 @@ export class FileInput extends Component {
106
140
}
107
141
108
142
/**
109
- * Gets called when click event is received on the files list, it originates from a delete button, handle the deletion
110
- * accordingly.
143
+ * Gets called when click event is received on the files list, it originates from a delete button, handle the deletion accordingly.
111
144
* @param {PointerEvent } e
112
145
*/
113
146
onClick ( e ) {
@@ -164,10 +197,14 @@ export class FileInput extends Component {
164
197
render ( ) {
165
198
const { files } = this . getInput ( )
166
199
const filesSection = this . getFilesSection ( )
200
+ const additionalLabel = this . getLabelSelected ( )
201
+ const emptyLabel = this . getLabelEmpty ( )
167
202
168
- // Only show files section when files are selected.
169
- filesSection . setAttribute ( 'hidden' , true )
170
- files . length && filesSection . removeAttribute ( 'hidden' )
203
+ // Only show these sections when files are selected.
204
+ filesSection . toggleAttribute ( 'hidden' , ! files . length )
205
+ additionalLabel . toggleAttribute ( 'hidden' , ! files . length )
206
+ // Hide label when no files are selected
207
+ emptyLabel . toggleAttribute ( 'hidden' , files . length > 0 )
171
208
172
209
// Populate the file list.
173
210
const html = [ ...files ] . map ( ( file ) => this . renderFileHTML ( file ) ) . join ( '' )
@@ -184,27 +221,50 @@ export class FileInput extends Component {
184
221
const ext = name . split ( '.' ) . pop ( ) . toUpperCase ( )
185
222
const sizeMB = ( size / ( 1024 * 1024 ) ) . toFixed ( 2 )
186
223
const labelDelete = this . getFilesList ( ) . dataset . labelDelete || 'Delete'
224
+ const getFormNonFieldError = this . getFormNonFieldError ( )
225
+
226
+ // Only show errors notification if data-max-file-size is exceeded + add error class to file-list
227
+ const maxMegabytes = this . getLimit ( )
187
228
188
- return `
229
+ const htmlStart = `
189
230
<li class="file-list__list-item">
190
231
<aside class="file">
191
- <div class="file__container">
192
- <div class="file__file">
193
- <p class="file__symbol">
232
+ <div class="file__container">
233
+ ${
234
+ sizeMB > maxMegabytes
235
+ ? '<div class="file__file error">'
236
+ : '<div class="file__file">'
237
+ }
238
+ <p class="file__symbol">
194
239
<span aria-hidden="true" class="material-icons-outlined">${
195
240
type . match ( 'image' ) ? 'image' : 'description'
196
241
} </span>
197
- </p>
198
- <p class="p file__data">
199
- <span class="file__name">${ name } (${ ext } , ${ sizeMB } MB)</span>
200
- </p>
201
- <a class="link link--primary" href="#" role="button" aria-label="${ labelDelete } ">
202
- <span aria-hidden="true" class="material-icons-outlined">delete</span>
203
- </a>
242
+ </p>
243
+ <p class="p file__data">
244
+ <span class="file__name">${ name } (${ ext } , ${ sizeMB } MB)</span>
245
+ </p>
246
+ <a class="link link--primary" href="#" role="button" aria-label="${ labelDelete } ">
247
+ <span aria-hidden="true" class="material-icons-outlined">delete</span>
248
+ </a>
204
249
</div>
205
250
</div>
206
251
</aside>
207
- </li>
208
- `
252
+ </li>`
253
+
254
+ if ( sizeMB > maxMegabytes ) {
255
+ getFormNonFieldError . removeAttribute ( 'hidden' )
256
+
257
+ return (
258
+ htmlStart +
259
+ `<p class="p p--small p--centered error">
260
+ <span aria-hidden="true" class="material-icons-outlined">warning_amber</span>
261
+ Dit bestand is te groot
262
+ </p>`
263
+ )
264
+ } else {
265
+ getFormNonFieldError . setAttribute ( 'hidden' , 'hidden' )
266
+ }
267
+
268
+ return htmlStart
209
269
}
210
270
}
0 commit comments