Adding JS libraries and code

Integrating third-party JavaScript libraries into your Genie applications can unlock new levels of interactivity and functionality. There exist two way to do this in Stipple: using the page function, which is simpler and results in less code, or with a layout, which offers more customization.

With the add_script method, you can insert links to javascript files in the page head:

Stipple.Layout.add_script("https://cdn.library.com/lib.js"),

Inserting code in the page body

You can include scripts in the page using the @deps macro as:

lib_module() = [
    script(type ="module", "
    // script code goes here
    Console.log('hello world')
    ")
]

@deps lib_module

Here's a full example that incorporates the CesiumJS library to create a 3D globe:

using GenieFramework

@genietools

cesium_token = "your token"

Stipple.Layout.add_script("https://cesium.com/downloads/cesiumjs/releases/1.113/Build/Cesium/Cesium.js")
Stipple.layout.add_css("https://cesium.com/downloads/cesiumjs/releases/1.113/Build/Cesium/Widgets/widgets.css")

cesium_module() = [
  script(type = "module", "
    Cesium.Ion.defaultAccessToken = '$cesium_token';

    // Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID.
    const viewer = new Cesium.Viewer('cesiumContainer', {
      terrain: Cesium.Terrain.fromWorldTerrain(),
    });    

    // Fly the camera to San Francisco at the given longitude, latitude, and height.
    viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(-122.4175, 37.655, 400),
      orientation: {
        heading: Cesium.Math.toRadians(0.0),
        pitch: Cesium.Math.toRadians(-15.0),
      }
    });

    // Add Cesium OSM Buildings, a global 3D buildings layer.
    const buildingTileset = await Cesium.createOsmBuildingsAsync();
    viewer.scene.primitives.add(buildingTileset);
  ")
]

@deps cesium_module


@app begin
  @in mybutton = false

  @onbutton mybutton begin
        println("button clicked")
  end
end

ui() = [
  row(cell(class = "st-module",
    h1("My first Cesium App")
  ))

  row(cell(class = "st-module", [
    h3("Demo")
    htmldiv(id="cesiumContainer")
  ]))
]

@page("/", ui, DEFAULT_LAYOUT(head_content = cesium_head))

up()

Using a layout

An alternative way to include third-party libraries is to use a layout. As a starting point, you can use the one returned by the function Stipple.ReactiveTools.BASE_LAYOUT, which includes everything a Stipple app needs. Then, you can edit its head and footer to include your JS libraries and code.

app.jl
@page("/", "ui.jl", layout = "layout.html")
layout.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">

    <% Stipple.sesstoken() %>
    <title>Genie App</title>
    <% if isfile(joinpath(Genie.config.server_document_root, "css", "genieapp.css")) %>
    <link rel='stylesheet' href='/css/genieapp.css'>
    <% else %>
    <% end %>
    <% if isfile(joinpath(Genie.config.server_document_root, "css", "autogenerated.css")) %>
    <link rel='stylesheet' href='/css/autogenerated.css'>
    <% else %>
    <% end %>
    <style>
      ._genie_logo {
        background:url('https://genieframework.com/logos/genie/logo-simple-with-padding.svg') no-repeat;background-size:40px;
        padding-top:22px;padding-right:10px;color:transparent;font-size:9pt;
      }
      ._genie .row .col-12 { width:50%;margin:auto; }
    </style>
  </head>
  <body>
    <div class='container'>
      <div class='row'>
        <div class='col-12'>
          <% page(model, partial = true, v__cloak = true, [@yield], @iif(:isready)) %>
        </div>
      </div>
    </div>
    <% if isfile(joinpath(Genie.config.server_document_root, "js", "genieapp.js")) %>
    <script src='/js/genieapp.js'></script>
    <% else %>
    <% end %>
    <footer class='_genie container'>
      <div class='row'>
        <div class='col-12'>
          <p class='text-muted credit' style='text-align:center;color:#8d99ae;'>Built with
            <a href='https://genieframework.com' target='_blank' class='_genie_logo' ref='nofollow'>Genie</a>
          </p>
        </div>
      </div>
    </footer>
  </body>
</html>