pod domkit

DOM Based UI Framework

Classes

AccordionBox

AccordionBox displays collapsible content panels for presenting information in a limited amount of vertical space.

Box

Box defaults style to

Button

Button is a widget that invokes an action when pressed.

CardBox

CardBox lays out child elements as a stack of cards, where only one card may be visible at a time.

Checkbox

Checkbox displays a checkbox that can be toggled on and off.

Combo

Combo combines a TextField and ListButton into a single widget that allows a user to select from a list or manually enter a value.

Dialog

Dialog manages a modal window above page content.

DomListener

DomListener monitors the DOM and invokes callbacks when modifications occur.

DragTarget

DragTarget converts an Elem into a drag target for a drag-and-drop events.

DropTarget

DropTarget converts an Elem into a drop target for drag and drop events.

FlexBox

FlexBox lays out child elements based on the CSS Flexbox Layout module, which primarily lays out items along a single axis (the main axis).

FlipBox

FlipBox displays content on a 3D card, and allows transitiong between the front and back using a flipping animation.

FlowBox

FlowBox lays out its children in a one-directional flow.

GridBox

GridBox lays its children out in a two dimensional grid.

Label

Simple text based element.

Link

Hyperlink anchor element

ListButton

ListButton allows user selection of an item in a list by showing a listbox popup on button press.

Menu

Popup menu

MenuItem

MenuItem for a Menu

Popup

Popup window which can be closed clicking outside of element.

ProgressBar

ProgressBar visualizes progress of a long running operation

RadioButton

RadioButton displays a radio button.

SashBox

SashBox lays out children in a single direction allowing both fixed and pertange sizes that can fill the parent container.

ScrollBox

ScrollBox displays content in a scrollable viewport.

Selection

Selection manages the selected items and/or indexes

Table

Table displays a grid of rows and columns.

TableEvent

TableEvents are generated by Table cells.

TableFlags

Table specific flags for eventing

TableModel

TableModel backs the data model for a Table

TextArea

Multi-line text input element

TextField

Text field input element

ToggleButton

ToggleButton models a boolean state toggled by pressing a button.

Tree

Tree visualizes a TreeModel as a series of expandable nodes.

TreeFlags

Tree specific flags for eventing

TreeNode

TreeNode models a node in a Tree.

Enums

Align

Alignment enums: top, left, bottom, right, center

Dir

Direction enums: up, down, left, right

Overview

DomKit is a DOM based UI toolkit.

Layout

DomKit leverages the standard browser layout engine. So anything you might do in a HTML page will translate to DomKit. However, since DomKit is specifically targeted at building rich user interfaces, it does include some standard widgets to simplify constructing common UI designs.

Box

Box is the base class for Elems who are intended to layout out their children in a specific way. Box defaults several CSS properties to simplify composition:

display: block;
box-sizing: border-box;
width: 100%;
height: 100%;
position: relative;

GridBox

GridBox lays out children in a table format with a fixed number of columns and rows. The GridBox.cellStyle command may be used to stylize groups of cells:

GridBox
{
  it.cellStyle("all", "all", "padding: 4px")
  it.cellStyle("all", "odd", "background: #eee")
  it.cellStyle("all",     3, "border-top: 1px solid #ddd")

  it.addRow([Label { it.text="First Name:" }, TextField { ... }])
  it.addRow([Label { it.text="Last Name:"  }, TextField { ... }])
  it.addRow([null], [2]) // colspan=2
  it.addRow([null, Button { it.text="Submit" }])
}

By default GridBox will use preferred sizes for all child cells. This will often times leave free space around the GridBox. To adjust how the GridBox is positioned in this space use GridBox.align:

GridBox
{
  it.align = "center"
  ...
}

SashBox

SashBox divides a container size in one direction with flexible child sizes:

