This commit is contained in:
Swrup 2024-04-11 15:46:46 +02:00
commit e068e34254
10 changed files with 282 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_build/

42
.ocamlformat Normal file
View File

@ -0,0 +1,42 @@
version=0.26.1
assignment-operator=end-line
break-cases=fit
break-fun-decl=wrap
break-fun-sig=wrap
break-infix=wrap
break-infix-before-func=false
break-separators=before
break-sequences=true
cases-exp-indent=2
cases-matching-exp-indent=normal
doc-comments=before
doc-comments-padding=2
doc-comments-tag-only=default
dock-collection-brackets=false
exp-grouping=preserve
field-space=loose
if-then-else=compact
indicate-multiline-delimiters=space
indicate-nested-or-patterns=unsafe-no
infix-precedence=indent
leading-nested-match-parens=false
let-and=sparse
let-binding-spacing=compact
let-module=compact
margin=80
max-indent=68
module-item-spacing=sparse
ocp-indent-compat=false
parens-ite=false
parens-tuple=always
parse-docstrings=true
sequence-blank-line=preserve-one
sequence-style=terminator
single-case=compact
space-around-arrays=true
space-around-lists=true
space-around-records=true
space-around-variants=true
type-decl=sparse
wrap-comments=false
wrap-fun-args=true

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# slippery_slidy
js_of_ocmal + brr library to make slider

26
dune-project Normal file
View File

