Standard library - dom and domUtil

module dom                  // whole module since PR#781
  type domRepr = dom
  type domProps

  // Property lists
  def propertyEmpty : domProps
  def propertyMap : map(data) -> domProps
  def propertyAdd : domProps -> domProps -> domProps
  def restoreProperties : domProps -> map(data)

  // Create
  def empty : dom
  def createNode : string -> map(data) -> map(data) -> map(data) -> map(data) -> map(data) -> array(dom) -> dom
  def createNodeFromProps : string -> domProps -> domProps -> domProps -> domProps -> domProps -> array(dom) -> dom
  def createCellRef : number -> option(string) -> dom
  def createTree : data -> dom

  // Access
  def children : dom -> array(dom)
  def rmxType : dom -> string
  def props : dom -> domProps
  def style : dom -> domProps
  def events : dom -> domProps

  // Serialize
  def toStream : dom -> number*
  def toArray : dom -> array(number)
  def fromStream : number* -> dom
  def fromArray : array(number) -> dom

  // Helpers
  def isDom : data -> bool
  def toDom : data -> option(dom)
  def isEmpty : data -> bool
  def isNode : data -> bool
  def isCellRef : data -> bool

  // Symbol table
  def symbolNumber : number -> number
  def symbol : data -> number
  def lookup : number -> data
  def emptyControlSymbol : number
  def firstChildControlSymbol : number
  def nextChildControlSymbol : number
  def endChildControlSymbol : number
  def dynamicControlSymbol : number
  def singleCellRefControlSymbol : number
  def arrayCellRefControlSymbol : number
  def numControlSymbols : number
  def numIntegerLiterals : number
  def numReservedSymbols : number
  def symbolOffset : number
  def integerOffset : number
module end
module domUtil                  // whole module since PR#786
  // Follow references
  def deref : dom -> dom

  // Restore
  def restore : dom -> data
  def restoreIf : bool -> dom -> data
  def restoreArrayIf : bool -> array(dom) -> array(data)
module end

The dom data type

The type dom is a predefined type, and there are special notations for it.

You can create dom values with

{ _rmx_type: "dom_group",
  props: { style: { s1: v1, ... },
           events: { e1: u1, ... },
           p1: q1,
           ...
         },
  children: [ ... ]
}:dom

which looks a lot like a normal nested object, but because of the :dom suffix a dom value is created instead. There are a couple of restrictions:

If you need to create dom values in a more dynamic way there is the helper function dom.createTree (see below). Note, however, that dom.createTree is a lot slower than the above dom literals.

dom values are considered as being data, so serialization is possible. Remember, however, that dom values include references to the symbol table which is stored with the session. In particular, you must not transmit dom values to other sessions, e.g. sending them to agents or retrieving them from agents!

DOM and sync cells

A sync cell is a special cell that can only contain DOM and whose contents are transmitted to the client via the synchronization protocol (so far enabled). The syntax is

sync cell x = ...

and the expression on the right-hand side must be of type dom.

If a sync cell is referenced from another cell (of any type), the DOM of the sync cell is not looked up directly, but by a so-called cell reference. Compare:

// x2 contains the DOM of x1 directly:
cell x1 = { _rmx_type: "dom_group" }:dom
cell x2 = { _rmx_type: "dom_group", children:[x1] }:dom

// y2 contains only a cell reference to y1:
sync cell y1 = { _rmx_type: "dom_group" }:dom
cell y2 = { _rmx_type: "dom_group", children:[y1] }:dom

If you convert here x2 and y2 back to a normal object (with domUtil.restore) you get:

cell x3 = domUtil.restore(x2)
// results in: { _rmx_type:"dom_group", children:[ { _rmx_type: "dom_group" } ] }

cell y3 = domUtil.restore(y2)
// results in: { _rmx_type:"dom_group", children:[ { _rmx_type: "cell", index: <index_of_y2> } ] }

and the index is the number of the cell y2 in the array of cells that is stored with the spreadsheet.

Property lists