Compare commits
3 commits
master
...
script-enh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f868e3e3f8 | ||
|
|
b6233a2a96 | ||
|
|
cd8d08c0a5 |
9 changed files with 411 additions and 34 deletions
|
|
@ -55,10 +55,12 @@ var re = regexp.MustCompile(`\s+`)
|
||||||
func compareIgnoreSpaces(t *testing.T, actual, expected string) {
|
func compareIgnoreSpaces(t *testing.T, actual, expected string) {
|
||||||
expected = strings.ReplaceAll(expected, "\n", "")
|
expected = strings.ReplaceAll(expected, "\n", "")
|
||||||
expected = strings.ReplaceAll(expected, "\t", "")
|
expected = strings.ReplaceAll(expected, "\t", "")
|
||||||
expected = re.ReplaceAllString(expected, " ")
|
|
||||||
actual = strings.ReplaceAll(actual, "\n", "")
|
actual = strings.ReplaceAll(actual, "\n", "")
|
||||||
actual = strings.ReplaceAll(actual, "\t", "")
|
actual = strings.ReplaceAll(actual, "\t", "")
|
||||||
actual = re.ReplaceAllString(actual, " ")
|
actual = re.ReplaceAllString(actual, " ")
|
||||||
|
spaceRegex := regexp.MustCompile(`\s+`)
|
||||||
|
actual = strings.TrimSpace(spaceRegex.ReplaceAllString(actual, ""))
|
||||||
|
expected = strings.TrimSpace(spaceRegex.ReplaceAllString(expected, ""))
|
||||||
assert.Equal(t, expected, actual)
|
assert.Equal(t, expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,11 +77,11 @@ func TestJsEval(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
compareIgnoreSpaces(t, renderJs(t, EvalJsOnParent("element.style.display = 'none'")), `
|
compareIgnoreSpaces(t, renderJs(t, EvalJsOnParent("element.style.display = 'none'")), `
|
||||||
if(!self.parentElement) { return; } let element = self.parentElement; element.style.display = 'none'
|
if(self.parentElement) { let element = self.parentElement; element.style.display = 'none' }
|
||||||
`)
|
`)
|
||||||
|
|
||||||
compareIgnoreSpaces(t, renderJs(t, EvalJsOnSibling("button", "element.style.display = 'none'")), `
|
compareIgnoreSpaces(t, renderJs(t, EvalJsOnSibling("button", "element.style.display = 'none'")), `
|
||||||
if(!self.parentElement) { return; }let siblings = self.parentElement.querySelectorAll('button');siblings.forEach(function(element) {element.style.display = 'none'});
|
if(self.parentElement) { let siblings = self.parentElement.querySelectorAll('button');siblings.forEach(function(element) {element.style.display = 'none'}); }
|
||||||
`)
|
`)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -145,13 +147,13 @@ func TestToggleClassOnElement(t *testing.T) {
|
||||||
|
|
||||||
func TestSetClassOnParent(t *testing.T) {
|
func TestSetClassOnParent(t *testing.T) {
|
||||||
compareIgnoreSpaces(t, renderJs(t, SetClassOnParent("active")), `
|
compareIgnoreSpaces(t, renderJs(t, SetClassOnParent("active")), `
|
||||||
if(!self.parentElement) { return; } let element = self.parentElement; element.classList.add('active')
|
if(self.parentElement) { let element = self.parentElement; element.classList.add('active') }
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveClassOnParent(t *testing.T) {
|
func TestRemoveClassOnParent(t *testing.T) {
|
||||||
compareIgnoreSpaces(t, renderJs(t, RemoveClassOnParent("active")), `
|
compareIgnoreSpaces(t, renderJs(t, RemoveClassOnParent("active")), `
|
||||||
if(!self.parentElement) { return; } let element = self.parentElement; element.classList.remove('active')
|
if(self.parentElement) { let element = self.parentElement; element.classList.remove('active') }
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -174,20 +176,28 @@ func TestRemoveClassOnChildren(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetClassOnSibling(t *testing.T) {
|
func TestSetClassOnSibling(t *testing.T) {
|
||||||
compareIgnoreSpaces(t, renderJs(t, SetClassOnSibling("button", "selected")), `
|
compareIgnoreSpaces(t, renderJs(t, SetClassOnSibling("button", "selected")),
|
||||||
if(!self.parentElement) { return; }let siblings = self.parentElement.querySelectorAll('button');
|
// language=JavaScript
|
||||||
siblings.forEach(function(element) {
|
`
|
||||||
element.classList.add('selected')
|
if(self.parentElement) {
|
||||||
});
|
let siblings = self.parentElement.querySelectorAll('button');
|
||||||
|
siblings.forEach(function(element) {
|
||||||
|
element.classList.add('selected')
|
||||||
|
});
|
||||||
|
}
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveClassOnSibling(t *testing.T) {
|
func TestRemoveClassOnSibling(t *testing.T) {
|
||||||
compareIgnoreSpaces(t, renderJs(t, RemoveClassOnSibling("button", "selected")), `
|
compareIgnoreSpaces(t, renderJs(t, RemoveClassOnSibling("button", "selected")),
|
||||||
if(!self.parentElement) { return; }let siblings = self.parentElement.querySelectorAll('button');
|
// language=JavaScript
|
||||||
siblings.forEach(function(element) {
|
`
|
||||||
element.classList.remove('selected')
|
if(self.parentElement) {
|
||||||
});
|
let siblings = self.parentElement.querySelectorAll('button');
|
||||||
|
siblings.forEach(function(element) {
|
||||||
|
element.classList.remove('selected')
|
||||||
|
});
|
||||||
|
}
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,3 +236,148 @@ func TestInjectScriptIfNotExist(t *testing.T) {
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEvalCommands(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
div := Div(Id("test"))
|
||||||
|
result := Render(EvalCommands(div,
|
||||||
|
SetText("hello"),
|
||||||
|
EvalJs(`
|
||||||
|
alert('test')
|
||||||
|
`),
|
||||||
|
SetClassOnParent("myclass"),
|
||||||
|
SetClassOnSibling("div", "myclass"),
|
||||||
|
))
|
||||||
|
|
||||||
|
evalId := ""
|
||||||
|
for _, child := range div.children {
|
||||||
|
switch child.(type) {
|
||||||
|
case *AttributeR:
|
||||||
|
attr := child.(*AttributeR)
|
||||||
|
if attr.Name == "data-eval-commands-id" {
|
||||||
|
evalId = attr.Value
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//language=JavaScript
|
||||||
|
compareIgnoreSpaces(t, result, fmt.Sprintf(`
|
||||||
|
let element = document.querySelector("[data-eval-commands-id='%s']");
|
||||||
|
if(!element) {return;}
|
||||||
|
self = element;
|
||||||
|
self.innerText = 'hello'
|
||||||
|
alert('test')
|
||||||
|
if(self.parentElement) {
|
||||||
|
element = self.parentElement;
|
||||||
|
element.classList.add('myclass')
|
||||||
|
}
|
||||||
|
if(self.parentElement) {
|
||||||
|
let siblings = self.parentElement.querySelectorAll('div');
|
||||||
|
siblings.forEach(function(element) {
|
||||||
|
element.classList.add('myclass')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
`, evalId))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToggleText(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
result := Render(ToggleText("hello", "world"))
|
||||||
|
//language=JavaScript
|
||||||
|
compareIgnoreSpaces(t, result, fmt.Sprintf(`
|
||||||
|
if(self.innerText === "hello") {
|
||||||
|
self.innerText = "world";
|
||||||
|
} else {
|
||||||
|
self.innerText = "hello";
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToggleTextOnSibling(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
result := Render(ToggleTextOnSibling("div", "hello", "world"))
|
||||||
|
//language=JavaScript
|
||||||
|
compareIgnoreSpaces(t, result, fmt.Sprintf(`
|
||||||
|
if(self.parentElement) {
|
||||||
|
let siblings = self.parentElement.querySelectorAll('div');
|
||||||
|
siblings.forEach(function(element){
|
||||||
|
if(element.innerText === "hello"){
|
||||||
|
element.innerText= "world";
|
||||||
|
} else {
|
||||||
|
element.innerText= "hello";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToggleTextOnChildren(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
result := Render(ToggleTextOnChildren("div", "hello", "world"))
|
||||||
|
//language=JavaScript
|
||||||
|
compareIgnoreSpaces(t, result, fmt.Sprintf(`
|
||||||
|
let children = self.querySelectorAll('div');
|
||||||
|
children.forEach(function(element) {
|
||||||
|
if(element.innerText === "hello") {
|
||||||
|
element.innerText = "world";
|
||||||
|
} else {
|
||||||
|
element.innerText = "hello";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToggleTextOnParent(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
result := Render(ToggleTextOnParent("hello", "world"))
|
||||||
|
//language=JavaScript
|
||||||
|
compareIgnoreSpaces(t, result, fmt.Sprintf(`
|
||||||
|
if(self.parentElement) {
|
||||||
|
let element = self.parentElement;
|
||||||
|
|
||||||
|
if(element.innerText === "hello") {
|
||||||
|
element.innerText = "world";
|
||||||
|
} else {
|
||||||
|
element.innerText = "hello";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToggleClassOnChildren(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
result := Render(ToggleClassOnChildren("div", "hidden"))
|
||||||
|
//language=JavaScript
|
||||||
|
compareIgnoreSpaces(t, result, fmt.Sprintf(`
|
||||||
|
let children = self.querySelectorAll('div');
|
||||||
|
children.forEach(function(element) {
|
||||||
|
element.classList.toggle('hidden')
|
||||||
|
});
|
||||||
|
`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToggleClassOnParent(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
result := Render(ToggleClassOnParent("hidden"))
|
||||||
|
//language=JavaScript
|
||||||
|
compareIgnoreSpaces(t, result, fmt.Sprintf(`
|
||||||
|
if(self.parentElement) {
|
||||||
|
let element = self.parentElement;
|
||||||
|
element.classList.toggle('hidden')
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToggleClassOnSibling(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
result := Render(ToggleClassOnSibling("div", "hidden"))
|
||||||
|
//language=JavaScript
|
||||||
|
compareIgnoreSpaces(t, result, fmt.Sprintf(`
|
||||||
|
if(self.parentElement) {
|
||||||
|
let siblings = self.parentElement.querySelectorAll('div');
|
||||||
|
siblings.forEach(function(element) {
|
||||||
|
element.classList.toggle('hidden')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package h
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/maddalax/htmgo/framework/hx"
|
"github.com/maddalax/htmgo/framework/hx"
|
||||||
"github.com/maddalax/htmgo/framework/internal/util"
|
"github.com/maddalax/htmgo/framework/internal/util"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -233,6 +234,54 @@ func ToggleClass(class string) SimpleJsCommand {
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.classList.toggle('%s')", class)}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.classList.toggle('%s')", class)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToggleText toggles the given text on the element.
|
||||||
|
func ToggleText(text string, textTwo string) Command {
|
||||||
|
// language=JavaScript
|
||||||
|
return EvalJs(fmt.Sprintf(`
|
||||||
|
if(self.innerText === "%s") {
|
||||||
|
self.innerText = "%s";
|
||||||
|
} else {
|
||||||
|
self.innerText = "%s";
|
||||||
|
}
|
||||||
|
`, text, textTwo, text))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleTextOnSibling toggles the given text on the siblings of the element.
|
||||||
|
func ToggleTextOnSibling(selector, text string, textTwo string) Command {
|
||||||
|
// language=JavaScript
|
||||||
|
return EvalJsOnSibling(selector, fmt.Sprintf(`
|
||||||
|
if(element.innerText === "%s") {
|
||||||
|
element.innerText = "%s";
|
||||||
|
} else {
|
||||||
|
element.innerText = "%s";
|
||||||
|
}
|
||||||
|
`, text, textTwo, text))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleTextOnChildren toggles the given text on the children of the element.
|
||||||
|
func ToggleTextOnChildren(selector, text string, textTwo string) Command {
|
||||||
|
// language=JavaScript
|
||||||
|
return EvalJsOnChildren(selector, fmt.Sprintf(`
|
||||||
|
if(element.innerText === "%s") {
|
||||||
|
element.innerText = "%s";
|
||||||
|
} else {
|
||||||
|
element.innerText = "%s";
|
||||||
|
}
|
||||||
|
`, text, textTwo, text))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleTextOnParent toggles the given text on the parent of the element.
|
||||||
|
func ToggleTextOnParent(text string, textTwo string) Command {
|
||||||
|
// language=JavaScript
|
||||||
|
return EvalJsOnParent(fmt.Sprintf(`
|
||||||
|
if(element.innerText === "%s") {
|
||||||
|
element.innerText = "%s";
|
||||||
|
} else {
|
||||||
|
element.innerText = "%s";
|
||||||
|
}
|
||||||
|
`, text, textTwo, text))
|
||||||
|
}
|
||||||
|
|
||||||
// ToggleClassOnElement toggles the given class on the elements returned by the selector.
|
// ToggleClassOnElement toggles the given class on the elements returned by the selector.
|
||||||
func ToggleClassOnElement(selector, class string) ComplexJsCommand {
|
func ToggleClassOnElement(selector, class string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
|
|
@ -247,9 +296,10 @@ func ToggleClassOnElement(selector, class string) ComplexJsCommand {
|
||||||
func EvalJsOnParent(js string) ComplexJsCommand {
|
func EvalJsOnParent(js string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJs(fmt.Sprintf(`
|
return EvalJs(fmt.Sprintf(`
|
||||||
if(!self.parentElement) { return; }
|
if(self.parentElement) {
|
||||||
let element = self.parentElement;
|
let element = self.parentElement;
|
||||||
%s
|
%s
|
||||||
|
}
|
||||||
`, js))
|
`, js))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,32 +318,51 @@ func EvalJsOnChildren(selector, js string) ComplexJsCommand {
|
||||||
func EvalJsOnSibling(selector, js string) ComplexJsCommand {
|
func EvalJsOnSibling(selector, js string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJs(fmt.Sprintf(`
|
return EvalJs(fmt.Sprintf(`
|
||||||
if(!self.parentElement) { return; }
|
if(self.parentElement) {
|
||||||
let siblings = self.parentElement.querySelectorAll('%s');
|
let siblings = self.parentElement.querySelectorAll('%s');
|
||||||
siblings.forEach(function(element) {
|
siblings.forEach(function(element) {
|
||||||
%s
|
%s
|
||||||
});
|
});
|
||||||
|
}
|
||||||
`, selector, js))
|
`, selector, js))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetClassOnParent sets the given class on the parent of the element. Reference the element using 'element'.
|
// SetClassOnParent sets the given class on the parent of the element.
|
||||||
func SetClassOnParent(class string) ComplexJsCommand {
|
func SetClassOnParent(class string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJsOnParent(fmt.Sprintf("element.classList.add('%s')", class))
|
return EvalJsOnParent(fmt.Sprintf("element.classList.add('%s')", class))
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveClassOnParent removes the given class from the parent of the element. Reference the element using 'element'.
|
// RemoveClassOnParent removes the given class from the parent of the element.
|
||||||
func RemoveClassOnParent(class string) ComplexJsCommand {
|
func RemoveClassOnParent(class string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJsOnParent(fmt.Sprintf("element.classList.remove('%s')", class))
|
return EvalJsOnParent(fmt.Sprintf("element.classList.remove('%s')", class))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetClassOnChildren sets the given class on the children of the element. Reference the element using 'element'.
|
// SetClassOnChildren sets the given class on the children of the element.
|
||||||
func SetClassOnChildren(selector, class string) ComplexJsCommand {
|
func SetClassOnChildren(selector, class string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJsOnChildren(selector, fmt.Sprintf("element.classList.add('%s')", class))
|
return EvalJsOnChildren(selector, fmt.Sprintf("element.classList.add('%s')", class))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToggleClassOnChildren toggles the given class on the children of the element.
|
||||||
|
func ToggleClassOnChildren(selector, class string) ComplexJsCommand {
|
||||||
|
// language=JavaScript
|
||||||
|
return EvalJsOnChildren(selector, fmt.Sprintf("element.classList.toggle('%s')", class))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleClassOnParent toggles the given class on the parent of the element.
|
||||||
|
func ToggleClassOnParent(class string) ComplexJsCommand {
|
||||||
|
// language=JavaScript
|
||||||
|
return EvalJsOnParent(fmt.Sprintf("element.classList.toggle('%s')", class))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleClassOnSibling toggles the given class on the siblings of the element.
|
||||||
|
func ToggleClassOnSibling(selector, class string) ComplexJsCommand {
|
||||||
|
// language=JavaScript
|
||||||
|
return EvalJsOnSibling(selector, fmt.Sprintf("element.classList.toggle('%s')", class))
|
||||||
|
}
|
||||||
|
|
||||||
// SetClassOnSibling sets the given class on the siblings of the element. Reference the element using 'element'.
|
// SetClassOnSibling sets the given class on the siblings of the element. Reference the element using 'element'.
|
||||||
func SetClassOnSibling(selector, class string) ComplexJsCommand {
|
func SetClassOnSibling(selector, class string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
|
|
@ -330,6 +399,36 @@ func EvalJs(js string) ComplexJsCommand {
|
||||||
return NewComplexJsCommand(js)
|
return NewComplexJsCommand(js)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func EvalCommandsOnSelector(selector string, cmds ...Command) ComplexJsCommand {
|
||||||
|
lines := make([]string, len(cmds))
|
||||||
|
for i, cmd := range cmds {
|
||||||
|
lines[i] = Render(cmd)
|
||||||
|
lines[i] = strings.ReplaceAll(lines[i], "this.", "self.")
|
||||||
|
// some commands set the element we need to fix it so we arent redeclaring it
|
||||||
|
lines[i] = strings.ReplaceAll(lines[i], "let element =", "element =")
|
||||||
|
}
|
||||||
|
code := strings.Join(lines, "\n")
|
||||||
|
return EvalJs(fmt.Sprintf(`
|
||||||
|
let element = document.querySelector("%s");
|
||||||
|
|
||||||
|
if(!element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self = element;
|
||||||
|
%s
|
||||||
|
`, selector, code))
|
||||||
|
}
|
||||||
|
|
||||||
|
func EvalCommands(element *Element, cmds ...Command) ComplexJsCommand {
|
||||||
|
id := strings.ReplaceAll(uuid.NewString(), "-", "")
|
||||||
|
element.AppendChildren(
|
||||||
|
Attribute("data-eval-commands-id", id),
|
||||||
|
)
|
||||||
|
return EvalCommandsOnSelector(
|
||||||
|
fmt.Sprintf(`[data-eval-commands-id='%s']`, id), cmds...)
|
||||||
|
}
|
||||||
|
|
||||||
// PreventDefault prevents the default action of the event.
|
// PreventDefault prevents the default action of the event.
|
||||||
func PreventDefault() SimpleJsCommand {
|
func PreventDefault() SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,15 @@ var voidTags = map[string]bool{
|
||||||
"wbr": true,
|
"wbr": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ScriptEntry struct {
|
||||||
|
Body string
|
||||||
|
ChildOf *Element
|
||||||
|
}
|
||||||
|
|
||||||
type RenderContext struct {
|
type RenderContext struct {
|
||||||
builder *strings.Builder
|
builder *strings.Builder
|
||||||
scripts []string
|
scripts []ScriptEntry
|
||||||
|
currentElement *Element
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *RenderContext) AddScript(funcName string, body string) {
|
func (ctx *RenderContext) AddScript(funcName string, body string) {
|
||||||
|
|
@ -48,7 +54,11 @@ func (ctx *RenderContext) AddScript(funcName string, body string) {
|
||||||
%s
|
%s
|
||||||
}
|
}
|
||||||
</script>`, funcName, funcName, body)
|
</script>`, funcName, funcName, body)
|
||||||
ctx.scripts = append(ctx.scripts, script)
|
|
||||||
|
ctx.scripts = append(ctx.scripts, ScriptEntry{
|
||||||
|
Body: script,
|
||||||
|
ChildOf: ctx.currentElement,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (node *Element) Render(context *RenderContext) {
|
func (node *Element) Render(context *RenderContext) {
|
||||||
|
|
@ -56,6 +66,8 @@ func (node *Element) Render(context *RenderContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.currentElement = node
|
||||||
|
|
||||||
if node.tag == CachedNodeTag {
|
if node.tag == CachedNodeTag {
|
||||||
meta := node.meta.(*CachedNode)
|
meta := node.meta.(*CachedNode)
|
||||||
meta.Render(context)
|
meta.Render(context)
|
||||||
|
|
@ -147,7 +159,7 @@ func (node *Element) Render(context *RenderContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.tag != "" {
|
if node.tag != "" {
|
||||||
renderScripts(context)
|
renderScripts(context, node)
|
||||||
if !voidTags[node.tag] {
|
if !voidTags[node.tag] {
|
||||||
context.builder.WriteString("</")
|
context.builder.WriteString("</")
|
||||||
context.builder.WriteString(node.tag)
|
context.builder.WriteString(node.tag)
|
||||||
|
|
@ -156,11 +168,19 @@ func (node *Element) Render(context *RenderContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderScripts(context *RenderContext) {
|
func renderScripts(context *RenderContext, parent *Element) {
|
||||||
for _, script := range context.scripts {
|
if len(context.scripts) == 0 {
|
||||||
context.builder.WriteString(script)
|
return
|
||||||
}
|
}
|
||||||
context.scripts = []string{}
|
notWritten := make([]ScriptEntry, 0)
|
||||||
|
for _, script := range context.scripts {
|
||||||
|
if script.ChildOf == parent {
|
||||||
|
context.builder.WriteString(script.Body)
|
||||||
|
} else {
|
||||||
|
notWritten = append(notWritten, script)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.scripts = notWritten
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AttributeR) Render(context *RenderContext) {
|
func (a *AttributeR) Render(context *RenderContext) {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,11 @@ var SetDisabled = h.SetDisabled
|
||||||
var RemoveClass = h.RemoveClass
|
var RemoveClass = h.RemoveClass
|
||||||
var Alert = h.Alert
|
var Alert = h.Alert
|
||||||
var SetClassOnChildren = h.SetClassOnChildren
|
var SetClassOnChildren = h.SetClassOnChildren
|
||||||
|
var ToggleClassOnChildren = h.ToggleClassOnChildren
|
||||||
|
var ToggleClassOnParent = h.ToggleClassOnParent
|
||||||
|
var SetClassOnParent = h.SetClassOnParent
|
||||||
|
var RemoveClassOnParent = h.RemoveClassOnParent
|
||||||
|
var ToggleClassOnSibling = h.ToggleClassOnSibling
|
||||||
var RemoveClassOnChildren = h.RemoveClassOnChildren
|
var RemoveClassOnChildren = h.RemoveClassOnChildren
|
||||||
var EvalJsOnChildren = h.EvalJsOnChildren
|
var EvalJsOnChildren = h.EvalJsOnChildren
|
||||||
var EvalJsOnSibling = h.EvalJsOnSibling
|
var EvalJsOnSibling = h.EvalJsOnSibling
|
||||||
|
|
@ -23,6 +28,8 @@ var RemoveClassOnSibling = h.RemoveClassOnSibling
|
||||||
var Remove = h.Remove
|
var Remove = h.Remove
|
||||||
var PreventDefault = h.PreventDefault
|
var PreventDefault = h.PreventDefault
|
||||||
var EvalJs = h.EvalJs
|
var EvalJs = h.EvalJs
|
||||||
|
var EvalCommands = h.EvalCommands
|
||||||
|
var EvalCommandsOnSelector = h.EvalCommandsOnSelector
|
||||||
var ConsoleLog = h.ConsoleLog
|
var ConsoleLog = h.ConsoleLog
|
||||||
var SetValue = h.SetValue
|
var SetValue = h.SetValue
|
||||||
var SubmitFormOnEnter = h.SubmitFormOnEnter
|
var SubmitFormOnEnter = h.SubmitFormOnEnter
|
||||||
|
|
@ -36,3 +43,7 @@ var GetWithQs = h.GetWithQs
|
||||||
var PostWithQs = h.PostWithQs
|
var PostWithQs = h.PostWithQs
|
||||||
var ToggleClass = h.ToggleClass
|
var ToggleClass = h.ToggleClass
|
||||||
var ToggleClassOnElement = h.ToggleClassOnElement
|
var ToggleClassOnElement = h.ToggleClassOnElement
|
||||||
|
var ToggleText = h.ToggleText
|
||||||
|
var ToggleTextOnSibling = h.ToggleTextOnSibling
|
||||||
|
var ToggleTextOnChildren = h.ToggleTextOnChildren
|
||||||
|
var ToggleTextOnParent = h.ToggleTextOnParent
|
||||||
|
|
|
||||||
|
|
@ -70,9 +70,31 @@ var ClickToEditSnippet = Snippet{
|
||||||
partial: snippets.ClickToEdit,
|
partial: snippets.ClickToEdit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var JsSetTextOnClick = Snippet{
|
||||||
|
category: "Interactivity (JS)",
|
||||||
|
name: "Set Element Text On Click",
|
||||||
|
description: "A simple example of how to use htmgo with javascript",
|
||||||
|
sidebarName: "Set Text On Click",
|
||||||
|
path: "/examples/js-set-text-on-click",
|
||||||
|
partial: snippets.SetTextOnClick,
|
||||||
|
}
|
||||||
|
|
||||||
|
var JsHideChildrenOnClick = Snippet{
|
||||||
|
category: "Interactivity (JS)",
|
||||||
|
name: "Hide / Show Children On Click",
|
||||||
|
description: "Use JS to hide and show children elements on click",
|
||||||
|
sidebarName: "Hide / Show Children",
|
||||||
|
path: "/examples/js-hide-children-on-click",
|
||||||
|
partial: snippets.JsHideChildrenOnClick,
|
||||||
|
}
|
||||||
|
|
||||||
var examples = []Snippet{
|
var examples = []Snippet{
|
||||||
FormWithLoadingStateSnippet,
|
FormWithLoadingStateSnippet,
|
||||||
ClickToEditSnippet,
|
ClickToEditSnippet,
|
||||||
|
|
||||||
|
JsSetTextOnClick,
|
||||||
|
JsHideChildrenOnClick,
|
||||||
|
|
||||||
UserAuthSnippet,
|
UserAuthSnippet,
|
||||||
ChatSnippet,
|
ChatSnippet,
|
||||||
HackerNewsSnippet,
|
HackerNewsSnippet,
|
||||||
|
|
|
||||||
10
htmgo-site/pages/examples/js-hide-children-on-click.go
Normal file
10
htmgo-site/pages/examples/js-hide-children-on-click.go
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
|
)
|
||||||
|
|
||||||
|
func JsHideChildrenOnClickPage(ctx *h.RequestContext) *h.Page {
|
||||||
|
SetSnippet(ctx, &JsHideChildrenOnClick)
|
||||||
|
return Index(ctx)
|
||||||
|
}
|
||||||
10
htmgo-site/pages/examples/js-set-text-on-click.go
Normal file
10
htmgo-site/pages/examples/js-set-text-on-click.go
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
|
)
|
||||||
|
|
||||||
|
func JsSetTextOnClickPage(ctx *h.RequestContext) *h.Page {
|
||||||
|
SetSnippet(ctx, &JsSetTextOnClick)
|
||||||
|
return Index(ctx)
|
||||||
|
}
|
||||||
32
htmgo-site/partials/snippets/js-hide-children-on-click.go
Normal file
32
htmgo-site/partials/snippets/js-hide-children-on-click.go
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
package snippets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
|
"github.com/maddalax/htmgo/framework/js"
|
||||||
|
)
|
||||||
|
|
||||||
|
func JsHideChildrenOnClick(ctx *h.RequestContext) *h.Partial {
|
||||||
|
text := h.Pf("- Parent")
|
||||||
|
return h.NewPartial(
|
||||||
|
h.Div(
|
||||||
|
text,
|
||||||
|
h.Class("cursor-pointer"),
|
||||||
|
h.Id("js-test"),
|
||||||
|
h.OnClick(
|
||||||
|
js.ToggleClassOnChildren("div", "hidden"),
|
||||||
|
js.EvalCommands(
|
||||||
|
text,
|
||||||
|
js.ToggleText("+ Parent", "- Parent"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
h.Div(
|
||||||
|
h.Class("ml-4"),
|
||||||
|
h.Text("Child 1"),
|
||||||
|
),
|
||||||
|
h.Div(
|
||||||
|
h.Class("ml-4"),
|
||||||
|
h.Text("Child 2"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
18
htmgo-site/partials/snippets/js-set-text-on-click.go
Normal file
18
htmgo-site/partials/snippets/js-set-text-on-click.go
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
package snippets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
|
"github.com/maddalax/htmgo/framework/js"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetTextOnClick(ctx *h.RequestContext) *h.Partial {
|
||||||
|
return h.NewPartial(
|
||||||
|
h.Button(
|
||||||
|
h.Text("Click to set text"),
|
||||||
|
h.Class("bg-slate-900 text-white py-2 px-4 rounded"),
|
||||||
|
h.OnClick(
|
||||||
|
js.SetText("Hello World"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue