aboutsummaryrefslogtreecommitdiff
path: root/editor/plugins/popin.ml
diff options
context:
space:
mode:
Diffstat (limited to 'editor/plugins/popin.ml')
-rwxr-xr-xeditor/plugins/popin.ml83
1 files changed, 83 insertions, 0 deletions
diff --git a/editor/plugins/popin.ml b/editor/plugins/popin.ml
new file mode 100755
index 0000000..63dcad1
--- /dev/null
+++ b/editor/plugins/popin.ml
@@ -0,0 +1,83 @@
+open Brr
+module Js = Js_of_ocaml.Js
+module PM = Prosemirror
+
+type binded_field =
+ { field: El.t
+ ; button: El.t
+ }
+
+(** Set the element position just above the selection *)
+let set_position
+ : start:int -> end':int -> PM.View.editor_view Js.t -> El.t -> unit
+ = fun ~start ~end' view el ->
+ El.set_inline_style El.Style.display (Jstr.v "") el;
+
+ (* These are in screen coordinates *)
+ let start = view##coordsAtPos start Js.null
+ and end' = view##coordsAtPos end' Js.null in
+ let offsetParent = Jv.(Id.of_jv @@ get (Jv.Id.to_jv el) "offsetParent") in
+
+ (* The box in which the tooltip is positioned, to use as base *)
+ let box = Jv.(Id.of_jv @@ call (Jv.Id.to_jv offsetParent) "getBoundingClientRect" [||]) in
+ let box_left = Jv.(Id.of_jv @@ get (Jv.Id.to_jv box) "left") in
+ let box_bottom = Jv.(Id.of_jv @@ get (Jv.Id.to_jv box) "bottom") in
+
+ (* Find a center-ish x position from the selection endpoints (when
+ crossing lines, end may be more to the left) *)
+ let left = (start##.left +. end'##.left) /. 2. in
+
+ El.set_inline_style (Jstr.v "left")
+ Jstr.( (of_float ( left -. box_left )) + (v "px") )
+ el;
+ El.set_inline_style (Jstr.v "bottom")
+ Jstr.( (of_float ( box_bottom -. start##.top )) + (v "px") )
+ el
+
+(** Build a button which allow to activate or desactivate the given Element.
+
+ The function f is called when the user validate the input.
+
+*)
+let build_field
+ : El.t -> (Jstr.t -> bool) -> binded_field
+ = fun field f ->
+
+ let button_content =
+ [ El.i []
+ ~at:At.[ class' (Jstr.v "fas")
+ ; class' (Jstr.v "fa-pen") ]
+ ] in
+
+ let button = El.button
+ button_content
+ in
+
+ Ev.listen Ev.click
+ (fun _ ->
+ match El.at (Jstr.v "contenteditable") field with
+ | Some value when (Jstr.equal value (Jstr.v "true")) ->
+ let new_value = El.prop
+ (El.Prop.jstr (Jstr.v "textContent"))
+ field in
+ begin match f new_value with
+ | true ->
+ El.set_at (Jstr.v "contenteditable") None field;
+ El.set_children button button_content
+ | false -> ()
+ end
+ | _ ->
+ El.set_at (Jstr.v "contenteditable")
+ (Some (Jstr.v "true")) field;
+ El.set_children button
+ [ El.i
+ ~at:At.[ class' (Jstr.v "fas")
+ ; class' (Jstr.v "fa-check") ]
+ []
+ ]
+ )
+ (El.as_target button);
+
+ { field
+ ; button = button
+ }