6  Transpile API reference ๐Ÿ“– - experimental ๐Ÿงช

Sometimes, data visualization in the browser requires not only plain JSON structures but also some Javascript code.

One way to generate such code from Clojure is through std.lang, a universal transpiler from Clojure to many languages.

The transpile API of Tableplot provides functions for using this practice in combination with various JS libraries. It is considered experimental at this stage.

6.1 Setup ๐Ÿ”จ

In this tutorial, we use:

  • The Tableplot transpile API namepace
  • Tablecloth for dataset processing and column processing
  • the datasets defined in the Datasets chapter
  • Kindly to annotate the kind of way certain values should be displayed
(ns tableplot-book.transpile-reference
  (:require [scicloj.tableplot.v1.transpile :as transpile]
            [tablecloth.api :as tc]
            [tableplot-book.datasets :as datasets]
            [tableplot-book.book-utils :as book-utils]
            [clojure.string :as str]
            [scicloj.kindly.v4.kind :as kind]))

6.2 Functions โš™

6.2.1 js

[& forms]

Transpile the given Clojure forms to Javascript code using Std.lang.

6.2.1.1 Examples

(kind/code
 (transpile/js '(var x 9)
               '(return (+ x 11))))
let x = 9;
return x + 11;

An adaptation of a Plotly.js example - Animations in Javascript:

(kind/hiccup
 [:div
  [:button {:onclick (transpile/js '(randomize))}
   "Randomize!"]
  [:div {:style {:height "auto"}}
   [:script
    (transpile/js
     '(var plotly-animaton-element document.currentScript.parentElement)
     '(Plotly.newPlot plotly-animaton-element
                      [{:x [1 2 3]
                        :y [0 0.5 1]
                        :line {:simplify false}}])
     '(defn randomize []
        (Plotly.animate plotly-animaton-element
                        {:data [{:y [(Math.random)
                                     (Math.random)
                                     (Math.random)]}]
                         :traces [0]
                         :layout {}}
                        {:transition {:duration 500
                                      :easing "cut-in-out"}
                         :frame {:duration 500}})))]]]
 {:html/deps [:plotly]})

6.2.2 div-with-script

[data script kindly-options]

Create a general transpiled data visualization.

Given a data structure data, a form script, and a map kindly-options create a corresponding Hiccup structure.

The structure will be a :div with a :script element that has some Javascript code.

The code is transpiled from script with some variable bindings preceeding it:

  • A Javscript variable called data is bound to the data value converted to JSON.
  • If data is a map that has some keys of symbol type, then corresponding Javascript variables named by these symbols are bound to the corresponding values converted to JSON.

The resulting structure is marked by the Kindly standard as kind/hiccup with Kindly options defined by deep-merging kindly-options into *base-kindly-options*.

6.2.2.1 Examples

Let us create an Apache Echarts plot.

(transpile/div-with-script
 ;; data
 [[1 2]
  [2 4]
  [3 9]
  [4 16]]
 ;; script
 ['(var myChart
        (echarts.init
         document.currentScript.parentElement))
  (list 'myChart.setOption
        {:xAxis {}
         :yAxis {}
         :series [{:type "scatter"
                   :data 'data}]})]
 ;; Kindly options (merged with default)
 {:html/deps [:echarts]
  :style {:height "300px"
          :background "floralwhite"}})

6.2.2.2 A closer look

Let us create a Plotly.js plot with some custom event handling. We will explore the resulting structure a little bit.

(def clickable-example
  (transpile/div-with-script
   ;; data (with symbol bindings)
   {'x [1 2 3 4]
    'y [3 4 9 16]}
   ;; script
   ['(var plotly-animaton-element document.currentScript.parentElement)
    '(Plotly.newPlot plotly-animaton-element
                     {:data
                      [{:x x
                        :y y
                        :mode "markers"
                        :type "scatter"
                        :marker {:size 20}}]
                      :layout {:title
                               "Would you please click the points?"}})
    '(. plotly-animaton-element
        (on "plotly_click"
            (fn []
              (alert "Thanks for clicking."))))]
   ;; Kindly options
   {:html/deps [:plotly]}))

First, let us see it visualized:

clickable-example

Now, let us check the metadata:

(meta clickable-example)
#:kindly{:kind :kind/hiccup,
         :options {:style {:height :auto}, :html/deps [:plotly]}}

Now, let us pretty-print it to see the Hiccup structure.

(kind/pprint
 clickable-example)
[:div
 [:script
  "(function () {\nlet data = {\"x\":[1,2,3,4],\"y\":[3,4,9,16]};\nlet x = data['x'];\nlet y = data['y'];\nlet plotly_animaton_element = document.currentScript.parentElement;\nPlotly.newPlot(plotly_animaton_element,{\n  \"data\":[\n    {\n    \"x\":x,\n    \"y\":y,\n    \"mode\":\"markers\",\n    \"type\":\"scatter\",\n    \"marker\":{\"size\":20}\n  }\n  ],\n  \"layout\":{\"title\":\"Would you please click the points?\"}\n});\nplotly_animaton_element.on(\"plotly_click\",function (){\n  alert(\"Thanks for clicking.\");\n});\n})();"]]

Let us focus on the code of the script:

(-> clickable-example
    second
    second
    kind/code)
(function () {
let data = {"x":[1,2,3,4],"y":[3,4,9,16]};
let x = data['x'];
let y = data['y'];
let plotly_animaton_element = document.currentScript.parentElement;
Plotly.newPlot(plotly_animaton_element,{
  "data":[
    {
    "x":x,
    "y":y,
    "mode":"markers",
    "type":"scatter",
    "marker":{"size":20}
  }
  ],
  "layout":{"title":"Would you please click the points?"}
});
plotly_animaton_element.on("plotly_click",function (){
  alert("Thanks for clicking.");
});
})();

6.2.3 echarts

[form]

[data form]

Given a data structure data and a form form, create a corresponding Apache Echarts data visualization using div-with-script.

The script will include the following:

  • A Javscript variable called data is bound to the data value converted to JSON.
  • If data is a map that has some keys of symbol type, then corresponding Javascript variables named by these symbols are bound to the corresponding values converted to JSON.
  • The form transpiled to Javascript.
  • Additional code to visualize it.

The resulting structure is marked by the Kindly standard as kind/hiccup with Kindly options necessart to make the plot work.

If no data value is passed, it is considered nil.

6.2.3.1 Examples

(transpile/echarts
 ;; data
 [[1 2]
  [2 4]
  [3 9]
  [4 16]]
 ;; form
 {:xAxis {}
  :yAxis {}
  :series [{:type "scatter"
            :data 'data}]})
(-> datasets/mtcars
    (tc/select-columns [:wt :mpg :cyl :gear])
    tc/rows
    (transpile/echarts {:xAxis {:name "weight"}
                        :yAxis {:name "miles per gallon"}
                        :visualMap [{:dimension 2
                                     :categories ["4" "6" "8"]
                                     :inRange {:color ["#51689b", "#ce5c5c", "#fbc357"]}
                                     :name "cylinders"}]
                        :tooltip {:formatter '(fn [obj]
                                                (return
                                                 (+ 
                                                  "<p>weight:" (. obj value [0]) "</p>"
                                                  "<p>miles per fallon:" (. obj value [1]) "</p>"
                                                  "<p>cylinders:" (. obj value [2]) "</p>"
                                                  "<p>gears:" (. obj value [3]) "</p>")))}
                        :series [{:type "scatter"
                                  :symbolSize '(fn [value]
                                                 (-> value
                                                     (. [3])
                                                     (* 5)
                                                     return))
                                  :data 'data}]}))

6.2.4 plotly

[form]

[data form]

Given a data structure data and a form form, reate a corrseponding Plotly.js data visualization using div-with-script.

The script will include the following:

  • A Javscript variable called data is bound to the data value converted to JSON.
  • If data is a map that has some keys of symbol type, then corresponding Javascript variables named by these symbols are bound to the corresponding values converted to JSON.
  • The form transpiled to Javascript.
  • Additional code to visualize it.

The resulting structure is marked by the Kindly standard as kind/hiccup with Kindly options necessart to make the plot work.

If no data value is passed, it is considered nil.

6.2.4.1 Examples

(transpile/plotly
 ;; data
 {:x [1 2 3 4]
  :y [3 4 9 16]}
 ;; form
 {:data ['{:x data.x
           :y data.y
           :mode "markers"
           :type "scatter"}]})
(transpile/plotly
 ;; data with symbol bindings
 {'x [1 2 3 4]
  'y [3 4 9 16]}
 ;; form
 {:data ['{:x x
           :y y
           :mode "markers"
           :type "scatter"}]})

6.2.5 vega-embed

[form]

[data form]

Given a data structure data and a form form, create a corresponding Vega-Embed data visualization using div-with-script.

The script will include the following:

  • A Javscript variable called data is bound to the data value converted to JSON.
  • If data is a map that has some keys of symbol type, then corresponding Javascript variables named by these symbols are bound to the corresponding values converted to JSON.
  • The form transpiled to Javascript.
  • Additional code to visualize it.

The resulting structure is marked by the Kindly standard as kind/hiccup with Kindly options necessart to make the plot work.

If no data value is passed, it is considered nil.

6.2.5.1 Example

(transpile/vega-embed
 ;; data
 [{:x 1 :y 1}
  {:x 2 :y 4}
  {:x 3 :y 9}
  {:x 4 :y 16}]
 ;; form
 {:data {:values 'data}
  :mark "point"
  :encoding {:x {:field "x" :type "quantitative"}
             :y {:field "y" :type "quantitative"}}})

6.2.6 highcharts

[form]

[data form]

Given a data structure data and a form form, create a corresponding Highcharts data visualization using div-with-script.

The script will include the following:

  • A Javscript variable called data is bound to the data value converted to JSON.
  • If data is a map that has some keys of symbol type, then corresponding Javascript variables named by these symbols are bound to the corresponding values converted to JSON.
  • The form transpiled to Javascript.
  • Additional code to visualize it.

The resulting structure is marked by the Kindly standard as kind/hiccup with Kindly options necessart to make the plot work.

If no data value is passed, it is considered nil.

6.2.6.1 Example

(transpile/highcharts
 ;; data
 [[1 2]
  [2 4]
  [3 9]
  [4 16]]
 ;; form
 {:title {:text "a scatterplot"}
  :chart {:type "scatter"}
  :series [{:data 'data}]})

6.2.7 leaflet

[form]

[data form]

Given a data structure data and a form form, create a corresponding Leaflet data visualization using div-with-script.

The script will include the following:

  • A Javscript variable called data is bound to the data value converted to JSON.
  • If data is a map that has some keys of symbol type, then corresponding Javascript variables named by these symbols are bound to the corresponding values converted to JSON.
  • The form transpiled to Javascript, and is assumed to define a function to process a Leaflet map.
  • Additional code to visualize it.

The resulting structure is marked by the Kindly standard as kind/hiccup with Kindly options necessart to make the plot work.

If no data value is passed, it is considered nil.

6.2.7.1 Example

(transpile/leaflet
 ;; data with symbol bindings
 {'center [-37.84 144.95]
  'zoom 11
  'provider "OpenStreetMap.Mapnik"
  'marker [-37.9 144.8]
  'popup "<i style='color:purple'>Have you been here?</i>"}
 ;; form
 '(fn [m]
    (m.setView center zoom)
    (-> (L.tileLayer.provider provider)
        (. (addTo m)))
    (-> marker
        L.marker
        (. (addTo m))
        (. (bindPopup popup))
        (. (openPopup)))))

6.3 Danymic vars ๐ŸŽง

6.3.1 *base-kindly-options*

Base Kindly options for structures generated by div-with-script.

transpile/*base-kindly-options*
{:style {:height :auto}}
source: notebooks/tableplot_book/transpile_reference.clj