diff --git a/sui/core/build.go b/sui/core/build.go index 0009c90c..b1b415c4 100644 --- a/sui/core/build.go +++ b/sui/core/build.go @@ -170,6 +170,9 @@ func (page *Page) BuildAsComponent(sel *goquery.Selection, ctx *BuildContext, op return "", err } + // Bind the component events + page.BindEvent(ctx, doc.Selection, component) + body := doc.Selection.Find("body") if body.Children().Length() == 0 { @@ -553,6 +556,11 @@ func (page *Page) BuildScripts(ctx *BuildContext, option *BuildOption, component component = ComponentName(page.Route, option.ScriptMinify) } + arguments := "" + if !ispage { + arguments = "arguments[0]" + } + scripts := []ScriptNode{} if page.Codes.JS.Code == "" && page.Codes.TS.Code == "" { return scripts, nil @@ -566,17 +574,18 @@ func (page *Page) BuildScripts(ctx *BuildContext, option *BuildOption, component var imports []string = nil var source []byte = nil if page.Codes.TS.Code != "" { - source, imports, err = page.CompileTS([]byte(page.Codes.TS.Code), option.ScriptMinify) + code := fmt.Sprintf("this.store = new __sui_store(%s);\n%s", arguments, page.Codes.TS.Code) + source, imports, err = page.CompileTS([]byte(code), option.ScriptMinify) if err != nil { return nil, err } } else if page.Codes.JS.Code != "" { - source, imports, err = page.CompileJS([]byte(page.Codes.JS.Code), option.ScriptMinify) + code := fmt.Sprintf("this.store = new __sui_store(%s);\n%s", arguments, page.Codes.JS.Code) + source, imports, err = page.CompileJS([]byte(code), option.ScriptMinify) if err != nil { return nil, err } - } // Add the script diff --git a/sui/core/compile.go b/sui/core/compile.go index 27cd6735..fb5a0693 100644 --- a/sui/core/compile.go +++ b/sui/core/compile.go @@ -58,6 +58,9 @@ func (page *Page) Compile(ctx *BuildContext, option *BuildOption) (string, []str } + // SUI lib + head.AppendHtml("\n\n" + `` + "\n\n") + // Page Config page.Config = page.GetConfig() diff --git a/sui/core/event.go b/sui/core/event.go index c959da48..dcdc6890 100644 --- a/sui/core/event.go +++ b/sui/core/event.go @@ -10,14 +10,26 @@ import ( ) // BindEvent is a method that binds events to the page. -func (page *Page) BindEvent(ctx *BuildContext, sel *goquery.Selection) { +func (page *Page) BindEvent(ctx *BuildContext, sel *goquery.Selection, component ...string) { + + // Component events + if len(component) > 0 && component[0] != "" { + fmt.Println("component events:", page.Route, component[0]) + matcher := NewAttrPrefixMatcher(`s:on-`) + sel.FindMatcher(matcher).Each(func(i int, s *goquery.Selection) { + fmt.Println("\tcomponent event", i, s.Nodes[0].Data) + page.appendEventScript(ctx, s, component[0]) + }) + return + } + matcher := NewAttrPrefixMatcher(`s:on-`) sel.FindMatcher(matcher).Each(func(i int, s *goquery.Selection) { - page.appendEventScript(ctx, s) + page.appendEventScript(ctx, s, "") }) } -func (page *Page) appendEventScript(ctx *BuildContext, sel *goquery.Selection) { +func (page *Page) appendEventScript(ctx *BuildContext, sel *goquery.Selection, component string) { if len(sel.Nodes) == 0 { return @@ -71,13 +83,18 @@ func (page *Page) appendEventScript(ctx *BuildContext, sel *goquery.Selection) { source := "" for name, handler := range events { - source += pageEventInjectScript(id, name, dataRaw, jsonRaw, handler) + "\n" + if component == "" { + source += pageEventInjectScript(id, name, dataRaw, jsonRaw, handler) + "\n" + } else { + source += compEventInjectScript(id, name, component, dataRaw, jsonRaw, handler) + "\n" + } sel.RemoveAttr(fmt.Sprintf("s:on-%s", name)) } ctx.scripts = append(ctx.scripts, ScriptNode{ Source: source, Namespace: page.namespace, + Component: component, Attrs: []html.Attribute{{Key: "event", Val: id}}, }) diff --git a/sui/core/injections.go b/sui/core/injections.go index 14eb5447..70375ad8 100644 --- a/sui/core/injections.go +++ b/sui/core/injections.go @@ -2,11 +2,7 @@ package core import "fmt" -const initScriptTmpl = ` - try { - var __sui_data = %s; - } catch (e) { console.log('init data error:', e); } - +const suiLibScript = ` function __sui_event_handler(event, dataKeys, jsonKeys, elm, handler) { const data = {}; @@ -26,10 +22,47 @@ const initScriptTmpl = ` } } }) - + handler && handler(event, data, elm); }; + function __sui_store(elm) { + elm = elm || document.body; + + this.Get = function (key) { + return elm.getAttribute("data:" + key); + } + + this.Set = function (key, value) { + elm.setAttribute("data:" + key, value); + } + + this.GetJSON = function (key) { + const value = elm.getAttribute("json:" + key); + if (value && value != "") { + try { + const res = JSON.parse(value); + return res; + } catch (e) { + const message = e.message || e || "An error occurred"; + console.error(` + "`[SUI] Event Handler Error: ${message}`" + `, elm); + return null; + } + } + return null; + } + + this.SetJSON = function (key, value) { + elm.setAttribute("json:" + key, JSON.stringify(value)); + } + } +` + +const initScriptTmpl = ` + try { + var __sui_data = %s; + } catch (e) { console.log('init data error:', e); } + document.addEventListener("DOMContentLoaded", function () { try { document.querySelectorAll("[s\\:ready]").forEach(function (element) { @@ -71,6 +104,15 @@ const pageEventScriptTmpl = ` }); ` +const compEventScriptTmpl = ` + document.querySelector("[s\\:event=%s]").addEventListener("%s", function (event) { + const dataKeys = %s; + const jsonKeys = %s; + const handler = new %s(this).%s; + __sui_event_handler(event, dataKeys, jsonKeys, this, handler); + }); +` + func bodyInjectionScript(jsonRaw string, debug bool) string { jsPrintData := "" if debug { @@ -86,3 +128,7 @@ func headInjectionScript(jsonRaw string) string { func pageEventInjectScript(eventID, eventName, dataKeys, jsonKeys, handler string) string { return fmt.Sprintf(pageEventScriptTmpl, eventID, eventName, dataKeys, jsonKeys, handler) } + +func compEventInjectScript(eventID, eventName, component, dataKeys, jsonKeys, handler string) string { + return fmt.Sprintf(compEventScriptTmpl, eventID, eventName, dataKeys, jsonKeys, component, handler) +}