@@ -2,12 +2,14 @@ module DragAndDropHalogenHooks.Main where
2
2
3
3
import Prelude hiding (top )
4
4
5
- import CSS (alignItems , border , borderRadius , color , column , dashed , display , displayNone , flex , flexDirection , gray , height , justifyContent , margin , padding , purple , px , solid , width )
5
+ import CSS (alignItems , backgroundColor , border , borderRadius , color , column , dashed , display , displayNone , flex , flexDirection , gray , height , justifyContent , lightblue , margin , padding , purple , px , solid , width )
6
6
import CSS as CSS
7
7
import CSS.Common (center )
8
+ import DOM.HTML.Indexed.InputAcceptType (mediaType )
8
9
import DOM.HTML.Indexed.InputType (InputType (..))
9
10
import Data.Interpolate (i )
10
11
import Data.Maybe (Maybe (..), maybe )
12
+ import Data.MediaType (MediaType (..))
11
13
import Data.String (toUpper )
12
14
import Data.Tuple.Nested ((/\))
13
15
import Effect (Effect )
@@ -69,40 +71,53 @@ hookComponent = Hooks.component \_ _ -> Hooks.do
69
71
mbFileList = DataTransfer .files $ dataTransfer e
70
72
fileArray = maybe [] FileList .items mbFileList
71
73
Hooks .put filesIdx fileArray
74
+ Hooks .put hoverIdx false
72
75
]
73
- -- Note: Elm uses a button that, when clicked, will do the following:
74
- -- 1. create an input element
75
- -- 2. add it to the DOM
76
- -- 3. create a mouse event
77
- -- 4. dispatch the mouse event to the input element
78
- -- 5. (implication) file dialogue appears
79
- -- 6. user selects a file
80
- -- 7. input event handler runs a callback using user's selected file
81
- -- 8. input element is removed from DOM
82
- --
83
- -- The approach used below is based on this SO answer:
84
- -- https://stackoverflow.com/a/47094148
85
76
[ HH .label
86
- [ HP .for " file-input" ]
87
- [ HH .div
88
- -- simulate button-like appearance
89
- [ HC .style do
90
- margin (px 4.0 ) (px 4.0 ) (px 4.0 ) (px 4.0 )
91
- border solid (px 2.0 ) gray
92
- borderRadius (px 20.0 ) (px 20.0 ) (px 20.0 ) (px 20.0 )
93
- padding (px 20.0 ) (px 20.0 ) (px 20.0 ) (px 20.0 )
94
- , HP .class_ $ ClassName " otherCssNotInPurescript-Css"
95
- ]
96
- [ HH .text " Upload images" ]
77
+ -- simulate button-like appearance
78
+ [ HC .style do
79
+ margin (px 4.0 ) (px 4.0 ) (px 4.0 ) (px 4.0 )
80
+ border solid (px 2.0 ) gray
81
+ borderRadius (px 20.0 ) (px 20.0 ) (px 20.0 ) (px 20.0 )
82
+ padding (px 20.0 ) (px 20.0 ) (px 20.0 ) (px 20.0 )
83
+ backgroundColor lightblue
84
+ , HP .class_ $ ClassName " otherCssNotInPurescript-Css"
85
+ ]
86
+ [ HH .text " Upload images"
87
+ , HH .input
88
+ [ HC .style $ display displayNone
89
+ , HP .type_ InputFile
90
+ , HP .multiple true
91
+ , HP .accept $ mediaType $ MediaType " image/*"
92
+ , HE .onFileUpload \fileArray -> Just $ Hooks .put filesIdx fileArray
93
+ ]
97
94
]
98
- , HH .input
99
- [ HP .id_ " file-input"
100
- , HC .style $ display displayNone
101
- , HP .type_ InputFile
102
- , HP .multiple true
103
- , HE .onFileUpload \fileArray -> Just $ Hooks .put filesIdx fileArray
104
- ]
105
95
, HH .span
106
- [ HC .style $ color ( CSS .fromInt 0xcccccc ) ]
96
+ [ HC .style $ color $ CSS .fromInt 0xcccccc ]
107
97
[ HH .text $ i " { files = " (show $ map File .name files)" , hover = " (toUpper $ show hover)" }" ]
108
98
]
99
+ {-
100
+ The easiest way to create a file input dialog is with the input element:
101
+
102
+ HH.input [ HP.type_ InputFile ]
103
+
104
+ However, this interface cannot be styled like a regular button - A common problem:
105
+ https://stackoverflow.com/q/5813344
106
+ https://stackoverflow.com/q/21842274
107
+ https://stackoverflow.com/q/2048026
108
+
109
+ The workaround used in this recipe is to put the `input` within a `label`
110
+ and style the label to appear as a button. Unfortunately, we can't just reuse
111
+ default button styling.
112
+
113
+ Elm's workaround for custom file input styling is to use its runtime to
114
+ let users call File.Select.files on button click, which performs the following:
115
+ 1. create an input element
116
+ 2. add it to the DOM
117
+ 3. create a mouse event
118
+ 4. dispatch the mouse event to the input element
119
+ 5. (implication) file dialogue appears
120
+ 6. user selects a file
121
+ 7. input event handler runs a callback using user's selected file
122
+ 8. input element is removed from DOM
123
+ -}
0 commit comments