aboutsummaryrefslogtreecommitdiff
path: root/src/View/Form/Autocomplete.ml
blob: 98e4b432c5fc9fb555140e23544e62804e249dae (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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
let search s xs =
  Js.Array.filter (Js.String.includes s) xs

let render_completion render_entry on_select entries =
  H.div
    [| HA.class_ "g-Autocomplete__Completion" |]
    (entries
      |> Js.Array.map (fun c ->
          Button.raw
            [| 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

  let
    input =
      H.input
        (HA.concat
          attrs
          [| HA.id id
          ;  HA.class_ "g-Autocomplete__Input"
          ;  HA.autocomplete "off"
          ;  HE.on_focus (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)
          |])
        [| |]
  in

  let () =
    Element.add_event_listener input "blur" (fun e ->
      if Js.isNullable (Event.related_target e) then
        hide_completion ())
  in

  H.div
    [| HA.class_ "g-Autocomplete" |]
    [| input
    ;  completion
    ;  Button.raw
        [| HA.class_ "g-Autocomplete__Clear fa fa-close"
        ;  HA.type_ "button"
        ;  HE.on_click (fun _ ->
            let () = on_input "" in
            let () = Element.set_value input "" in
            Element.focus input)
        |]
        [| |]
    |]