SashBox
{
  it.sizes = ["25px, "100%", "50px"]
  Elem { ... },
  Elem { ... },
  Elem { ... },
}

Fixed px sizes can be mixed with % sizes to divide space. By default children are laid out left to right. To layout to to bottom, configure the SashBox.dir field:

SashBox
{
  it.dir = Dir.down
  it.sizes = ["100px", "100%"]
  Elem { ... },
  Elem { ... },
}

By default, sashes are fixed, but you can enable resizing by setting the SashBox.resizable field:

SashBox
{
  it.sizes = ["40%", "60%"]
  it.resizable = true
  Elem { ... },
  Elem { ... },
}

FlowBox

FlowBox lays out child nodes in a single direction:

FlowBox
{
  Button { ... },
  Button { ... },
  Button { ... },
}

The alignment of children inside a FlowBox can be adjusted using FlowBox.halign:

FlowBox
{
  it.halign = Align.center
  ...
}

The spacing between each child can be configured use FlowBox.gaps, where each gap is the space between index and index+1 children:

FlowBox
{
  it.gaps = ["4px", "10px"]
  Button { ... },  // 4px gap
  Button { ... },  // 10px gap
  Button { ... },
}

FlowBox.gaps will be cycled if < children:

FlowBox
{
  it.gaps = ["4px", "1px"]
  Button { ... },   // 4px gap
  Button { ... },   // 1px gap
  Button { ... },   // 4px gap
  Button { ... },
}

FlowBox
{
  it.gaps = ["4px"]
  ...  // 4px gap between all children
}

CardBox

CardBox lays out child elements as a stack of cards, where only one card may be visible at a time:

CardBox
{
  Elem { ... },
  Elem { ... },
  Elem { ... },
  Elem { ... },
}

The visible card is changed using CardBox.selectedIndex:

cardBox.selectedIndex = 2

AccordionBox

AccordionBox displays collapsible content panels with a header element for presenting information in a limited amount of vertical space. The header element is used to collapse or expand the child content.

AccordionBox
{
  it.addGroup(Label { it.text="Section 1 "}, [...])
  it.addGroup(Label { it.text="Section 2 "}, [...])
  it.addGroup(Label { it.text="Section 3 "}, [...])
}

FlexBox

FlexBox lays out children based on the CSS Flexbox layout model. Flexbox can be a little overwhelming to wrap your head around. A great tutorial that manages to explain it can be found here:

https://css-tricks.com/snippets/css/a-guide-to-flexbox/

In practice, only a subset of the flex model is used in domkit, and should be contained to "micro-layouts" for best results. The most common use case is to layout toolbars, such that items are centered vertically and to left/center/right align items.

This example creates a toolbar with several buttons left-aligned:

FlexBox
{
  it.flex = ["1 1 auto"]
  GridBox {
    it.colGaps = "4px"
    Button { ... },
    Button { ... },
    Button { ... },
  },
}

To add another button that is right-aligned to the toolbar:

FlexBox
{
  it.flex = ["1 1 auto", "0 0 auto"]
  GridBox { ... },
  Button { ... },
}

The flex argument specifies how the parents size should be distributed to its children. There should be a flex entry for each child. The "0 0 auto" entry indicates this child should be given its preferred width, and should not grow or shrink as the parent size changes. The "1 1 auto" argument indicates that first our child should be laid out with its preferred size, and then any left over space should be allocated as well. This in effect pushes the second child to be right aligned in the container.

Widgets

Label

Label simply displays text content. Labels are designed to naturally align vertically with control widgets like Button:

Label { it.text="My Label" }

Button

Button is a widget that invokes an action when pressed.

Button
{
  it.text = "Press me"
  it.onAction { echo("Pressed!") }
}

Button
{
  onAction { echo("Pressed!") }
  Elem("b") { it.text="Really Press me!" },
}

ToggleButton

ToggleButton models a boolean state toggled by pressing a button:

ToggleButton
{
  it.text = "Toggle Me"
  it.onAction |b| { echo("state: $b.selected") }
}

The content may be modified based on selected state by specifying elemOn and elemOff:

ToggleButton
{
  it.elemOn  = Elem { it.text="On" }
  it.elemOff = Elem { it.text="Off" }
  it.selected = false   // make sure to set default state last
}

You may also pass any object to elemOn and elemOff and the Elem instance will be created using Obj.toStr:

ToggleButton
{
  it.elemOn  = "On"
  it.elemOff = "Off"
}

ListButton

ListButton allows user selection of a list item by showing a listbox popup when a button is pressed:

ListButton
{
  it.items = ["Alpha", "Beta", "Gamma"]
  it.onSelect |b| { echo("Selected $b.sel.item") }
}

By default ListButton will display items using toStr. To customize how the display element is is created, use onElem:

ListButton
{
  it.items = [1,2,3,4]
  it.onElem |v| { "Item #$v" }
}

Combo

Combo combines a TextField and ListButton into a single widget that allows a user to select from a list or manually enter a value. The internal TextField component is available with Combo.field. In practice you will interact with Combo the same as TextField, so Combo.field is the right place to register event callbacks such as onModify and onAction.

Combo
{
  it.items = ["Alpha, "Beta", "Gamma"]
  it.field.onAction |f| { echo("value: $f.val") }
}

Checkbox

Checkbox displays a checkbox that can be toggled on and off.

Checkbox {}
Checkbox { it.checked = true }

On its own, only the actual checkbox is displayed. Generally its desirable to display a text label attached to the checkbox. You can extend the click target area to this label using the wrap method:

Checkbox {}.wrap("You can click here too!")

To receive callbacks when the state changes, add an onAction event handler:

Checkbox
{
  it.onAction |c| { echo("checked: $c.checked") }
}

TODO

ProgressBar

TODO

RadioButton

TODO

TextField

TODO

TextArea

TODO

Groups

Some widgets can be combined to create a seamless group by using a a FlowBox with a -1px gap spacing:

FlowBox
{
  it.gaps = ["-1px"]
  Button { ... }
  Button { ... }
  Button { ... }
}

These are the supported widgets for group spacing:

TODO: doc domkit-group CSS classs

Table

TODO

Tree

TODO

Modals

Dialog

Dialog opens a modal window above page content.

d := Dialog
{
  it.title = "Hello"
  Box
  {
    it.style->padding = "12px"
    it.text = "Hello, World"
  },
}
d.buttons = [
  Button { it.text="Close"; onAction { d.close }}
}
d.open

To modify the default size of dialog, override the width and height styles:

Dialog
{
 it.style->width  = "600px"
 it.style->height = "400px"
 it.title = "Hello"
 Box { ... },
}

Popup opens a popup window above page content. The popup is dismissed by clicking anywhere outside of the popup, or by pressing the Esc key:

p := Popup
{
  Elem {... },
}
p.open(100, 100)

Drag and Drop

Any Elem can be converted into a drag target using DragTarget:

Box
{
  it.text = "Drag me"
  DragTarget.bind(it)
  {
    // get the data payload when a drag event starts
    it.onDrag { "Hi :)" }
  }
}

Likewise any Elem can be converted into a drop target using DropTarget:

Box
{
  it.text = "Drop on me"
  DropTarget.bind(it)
  {
    it.onDrop |data| { echo("# drop: $data") }
  }
}

You may specify if the given drag data is able to be dropped on a DropTarget using canDrop:

DropTarget.bind(elem)
{
  it.canDrop |data| { data == "foo" }
  it.onDrop  |data| { echo("# drop: $data") }
}

DomListener

TODO