@@ -3,23 +3,27 @@ import {click} from './click'
33import { blur } from './blur'
44import { focus } from './focus'
55
6- function upload ( element , fileOrFiles , init ) {
6+ function upload ( element , fileOrFiles , init , { applyAccept = false } = { } ) {
77 if ( element . disabled ) return
88
99 click ( element , init )
1010
1111 const input = element . tagName === 'LABEL' ? element . control : element
1212
13- const files = ( Array . isArray ( fileOrFiles )
14- ? fileOrFiles
15- : [ fileOrFiles ]
16- ) . slice ( 0 , input . multiple ? undefined : 1 )
13+ const files = ( Array . isArray ( fileOrFiles ) ? fileOrFiles : [ fileOrFiles ] )
14+ . filter ( file => ! applyAccept || isAcceptableFile ( file , element . accept ) )
15+ . slice ( 0 , input . multiple ? undefined : 1 )
1716
1817 // blur fires when the file selector pops up
1918 blur ( element , init )
2019 // focus fires when they make their selection
2120 focus ( element , init )
2221
22+ // treat empty array as if the user just closed the file upload dialog
23+ if ( files . length === 0 ) {
24+ return
25+ }
26+
2327 // the event fired in the browser isn't actually an "input" or "change" event
2428 // but a new Event with a type set to "input" and "change"
2529 // Kinda odd...
@@ -46,4 +50,22 @@ function upload(element, fileOrFiles, init) {
4650 } )
4751}
4852
53+ function isAcceptableFile ( file , accept ) {
54+ if ( ! accept ) {
55+ return true
56+ }
57+
58+ const wildcards = [ 'audio/*' , 'image/*' , 'video/*' ]
59+
60+ return accept . split ( ',' ) . some ( acceptToken => {
61+ if ( acceptToken [ 0 ] === '.' ) {
62+ // tokens starting with a dot represent a file extension
63+ return file . name . endsWith ( acceptToken )
64+ } else if ( wildcards . includes ( acceptToken ) ) {
65+ return file . type . startsWith ( acceptToken . substr ( 0 , acceptToken . length - 1 ) )
66+ }
67+ return file . type === acceptToken
68+ } )
69+ }
70+
4971export { upload }
0 commit comments