| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- package app
- import (
- "context"
- "io"
- "reflect"
- "strings"
- )
- // UI is the interface that describes a user interface element such as
- // components and HTML elements.
- type UI interface {
- // Kind represents the specific kind of a UI element.
- Kind() Kind
- // JSValue returns the javascript value linked to the element.
- JSValue() Value
- // Reports whether the element is mounted.
- Mounted() bool
- name() string
- self() UI
- setSelf(UI)
- getContext() context.Context
- getDispatcher() Dispatcher
- getAttributes() attributes
- getEventHandlers() eventHandlers
- getParent() UI
- setParent(UI)
- getChildren() []UI
- mount(Dispatcher) error
- dismount()
- canUpdateWith(UI) bool
- updateWith(UI) error
- preRender(Page)
- onComponentEvent(any)
- html(w io.Writer)
- htmlWithIndent(w io.Writer, indent int)
- }
- // Kind represents the specific kind of a user interface element.
- type Kind uint
- func (k Kind) String() string {
- switch k {
- case SimpleText:
- return "text"
- case HTML:
- return "html"
- case Component:
- return "component"
- case Selector:
- return "selector"
- case RawHTML:
- return "raw"
- default:
- return "undefined"
- }
- }
- const (
- // UndefinedElem represents an undefined UI element.
- UndefinedElem Kind = iota
- // SimpleText represents a simple text element.
- SimpleText
- // HTML represents an HTML element.
- HTML
- // Component represents a customized, independent and reusable UI element.
- Component
- // Selector represents an element that is used to select a subset of
- // elements within a given list.
- Selector
- // RawHTML represents an HTML element obtained from a raw HTML code snippet.
- RawHTML
- )
- // FilterUIElems returns a filtered version of the given UI elements where
- // selector elements such as If and Range are interpreted and removed. It also
- // remove nil elements.
- //
- // It should be used only when implementing components that can accept content
- // with variadic arguments like HTML elements Body method.
- func FilterUIElems(v ...UI) []UI {
- if len(v) == 0 {
- return nil
- }
- remove := func(i int) {
- copy(v[i:], v[i+1:])
- v[len(v)-1] = nil
- v = v[:len(v)-1]
- }
- var b []UI
- replaceAt := func(i int, s ...UI) {
- b = append(b, v[i+1:]...)
- v = append(v[:i], s...)
- v = append(v, b...)
- b = b[:0]
- }
- for i := len(v) - 1; i >= 0; i-- {
- e := v[i]
- if ev := reflect.ValueOf(e); e == nil || ev.Kind() == reflect.Pointer && ev.IsNil() {
- remove(i)
- continue
- }
- switch e.Kind() {
- case SimpleText, HTML, Component, RawHTML:
- case Selector:
- replaceAt(i, e.getChildren()...)
- default:
- remove(i)
- }
- }
- return v
- }
- func mount(d Dispatcher, n UI) error {
- n.setSelf(n)
- return n.mount(d)
- }
- func dismount(n UI) {
- n.dismount()
- n.setSelf(nil)
- }
- func canUpdate(a, b UI) bool {
- a.setSelf(a)
- b.setSelf(b)
- return a.canUpdateWith(b)
- }
- func update(a, b UI) error {
- a.setSelf(a)
- b.setSelf(b)
- return a.updateWith(b)
- }
- // HTMLString return an HTML string representation of the given UI element.
- func HTMLString(ui UI) string {
- var w strings.Builder
- PrintHTML(&w, ui)
- return w.String()
- }
- // HTMLStringWithIndent return an indented HTML string representation of the
- // given UI element.
- func HTMLStringWithIndent(ui UI) string {
- var w strings.Builder
- PrintHTMLWithIndent(&w, ui)
- return w.String()
- }
- // PrintHTML writes an HTML representation of the UI element into the given
- // writer.
- func PrintHTML(w io.Writer, ui UI) {
- if !ui.Mounted() {
- ui.setSelf(ui)
- }
- ui.html(w)
- }
- // PrintHTMLWithIndent writes an idented HTML representation of the UI element
- // into the given writer.
- func PrintHTMLWithIndent(w io.Writer, ui UI) {
- if !ui.Mounted() {
- ui.setSelf(ui)
- }
- ui.htmlWithIndent(w, 0)
- }
|