= How to bind a JS library for OCaml

==Accessing a JS variable, ex: {{{document}}}:
Write in .ml:

<<code language="ocaml"|
let v = (Js.Unsafe.js_expr "window")##.document
>>
Alternatively, the global object can be used. In the browser, it refers to {{{window}}}.
<<code language="ocaml"|
let v = Js.Unsafe.global##.document
>>

and in .mli:

<<code language="ocaml"|
val v : ... Js.t
>>

Be careful the function <<a_api subproject="js_of_ocaml"|val Js_of_ocaml.Js.Unsafe.js_expr>>
and the value <<a_api subproject="js_of_ocaml"|val Js_of_ocaml.Js.Unsafe.global>> are not typed.
Verify the library documentation before writing the type.

==Binding a JS function

Example from the Js module:
<<code language="ocaml"|
let decodeURI (s : js_string t) : js_string t =
  Js.Unsafe.fun_call (Js.Unsafe.js_expr "decodeURI") [|Js.Unsafe.inject s|]
>>

Have a look at the <<a_api subproject="js_of_ocaml"|module Js_of_ocaml.Js.Unsafe>> module API.

==Using a JS constructor, ex: {{{F}}}:
Write in .ml:

<<code language="ocaml"|
let f = Js.Unsafe.global##._F
>>
and in .mli:

<<code language="ocaml"|
val f : (... -> ... Js.t) Js.constr
>>

and if you want to use JS overloading, do, for example:
<<code language="ocaml"|
val f_fromInt : (int -> ... Js.t) Js.constr
val f_fromString : (js_string t -> ... Js.t) Js.constr
val f_blah : (#Dom_html.element t -> js_string t -> ... Js.t) Js.constr
>>

==Accessing or modifying a JS property to an element

When a property is missing in the OCaml interface of an element (for example
it has been dynamically added by a library), you can access using unsafe
features:

<<code language="ocaml"|
(Js.Unsafe.coerce elt)##.blah
>>

If you want to add yourself a new property:
<<code language="ocaml"|
(Js.Unsafe.coerce elt)##.blah := v
>>

Here, {{{v}}} may be a JS value or an OCaml value.

If you want to do that in type safe manner, just define new types for the
extended elements, or wrap the unsafe functions inside a getter and setter.

== Binding a JS object ==

Write in .ml and in .mli:

<<code language="ocaml"|
class type my_js_type = object

  (* read only property, read value with t##.prop1 *)
  method prop1 : int readonly_prop

  (* write only property, write value with t##.prop2 := 3.14 *)
  method prop2 : float writeonly_prop

  (* both read and write *)
  method prop3 : int prop

  (* method or property starting with a capital letter can be prepend
     with an underscore. *)
  method _Array : ... (* to access the JavasScript property or method Array *)

  (* Define two methods with different types, that translate to
     the same JavaScript method. *)
  method my_fun_int : int -> unit meth
  method my_fun_string : js_string t -> unit meth
  (* Both will actually call the my_fun JavaScript method. *)

  (* To call a javascript method starting with one underscore *)
  method __hiddenfun : ..
  method __hiddenfun_ : ..
  method __hiddenfun_something : ..
  (* This will call the _hiddenfun Javascript method *)

  (* To call the javascript method '_' *)
  method __ : ..
end
>>

===Example binding some constants:

For example if the JS class is used to define three constants {{{thelib.Theclass.VALUEA}}}, {{{thelib.Theclass.VALUEB}}}, {{{thelib.Theclass.VALUEC}}},

Since ocaml doesn't allows method name to start with capitalised letter, we can add an {{{_}}}

write in .ml and .mli:

<<code language="ocaml"|
type thetype

class type theclass = object
  method _VALUEA : thetype readonly_prop
  method _VALUEB : thetype readonly_prop
  method _VALUEC : thetype readonly_prop
end
>>

and in .ml:

<<code language="ocaml"|
let theclass = (Js.Unsafe.js_expr "thelib")##._Theclass
>>

and in .mli:

<<code language="ocaml"|
val theclass : theclass t
>>

==Constructing JS objects manually
If you want to construct a JS object manually
(without calling a function or a constructor), you can use
the <<a_manual chapter="Ppx"|Ppx>> syntax extension.

For example:
<<code language="ocaml"|
let options = object%js
  val x = 3 (* read-only prop *)
  val mutable y = 4 (* read/write prop *)
end
>>

You can also use the unsafe <<a_api subproject="js_of_ocaml"|val Js_of_ocaml.Js.Unsafe.obj>>.

== Set/get variables

You can access every variable through the global javascript object ({{{window}}}):

If the variable {{{var}}} has type {{{t Js.t}}}

<<code language="ocaml"|
let set (x:t Js.t) = Js.Unsafe.global##.var := x
let get x : t Js.t = Js.Unsafe.global##.var
>>

== Object property with multiple types

If you want to read a property of an object which can have multiple types, you can define an intermediate type to do typesafe casting ex:

Suppose the object {{{obj}}} has a property {{{prop}}} which can be either a string or a Dom node:

<<code language="ocaml"|

type dom_or_string

class type obj = object
  method prop : dom_or_string Js.t prop
end

let obj : obj Js.t = Js.Unsafe.js_expr "obj"

let string_constr : Js.js_string Js.t Js.constr = Js.Unsafe.global##._String

let cast_string (x:dom_or_string Js.t) : Js.js_string Js.t Js.opt =
  if Js.instanceof x string_constr
  then Js.some (Js.Unsafe.coerce x)
  else Js.null

let node_constr : Dom.node Js.t Js.constr = Js.Unsafe.global##._Node

let cast_node (x:dom_or_string Js.t) : Dom.node Js.t Js.opt =
  if Js.instanceof x node_constr
  then Js.some (Js.Unsafe.coerce x)
  else Js.null

>>

== Check availability of method

It is frequent that some method are not to be implemented in some browser.

To check the presence of method {{{met}}}:

<<code language="ocaml"|
let check_met obj = Js.Optdef.test ((Js.Unsafe.coerce obj)##.met)
>>
