aboutsummaryrefslogtreecommitdiff
path: root/src/View/Form/Autocomplete.ml
blob: 324a83407bc5c5b98c3b0677a3dead777344c707 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
let search s xs =
  let results = Js.Array.filter (Js.String.includes s) xs in
  if Js.Array.length results == 1 && results.(0) == s then [| |] else results

let render_completion render_entry on_select entries =
  H.div
    [| HA.class_ "g-Autocomplete__Completion" |]
    (entries
      |> Js.Array.map (fun c ->
          H.button
            [| HA.class_ "g-Autocomplete__Entry"
            ;  HA.type_ "button"
            ;  HE.on_click (fun e ->
                let () = Event.stop_propagation e in
                let () = Event.prevent_default e in
                on_select c)
            |]
            (render_entry c)))

let create attrs id values render_entry on_input =

  let completion =
    H.div [| |] [| |]
  in

  let update_completion target value =
    let entries = search value values in
    Element.mount_on completion (render_completion
      render_entry
      (fun selected ->
        let () = Element.set_value target selected in
        let () = Element.remove_children completion in
        on_input selected)
      entries)
  in

  let hide_completion () =
    Element.mount_on completion (H.text "")
  in

  H.div
    [| HA.class_ "g-Autocomplete" |]
    [| H.input
      (Js.Array.concat
        [| HA.id id
        ; HA.class_ "g-Autocomplete__Input"
        ; HA.autocomplete "off"
        ;  HE.on_click (fun e ->
            let target = Event.target e in
            let value = Element.value target in
            update_completion target value)
        ;  HE.on_input (fun e ->
            let target = Event.target e in
            let value = Element.value target in
            let () = update_completion target value in
            on_input value)
        ; HE.on_blur (fun _ ->
            let _ = Js.Global.setTimeout
              (fun _ -> hide_completion ())
              100
            in ())
        |]
        attrs)
      [| |]
    ;  completion
    |]