From 84c32945ec47bcbd6b45ac4c8b23dca8a4e82ec9 Mon Sep 17 00:00:00 2001 From: Johan Lindh Date: Mon, 30 Oct 2023 12:30:27 +0100 Subject: [PATCH] wip --- element.go | 46 +++++++-------------------------------- element_test.go | 4 ++-- jaws.js | 3 +-- jawsboot/jawsboot_test.go | 4 +++- js.go | 5 +++++ request.go | 27 +++++++++++++---------- request_test.go | 4 +++- requestwriter.go | 39 ++++++++++++++++++++++++++++++--- session_test.go | 7 +++--- template.go | 6 ++--- ui.go | 2 +- ui_test.go | 2 +- uihtml.go | 2 +- uiradiogroup.go | 8 +++---- uitemplate.go | 2 +- uitemplate_test.go | 2 +- uiwrapcontainer.go | 10 ++++----- 17 files changed, 94 insertions(+), 79 deletions(-) diff --git a/element.go b/element.go index 905444e..fbebcc5 100644 --- a/element.go +++ b/element.go @@ -12,9 +12,9 @@ import ( // An Element is an instance of a *Request, an UI object and a Jid. type Element struct { - ui UI // (read-only) the UI object - jid jid.Jid // (read-only) JaWS ID, unique to this Element within it's Request - rq *Request // (read-only) the Request the Element belongs to + *Request // (read-only) the Request the Element belongs to + ui UI // (read-only) the UI object + jid jid.Jid // (read-only) JaWS ID, unique to this Element within it's Request // internals updating bool // about to have Update() called wsQueue []wsMsg // changes queued @@ -22,47 +22,17 @@ type Element struct { } func (e *Element) String() string { - return fmt.Sprintf("Element{%T, id=%q, Tags: %v}", e.ui, e.jid, e.rq.TagsOf(e)) -} - -// Jaws returns the Jaws the Element belongs to. -func (e *Element) Jaws() *Jaws { - return e.rq.Jaws -} - -// Request returns the Request the Element belongs to. -func (e *Element) Request() *Request { - return e.rq -} - -// Session returns the Elements's Session, or nil. -func (e *Element) Session() *Session { - return e.rq.Session() -} - -// Get calls Session().Get() -func (e *Element) Get(key string) (val interface{}) { - return e.Session().Get(key) -} - -// Set calls Session().Get() -func (e *Element) Set(key string, val interface{}) { - e.Session().Set(key, val) -} - -// Dirty calls Request().Dirty() -func (e *Element) Dirty(tags ...interface{}) { - e.rq.Dirty(tags...) + return fmt.Sprintf("Element{%T, id=%q, Tags: %v}", e.ui, e.jid, e.Request.TagsOf(e)) } // Tag adds the given tags to the Element. func (e *Element) Tag(tags ...interface{}) { - e.rq.Tag(e, tags...) + e.Request.Tag(e, tags...) } // HasTag returns true if this Element has the given tag. func (e *Element) HasTag(tag interface{}) bool { - return e.rq.HasTag(e, tag) + return e.Request.HasTag(e, tag) } // Jid returns the JaWS ID for this Element, unique within it's Request. @@ -77,7 +47,7 @@ func (e *Element) Ui() UI { // Render calls Request.JawsRender() for this Element. func (e *Element) Render(w io.Writer, params []interface{}) error { - return e.rq.JawsRender(e, w, params) + return e.Request.JawsRender(e, w, params) } func (e *Element) queue(wht what.What, data string) { @@ -88,7 +58,7 @@ func (e *Element) queue(wht what.What, data string) { What: wht, }) } else { - e.rq.cancel(ErrWebsocketQueueOverflow) + e.Request.cancel(ErrWebsocketQueueOverflow) } } diff --git a/element_test.go b/element_test.go index 697c7c7..4f4c4a0 100644 --- a/element_test.go +++ b/element_test.go @@ -62,8 +62,8 @@ func TestElement_helpers(t *testing.T) { tss := &testUi{} e := rq.NewElement(tss) - is.Equal(e.Jaws(), rq.jw.Jaws) - is.Equal(e.Request(), rq.Request) + is.Equal(e.Jaws, rq.jw.Jaws) + is.Equal(e.Request, rq.Request) is.Equal(e.Session(), nil) e.Set("foo", "bar") // no session, so no effect is.Equal(e.Get("foo"), nil) diff --git a/jaws.js b/jaws.js index d536d86..04ed35e 100644 --- a/jaws.js +++ b/jaws.js @@ -188,8 +188,7 @@ function jawsLost() { innerHTML += '. Trying to reconnect.'; var elem = document.getElementById('jaws-lost'); if (elem == null) { - elem = jawsElement('
' + - innerHTML + '
'); + elem = jawsElement('
' + innerHTML + '
'); document.body.prepend(elem); document.body.scrollTop = document.documentElement.scrollTop = 0; } else { diff --git a/jawsboot/jawsboot_test.go b/jawsboot/jawsboot_test.go index 5d289a5..b2b9f5e 100644 --- a/jawsboot/jawsboot_test.go +++ b/jawsboot/jawsboot_test.go @@ -16,7 +16,9 @@ func TestJawsBoot_Setup(t *testing.T) { } rq := jw.NewRequest(nil) - txt := string(rq.HeadHTML()) + var sb strings.Builder + rq.Writer(&sb).HeadHTML() + txt := sb.String() if !strings.Contains(txt, rq.JawsKeyString()) { t.Error(txt) } diff --git a/js.go b/js.go index 22ef751..fee2443 100644 --- a/js.go +++ b/js.go @@ -54,6 +54,7 @@ func JawsKeyValue(jawsKey string) uint64 { const jsLoader = `.forEach(function(c){var e=document.createElement("script");e.src=c;e.async=!1;document.head.appendChild(e);});` // HeadHTML returns HTML code to load the given scripts and CSS files efficiently, +// as well as a basic CSS "jaws-alert" class for JaWS to use. func HeadHTML(js []string, css []string) string { var s []byte @@ -67,6 +68,10 @@ func HeadHTML(js []string, css []string) string { s = strconv.AppendQuote(s, e) s = append(s, " as=\"script\">\n"...) } + s = append(s, ` +`...) s = append(s, "` - return template.HTML(s) // #nosec G203 +// HeadHTML writes the HTML code needed in the HTML page's HEAD section. +func (rq *Request) HeadHTML(w io.Writer) (err error) { + if _, err = w.Write([]byte(rq.Jaws.headPrefix)); err == nil { + if _, err = w.Write([]byte(rq.JawsKeyString())); err == nil { + _, err = w.Write([]byte(`";`)) + } + } + return } // GetConnectFn returns the currently set ConnectFn. That function will be called before starting the WebSocket tunnel if not nil. @@ -298,9 +301,9 @@ var nextJid Jid func (rq *Request) newElementLocked(ui UI) (elem *Element) { elem = &Element{ - jid: Jid(atomic.AddInt64((*int64)(&nextJid), 1)), - ui: ui, - rq: rq, + jid: Jid(atomic.AddInt64((*int64)(&nextJid), 1)), + ui: ui, + Request: rq, } rq.elems = append(rq.elems, elem) return @@ -364,8 +367,8 @@ func (rq *Request) tagExpanded(elem *Element, expandedtags []interface{}) { // Tag adds the given tags to the given Element. func (rq *Request) Tag(elem *Element, tags ...interface{}) { - if elem != nil && len(tags) > 0 && elem.rq == rq { - rq.tagExpanded(elem, MustTagExpand(elem.rq, tags)) + if elem != nil && len(tags) > 0 && elem.Request == rq { + rq.tagExpanded(elem, MustTagExpand(elem.Request, tags)) } } @@ -635,7 +638,7 @@ func (rq *Request) sendQueue(outboundCh chan<- string, wsQueue []wsMsg) []wsMsg } func (rq *Request) deleteElementLocked(e *Element) { - e.rq = nil + e.Request = nil rq.elems = slices.DeleteFunc(rq.elems, func(elem *Element) bool { return elem == e }) for k := range rq.tagMap { rq.tagMap[k] = slices.DeleteFunc(rq.tagMap[k], func(elem *Element) bool { return elem == e }) @@ -695,5 +698,5 @@ func (rq *Request) onConnect() (err error) { } func (rq *Request) Writer(w io.Writer) RequestWriter { - return RequestWriter{Request: rq, Writer: w} + return RequestWriter{rq: rq, Writer: w} } diff --git a/request_test.go b/request_test.go index 5c1a1e8..75dc287 100644 --- a/request_test.go +++ b/request_test.go @@ -56,7 +56,9 @@ func TestRequest_HeadHTML(t *testing.T) { rq := jw.NewRequest(nil) defer jw.recycle(rq) - txt := rq.HeadHTML() + var sb strings.Builder + rq.Writer(&sb).HeadHTML() + txt := sb.String() is.Equal(strings.Contains(string(txt), rq.JawsKeyString()), true) is.Equal(strings.Contains(string(txt), JavascriptPath), true) } diff --git a/requestwriter.go b/requestwriter.go index 351271d..03cff88 100644 --- a/requestwriter.go +++ b/requestwriter.go @@ -1,12 +1,45 @@ package jaws -import "io" +import ( + "io" + "net/http" +) type RequestWriter struct { - *Request + rq *Request io.Writer } func (rw RequestWriter) UI(ui UI, params ...interface{}) error { - return rw.JawsRender(rw.NewElement(ui), rw.Writer, params) + return rw.rq.JawsRender(rw.rq.NewElement(ui), rw.Writer, params) +} + +// Request returns the current jaws.Request. +func (rw RequestWriter) Request() *Request { + return rw.rq +} + +// Initial returns the initial http.Request. +func (rw RequestWriter) Initial() *http.Request { + return rw.Request().Initial +} + +// HeadHTML outputs the HTML code needed in the HEAD section. +func (rw RequestWriter) HeadHTML() error { + return rw.Request().HeadHTML(rw) +} + +// Session returns the Requests's Session, or nil. +func (rw RequestWriter) Session() *Session { + return rw.Request().Session() +} + +// Get calls Request().Get() +func (rw RequestWriter) Get(key string) (val interface{}) { + return rw.Request().Get(key) +} + +// Set calls Request().Set() +func (rw RequestWriter) Set(key string, val interface{}) { + rw.Request().Set(key, val) } diff --git a/session_test.go b/session_test.go index 8edd8e8..a1387d9 100644 --- a/session_test.go +++ b/session_test.go @@ -70,8 +70,9 @@ func TestSession_Use(t *testing.T) { return } + var sb strings.Builder sess := jw.GetSession(r) - rq := jw.NewRequest(r) + rq := jw.NewRequest(r).Writer(&sb) if sess != rq.Session() { t.Error(sess) } @@ -100,7 +101,7 @@ func TestSession_Use(t *testing.T) { rq.Set("bar", "quux") } w.WriteHeader(http.StatusOK) - jw.UseRequest(rq.JawsKey, r) + jw.UseRequest(rq.Request().JawsKey, r) }) srv := httptest.NewServer(h) @@ -276,7 +277,7 @@ func TestSession_Delete(t *testing.T) { } ts.rq.Register("byebye", func(e *Element, evt what.What, val string) error { - sess2 := ts.jw.GetSession(e.Request().Initial) + sess2 := ts.jw.GetSession(e.Request.Initial) if x := sess2; x != ts.sess { t.Error(x) } diff --git a/template.go b/template.go index d0d25c1..4db9607 100644 --- a/template.go +++ b/template.go @@ -40,8 +40,8 @@ func (t Template) String() string { } func (t Template) JawsRender(e *Element, w io.Writer, params []interface{}) error { - if expandedtags, err := TagExpand(e.Request(), t.Dot); err != ErrIllegalTagType { - e.Request().tagExpanded(e, expandedtags) + if expandedtags, err := TagExpand(e.Request, t.Dot); err != ErrIllegalTagType { + e.Request.tagExpanded(e, expandedtags) } var sb strings.Builder for _, s := range parseParams(e, params) { @@ -51,7 +51,7 @@ func (t Template) JawsRender(e *Element, w io.Writer, params []interface{}) erro attrs := template.HTMLAttr(sb.String()) // #nosec G203 return t.Execute(w, With{ Element: e, - RequestWriter: e.Request().Writer(w), + RequestWriter: e.Request.Writer(w), Dot: t.Dot, Attrs: attrs, }) diff --git a/ui.go b/ui.go index 81cc575..95c2396 100644 --- a/ui.go +++ b/ui.go @@ -18,7 +18,7 @@ func (rq *Request) JawsRender(elem *Element, w io.Writer, params []interface{}) if rq.Jaws.Debug { var sb strings.Builder _, _ = fmt.Fprintf(&sb, "