Skip to content

Commit

Permalink
event handlers returns stop indication
Browse files Browse the repository at this point in the history
  • Loading branch information
linkdata committed Oct 11, 2023
1 parent ab6c9b7 commit d4772f3
Show file tree
Hide file tree
Showing 13 changed files with 70 additions and 66 deletions.
6 changes: 3 additions & 3 deletions clickhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package jaws
import "github.com/linkdata/jaws/what"

type ClickHandler interface {
JawsClick(e *Element, name string) (err error)
JawsClick(e *Element, name string) (stop bool, err error)
}

type clickHandlerWapper struct{ ClickHandler }

func (chw clickHandlerWapper) JawsEvent(e *Element, w what.What, v string) (err error) {
func (chw clickHandlerWapper) JawsEvent(e *Element, w what.What, v string) (stop bool, err error) {
if w == what.Click {
err = chw.JawsClick(e, v)
return chw.JawsClick(e, v)
}
return
}
22 changes: 10 additions & 12 deletions eventhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,41 @@ package jaws
import "github.com/linkdata/jaws/what"

type EventHandler interface {
JawsEvent(e *Element, wht what.What, val string) (err error)
JawsEvent(e *Element, wht what.What, val string) (stop bool, err error)
}

// EventFn is the signature of a event handling function to be called when JaWS receives
// an event message from the Javascript via the WebSocket connection.
type EventFn = func(e *Element, wht what.What, val string) error
type EventFn = func(e *Element, wht what.What, val string) (stop bool, err error)

type eventFnWrapper struct{ EventFn }

func (ehf eventFnWrapper) JawsEvent(e *Element, w what.What, v string) error {
func (ehf eventFnWrapper) JawsEvent(e *Element, w what.What, v string) (stop bool, err error) {
return ehf.EventFn(e, w, v)
}

var _ EventFn = eventFnWrapper{}.JawsEvent // statically ensure JawsEvent and EventFn are compatible

func callEventHandler(obj any, e *Element, wht what.What, val string) error {
func callEventHandler(obj any, e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Click {
if h, ok := obj.(ClickHandler); ok {
if err := h.JawsClick(e, val); err != nil {
return err
if stop, err = h.JawsClick(e, val); stop || err != nil {
return
}
}
}
if h, ok := obj.(EventHandler); ok {
if err := h.JawsEvent(e, wht, val); err != nil {
return err
}
return h.JawsEvent(e, wht, val)
}
return nil
return
}

func callAllEventHandlers(e *Element, wht what.What, val string) error {
if err := callEventHandler(e.ui, e, wht, val); err != nil {
if stop, err := callEventHandler(e.ui, e, wht, val); stop || err != nil {
return err
}
for _, h := range e.handlers {
if err := h.JawsEvent(e, wht, val); err != nil {
if stop, err := h.JawsEvent(e, wht, val); stop || err != nil {
return err
}
}
Expand Down
32 changes: 16 additions & 16 deletions request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,11 @@ func TestRequest_OutboundRespectsJawsClosed(t *testing.T) {
jw := rq.jw
var callCount int32
tag := Tag("foo")
rq.Register(tag, func(e *Element, evt what.What, val string) error {
rq.Register(tag, func(e *Element, evt what.What, val string) (bool, error) {
atomic.AddInt32(&callCount, 1)
is.Equal(1, jw.RequestCount())
jw.Close()
return errors.New(val)
return false, errors.New(val)
})
fillWsCh(rq.outCh)
jw.Broadcast(Message{Dest: Tag("foo"), What: what.Hook, Data: "bar"})
Expand All @@ -233,10 +233,10 @@ func TestRequest_OutboundRespectsContextDone(t *testing.T) {
defer rq.Close()
var callCount int32
tag := Tag("foo")
rq.Register(tag, func(e *Element, evt what.What, val string) error {
rq.Register(tag, func(e *Element, evt what.What, val string) (bool, error) {
atomic.AddInt32(&callCount, 1)
rq.cancel()
return errors.New(val)
return false, errors.New(val)
})
fillWsCh(rq.outCh)
rq.jw.Broadcast(Message{Dest: Tag("foo"), What: what.Hook, Data: "bar"})
Expand Down Expand Up @@ -278,16 +278,16 @@ func TestRequest_Trigger(t *testing.T) {
defer rq.Close()
gotFooCall := make(chan struct{})
gotEndCall := make(chan struct{})
rq.Register("foo", func(e *Element, evt what.What, val string) error {
rq.Register("foo", func(e *Element, evt what.What, val string) (bool, error) {
defer close(gotFooCall)
return nil
return false, nil
})
rq.Register(("err"), func(e *Element, evt what.What, val string) error {
return errors.New(val)
rq.Register(("err"), func(e *Element, evt what.What, val string) (bool, error) {
return false, errors.New(val)
})
rq.Register(("end"), func(e *Element, evt what.What, val string) error {
rq.Register(("end"), func(e *Element, evt what.What, val string) (bool, error) {
defer close(gotEndCall)
return nil
return false, nil
})

// broadcasts from ourselves should not invoke fn
Expand Down Expand Up @@ -337,7 +337,7 @@ func TestRequest_EventFnQueue(t *testing.T) {
firstDoneCh := make(chan struct{})
var sleepDone int32
var callCount int32
rq.Register(("sleep"), func(e *Element, evt what.What, val string) error {
rq.Register(("sleep"), func(e *Element, evt what.What, val string) (bool, error) {
count := int(atomic.AddInt32(&callCount, 1))
if val != strconv.Itoa(count) {
t.Logf("val=%s, count=%d, cap=%d", val, count, cap(rq.outCh))
Expand All @@ -349,7 +349,7 @@ func TestRequest_EventFnQueue(t *testing.T) {
for atomic.LoadInt32(&sleepDone) == 0 {
time.Sleep(time.Millisecond)
}
return nil
return false, nil
})

for i := 0; i < cap(rq.outCh); i++ {
Expand Down Expand Up @@ -389,9 +389,9 @@ func TestRequest_EventFnQueueOverflowPanicsWithNoLogger(t *testing.T) {

var wait int32

rq.Register(("bomb"), func(e *Element, evt what.What, val string) error {
rq.Register(("bomb"), func(e *Element, evt what.What, val string) (bool, error) {
time.Sleep(time.Millisecond * time.Duration(atomic.AddInt32(&wait, 1)))
return nil
return false, nil
})

rq.expectPanic = true
Expand All @@ -418,7 +418,7 @@ func TestRequest_IgnoresIncomingMsgsDuringShutdown(t *testing.T) {

var spewState int32
var callCount int32
rq.Register(("spew"), func(e *Element, evt what.What, val string) error {
rq.Register(("spew"), func(e *Element, evt what.What, val string) (bool, error) {
atomic.AddInt32(&callCount, 1)
if len(rq.outCh) < cap(rq.outCh) {
rq.jw.Broadcast(Message{Dest: Tag("spew"), What: what.Input})
Expand All @@ -428,7 +428,7 @@ func TestRequest_IgnoresIncomingMsgsDuringShutdown(t *testing.T) {
time.Sleep(time.Millisecond)
}
}
return errors.New("chunks")
return false, errors.New("chunks")
})
rq.Register(Tag("foo"))

Expand Down
4 changes: 2 additions & 2 deletions session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ func TestSession_Delete(t *testing.T) {
rq2 := ts.jw.NewRequest(hr2)
is.Equal(ts.sess, rq2.Session())

ts.rq.Register("byebye", func(e *Element, evt what.What, val string) error {
ts.rq.Register("byebye", func(e *Element, evt what.What, val string) (bool, error) {
sess2 := ts.jw.GetSession(e.Request.Initial)
is.Equal(ts.sess, sess2)
cookie2 := sess2.Close()
Expand All @@ -185,7 +185,7 @@ func TestSession_Delete(t *testing.T) {
is.True(cookie2.Expires.IsZero())
is.Equal(cookie1.Name, cookie2.Name)
is.Equal(cookie1.Value, cookie2.Value)
return nil
return false, nil
})

conn, resp, err := websocket.Dial(ts.ctx, ts.Url(), nil)
Expand Down
2 changes: 1 addition & 1 deletion template.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ func (t Template) JawsUpdate(e *Element) {

var _ EventHandler = (*Template)(nil) // statically ensure interface is defined

func (t Template) JawsEvent(e *Element, wht what.What, val string) error {
func (t Template) JawsEvent(e *Element, wht what.What, val string) (bool, error) {
return callEventHandler(t.Dot, e, wht, val)
}
12 changes: 6 additions & 6 deletions uihtml.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func parseParams(elem *Element, params []interface{}) (attrs []string) {
case func(*Request, string) error: // Deprecated: ClickFn
if data != nil {
elem.handlers = append(elem.handlers, eventFnWrapper{
func(e *Element, wht what.What, val string) (err error) {
func(e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Click {
err = data(e.Request, e.jid.String())
}
Expand All @@ -59,7 +59,7 @@ func parseParams(elem *Element, params []interface{}) (attrs []string) {
}
case func(*Request, string, string) error: // Deprecated: InputTextFn
if data != nil {
elem.handlers = append(elem.handlers, eventFnWrapper{func(e *Element, wht what.What, val string) (err error) {
elem.handlers = append(elem.handlers, eventFnWrapper{func(e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Input {
err = data(e.Request, e.jid.String(), val)
}
Expand All @@ -68,7 +68,7 @@ func parseParams(elem *Element, params []interface{}) (attrs []string) {
}
case func(*Request, string, bool) error: // Deprecated: InputBoolFn
if data != nil {
elem.handlers = append(elem.handlers, eventFnWrapper{func(e *Element, wht what.What, val string) (err error) {
elem.handlers = append(elem.handlers, eventFnWrapper{func(e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Input {
var v bool
if val != "" {
Expand All @@ -83,7 +83,7 @@ func parseParams(elem *Element, params []interface{}) (attrs []string) {
}
case func(*Request, string, float64) error: // Deprecated: InputFloatFn
if data != nil {
elem.handlers = append(elem.handlers, eventFnWrapper{func(e *Element, wht what.What, val string) (err error) {
elem.handlers = append(elem.handlers, eventFnWrapper{func(e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Input {
var v float64
if val != "" {
Expand All @@ -98,7 +98,7 @@ func parseParams(elem *Element, params []interface{}) (attrs []string) {
}
case func(*Request, string, time.Time) error: // Deprecated: InputDateFn
if data != nil {
elem.handlers = append(elem.handlers, eventFnWrapper{func(e *Element, wht what.What, val string) (err error) {
elem.handlers = append(elem.handlers, eventFnWrapper{func(e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Input {
var v time.Time
if val != "" {
Expand Down Expand Up @@ -141,6 +141,6 @@ func (ui *UiHtml) JawsUpdate(e *Element) {
}
}

func (ui *UiHtml) JawsEvent(e *Element, wht what.What, val string) error {
func (ui *UiHtml) JawsEvent(e *Element, wht what.What, val string) (bool, error) {
return callEventHandler(ui.Tag, e, wht, val)
}
10 changes: 5 additions & 5 deletions uiinputbool.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (ui *UiInputBool) JawsUpdate(e *Element) {
}
}

func (ui *UiInputBool) JawsEvent(e *Element, wht what.What, val string) (err error) {
func (ui *UiInputBool) JawsEvent(e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Input {
var v bool
if val != "" {
Expand All @@ -45,9 +45,9 @@ func (ui *UiInputBool) JawsEvent(e *Element, wht what.What, val string) (err err
ui.Last.Store(v)
err = ui.BoolGetter.(BoolSetter).JawsSetBool(e, v)
e.Dirty(ui.Tag)
if err != nil {
return
}
}
if err == nil {
err = ui.UiHtml.JawsEvent(e, wht, val)
}
return
return ui.UiHtml.JawsEvent(e, wht, val)
}
10 changes: 5 additions & 5 deletions uiinputdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (ui *UiInputDate) JawsUpdate(e *Element) {
}
}

func (ui *UiInputDate) JawsEvent(e *Element, wht what.What, val string) (err error) {
func (ui *UiInputDate) JawsEvent(e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Input {
var v time.Time
if val != "" {
Expand All @@ -40,9 +40,9 @@ func (ui *UiInputDate) JawsEvent(e *Element, wht what.What, val string) (err err
ui.Last.Store(v)
err = ui.TimeGetter.(TimeSetter).JawsSetTime(e, v)
e.Dirty(ui.Tag)
if err != nil {
return
}
}
if err == nil {
err = ui.UiHtml.JawsEvent(e, wht, val)
}
return
return ui.UiHtml.JawsEvent(e, wht, val)
}
10 changes: 5 additions & 5 deletions uiinputfloat.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (ui *UiInputFloat) JawsUpdate(e *Element) {
}
}

func (ui *UiInputFloat) JawsEvent(e *Element, wht what.What, val string) (err error) {
func (ui *UiInputFloat) JawsEvent(e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Input {
var v float64
if val != "" {
Expand All @@ -40,9 +40,9 @@ func (ui *UiInputFloat) JawsEvent(e *Element, wht what.What, val string) (err er
ui.Last.Store(v)
err = ui.FloatGetter.(FloatSetter).JawsSetFloat(e, v)
e.Dirty(ui.Tag)
if err != nil {
return
}
}
if err == nil {
err = ui.UiHtml.JawsEvent(e, wht, val)
}
return
return ui.UiHtml.JawsEvent(e, wht, val)
}
10 changes: 5 additions & 5 deletions uiinputtext.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ func (ui *UiInputText) JawsUpdate(e *Element) {
}
}

func (ui *UiInputText) JawsEvent(e *Element, wht what.What, val string) (err error) {
func (ui *UiInputText) JawsEvent(e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Input {
ui.Last.Store(val)
err = ui.StringGetter.(StringSetter).JawsSetString(e, val)
e.Dirty(ui.Tag)
if err != nil {
return
}
}
if err == nil {
err = ui.UiHtml.JawsEvent(e, wht, val)
}
return
return ui.UiHtml.JawsEvent(e, wht, val)
}
7 changes: 5 additions & 2 deletions uiselect.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@ func (ui *UiSelect) JawsUpdate(e *Element) {
ui.uiWrapContainer.JawsUpdate(e)
}

func (ui *UiSelect) JawsEvent(e *Element, wht what.What, val string) (err error) {
func (ui *UiSelect) JawsEvent(e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Input {
err = ui.uiWrapContainer.Container.(StringSetter).JawsSetString(e, val)
e.Dirty(ui.Tag)
if err != nil {
return
}
}
return
return ui.UiHtml.JawsEvent(e, wht, val)
}

func (rq *Request) Select(sh SelectHandler, params ...interface{}) template.HTML {
Expand Down
7 changes: 5 additions & 2 deletions uitextarea.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ func (ui *UiTextarea) JawsUpdate(e *Element) {
e.SetInner(template.HTML(ui.JawsGetString(e))) // #nosec G203
}

func (ui *UiTextarea) JawsEvent(e *Element, wht what.What, val string) (err error) {
func (ui *UiTextarea) JawsEvent(e *Element, wht what.What, val string) (stop bool, err error) {
if wht == what.Input {
err = ui.StringGetter.(StringSetter).JawsSetString(e, val)
e.Dirty(ui.Tag)
if err != nil {
return
}
}
return
return ui.UiHtml.JawsEvent(e, wht, val)
}

func NewUiTextarea(g StringGetter) (ui *UiTextarea) {
Expand Down
4 changes: 2 additions & 2 deletions ws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ func TestWS_NormalExchange(t *testing.T) {

gotCallCh := make(chan struct{})

ts.rq.Register(("foo"), func(e *Element, evt what.What, val string) error {
ts.rq.Register(("foo"), func(e *Element, evt what.What, val string) (bool, error) {
close(gotCallCh)
return fooError
return false, fooError
})

conn, resp, err := websocket.Dial(ts.ctx, ts.Url(), nil)
Expand Down

0 comments on commit d4772f3

Please sign in to comment.