2022-04-16 15:22:02 +02:00
open Brr
2022-02-14 17:09:29 +01:00
2022-04-16 15:22:02 +02:00
let log = Format . printf
2022-04-15 23:35:17 +02:00
2022-02-18 01:37:25 +01:00
type image_size =
| Big
| Small
let of_string = function
2022-02-18 20:17:24 +01:00
| " post-image " -> Some Small
| " post-image-big " -> Some Big
2022-02-18 01:37:25 +01:00
| _ -> None
2022-02-18 20:17:24 +01:00
let to_string = function Small -> " post-image " | Big -> " post-image-big "
2022-02-18 01:37:25 +01:00
2022-02-14 17:09:29 +01:00
(* change postImage class to make it bigger/smaller on click *)
let image_click post_image event =
2022-02-19 00:59:01 +01:00
log " image_click@ \n " ;
2022-04-16 15:22:02 +02:00
let class_jstr = Jstr . of_string " class " in
2022-02-14 17:09:29 +01:00
let current_class =
2022-04-16 15:22:02 +02:00
match El . at class_jstr post_image with
| None -> failwith " no class for post_image "
| Some c -> Jstr . to_string c
2022-02-14 17:09:29 +01:00
in
let new_class =
2022-02-18 01:37:25 +01:00
match of_string current_class with
2022-03-15 00:12:36 +01:00
| Some image_size -> ( match image_size with Big -> Small | Small -> Big )
2022-02-18 01:37:25 +01:00
| None -> failwith " invalid image class name "
2022-02-14 17:09:29 +01:00
in
2022-04-16 15:22:02 +02:00
El . set_at class_jstr ( Some ( Jstr . of_string ( to_string new_class ) ) ) post_image ;
2022-03-15 00:12:36 +01:00
let id =
2022-04-16 15:22:02 +02:00
match El . at ( Jstr . of_string " data-id " ) post_image with
| None -> failwith " no data-id on post_image "
| Some id -> Jstr . to_string id
2022-03-15 00:12:36 +01:00
in
let src =
match new_class with
| Small -> Format . sprintf " /img/s/%s " id
| Big -> Format . sprintf " /img/%s " id
in
2022-04-16 15:22:02 +02:00
El . set_at ( Jstr . of_string " src " ) ( Some ( Jstr . of_string src ) ) post_image ;
2022-02-21 04:11:25 +01:00
(* prevent redirect to /img/:img *)
2022-04-16 15:22:02 +02:00
Ev . prevent_default event ;
Ev . stop_propagation event
2022-02-14 17:09:29 +01:00
let render_time date_span =
2022-02-19 00:59:01 +01:00
log " render time@ \n " ;
2022-04-15 23:35:17 +02:00
let data_time =
2022-04-16 15:22:02 +02:00
match El . at ( Jstr . of_string " data-time " ) date_span with
2022-04-15 23:35:17 +02:00
| None -> failwith " no attribute data-time for date element "
| Some data_time -> Jstr . to_float data_time
2022-02-14 17:09:29 +01:00
in
2022-04-15 23:35:17 +02:00
(*
let t =
Jv . to_float
( Jv . call date_span " getAttribute " [| Jv . of_string " data-time " |] )
in
* )
let t = Unix . localtime data_time in
2022-02-18 03:22:24 +01:00
let date =
Format . sprintf " %02d-%02d-%02d %02d:%02d " ( 1900 + t . tm_year ) ( 1 + t . tm_mon )
t . tm_mday t . tm_hour t . tm_min
2022-02-14 17:09:29 +01:00
in
2022-04-16 15:22:02 +02:00
let inner_html = El . Prop . jstr ( Jstr . of_string " innerHTML " ) in
El . set_prop inner_html ( Jstr . of_string date ) date_span
2022-02-14 17:09:29 +01:00
2022-04-10 14:04:26 +02:00
let preview_ref = ref None
let highlighted_ref = ref None
2022-04-15 23:35:17 +02:00
let selected_ref = ref None
let on_hashchange _ event =
log " on hashchange " ;
2022-04-16 15:22:02 +02:00
let frag = Jstr . to_string @@ Uri . fragment @@ Window . location G . window in
if frag = " " then ()
else
match Document . find_el_by_id G . document ( Jstr . of_string frag ) with
| None -> log " fragment not found on the page "
| Some reply ->
let () =
match ! selected_ref with
| None -> ()
| Some item -> El . set_class ( Jstr . of_string " selected " ) false item
in
El . set_class ( Jstr . of_string " selected " ) true reply ;
selected_ref := Some reply
let clone_element el =
(* TODO: how to clone with Brr? *)
let id =
match El . at ( Jstr . of_string " id " ) el with
| None -> failwith " element as no id for cloning "
| Some id -> Jstr . to_string id
2022-04-15 23:35:17 +02:00
in
2022-04-16 15:22:02 +02:00
(* get reply_div as a Jv.t *)
let original_div = Jv . get Jv . global id in
let div = Jv . call original_div " cloneNode " [| Jv . of_bool true |] in
ignore
@@ Jv . call div " setAttribute "
[| Jv . of_string " id " ; Jv . of_string " floating-reply-preview " |] ;
ignore
@@ Jv . call div " setAttribute "
[| Jv . of_string " class " ; Jv . of_string " post highlight " |] ;
(* append to DOM *)
(* we needs to add it to `body` and not `original_div` or it might change the display
* and do buggy things with mouse events on ` original_div ` * )
let document = Jv . get Jv . global " document " in
let body = Jv . get document " body " in
ignore @@ Jv . call body " append " [| div |] ;
(* go back to El *)
match
Document . find_el_by_id G . document ( Jstr . of_string " floating-reply-preview " )
with
| None -> failwith " error cloning element "
| Some el -> el
2022-04-15 23:35:17 +02:00
2022-04-10 14:04:26 +02:00
let on_mouse_over el _ event =
log " on mouse over@ \n " ;
2022-04-16 15:22:02 +02:00
2022-04-10 14:04:26 +02:00
let reply_id =
2022-04-16 15:22:02 +02:00
match El . at ( Jstr . of_string " data-id " ) el with
| None -> failwith " no data-id on element "
| Some data_id -> data_id
2022-04-10 14:04:26 +02:00
in
2022-04-16 15:22:02 +02:00
match Document . find_el_by_id G . document reply_id with
2022-04-10 14:04:26 +02:00
| None -> failwith " error getting reply_div, this reply is not on this page "
| Some reply_div ->
(* check if it in view, if it is, just make it of class `highlight` *)
let window = Jv . get Jv . global " window " in
let window_height = Jv . get window " innerHeight " | > Jv . to_int in
2022-04-16 15:22:02 +02:00
let reply_top = El . bound_y reply_div | > int_of_float in
if reply_top < window_height - 50 && reply_top + 50 > 0 then (
(* just highlight if reply is in viewport *)
El . set_class ( Jstr . of_string " highlight " ) true reply_div ;
2022-04-10 14:04:26 +02:00
highlighted_ref := Some reply_div )
else
(* copy it to make new div `floating-reply-preview` *)
2022-04-16 15:22:02 +02:00
let preview_div = clone_element reply_div in
2022-04-10 14:04:26 +02:00
(* place it next to the reply-link el *)
let top =
2022-04-16 15:22:02 +02:00
let el_top = El . bound_y el in
let h = El . bound_h preview_div in
(* clamp to viewport *)
let top =
Float . min
( el_top -. ( 0 . 5 * . h ) )
( float_of_int window_height -. h -. 7 . 0 )
in
let top = Float . max top 0 . 0 in
top | > int_of_float | > Format . sprintf " %dpx " | > Jstr . of_string
2022-04-10 14:04:26 +02:00
in
2022-04-16 15:22:02 +02:00
let left =
El . bound_x el + . El . bound_w el
| > int_of_float | > Format . sprintf " %dpx " | > Jstr . of_string
2022-04-10 14:04:26 +02:00
in
2022-04-16 15:22:02 +02:00
El . set_inline_style El . Style . position ( Jstr . of_string " fixed " ) preview_div ;
El . set_inline_style El . Style . z_index ( Jstr . of_string " 42 " ) preview_div ;
El . set_inline_style El . Style . top top preview_div ;
El . set_inline_style El . Style . left left preview_div ;
(* also highlight class doesn't work if we set inline style idk why wtf css *)
El . set_inline_style El . Style . background_color ( Jstr . of_string " #9dd162 " )
preview_div ;
2022-04-10 14:04:26 +02:00
(* set preview_div ref for on_mouse_out *)
2022-04-16 15:22:02 +02:00
preview_ref := Some preview_div
2022-04-10 14:04:26 +02:00
let on_mouse_out _ el _ event =
log " on mouse out@ \n " ;
(* get the `reply-preview` element, delete it if Some *)
let () =
match ! highlighted_ref with
| None -> ()
| Some highlighted_div ->
2022-04-16 15:22:02 +02:00
El . set_class ( Jstr . of_string " highlight " ) false highlighted_div
2022-04-10 14:04:26 +02:00
in
match ! preview_ref with
| None -> ()
2022-04-16 15:22:02 +02:00
| Some preview_div -> El . remove preview_div
2022-04-10 14:04:26 +02:00
2022-02-18 18:31:55 +01:00
let make_pretty _ event =
2022-02-19 00:59:01 +01:00
log " make pretty@ \n " ;
2022-02-14 17:09:29 +01:00
2022-04-10 14:04:26 +02:00
let add_event_to_class ~ name ~ event handler =
2022-04-16 15:22:02 +02:00
let event = Ev . Type . create ( Jstr . of_string event ) in
let el_list = El . find_by_class ( Jstr . of_string name ) in
List . iter ( fun el -> Ev . listen event ( handler el ) ( El . as_target el ) ) el_list
2022-02-14 17:09:29 +01:00
in
2022-04-10 14:04:26 +02:00
2022-04-16 15:22:02 +02:00
let dates = El . find_by_class ( Jstr . of_string " date " ) in
2022-04-15 23:35:17 +02:00
List . iter render_time dates ;
2022-04-10 14:04:26 +02:00
2022-04-16 15:22:02 +02:00
(* add event image_click to all postImage *)
let () = add_event_to_class ~ name : " post-image " ~ event : " click " image_click in
2022-04-10 14:04:26 +02:00
2022-04-16 15:22:02 +02:00
(* add event mouse_over/out to all reply-link *)
let () =
add_event_to_class ~ name : " reply-link " ~ event : " mouseover " on_mouse_over
in
2022-04-10 14:04:26 +02:00
let () =
2022-04-15 23:35:17 +02:00
add_event_to_class ~ name : " reply-link " ~ event : " mouseout " on_mouse_out
2022-02-14 17:09:29 +01:00
in
2022-04-15 23:35:17 +02:00
(* add fragment listener to mark as selected the linked post *)
2022-04-16 15:22:02 +02:00
(* TODO call with brr *)
let hashchange = Ev . Type . create ( Jstr . of_string " hashchange " ) in
Ev . listen hashchange on_hashchange ( Window . as_target G . window ) ;
(* call hashchange on page load too *)
on_hashchange ()
2022-02-14 17:09:29 +01:00
(* make pretty after page load *)
let () =
2022-02-19 00:59:01 +01:00
log " add load eventlistener to make pretty@ \n " ;
2022-04-16 15:22:02 +02:00
let load = Ev . Type . create ( Jstr . of_string " load " ) in
Ev . listen load make_pretty ( Window . as_target G . window )
2022-04-10 14:04:26 +02:00
(* TODO reply can be in another thread, how to display it? if displaying it on mouseover we need to fetch it. and display it in special color. need to change pp_post in pp_babillard *)