diff --git a/examples/cssclasstest-brr/index.html b/examples/cssclasstest-brr/index.html
index 41b943c..4e64b15 100644
--- a/examples/cssclasstest-brr/index.html
+++ b/examples/cssclasstest-brr/index.html
@@ -3,14 +3,14 @@
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
- Minesweeper
+ Minesweeper embryo
-
+
diff --git a/examples/cssclasstest-brr/main.ml b/examples/cssclasstest-brr/main.ml
index 0175ef6..bf9ddfc 100644
--- a/examples/cssclasstest-brr/main.ml
+++ b/examples/cssclasstest-brr/main.ml
@@ -40,18 +40,21 @@ let ui =
Lwd_seq.monoid
squares
in
- Elwd.div ~at:[ `P (At.class' (Jstr.v "game-board")) ] [
+ [
`S (Lwd_seq.lift board)
]
-let () =
- let ui = Lwd.observe ui in
- let on_invalidate _ =
- ignore @@ G.request_animation_frame @@ fun _ ->
- ignore @@ Lwd.quick_sample ui
- in
- let on_load _ =
- El.append_children (Document.body G.document) [ Lwd.quick_sample ui ];
- Lwd.set_on_invalidate ui on_invalidate
+let defer_after_dom_loading f =
+ let on_load _ = f () in
+ let _listen_id =
+ Ev.listen Ev.dom_content_loaded on_load (Window.as_target G.window)
in
- ignore @@ Ev.listen Ev.dom_content_loaded on_load (Window.as_target G.window)
+ ()
+
+let () =
+ defer_after_dom_loading @@ fun () ->
+ match El.find_first_by_selector (Jstr.v ".game-board") with
+ | None -> failwith ".game-board could not be found, check your html"
+ | Some main ->
+ let _remove_token = Elwd.set_children main ui in
+ ()
diff --git a/examples/focustest-brr/main.ml b/examples/focustest-brr/main.ml
index 4b81ab8..eb1ee20 100644
--- a/examples/focustest-brr/main.ml
+++ b/examples/focustest-brr/main.ml
@@ -46,22 +46,17 @@ let ui =
`S (Lwd_seq.map El.txt' values);
]
-let () =
- let ui = Lwd.observe ui in
- let on_invalidate _ =
- Console.(log [str "on invalidate"]);
- let _ : int =
- G.request_animation_frame @@ fun _ ->
- let _ui = Lwd.quick_sample ui in
- (*El.set_children (Document.body G.document) [ui]*)
- ()
- in
- ()
- in
- let on_load _ =
- Console.(log [str "onload"]);
- El.append_children (Document.body G.document) [Lwd.quick_sample ui];
- Lwd.set_on_invalidate ui on_invalidate
+let defer_after_dom_loading f =
+ let on_load _ = f () in
+ let _listen_id =
+ Ev.listen Ev.dom_content_loaded on_load (Window.as_target G.window)
in
- ignore (Ev.listen Ev.dom_content_loaded on_load (Window.as_target G.window));
()
+
+let () =
+ defer_after_dom_loading @@ fun () ->
+ match El.find_first_by_selector (Jstr.v "#main") with
+ | None -> failwith "#main could not be found, check your html"
+ | Some main ->
+ let _remove_token = Elwd.insert_sibling `Replace main ui in
+ ()
diff --git a/lib/brr-lwd/elwd.ml b/lib/brr-lwd/elwd.ml
index 4b09c03..ba89973 100644
--- a/lib/brr-lwd/elwd.ml
+++ b/lib/brr-lwd/elwd.ml
@@ -409,3 +409,61 @@ let ul = cons Name.ul
let var = cons Name.var
let video = cons Name.video
let wbr = void_cons Name.wbr
+
+type root = t Lwd.root
+
+let insert first_insert anchor reactive =
+ let root = Lwd.observe reactive in
+ let last_element = ref (Lwd.quick_sample root) in
+ first_insert anchor [!last_element];
+ let on_invalidate _ =
+ let _ : int =
+ G.request_animation_frame @@ fun _ ->
+ let new_element = Lwd.quick_sample root in
+ if !last_element = new_element then ()
+ else (
+ El.insert_siblings `Replace !last_element [ new_element ];
+ last_element := new_element
+ )
+ in
+ ()
+ in
+ Lwd.set_on_invalidate root on_invalidate;
+ root
+
+let insert_sibling where anchor reactive =
+ let first_insert = El.insert_siblings where in
+ insert first_insert anchor reactive
+
+let append_child anchor reactive =
+ insert El.append_children anchor reactive
+
+let prepend_child anchor reactive =
+ insert El.prepend_children anchor reactive
+
+let set_children el children =
+ let reactive =
+ let children, impure_children = consume_children children in
+ match impure_children with
+ | None -> El.set_children el children; Lwd.pure el
+ | Some children ->
+ let root = Lwd.observe children in
+ let c = Lwd.quick_sample root in
+ El.set_children el (Lwd_seq.to_list c);
+ Lwd.quick_release root;
+ update_children el children
+ in
+ let root = Lwd.observe reactive in
+ let _el = Lwd.quick_sample root in
+ let on_invalidate _ =
+ let _ : int =
+ G.request_animation_frame @@ fun _ ->
+ let _el = Lwd.quick_sample root in
+ ()
+ in
+ ()
+ in
+ Lwd.set_on_invalidate root on_invalidate;
+ root
+
+let release root = Lwd.quick_release root
diff --git a/lib/brr-lwd/elwd.mli b/lib/brr-lwd/elwd.mli
index 38fc4ea..2d89172 100644
--- a/lib/brr-lwd/elwd.mli
+++ b/lib/brr-lwd/elwd.mli
@@ -24,6 +24,33 @@ val v : ?d:document -> ?at:At.t col -> ?ev:handler col -> tag_name -> t col -> t
the final value. [d] is the document on which the element is
defined it defaults {!Brr.G.document}. *)
+
+(** {1 Inserting reactive elements in the DOM} *)
+
+type root
+
+val insert_sibling : [ `Before | `After | `Replace ] -> t -> t Lwd.t -> root
+(** Inserts a reactive element in the DOM, right before/after/instead of the
+ given element. The element is updated until the return value is passed to
+ {!release}. *)
+
+val set_children : t -> t col -> root
+(** Sets a set of reactive elements as the children of the given element. The
+ set is updated until the return value is passed to {!release}. *)
+
+val append_child : t -> t Lwd.t -> root
+(** Inserts a reactive element in the DOM, as last child of the given
+ element. The element is updated until the return value is passed to
+ {!release}. *)
+
+val prepend_child : t -> t Lwd.t -> root
+(** Inserts a reactive element in the DOM, as first child of the given
+ element. The element is updated until the return value is passed to
+ {!release}. *)
+
+val release : root -> unit
+(** Stop updating the reactive elements, leaving what is currently there. *)
+
(** {1:els Element constructors} *)
type cons = ?d:document -> ?at:At.t col -> ?ev:handler col -> t col -> t Lwd.t