Browse Source

Rework the structure/API a bit

master
Brett Langdon 7 years ago
parent
commit
2707fae972
No known key found for this signature in database GPG Key ID: B664881177781B04
24 changed files with 648 additions and 191 deletions
  1. +9
    -0
      Makefile
  2. +19
    -0
      callback.go
  3. +14
    -11
      cmd/dom/main.go
  4. +37
    -0
      console.go
  5. +20
    -0
      console/console.go
  6. +70
    -61
      document.go
  7. +83
    -0
      document/document.go
  8. +36
    -28
      element.go
  9. +25
    -15
      event.go
  10. +1
    -3
      eventtargetiface.go
  11. +36
    -0
      generate/console.json
  12. +3
    -1
      generate/document.json
  13. +1
    -0
      generate/element.json
  14. +1
    -0
      generate/event.json
  15. +3
    -3
      generate/eventiface.json
  16. +1
    -2
      generate/eventtargetiface.json
  17. +219
    -28
      generate/main.go
  18. +1
    -0
      generate/node.json
  19. +3
    -1
      generate/window.json
  20. +0
    -13
      init.go
  21. +30
    -22
      node.go
  22. +15
    -0
      value.go
  23. +10
    -3
      window.go
  24. +11
    -0
      window/window.go

+ 9
- 0
Makefile View File

