Skip to content

Commit ef83e34

Browse files
committed
add RunAfterTimeout & RunOnInterval
1 parent a1af01a commit ef83e34

File tree

4 files changed

+82
-26
lines changed

4 files changed

+82
-26
lines changed

framework/h/command_test.go

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"regexp"
88
"strings"
99
"testing"
10+
"time"
1011
)
1112

1213
func findScriptById(n *html.Node, id string) *html.Node {
@@ -87,7 +88,7 @@ func TestJsEval(t *testing.T) {
8788
}
8889

8990
func TestSetText(t *testing.T) {
90-
compareIgnoreSpaces(t, renderJs(t, SetText("Hello World")), "this.innerText = 'Hello World';")
91+
compareIgnoreSpaces(t, renderJs(t, SetText("Hello World")), "(self||this).innerText = 'Hello World';")
9192
}
9293

9394
func TestSetTextOnChildren(t *testing.T) {
@@ -100,42 +101,42 @@ func TestSetTextOnChildren(t *testing.T) {
100101
}
101102

102103
func TestIncrement(t *testing.T) {
103-
compareIgnoreSpaces(t, renderJs(t, Increment(5)), "this.innerText = parseInt(this.innerText) + 5;")
104+
compareIgnoreSpaces(t, renderJs(t, Increment(5)), "(self||this).innerText = parseInt((self||this).innerText) + 5;")
104105
}
105106

106107
func TestSetInnerHtml(t *testing.T) {
107108
htmlContent := Div(Span(UnsafeRaw("inner content")))
108-
compareIgnoreSpaces(t, renderJs(t, SetInnerHtml(htmlContent)), "this.innerHTML = `<div><span>inner content</span></div>`;")
109+
compareIgnoreSpaces(t, renderJs(t, SetInnerHtml(htmlContent)), "(self||this).innerHTML = `<div><span>inner content</span></div>`;")
109110
}
110111

111112
func TestSetOuterHtml(t *testing.T) {
112113
htmlContent := Div(Span(UnsafeRaw("outer content")))
113-
compareIgnoreSpaces(t, renderJs(t, SetOuterHtml(htmlContent)), "this.outerHTML = `<div><span>outer content</span></div>`;")
114+
compareIgnoreSpaces(t, renderJs(t, SetOuterHtml(htmlContent)), "(self||this).outerHTML = `<div><span>outer content</span></div>`;")
114115
}
115116

116117
func TestAddAttribute(t *testing.T) {
117-
compareIgnoreSpaces(t, renderJs(t, AddAttribute("data-id", "123")), "this.setAttribute('data-id', '123');")
118+
compareIgnoreSpaces(t, renderJs(t, AddAttribute("data-id", "123")), "(self||this).setAttribute('data-id', '123');")
118119
}
119120

120121
func TestSetDisabled(t *testing.T) {
121-
compareIgnoreSpaces(t, renderJs(t, SetDisabled(true)), "this.setAttribute('disabled', 'true');")
122-
compareIgnoreSpaces(t, renderJs(t, SetDisabled(false)), "this.removeAttribute('disabled');")
122+
compareIgnoreSpaces(t, renderJs(t, SetDisabled(true)), "(self||this).setAttribute('disabled', 'true');")
123+
compareIgnoreSpaces(t, renderJs(t, SetDisabled(false)), "(self||this).removeAttribute('disabled');")
123124
}
124125

125126
func TestRemoveAttribute(t *testing.T) {
126-
compareIgnoreSpaces(t, renderJs(t, RemoveAttribute("data-id")), "this.removeAttribute('data-id');")
127+
compareIgnoreSpaces(t, renderJs(t, RemoveAttribute("data-id")), "(self||this).removeAttribute('data-id');")
127128
}
128129

129130
func TestAddClass(t *testing.T) {
130-
compareIgnoreSpaces(t, renderJs(t, AddClass("active")), "this.classList.add('active');")
131+
compareIgnoreSpaces(t, renderJs(t, AddClass("active")), "(self||this).classList.add('active');")
131132
}
132133

133134
func TestRemoveClass(t *testing.T) {
134-
compareIgnoreSpaces(t, renderJs(t, RemoveClass("active")), "this.classList.remove('active');")
135+
compareIgnoreSpaces(t, renderJs(t, RemoveClass("active")), "(self||this).classList.remove('active');")
135136
}
136137

137138
func TestToggleClass(t *testing.T) {
138-
compareIgnoreSpaces(t, renderJs(t, ToggleClass("hidden")), "this.classList.toggle('hidden');")
139+
compareIgnoreSpaces(t, renderJs(t, ToggleClass("hidden")), "(self||this).classList.toggle('hidden');")
139140
}
140141

141142
func TestToggleClassOnElement(t *testing.T) {
@@ -206,7 +207,7 @@ func TestAlert(t *testing.T) {
206207
}
207208

208209
func TestRemove(t *testing.T) {
209-
compareIgnoreSpaces(t, renderJs(t, Remove()), "this.remove();")
210+
compareIgnoreSpaces(t, renderJs(t, Remove()), "(self||this).remove();")
210211
}
211212

212213
func TestSubmitFormOnEnter(t *testing.T) {
@@ -394,5 +395,23 @@ func TestConsoleLog(t *testing.T) {
394395

395396
func TestSetValue(t *testing.T) {
396397
t.Parallel()
397-
compareIgnoreSpaces(t, renderJs(t, SetValue("New Value")), "this.value = 'New Value';")
398+
compareIgnoreSpaces(t, renderJs(t, SetValue("New Value")), "(self||this).value = 'New Value';")
399+
}
400+
401+
func TestRunAfterTimeout(t *testing.T) {
402+
t.Parallel()
403+
compareIgnoreSpaces(t, renderJs(t, RunAfterTimeout(time.Second*5, SetText("Hello"))), `
404+
setTimeout(function() {
405+
(self||this).innerText = 'Hello'
406+
}, 5000)
407+
`)
408+
}
409+
410+
func TestRunOnInterval(t *testing.T) {
411+
t.Parallel()
412+
compareIgnoreSpaces(t, renderJs(t, RunOnInterval(time.Second, SetText("Hello"))), `
413+
setInterval(function() {
414+
(self||this).innerText = 'Hello'
415+
}, 1000)
416+
`)
398417
}

framework/h/lifecycle.go

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/maddalax/htmgo/framework/hx"
77
"github.com/maddalax/htmgo/framework/internal/util"
88
"strings"
9+
"time"
910
)
1011

1112
type LifeCycle struct {
@@ -163,7 +164,7 @@ func NewComplexJsCommand(command string) ComplexJsCommand {
163164
// SetText sets the inner text of the element.
164165
func SetText(text string) SimpleJsCommand {
165166
// language=JavaScript
166-
return SimpleJsCommand{Command: fmt.Sprintf("this.innerText = '%s'", text)}
167+
return SimpleJsCommand{Command: fmt.Sprintf("(self || this).innerText = '%s'", text)}
167168
}
168169

169170
// SetTextOnChildren sets the inner text of all the children of the element that match the selector.
@@ -180,25 +181,25 @@ func SetTextOnChildren(selector, text string) ComplexJsCommand {
180181
// Increment increments the inner text of the element by the given amount.
181182
func Increment(amount int) SimpleJsCommand {
182183
// language=JavaScript
183-
return SimpleJsCommand{Command: fmt.Sprintf("this.innerText = parseInt(this.innerText) + %d", amount)}
184+
return SimpleJsCommand{Command: fmt.Sprintf("(self || this).innerText = parseInt((self || this).innerText) + %d", amount)}
184185
}
185186

186187
// SetInnerHtml sets the inner HTML of the element.
187188
func SetInnerHtml(r Ren) SimpleJsCommand {
188189
// language=JavaScript
189-
return SimpleJsCommand{Command: fmt.Sprintf("this.innerHTML = `%s`", Render(r))}
190+
return SimpleJsCommand{Command: fmt.Sprintf("(self || this).innerHTML = `%s`", Render(r))}
190191
}
191192

192193
// SetOuterHtml sets the outer HTML of the element.
193194
func SetOuterHtml(r Ren) SimpleJsCommand {
194195
// language=JavaScript
195-
return SimpleJsCommand{Command: fmt.Sprintf("this.outerHTML = `%s`", Render(r))}
196+
return SimpleJsCommand{Command: fmt.Sprintf("(self || this).outerHTML = `%s`", Render(r))}
196197
}
197198

198199
// AddAttribute adds the given attribute to the element.
199200
func AddAttribute(name, value string) SimpleJsCommand {
200201
// language=JavaScript
201-
return SimpleJsCommand{Command: fmt.Sprintf("this.setAttribute('%s', '%s')", name, value)}
202+
return SimpleJsCommand{Command: fmt.Sprintf("(self || this).setAttribute('%s', '%s')", name, value)}
202203
}
203204

204205
// SetDisabled sets the disabled attribute on the element.
@@ -213,25 +214,25 @@ func SetDisabled(disabled bool) SimpleJsCommand {
213214
// RemoveAttribute removes the given attribute from the element.
214215
func RemoveAttribute(name string) SimpleJsCommand {
215216
// language=JavaScript
216-
return SimpleJsCommand{Command: fmt.Sprintf("this.removeAttribute('%s')", name)}
217+
return SimpleJsCommand{Command: fmt.Sprintf("(self || this).removeAttribute('%s')", name)}
217218
}
218219

219220
// AddClass adds the given class to the element.
220221
func AddClass(class string) SimpleJsCommand {
221222
// language=JavaScript
222-
return SimpleJsCommand{Command: fmt.Sprintf("this.classList.add('%s')", class)}
223+
return SimpleJsCommand{Command: fmt.Sprintf("(self || this).classList.add('%s')", class)}
223224
}
224225

225226
// RemoveClass removes the given class from the element.
226227
func RemoveClass(class string) SimpleJsCommand {
227228
// language=JavaScript
228-
return SimpleJsCommand{Command: fmt.Sprintf("this.classList.remove('%s')", class)}
229+
return SimpleJsCommand{Command: fmt.Sprintf("(self || this).classList.remove('%s')", class)}
229230
}
230231

231232
// ToggleClass toggles the given class on the element.
232233
func ToggleClass(class string) SimpleJsCommand {
233234
// language=JavaScript
234-
return SimpleJsCommand{Command: fmt.Sprintf("this.classList.toggle('%s')", class)}
235+
return SimpleJsCommand{Command: fmt.Sprintf("(self || this).classList.toggle('%s')", class)}
235236
}
236237

237238
// ToggleText toggles the given text on the element.
@@ -391,23 +392,29 @@ func Alert(text string) SimpleJsCommand {
391392
// Remove removes the element from the DOM.
392393
func Remove() SimpleJsCommand {
393394
// language=JavaScript
394-
return SimpleJsCommand{Command: "this.remove()"}
395+
return SimpleJsCommand{Command: "(self || this).remove()"}
395396
}
396397

397398
// EvalJs evaluates the given JavaScript code.
398399
func EvalJs(js string) ComplexJsCommand {
399400
return NewComplexJsCommand(js)
400401
}
401402

402-
func EvalCommandsOnSelector(selector string, cmds ...Command) ComplexJsCommand {
403+
func CombineCommands(cmds ...Command) string {
403404
lines := make([]string, len(cmds))
404405
for i, cmd := range cmds {
405406
lines[i] = Render(cmd)
407+
lines[i] = strings.ReplaceAll(lines[i], "(self || this).", "self.")
406408
lines[i] = strings.ReplaceAll(lines[i], "this.", "self.")
407409
// some commands set the element we need to fix it so we arent redeclaring it
408410
lines[i] = strings.ReplaceAll(lines[i], "let element =", "element =")
409411
}
410412
code := strings.Join(lines, "\n")
413+
return code
414+
}
415+
416+
func EvalCommandsOnSelector(selector string, cmds ...Command) ComplexJsCommand {
417+
code := CombineCommands(cmds...)
411418
return EvalJs(fmt.Sprintf(`
412419
let element = document.querySelector("%s");
413420
@@ -444,7 +451,7 @@ func ConsoleLog(text string) SimpleJsCommand {
444451
// SetValue sets the value of the element.
445452
func SetValue(value string) SimpleJsCommand {
446453
// language=JavaScript
447-
return SimpleJsCommand{Command: fmt.Sprintf("this.value = '%s'", value)}
454+
return SimpleJsCommand{Command: fmt.Sprintf("(self || this).value = '%s'", value)}
448455
}
449456

450457
// SubmitFormOnEnter submits the form when the user presses the enter key.
@@ -478,3 +485,31 @@ func InjectScriptIfNotExist(src string) ComplexJsCommand {
478485
}
479486
`, src, src))
480487
}
488+
489+
func RunOnInterval(time time.Duration, cmds ...Command) ComplexJsCommand {
490+
code := strings.Builder{}
491+
492+
for _, cmd := range cmds {
493+
code.WriteString(fmt.Sprintf(`
494+
setInterval(function() {
495+
%s
496+
}, %d)
497+
`, Render(cmd), time.Milliseconds()))
498+
}
499+
500+
return EvalJs(code.String())
501+
}
502+
503+
func RunAfterTimeout(time time.Duration, cmds ...Command) ComplexJsCommand {
504+
code := strings.Builder{}
505+
506+
for _, cmd := range cmds {
507+
code.WriteString(fmt.Sprintf(`
508+
setTimeout(function() {
509+
%s
510+
}, %d)
511+
`, Render(cmd), time.Milliseconds()))
512+
}
513+
514+
return EvalJs(code.String())
515+
}

framework/h/render_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func TestRender(t *testing.T) {
4848

4949
div.attributes.Set("data-attr-1", "value")
5050

51-
expected := `<div data-attr-1="value" id="my-div" data-attr-2="value" data-attr-3="value" hx-on::before-request="this.innerText = &#39;before request&#39;;" hx-on::after-request="this.innerText = &#39;after request&#39;;"><div>hello, world</div>hello, child</div>`
51+
expected := `<div data-attr-1="value" id="my-div" data-attr-2="value" data-attr-3="value" hx-on::before-request="(self || this).innerText = &#39;before request&#39;;" hx-on::after-request="(self || this).innerText = &#39;after request&#39;;"><div>hello, world</div>hello, child</div>`
5252
result := Render(div)
5353

5454
assert.Equal(t,

framework/js/commands.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,5 @@ var ToggleText = h.ToggleText
4747
var ToggleTextOnSibling = h.ToggleTextOnSibling
4848
var ToggleTextOnChildren = h.ToggleTextOnChildren
4949
var ToggleTextOnParent = h.ToggleTextOnParent
50+
var RunAfterTimeout = h.RunAfterTimeout
51+
var RunOnInterval = h.RunOnInterval

0 commit comments

Comments
 (0)