-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy patheffect.ml
107 lines (92 loc) · 2.89 KB
/
effect.ml
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
open Base
open Js_of_ocaml
include Ui_effect
(* All visibility handlers see all events, so a simple list is enough. *)
let visibility_handlers : (unit -> unit) list ref = ref []
module type Visibility_handler = sig
val handle : unit -> unit
end
module Define_visibility (VH : Visibility_handler) = struct
let () = visibility_handlers := VH.handle :: !visibility_handlers
end
module Open_url_target = struct
type t =
| This_tab
| New_tab_or_window
| Iframe_parent_or_this_tab
| Iframe_root_parent_or_this_tab
let to_target = function
(* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target *)
| This_tab -> "_self"
| New_tab_or_window -> "_blank"
| Iframe_parent_or_this_tab -> "_parent"
| Iframe_root_parent_or_this_tab -> "_top"
;;
end
type _ t +=
| Viewport_changed
| Stop_propagation
| Stop_immediate_propagation
| Prevent_default
| Open :
{ url : string
; target : Open_url_target.t
}
-> unit t
let sequence_as_sibling left ~unless_stopped =
let rec contains_stop = function
| Many es -> List.exists es ~f:contains_stop
| Stop_immediate_propagation -> true
| _ -> false
in
if contains_stop left then left else Ui_effect.Many [ left; unless_stopped () ]
;;
let open_url ?(in_ = Open_url_target.This_tab) url = Open { url; target = in_ }
(* We need to keep track of the current dom event here so that
movement between [Vdom.Effect.Expert.handle] and
[Ui_concrete.Effect.Expert.handle] keeps the original
dom event around. *)
let current_dom_event = ref None
let () =
Hashtbl.add_exn
Expert.handlers
~key:Stdlib.Obj.Extension_constructor.(id (of_val Viewport_changed))
~data:(fun _ -> List.iter !visibility_handlers ~f:(fun f -> f ()))
;;
let () =
Hashtbl.add_exn
Expert.handlers
~key:Stdlib.Obj.Extension_constructor.(id (of_val Stop_propagation))
~data:(fun _ -> Option.iter !current_dom_event ~f:Dom_html.stopPropagation)
;;
let () =
Hashtbl.add_exn
Expert.handlers
~key:Stdlib.Obj.Extension_constructor.(id (of_val Prevent_default))
~data:(fun _ -> Option.iter !current_dom_event ~f:Dom.preventDefault)
;;
let () =
Hashtbl.add_exn
Expert.handlers
~key:(Stdlib.Obj.Extension_constructor.id [%extension_constructor Open])
~data:(fun hidden ->
match hidden with
| T (Open { url; target }, callback) ->
let (_ : Dom_html.window Js.t Js.Opt.t) =
Dom_html.window##open_
(Js.string url)
(Js.string (Open_url_target.to_target target))
Js.Opt.empty
in
callback ()
| _ -> failwith "Unrecognized variant")
;;
module Expert = struct
let handle_non_dom_event_exn = Expert.handle
let handle dom_event event =
let old = !current_dom_event in
current_dom_event := Some (dom_event :> Dom_html.element Dom.event Js.t);
Expert.handle event;
current_dom_event := old
;;
end