@ -0,0 +1,9 @@
GO_FILES = $(shell find generate/*.json | ack '/(?P<fname>.*?)\.' --output '$$+{fname}.go')
all:
go generate
.PHONY: all
clean:
rm $(GO_FILES)
.PHONY: clean

+ 19
- 0
callback.go View File

@ -0,0 +1,19 @@
package dom
import "syscall/js"
type Callback struct {
js.Callback
}
func (c *Callback) JSValue() js.Value { return c.Callback.Value }
type EventCallbackFunction func(*Event)
func NewEventCallback(c EventCallbackFunction) *Callback {
return &Callback{
Callback: js.NewEventCallback(0, func(evt js.Value) {
c(NewEvent(evt))
}),
}
}

+ 14
- 11
cmd/dom/main.go View File

@ -1,22 +1,25 @@
package main
import (
"fmt"
"syscall/js"
dom "github.com/brettlangdon/go-dom/v1"
console "github.com/brettlangdon/go-dom/v1/console"
document "github.com/brettlangdon/go-dom/v1/document"
)
func onLoad(evt js.Value) {
fmt.Println("LOADED")
fmt.Printf("%#v\r\n", evt)
func onClick(evt *dom.Event) {
elm := evt.GetTarget().ToElement()
console.Log(evt, elm)
}
func main() {
dom.Document.AddEventListener("DOMContentLoaded", js.NewEventCallback(0, onLoad))
fmt.Printf("%#v\r\n", dom.Document)
body := dom.Document.GetBody()
for i := 0; i < 50; i += 1 {
body.AppendChild(dom.Document.CreateElement(fmt.Sprintf("TEST-%d", i)))
id := "app"
app := document.GetElementById(id)
if app == nil {
console.Error("Could not find element with id %s\r\n", id)
return
}
document.AddEventListener("click", dom.NewEventCallback(onClick))
stop := make(chan int)
<-stop
}

+ 37
- 0
console.go View File

@ -0,0 +1,37 @@
// DO NOT EDIT - generated file
package dom
import "syscall/js"
type Console struct {
Value
}
func NewConsole(v js.Value) *Console {
val := Value{Value: v}
if val.IsNull() || val.IsUndefined() {
return nil
}
return val.ToConsole()
}
func (v Value) ToConsole() *Console { return &Console{Value: v} }
func (c *Console) Log(v ...interface{}) Value {
vVaridic := make([]interface{}, 0)
for _, a := range v {
vVaridic = append(vVaridic, ToJSValue(a))
}
val := Value{Value: c.Call("log", vVaridic...)}
return val
}
func (c *Console) Error(v ...interface{}) Value {
vVaridic := make([]interface{}, 0)
for _, a := range v {
vVaridic = append(vVaridic, ToJSValue(a))
}
val := Value{Value: c.Call("error", vVaridic...)}
return val
}
func (c *Console) Dir(v JSValue) Value {
val := Value{Value: c.Call("dir", ToJSValue(v))}
return val
}

+ 20
- 0
console/console.go View File

@ -0,0 +1,20 @@
// DO NOT EDIT - generated file
package console
import "syscall/js"
import dom "github.com/brettlangdon/go-dom/v1"
var c *dom.Console
func init() {
c = dom.NewConsole(js.Global().Get("console"))
}
func Log(v ...interface{}) dom.Value {
return c.Log(v...)
}
func Error(v ...interface{}) dom.Value {
return c.Error(v...)
}
func Dir(v dom.JSValue) dom.Value {
return c.Dir(v)
}

+ 70
- 61
document.go View File

@ -3,107 +3,116 @@ package dom
import "syscall/js"
type document struct {
js.Value
type Document struct {
Value
}
func (d *document) JSValue() js.Value { return d.Value }
func (d *document) GetBody() *Element {
val := d.Get("body")
return &Element{Value: val}
func NewDocument(v js.Value) *Document {
val := Value{Value: v}
if val.IsNull() || val.IsUndefined() {
return nil
}
return val.ToDocument()
}
func (v Value) ToDocument() *Document { return &Document{Value: v} }
func (d *Document) GetBody() *Element {
val := Value{Value: d.Get("body")}
return NewElement(val.JSValue())
}
func (d *document) CreateElement(tagName string) *Element {
val := d.Call("createElement", ToJSValue(tagName))
return &Element{Value: val}
func (d *Document) CreateElement(tagName string) *Element {
val := Value{Value: d.Call("createElement", ToJSValue(tagName))}
return NewElement(val.JSValue())
}
func (d *document) GetElementById(id string) *Element {
val := d.Call("getElementById", ToJSValue(id))
return &Element{Value: val}
func (d *Document) GetElementById(id string) *Element {
val := Value{Value: d.Call("getElementById", ToJSValue(id))}
return NewElement(val.JSValue())
}
func (d *document) GetElementsByName(name string) []*Element {
val := d.Call("getElementsByName", ToJSValue(name))
func (d *Document) GetElementsByName(name string) []*Element {
val := Value{Value: d.Call("getElementsByName", ToJSValue(name))}
elms := make([]*Element, 0)
for i := 0; i < val.Length(); i += 1 {
elms = append(elms, &Element{Value: val.Index(i)})
elms = append(elms, NewElement(val.Index(i)))
}
return elms
}
func (d *document) Write(markup string) {
d.Call("write", ToJSValue(markup))
func (d *Document) Write(markup string) Value {
val := Value{Value: d.Call("write", ToJSValue(markup))}
return val
}
func (d *document) AddEventListener(t string, listener js.Callback) {
d.Call("addEventListener", ToJSValue(t), ToJSValue(listener))
func (d *Document) AddEventListener(t string, listener *Callback) Value {
val := Value{Value: d.Call("addEventListener", ToJSValue(t), ToJSValue(listener))}
return val
}
func (d *document) AppendChild(aChild *Element) *Element {
val := d.Call("appendChild", ToJSValue(aChild))
return &Element{Value: val}
func (d *Document) AppendChild(aChild *Element) *Element {
val := Value{Value: d.Call("appendChild", ToJSValue(aChild))}
return NewElement(val.JSValue())
}
func (d *document) GetBaseURI() string {
val := d.Get("baseURI")
func (d *Document) GetBaseURI() string {
val := Value{Value: d.Get("baseURI")}
return val.String()
}
func (d *document) GetFirstChild() *Element {
val := d.Get("firstChild")
return &Element{Value: val}
func (d *Document) GetFirstChild() *Element {
val := Value{Value: d.Get("firstChild")}
return NewElement(val.JSValue())
}
func (d *document) GetLastChild() *Element {
val := d.Get("lastChild")
return &Element{Value: val}
func (d *Document) GetLastChild() *Element {
val := Value{Value: d.Get("lastChild")}
return NewElement(val.JSValue())
}
func (d *document) GetNextSibling() *Element {
val := d.Get("nextSibling")
return &Element{Value: val}
func (d *Document) GetNextSibling() *Element {
val := Value{Value: d.Get("nextSibling")}
return NewElement(val.JSValue())
}
func (d *document) GetPreviousSibling() *Element {
val := d.Get("previousSibling")
return &Element{Value: val}
func (d *Document) GetPreviousSibling() *Element {
val := Value{Value: d.Get("previousSibling")}
return NewElement(val.JSValue())
}
func (d *document) GetParentElement() *Element {
val := d.Get("parentElement")
return &Element{Value: val}
func (d *Document) GetParentElement() *Element {
val := Value{Value: d.Get("parentElement")}
return NewElement(val.JSValue())
}
func (d *document) GetRootElement() *Element {
val := d.Get("rootElement")
return &Element{Value: val}
func (d *Document) GetRootElement() *Element {
val := Value{Value: d.Get("rootElement")}
return NewElement(val.JSValue())
}
func (d *document) GetPrefix() string {
val := d.Get("prefix")
func (d *Document) GetPrefix() string {
val := Value{Value: d.Get("prefix")}
return val.String()
}
func (d *document) GetNodeName() string {
val := d.Get("nodeName")
func (d *Document) GetNodeName() string {
val := Value{Value: d.Get("nodeName")}
return val.String()
}
func (d *document) GetTextContent() string {
val := d.Get("textContent")
func (d *Document) GetTextContent() string {
val := Value{Value: d.Get("textContent")}
return val.String()
}
func (d *document) SetTextContent(v string) {
func (d *Document) SetTextContent(v string) {
d.Set("textContent", v)
}
func (d *document) QuerySelector(selector string) *Element {
val := d.Call("querySelector", ToJSValue(selector))
return &Element{Value: val}
func (d *Document) QuerySelector(selector string) *Element {
val := Value{Value: d.Call("querySelector", ToJSValue(selector))}
return NewElement(val.JSValue())
}
func (d *document) QuerySelectorAll(selector string) []*Element {
val := d.Call("querySelectorAll", ToJSValue(selector))
func (d *Document) QuerySelectorAll(selector string) []*Element {
val := Value{Value: d.Call("querySelectorAll", ToJSValue(selector))}
elms := make([]*Element, 0)
for i := 0; i < val.Length(); i += 1 {
elms = append(elms, &Element{Value: val.Index(i)})
elms = append(elms, NewElement(val.Index(i)))
}
return elms
}
func (d *document) GetClassName() string {
val := d.Get("className")
func (d *Document) GetClassName() string {
val := Value{Value: d.Get("className")}
return val.String()
}
func (d *document) SetClassName(v string) {
func (d *Document) SetClassName(v string) {
d.Set("className", v)
}
func (d *document) GetId() string {
val := d.Get("id")
func (d *Document) GetId() string {
val := Value{Value: d.Get("id")}
return val.String()
}
func (d *document) SetId(v string) {
func (d *Document) SetId(v string) {
d.Set("id", v)
}

+ 83
- 0
document/document.go View File

@ -0,0 +1,83 @@
// DO NOT EDIT - generated file
package document
import "syscall/js"
import dom "github.com/brettlangdon/go-dom/v1"
var d *dom.Document
func init() {
d = dom.NewDocument(js.Global().Get("document"))
}
func GetBody() *dom.Element {
return d.GetBody()
}
func CreateElement(tagName string) *dom.Element {
return d.CreateElement(tagName)
}
func GetElementById(id string) *dom.Element {
return d.GetElementById(id)
}
func GetElementsByName(name string) []*dom.Element {
return d.GetElementsByName(name)
}
func Write(markup string) dom.Value {
return d.Write(markup)
}
func AddEventListener(t string, listener *dom.Callback) dom.Value {
return d.AddEventListener(t, listener)
}
func AppendChild(aChild *dom.Element) *dom.Element {
return d.AppendChild(aChild)
}
func GetBaseURI() string {
return d.GetBaseURI()
}
func GetFirstChild() *dom.Element {
return d.GetFirstChild()
}
func GetLastChild() *dom.Element {
return d.GetLastChild()
}
func GetNextSibling() *dom.Element {
return d.GetNextSibling()
}
func GetPreviousSibling() *dom.Element {
return d.GetPreviousSibling()
}
func GetParentElement() *dom.Element {
return d.GetParentElement()
}
func GetRootElement() *dom.Element {
return d.GetRootElement()
}
func GetPrefix() string {
return d.GetPrefix()
}
func GetNodeName() string {
return d.GetNodeName()
}
func GetTextContent() string {
return d.GetTextContent()
}
func SetTextContent(v string) {
d.SetTextContent(v)
}
func QuerySelector(selector string) *dom.Element {
return d.QuerySelector(selector)
}
func QuerySelectorAll(selector string) []*dom.Element {
return d.QuerySelectorAll(selector)
}
func GetClassName() string {
return d.GetClassName()
}
func SetClassName(v string) {
d.SetClassName(v)
}
func GetId() string {
return d.GetId()
}
func SetId(v string) {
d.SetId(v)
}

+ 36
- 28
element.go View File

@ -4,81 +4,89 @@ package dom
import "syscall/js"
type Element struct {
js.Value
Value
}
func (e *Element) JSValue() js.Value { return e.Value }
func (e *Element) AddEventListener(t string, listener js.Callback) {
e.Call("addEventListener", ToJSValue(t), ToJSValue(listener))
func NewElement(v js.Value) *Element {
val := Value{Value: v}
if val.IsNull() || val.IsUndefined() {
return nil
}
return val.ToElement()
}
func (v Value) ToElement() *Element { return &Element{Value: v} }
func (e *Element) AddEventListener(t string, listener *Callback) Value {
val := Value{Value: e.Call("addEventListener", ToJSValue(t), ToJSValue(listener))}
return val
}
func (e *Element) AppendChild(aChild *Element) *Element {
val := e.Call("appendChild", ToJSValue(aChild))
return &Element{Value: val}
val := Value{Value: e.Call("appendChild", ToJSValue(aChild))}
return NewElement(val.JSValue())
}
func (e *Element) GetBaseURI() string {
val := e.Get("baseURI")
val := Value{Value: e.Get("baseURI")}
return val.String()
}
func (e *Element) GetFirstChild() *Element {
val := e.Get("firstChild")
return &Element{Value: val}
val := Value{Value: e.Get("firstChild")}
return NewElement(val.JSValue())
}
func (e *Element) GetLastChild() *Element {
val := e.Get("lastChild")
return &Element{Value: val}
val := Value{Value: e.Get("lastChild")}
return NewElement(val.JSValue())
}
func (e *Element) GetNextSibling() *Element {
val := e.Get("nextSibling")
return &Element{Value: val}
val := Value{Value: e.Get("nextSibling")}
return NewElement(val.JSValue())
}
func (e *Element) GetPreviousSibling() *Element {
val := e.Get("previousSibling")
return &Element{Value: val}
val := Value{Value: e.Get("previousSibling")}
return NewElement(val.JSValue())
}
func (e *Element) GetParentElement() *Element {
val := e.Get("parentElement")
return &Element{Value: val}
val := Value{Value: e.Get("parentElement")}
return NewElement(val.JSValue())
}
func (e *Element) GetRootElement() *Element {
val := e.Get("rootElement")
return &Element{Value: val}
val := Value{Value: e.Get("rootElement")}
return NewElement(val.JSValue())
}
func (e *Element) GetPrefix() string {
val := e.Get("prefix")
val := Value{Value: e.Get("prefix")}
return val.String()
}
func (e *Element) GetNodeName() string {
val := e.Get("nodeName")
val := Value{Value: e.Get("nodeName")}
return val.String()
}
func (e *Element) GetTextContent() string {
val := e.Get("textContent")
val := Value{Value: e.Get("textContent")}
return val.String()
}
func (e *Element) SetTextContent(v string) {
e.Set("textContent", v)
}
func (e *Element) QuerySelector(selector string) *Element {
val := e.Call("querySelector", ToJSValue(selector))
return &Element{Value: val}
val := Value{Value: e.Call("querySelector", ToJSValue(selector))}
return NewElement(val.JSValue())
}
func (e *Element) QuerySelectorAll(selector string) []*Element {
val := e.Call("querySelectorAll", ToJSValue(selector))
val := Value{Value: e.Call("querySelectorAll", ToJSValue(selector))}
elms := make([]*Element, 0)
for i := 0; i < val.Length(); i += 1 {
elms = append(elms, &Element{Value: val.Index(i)})
elms = append(elms, NewElement(val.Index(i)))
}
return elms
}
func (e *Element) GetClassName() string {
val := e.Get("className")
val := Value{Value: e.Get("className")}
return val.String()
}
func (e *Element) SetClassName(v string) {
e.Set("className", v)
}
func (e *Element) GetId() string {
val := e.Get("id")
val := Value{Value: e.Get("id")}
return val.String()
}
func (e *Element) SetId(v string) {


+ 25
- 15
event.go View File

@ -4,32 +4,42 @@ package dom
import "syscall/js"
type Event struct {
js.Value
Value
}
func (e *Event) JSValue() js.Value { return e.Value }
func (e *Event) PreventDefault() {
e.Call("preventDefault")
func NewEvent(v js.Value) *Event {
val := Value{Value: v}
if val.IsNull() || val.IsUndefined() {
return nil
}
return val.ToEvent()
}
func (v Value) ToEvent() *Event { return &Event{Value: v} }
func (e *Event) PreventDefault() Value {
val := Value{Value: e.Call("preventDefault")}
return val
}
func (e *Event) StopPropagation() {
e.Call("stopPropagation")
func (e *Event) StopPropagation() Value {
val := Value{Value: e.Call("stopPropagation")}
return val
}
func (e *Event) StopImmediatePropagation() {
e.Call("stopImmediatePropagation")
func (e *Event) StopImmediatePropagation() Value {
val := Value{Value: e.Call("stopImmediatePropagation")}
return val
}
func (e *Event) GetCurrentTarget() js.Value {
val := e.Get("currentTarget")
func (e *Event) GetCurrentTarget() Value {
val := Value{Value: e.Get("currentTarget")}
return val
}
func (e *Event) GetTarget() js.Value {
val := e.Get("target")
func (e *Event) GetTarget() Value {
val := Value{Value: e.Get("target")}
return val
}
func (e *Event) GetType() string {
val := e.Get("type")
val := Value{Value: e.Get("type")}
return val.String()
}
func (e *Event) GetSrcElement() js.Value {
val := e.Get("srcElement")
func (e *Event) GetSrcElement() Value {
val := Value{Value: e.Get("srcElement")}
return val
}

+ 1
- 3
eventtargetiface.go View File

@ -1,8 +1,6 @@
// DO NOT EDIT - generated file
package dom
import "syscall/js"
type EventTargetIFace interface {
AddEventListener(t string, listener js.Callback)
AddEventListener(t string, listener *Callback)
}

+ 36
- 0
generate/console.json View File

@ -0,0 +1,36 @@
{
"Type": "Console",
"ImportJS": true,
"GlobalAPI": "console",
"Functions": [
{
"Name": "log",
"Arguments": [
{
"Name": "v",
"Varidic": true,
"Type": "interface{}"
}
]
},
{
"Name": "error",
"Arguments": [
{
"Name": "v",
"Varidic": true,
"Type": "interface{}"
}
]
},
{
"Name": "dir",
"Arguments": [
{
"Name": "v",
"Type": "JSValue"
}
]
}
]
}

+ 3
- 1
generate/document.json View File

@ -1,5 +1,7 @@
{
"Type": "document",
"Type": "Document",
"GlobalAPI": "document",
"ImportJS": true,
"Implements": [
"EventTargetIFace",
"NodeIFace",


+ 1
- 0
generate/element.json View File

@ -1,5 +1,6 @@
{
"Type": "Element",
"ImportJS": true,
"Implements": [
"EventTargetIFace",
"NodeIFace",


+ 1
- 0
generate/event.json View File

@ -1,5 +1,6 @@
{
"Type": "Event",
"ImportJS": true,
"Implements": [
"EventIFace"
]


+ 3
- 3
generate/eventiface.json View File

@ -4,12 +4,12 @@
"Properties": [
{
"Name": "currentTarget",
"Type": "js.Value",
"Type": "Value",
"ReadOnly": true
},
{
"Name": "target",
"Type": "js.Value",
"Type": "Value",
"ReadOnly": true
},
{
@ -19,7 +19,7 @@
},
{
"Name": "srcElement",
"Type": "js.Value",
"Type": "Value",
"ReadOnly": true
}
],


+ 1
- 2
generate/eventtargetiface.json View File

@ -1,6 +1,5 @@
{
"Type": "EventTargetIFace",
"ImportJS": true,
"Interface": true,
"Functions": [
{
@ -12,7 +11,7 @@
},
{
"Name": "listener",
"Type": "js.Callback"
"Type": "*Callback"
}
]
}


+ 219
- 28
generate/main.go View File

@ -27,8 +27,9 @@ func (p TypeProperty) SetterName() string {
}
type FunctionArgument struct {
Name string
Type string
Name string
Type string
Varidic bool
}
type TypeFunction struct {
@ -43,18 +44,28 @@ func (f TypeFunction) GoName() string {
type TypeStructure struct {
Type string
GlobalAPI string
ImportJS bool
Interface bool
Inherits []string
Implements []string
Properties []TypeProperty
Functions []TypeFunction
String []string
}
func (t TypeStructure) Filename() string {
return fmt.Sprintf("%s.go", strings.ToLower(t.Type))
}
func (t TypeStructure) APIFilename() string {
return fmt.Sprintf("%s/%s.go", t.PackageName(), strings.ToLower(t.Type))
}
func (t TypeStructure) PackageName() string {
return strings.ToLower(t.GlobalAPI)
}
func (t TypeStructure) ShortName() string {
return strings.ToLower(string(t.Type[0]))
}
@ -72,20 +83,20 @@ func (t TypeStructure) writeReturnValue(out *bytes.Buffer, rt string) error {
switch rt {
case "string":
out.WriteString("return val.String()\r\n")
case "js.Value":
case "Value":
out.WriteString("return val")
case "NodeIFace":
out.WriteString("return &Node{ Value: val }\r\n")
out.WriteString("return NewNode(val.JSValue())\r\n")
case "*Element":
out.WriteString("return &Element{ Value: val }\r\n")
out.WriteString("return NewElement(val.JSValue())\r\n")
case "[]*Element":
out.WriteString("elms := make([]*Element, 0)\r\n")
out.WriteString("for i := 0; i < val.Length(); i += 1 {\r\n")
out.WriteString("\telms = append(elms, &Element{Value: val.Index(i)})\r\n")
out.WriteString("\telms = append(elms, NewElement(val.Index(i)))\r\n")
out.WriteString("}\r\n")
out.WriteString("return elms\r\n")
case "":
// skip
out.WriteString("return val")
default:
return fmt.Errorf("Unknown function return type %s", rt)
}
@ -100,44 +111,117 @@ func (t TypeStructure) writeFunctions(out *bytes.Buffer, funcs []TypeFunction) e
if i > 0 {
out.WriteString(",")
}
out.WriteString(fmt.Sprintf("%s %s", arg.Name, arg.Type))
at := arg.Type
if arg.Varidic {
at = "..." + at
}
out.WriteString(fmt.Sprintf("%s %s", arg.Name, at))
}
rt := f.ReturnType
if rt == "" {
rt = "Value"
}
out.WriteString(fmt.Sprintf(") %s {\r\n", f.ReturnType))
out.WriteString(fmt.Sprintf(") %s {\r\n", rt))
if f.ReturnType != "" {
out.WriteString("val := ")
for _, arg := range f.Arguments {
if !arg.Varidic {
continue
}
out.WriteString(fmt.Sprintf("%sVaridic := make([]interface{}, 0)\r\n", arg.Name))
out.WriteString(fmt.Sprintf("for _, a := range %s {\r\n", arg.Name))
out.WriteString(fmt.Sprintf("%sVaridic = append(%sVaridic, ToJSValue(a))\r\n", arg.Name, arg.Name))
out.WriteString("}\r\n")
}
out.WriteString(fmt.Sprintf("%s.Call(\"%s\"", t.ShortName(), f.Name))
out.WriteString(fmt.Sprintf("val := Value{ Value: %s.Call(\"%s\"", t.ShortName(), f.Name))
for _, arg := range f.Arguments {
out.WriteString(",")
out.WriteString(fmt.Sprintf("ToJSValue(%s)", arg.Name))
if arg.Varidic {
out.WriteString(fmt.Sprintf("%sVaridic...", arg.Name))
} else {
out.WriteString(fmt.Sprintf("ToJSValue(%s)", arg.Name))
}
}
out.WriteString(")\r\n")
out.WriteString(")}\r\n")
// Return value
t.writeReturnValue(out, f.ReturnType)
t.writeReturnValue(out, rt)
out.WriteString("}\r\n")
}
return nil
}
func (t TypeStructure) writeAPIFunctions(out *bytes.Buffer, funcs []TypeFunction) error {
for _, f := range funcs {
out.WriteString(fmt.Sprintf("func %s(", f.GoName()))
for i, arg := range f.Arguments {
if i > 0 {
out.WriteString(",")
}
rt := arg.Type
if rt == "*Element" {
rt = "*dom.Element"
} else if rt == "JSValue" {
rt = "dom.JSValue"
} else if rt == "*Callback" {
rt = "*dom.Callback"
}
if arg.Varidic {
rt = "..." + rt
}
out.WriteString(fmt.Sprintf("%s %s", arg.Name, rt))
}
rt := f.ReturnType
if rt == "" {
rt = "Value"
}
if rt != "string" {
if rt[0] == '*' {
rt = "*dom." + strings.TrimLeft(rt, "*")
} else if rt[0] == '[' {
rt = "[]*dom." + strings.TrimLeft(rt, "[]*")
} else {
rt = "dom." + rt
}
}
out.WriteString(fmt.Sprintf(") %s {\r\n", rt))
out.WriteString(fmt.Sprintf("return %s.%s(", t.ShortName(), f.GoName()))
for i, arg := range f.Arguments {
if i > 0 {
out.WriteString(",")
}
if arg.Varidic {
out.WriteString(fmt.Sprintf("%s...", arg.Name))
} else {
out.WriteString(fmt.Sprintf("%s", arg.Name))
}
}
out.WriteString(")}\r\n")
}
return nil
}
func (t TypeStructure) writeProperties(out *bytes.Buffer, props []TypeProperty) error {
for _, p := range props {
out.WriteString(fmt.Sprintf("func (%s *%s) %s() %s {\r\n", t.ShortName(), t.Type, p.GetterName(), p.Type))
if p.Type == "" {
return fmt.Errorf("Property %q must have a type defined", p.Name)
out.WriteString("\tval := ")
rt := p.Type
if rt == "" {
rt = "Value"
}
out.WriteString(fmt.Sprintf("val := %s.Get(\"%s\")\r\n", t.ShortName(), p.Name))
out.WriteString(fmt.Sprintf("func (%s *%s) %s() %s {\r\n", t.ShortName(), t.Type, p.GetterName(), rt))
out.WriteString(fmt.Sprintf("val := Value{ Value: %s.Get(\"%s\")}\r\n", t.ShortName(), p.Name))
// Return value
t.writeReturnValue(out, p.Type)
t.writeReturnValue(out, rt)
out.WriteString(fmt.Sprintf("}\r\n"))
if !p.ReadOnly {
out.WriteString(fmt.Sprintf("func (%s *%s) %s(v %s){\r\n", t.ShortName(), t.Type, p.SetterName(), p.Type))
out.WriteString(fmt.Sprintf("func (%s *%s) %s(v %s){\r\n", t.ShortName(), t.Type, p.SetterName(), rt))
out.WriteString(fmt.Sprintf("\t%s.Set(\"%s\", v)\r\n", t.ShortName(), p.Name))
out.WriteString("}\r\n")
}
@ -145,6 +229,35 @@ func (t TypeStructure) writeProperties(out *bytes.Buffer, props []TypeProperty)
return nil
}
func (t TypeStructure) writeAPIProperties(out *bytes.Buffer, props []TypeProperty) error {
for _, p := range props {
rt := p.Type
if rt == "" {
rt = "Value"
}
if rt != "string" {
if rt[0] == '*' {
rt = "*dom." + strings.TrimLeft(rt, "*")
} else if rt[0] == '[' {
rt = "[]*dom." + strings.TrimLeft(rt, "[]*")
} else {
rt = "dom." + rt
}
}
out.WriteString(fmt.Sprintf("func %s() %s {\r\n", p.GetterName(), rt))
out.WriteString(fmt.Sprintf("return %s.%s()", t.ShortName(), p.GetterName()))
out.WriteString(fmt.Sprintf("}\r\n"))
if !p.ReadOnly {
out.WriteString(fmt.Sprintf("func %s(v %s){\r\n", p.SetterName(), rt))
out.WriteString(fmt.Sprintf("%s.%s(v)", t.ShortName(), p.SetterName()))
out.WriteString("}\r\n")
}
}
return nil
}
func (t TypeStructure) generateInterface(out *bytes.Buffer, types map[string]TypeStructure) error {
out.WriteString(fmt.Sprintf("type %s interface {\r\n", t.Type))
@ -161,18 +274,25 @@ func (t TypeStructure) generateInterface(out *bytes.Buffer, types map[string]Typ
func (t TypeStructure) generateStruct(out *bytes.Buffer, types map[string]TypeStructure) (err error) {
out.WriteString(fmt.Sprintf("type %s struct {\r\n", t.Type))
out.WriteString("\tjs.Value\r\n")
out.WriteString("\tValue\r\n")
for _, name := range t.Inherits {
out.WriteString(fmt.Sprintf("\t%s\r\n", name))
}
out.WriteString("}\r\n")
// Convert to type
out.WriteString(fmt.Sprintf("func JSTo%s (v js.Value) *%s { return &%s{ Value: v }}", t.Type, t.Type, t.Type))
// DEV: Start with upper case means it is public
if t.Type[0] == strings.ToUpper(string(t.Type[0]))[0] {
// Constructor
out.WriteString(fmt.Sprintf("func New%s(v js.Value) *%s {\r\n", t.Type, t.Type))
out.WriteString("val := Value{ Value: v }\r\n")
out.WriteString("if val.IsNull() || val.IsUndefined() { return nil }\r\n")
out.WriteString(fmt.Sprintf("return val.To%s()\r\n", t.Type))
out.WriteString("}\r\n")
// JSValue
out.WriteString(fmt.Sprintf("func (%s *%s) JSValue() js.Value { return %s.Value }\r\n", t.ShortName(), t.Type, t.ShortName()))
// Convert to specific type helper
out.WriteString(fmt.Sprintf("func (v Value) To%s () *%s { return &%s{ Value: v }}\r\n", t.Type, t.Type, t.Type))
}
// Properties
err = t.writeProperties(out, t.Properties)
@ -214,7 +334,7 @@ func (t TypeStructure) Generate(types map[string]TypeStructure) ([]byte, error)
out.WriteString("// DO NOT EDIT - generated file\r\n")
out.WriteString("package dom\r\n")
if t.Interface == false || t.ImportJS == true {
if t.ImportJS {
out.WriteString("import \"syscall/js\"\r\n")
}
@ -231,6 +351,55 @@ func (t TypeStructure) Generate(types map[string]TypeStructure) ([]byte, error)
return format.Source(out.Bytes())
}
func (t TypeStructure) GenerateAPI(types map[string]TypeStructure) ([]byte, error) {
pkg := strings.ToLower(t.GlobalAPI)
out := bytes.NewBuffer(make([]byte, 0))
out.WriteString("// DO NOT EDIT - generated file\r\n")
out.WriteString(fmt.Sprintf("package %s\r\n", pkg))
if t.ImportJS {
out.WriteString("import \"syscall/js\"\r\n")
}
out.WriteString("import dom \"github.com/brettlangdon/go-dom/v1\"\r\n")
out.WriteString(fmt.Sprintf("var %s *dom.%s\r\n", t.ShortName(), t.Type))
out.WriteString("func init() {\r\n")
out.WriteString(fmt.Sprintf("%s = dom.New%s(js.Global().Get(\"%s\"))\r\n", t.ShortName(), t.Type, t.GlobalAPI))
out.WriteString("}\r\n")
err := t.writeAPIProperties(out, t.Properties)
if err != nil {
return nil, err
}
err = t.writeAPIFunctions(out, t.Functions)
if err != nil {
return nil, err
}
// Interfaces
for _, it := range t.Implements {
i, ok := types[it]
if !ok {
return nil, fmt.Errorf("%q cannot implement unknown type %q", t.Type, it)
}
// Functions
err = t.writeAPIFunctions(out, i.Functions)
if err != nil {
return nil, err
}
// Properties
err = t.writeAPIProperties(out, i.Properties)
if err != nil {
return nil, err
}
}
return format.Source(out.Bytes())
}
func loadFile(fname string) (t TypeStructure, err error) {
fp, err := os.Open(fname)
if err != nil {
@ -259,6 +428,28 @@ func processType(t TypeStructure, types map[string]TypeStructure) error {
}
defer out.Close()
_, err = out.Write(contents)
if err != nil {
return err
}
if t.GlobalAPI == "" {
return nil
}
contents, err = t.GenerateAPI(types)
if err != nil {
return err
}
err = os.MkdirAll(t.PackageName(), os.ModePerm)
if err != nil {
return err
}
api, err := os.OpenFile(t.APIFilename(), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer api.Close()
_, err = api.Write(contents)
return err
}


+ 1
- 0
generate/node.json View File

@ -1,5 +1,6 @@
{
"Type": "Node",
"ImportJS": true,
"Implements": [
"EventTargetIFace",
"NodeIFace"


+ 3
- 1
generate/window.json View File

@ -1,3 +1,5 @@
{
"Type": "window"
"Type": "Window",
"GlobalAPI": "window",
"ImportJS": true
}

+ 0
- 13
init.go View File

@ -1,15 +1,2 @@
//go:generate go run generate/main.go
package dom
import "syscall/js"
var (
Document *document
Window *window
)
func init() {
g := js.Global()
Document = &document{Value: g.Get("document")}
Window = &window{Value: g.Get("window")}
}

+ 30
- 22
node.go View File

@ -4,55 +4,63 @@ package dom
import "syscall/js"
type Node struct {
js.Value
Value
}
func (n *Node) JSValue() js.Value { return n.Value }
func (n *Node) AddEventListener(t string, listener js.Callback) {
n.Call("addEventListener", ToJSValue(t), ToJSValue(listener))
func NewNode(v js.Value) *Node {
val := Value{Value: v}
if val.IsNull() || val.IsUndefined() {
return nil
}
return val.ToNode()
}
func (v Value) ToNode() *Node { return &Node{Value: v} }
func (n *Node) AddEventListener(t string, listener *Callback) Value {
val := Value{Value: n.Call("addEventListener", ToJSValue(t), ToJSValue(listener))}
return val
}
func (n *Node) AppendChild(aChild *Element) *Element {
val := n.Call("appendChild", ToJSValue(aChild))
return &Element{Value: val}
val := Value{Value: n.Call("appendChild", ToJSValue(aChild))}
return NewElement(val.JSValue())
}
func (n *Node) GetBaseURI() string {
val := n.Get("baseURI")
val := Value{Value: n.Get("baseURI")}
return val.String()
}
func (n *Node) GetFirstChild() *Element {
val := n.Get("firstChild")
return &Element{Value: val}
val := Value{Value: n.Get("firstChild")}
return NewElement(val.JSValue())
}
func (n *Node) GetLastChild() *Element {
val := n.Get("lastChild")
return &Element{Value: val}
val := Value{Value: n.Get("lastChild")}
return NewElement(val.JSValue())
}
func (n *Node) GetNextSibling() *Element {
val := n.Get("nextSibling")
return &Element{Value: val}
val := Value{Value: n.Get("nextSibling")}
return NewElement(val.JSValue())
}
func (n *Node) GetPreviousSibling() *Element {
val := n.Get("previousSibling")
return &Element{Value: val}
val := Value{Value: n.Get("previousSibling")}
return NewElement(val.JSValue())
}
func (n *Node) GetParentElement() *Element {
val := n.Get("parentElement")
return &Element{Value: val}
val := Value{Value: n.Get("parentElement")}
return NewElement(val.JSValue())
}
func (n *Node) GetRootElement() *Element {
val := n.Get("rootElement")
return &Element{Value: val}
val := Value{Value: n.Get("rootElement")}
return NewElement(val.JSValue())
}
func (n *Node) GetPrefix() string {
val := n.Get("prefix")
val := Value{Value: n.Get("prefix")}
return val.String()
}
func (n *Node) GetNodeName() string {
val := n.Get("nodeName")
val := Value{Value: n.Get("nodeName")}
return val.String()
}
func (n *Node) GetTextContent() string {
val := n.Get("textContent")
val := Value{Value: n.Get("textContent")}
return val.String()
}
func (n *Node) SetTextContent(v string) {


+ 15
- 0
value.go View File

@ -12,3 +12,18 @@ func ToJSValue(x interface{}) js.Value {
}
return js.ValueOf(x)
}
type Value struct {
js.Value
}
func (v Value) JSValue() js.Value { return v.Value }
func (v Value) IsUndefined() bool { return v.Type() == js.TypeUndefined }
func (v Value) IsNull() bool { return v.Type() == js.TypeNull }
func (v Value) IsBoolean() bool { return v.Type() == js.TypeBoolean }
func (v Value) IsNumber() bool { return v.Type() == js.TypeNumber }
func (v Value) IsString() bool { return v.Type() == js.TypeString }
func (v Value) IsSymbol() bool { return v.Type() == js.TypeSymbol }
func (v Value) IsObject() bool { return v.Type() == js.TypeObject }
func (v Value) IsFunction() bool { return v.Type() == js.TypeFunction }

+ 10
- 3
window.go View File

@ -3,8 +3,15 @@ package dom
import "syscall/js"
type window struct {
js.Value
type Window struct {
Value
}
func (w *window) JSValue() js.Value { return w.Value }
func NewWindow(v js.Value) *Window {
val := Value{Value: v}
if val.IsNull() || val.IsUndefined() {
return nil
}
return val.ToWindow()
}
func (v Value) ToWindow() *Window { return &Window{Value: v} }

+ 11
- 0
window/window.go View File

@ -0,0 +1,11 @@
// DO NOT EDIT - generated file
package window
import "syscall/js"
import dom "github.com/brettlangdon/go-dom/v1"
var w *dom.Window
func init() {
w = dom.NewWindow(js.Global().Get("window"))
}

Loading…
Cancel
Save