Source

chart / chart3 / chart.ml

open Js
open XJs
open Lwt

open Google

let _ = google##load (Js.string "visualization", Js.string "1.0", Unsafe.variable "{'packages':['corechart']}")

(* eval_string cannot define a function. i.e.

   eval_string "function drawChart () { ... }"

   has no effect after eval_string.
*)

module Data = struct
  let get_line s pos =
    try 
      `Line (String.index_from s pos '\n')
    with
    | Not_found ->
        let len = String.length s in
        if pos < len - 1 then `LineEnd
        else `EOS

  let iter_by_lines f s =
    let rec iter pos =
      match get_line s pos with
      | `Line pos' -> 
          f (String.sub s pos (pos' - pos));
          iter (pos'+1)
      | `LineEnd -> f (String.sub s pos (String.length s - pos))
      | `EOS -> ()
    in
    iter 0

  let parse_row s =
    try
      let pos = String.index s ' ' in
      let len = String.length s in
      Some (String.sub s 0 pos,
            String.sub s (pos + 1) (len - pos - 1))
    with
    | _ -> None

  let parse_rows s =
    let items = ref [] in
    iter_by_lines (fun s -> 
      match parse_row s with
      | None -> ()
      | Some (x,y) ->
          begin try
            items := (int_of_string x, int_of_string y) :: !items
          with
          | _ -> ()
          end) s;
    !items

  let get url =
    Http.get url >>= function
      | None -> return []
      | Some s -> return (parse_rows s)
end

let drawChart () = 
  let data = jsnew (google##visualization##_DataTable) () in
  data##addColumn(Js.string "number", Js.string "X");
  data##addColumn(Js.string "number", Js.string "Y");

  (* eval_string of JavaScript object literal fails *)
  (* Someone has written a patch for a syntax sugar of Javascript object literal. So wait and see. *)
  let options = Unsafe.variable "{'title':'Random value distribution', 
                                  'width':400, 
                                  'height':300
                                 }" in

  let div = match Opt.to_option (Dom_html.window##document##getElementById (Js.string "chart_div")) with
    | None -> assert false
    | Some div -> div
  in
  let chart = jsnew (google##visualization##_ScatterChart) (div) in
  chart##draw(data, options);

  ignore begin
    Data.get "data.txt" >>= fun rows ->

    data##addRows(Js.array (Array.of_list (List.map (fun (x,y) -> 
      Js.array [| Obj.magic x;
                  Obj.magic y; |]) rows)));
    chart##draw(data, options);
    return ()
  end

let _ = google##setOnLoadCallback(drawChart)