@ -0,0 +1,26 @@
(lang dune 3.14)
(name slippery_slidy)
(generate_opam_files true)
(source
(github username/reponame))
(authors "Author Name")
(maintainers "Maintainer Name")
(license LICENSE)
(documentation https://url/to/documentation)
(package
(name slippery_slidy)
(synopsis "A short synopsis")
(description "A longer description")
(depends ocaml dune js_of_ocaml brr)
(tags
(topics "to describe" your project)))
; See the complete stanza docs at https://dune.readthedocs.io/en/stable/dune-files.html#dune-project

5
examples/dune Normal file
View File

@ -0,0 +1,5 @@
(executable
(name slider)
(modules slider)
(libraries js_of_ocaml brr slippery_slidy)
(modes js))

32
examples/slider.ml Normal file
View File

@ -0,0 +1,32 @@
(* This add a slidder to into <main>
moving the slider print its value to the console *)
open Brr
let append_el_to_main el =
let main =
match El.find_first_by_selector (Jstr.v "main") with
| Some main -> main
| None -> failwith "append_el_to_main: main element not found"
in
El.append_children main [ el ];
()
let () =
let datalist =
Slippery_slidy.mk_datalist
(List.map Jstr.of_float [ 2.; 3.; 5.; 8.; 13. ])
"my-slider-datalist"
in
let slider =
Slippery_slidy.mk_slider ~min:0. ~max:100. ~step:Any ~value:50.
~id:"my-slider" ~label:"Important slider, slide carefully"
~datalist_id:(Some datalist.datalist_id)
in
append_el_to_main slider.slider_el;
(* don't forget to add datalist to document too! *)
append_el_to_main datalist.datalist_el;
(* add listener on slider change *)
Slippery_slidy.add_slider_input_listener slider (fun x ->
Printf.printf "slider value: %f !!@." x );
()

4
lib/dune Normal file
View File

@ -0,0 +1,4 @@
(library
(name slippery_slidy)
(public_name slippery_slidy)
(libraries js_of_ocaml brr))

100
lib/slippery_slidy.ml Normal file
View File

@ -0,0 +1,100 @@
open Brr
type datalist =
{ datalist_id : string
; datalist_el : El.t
}
type slider =
{ slider_id : string
; slider_el : El.t
}
(* Any is for continuous slider *)
type step_kind =
| Any
| Step_value of float
let step_to_string step =
match step with Any -> "any" | Step_value f -> Float.to_string f
let mk_datalist : Jstr.t list -> string -> datalist =
fun l id ->
let option_el_l =
List.map (fun s -> El.option ~d:G.document ~at:[ At.value s ] []) l
in
let datalist =
El.datalist ~d:G.document ~at:[ At.id (Jstr.v id) ] option_el_l
in
{ datalist_id = id; datalist_el = datalist }
(* make a div of class slippery-slidy-container containing a
slider of class slippery-slidy-slider *)
let mk_slider :
min:float
-> max:float
-> step:step_kind
-> value:float
-> id:string
-> label:string
-> datalist_id:string option
-> slider =
fun ~min ~max ~step ~value ~id ~label ~datalist_id ->
(* some checks *)
let b = min <= max && value <= max && value >= min in
if not b then
raise (Invalid_argument "mk_slider: parameters did not pass validation")
else
let datalist =
match datalist_id with
| None -> []
| Some datalist_id -> [ At.v (Jstr.v "list") (Jstr.v datalist_id) ]
in
let input_el =
El.input ~d:G.document
~at:
( datalist
@ [ At.type' (Jstr.v "range")
; At.float (Jstr.v "min") min
; At.float (Jstr.v "max") max
; At.v (Jstr.v "step") (Jstr.v (step_to_string step))
; At.value (Jstr.of_float value)
; At.id (Jstr.v id)
; At.class' (Jstr.v "slippery-slidy-slider")
] )
()
in
let label =
El.label ~d:G.document
~at:[ At.for' (Jstr.v id) ]
[ El.txt' ~d:G.document label ]
in
let slider_container_el =
El.div ~d:G.document
~at:[ At.class' (Jstr.v "slippery-slidy-container") ]
[ label; input_el ]
in
{ slider_id = id; slider_el = slider_container_el }
let add_slider_input_listener slider f =
(* we do not use Ev.input because it makes a Ev.Input.t but:
"For <textarea> and <input> elements that accept
text input (type=text, type=tel, etc.), the interface is InputEvent;
for others, the interface is Event."
passing the El.t to the handler to avoid using Obj.magic to get "evt.target"
and directly doing "el.value" in the handler does not work for some reason
(we get a value="") *)
let handler evt =
(* here evt is a "Event" not a "EventInput"
no need to take Ev.as_type *)
let evt : Jv.t = Obj.magic evt in
let target : Jv.t = Jv.get evt "target" in
let value : Jv.t = Jv.get target "value" in
let x = float_of_string (Jv.to_string value) in
f x
in
let target = El.as_target slider.slider_el in
let input_ev = Ev.Type.create (Jstr.v "input") in
let _ : Ev.listener = Ev.listen input_ev handler target in
()

36
lib/slippery_slidy.mli Normal file
View File

@ -0,0 +1,36 @@
open Brr
type datalist =
{ datalist_id : string
; datalist_el : El.t
}
type slider =
{ slider_id : string
; slider_el : El.t
}
(** Any is for continuous slider *)
type step_kind =
| Any
| Step_value of float
val step_to_string : step_kind -> string
val mk_datalist : Jstr.t list -> string -> datalist
(** make a div of class "slippery-slidy-container" containing a slider of class
"slippery-slidy-slider" wi id [id]
don't forget to add your slider and datalist to your document *)
val mk_slider :
min:float
-> max:float
-> step:step_kind
-> value:float
-> id:string
-> label:string
-> datalist_id:string option
-> slider
val add_slider_input_listener : slider -> (float -> unit) -> unit

33
slippery_slidy.opam Normal file
View File

@ -0,0 +1,33 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
synopsis: "A short synopsis"
description: "A longer description"
maintainer: ["Maintainer Name"]
authors: ["Author Name"]
license: "LICENSE"
tags: ["topics" "to describe" "your" "project"]
homepage: "https://github.com/username/reponame"
doc: "https://url/to/documentation"
bug-reports: "https://github.com/username/reponame/issues"
depends: [
"ocaml"
"dune" {>= "3.14"}
"js_of_ocaml"
"brr"
"odoc" {with-doc}
]
build: [
["dune" "subst"] {dev}
[
"dune"
"build"
"-p"
name
"-j"
jobs
"@install"
"@runtest" {with-test}
"@doc" {with-doc}
]
]
dev-repo: "git+https://github.com/username/reponame.git"