add some comments
This commit is contained in:
parent
f06feffb9e
commit
cf76ca4f98
10 changed files with 131 additions and 0 deletions
|
|
@ -47,6 +47,10 @@ func (c *RequestContext) Get(key string) interface{} {
|
||||||
return c.kv[key]
|
return c.kv[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServiceLocator returns the service locator to register and retrieve services
|
||||||
|
// Usage:
|
||||||
|
// service.Set[db.Queries](locator, service.Singleton, db.Provide)
|
||||||
|
// service.Get[db.Queries](locator)
|
||||||
func (c *RequestContext) ServiceLocator() *service.Locator {
|
func (c *RequestContext) ServiceLocator() *service.Locator {
|
||||||
return c.locator
|
return c.locator
|
||||||
}
|
}
|
||||||
|
|
@ -62,6 +66,7 @@ type App struct {
|
||||||
Router *chi.Mux
|
Router *chi.Mux
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start starts the htmgo server
|
||||||
func Start(opts AppOpts) {
|
func Start(opts AppOpts) {
|
||||||
router := chi.NewRouter()
|
router := chi.NewRouter()
|
||||||
instance := App{
|
instance := App{
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package h
|
package h
|
||||||
|
|
||||||
|
// Unique returns a new slice with only unique items.
|
||||||
func Unique[T any](slice []T, key func(item T) string) []T {
|
func Unique[T any](slice []T, key func(item T) string) []T {
|
||||||
var result []T
|
var result []T
|
||||||
seen := make(map[string]bool)
|
seen := make(map[string]bool)
|
||||||
|
|
@ -13,6 +14,7 @@ func Unique[T any](slice []T, key func(item T) string) []T {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter returns a new slice with only items that match the predicate.
|
||||||
func Filter[T any](slice []T, predicate func(item T) bool) []T {
|
func Filter[T any](slice []T, predicate func(item T) bool) []T {
|
||||||
var result []T
|
var result []T
|
||||||
for _, v := range slice {
|
for _, v := range slice {
|
||||||
|
|
@ -23,6 +25,7 @@ func Filter[T any](slice []T, predicate func(item T) bool) []T {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map returns a new slice with the results of the mapper function.
|
||||||
func Map[T, U any](slice []T, mapper func(item T) U) []U {
|
func Map[T, U any](slice []T, mapper func(item T) U) []U {
|
||||||
var result []U
|
var result []U
|
||||||
for _, v := range slice {
|
for _, v := range slice {
|
||||||
|
|
|
||||||
|
|
@ -120,27 +120,34 @@ func HxIndicator(tag string) *AttributeR {
|
||||||
return Attribute(hx.IndicatorAttr, tag)
|
return Attribute(hx.IndicatorAttr, tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TriggerChildren Adds the hx-extension="trigger-children" to an element
|
||||||
|
// See https://htmgo.dev/docs#htmx-extensions-trigger-children
|
||||||
func TriggerChildren() *AttributeR {
|
func TriggerChildren() *AttributeR {
|
||||||
return HxExtension("trigger-children")
|
return HxExtension("trigger-children")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxTriggerString Adds a hx-trigger to an element based on a string of triggers
|
||||||
func HxTriggerString(triggers ...string) *AttributeR {
|
func HxTriggerString(triggers ...string) *AttributeR {
|
||||||
trigger := hx.NewStringTrigger(strings.Join(triggers, ", "))
|
trigger := hx.NewStringTrigger(strings.Join(triggers, ", "))
|
||||||
return Attribute(hx.TriggerAttr, trigger.ToString())
|
return Attribute(hx.TriggerAttr, trigger.ToString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxTrigger Adds a hx-trigger to an element
|
||||||
func HxTrigger(opts ...hx.TriggerEvent) *AttributeR {
|
func HxTrigger(opts ...hx.TriggerEvent) *AttributeR {
|
||||||
return Attribute(hx.TriggerAttr, hx.NewTrigger(opts...).ToString())
|
return Attribute(hx.TriggerAttr, hx.NewTrigger(opts...).ToString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxTriggerClick Adds a hx-trigger="click" to an element
|
||||||
func HxTriggerClick(opts ...hx.Modifier) *AttributeR {
|
func HxTriggerClick(opts ...hx.Modifier) *AttributeR {
|
||||||
return HxTrigger(hx.OnClick(opts...))
|
return HxTrigger(hx.OnClick(opts...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxExtension Adds a hx-ext to an element
|
||||||
func HxExtension(value string) *AttributeR {
|
func HxExtension(value string) *AttributeR {
|
||||||
return Attribute(hx.ExtAttr, value)
|
return Attribute(hx.ExtAttr, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxExtensions Adds multiple hx-ext to an element, separated by commas
|
||||||
func HxExtensions(value ...string) Ren {
|
func HxExtensions(value ...string) Ren {
|
||||||
return Attribute(hx.ExtAttr, strings.Join(value, ","))
|
return Attribute(hx.ExtAttr, strings.Join(value, ","))
|
||||||
}
|
}
|
||||||
|
|
@ -149,6 +156,8 @@ func JoinExtensions(attrs ...*AttributeR) Ren {
|
||||||
return JoinAttributes(", ", attrs...)
|
return JoinAttributes(", ", attrs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JoinAttributes joins multiple attributes into a single attribute string based on a separator
|
||||||
|
// Example: JoinAttributes(", ", Attribute("hx-extension", "one"), Attribute("hx-extension", "two")) = hx-extension="one,two"
|
||||||
func JoinAttributes(sep string, attrs ...*AttributeR) *AttributeR {
|
func JoinAttributes(sep string, attrs ...*AttributeR) *AttributeR {
|
||||||
values := make([]string, 0, len(attrs))
|
values := make([]string, 0, len(attrs))
|
||||||
for _, a := range attrs {
|
for _, a := range attrs {
|
||||||
|
|
@ -193,6 +202,9 @@ func Class(value ...string) *AttributeR {
|
||||||
return Attribute("class", MergeClasses(value...))
|
return Attribute("class", MergeClasses(value...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClassX conditionally renders a class based on a map of class names and boolean values
|
||||||
|
// value is any non-conditional class name you'd like to add
|
||||||
|
// m is a map of class names and boolean values
|
||||||
func ClassX(value string, m ClassMap) Ren {
|
func ClassX(value string, m ClassMap) Ren {
|
||||||
builder := strings.Builder{}
|
builder := strings.Builder{}
|
||||||
builder.WriteString(value)
|
builder.WriteString(value)
|
||||||
|
|
@ -206,6 +218,7 @@ func ClassX(value string, m ClassMap) Ren {
|
||||||
return Class(builder.String())
|
return Class(builder.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MergeClasses merges multiple classes into a single class string
|
||||||
func MergeClasses(classes ...string) string {
|
func MergeClasses(classes ...string) string {
|
||||||
if len(classes) == 1 {
|
if len(classes) == 1 {
|
||||||
return classes[0]
|
return classes[0]
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,9 @@ func startExpiredCacheCleaner(node *CachedNode) {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cached caches the given element for the given duration. The element is only rendered once, and then cached for the given duration.
|
||||||
|
// Please note this element is globally cached, and not per unique identifier / user.
|
||||||
|
// Use CachedPerKey to cache elements per unqiue identifier.
|
||||||
func Cached(duration time.Duration, cb GetElementFunc) func() *Element {
|
func Cached(duration time.Duration, cb GetElementFunc) func() *Element {
|
||||||
element := &Element{
|
element := &Element{
|
||||||
tag: CachedNodeTag,
|
tag: CachedNodeTag,
|
||||||
|
|
@ -64,6 +67,8 @@ func Cached(duration time.Duration, cb GetElementFunc) func() *Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CachedPerKey caches the given element for the given duration. The element is only rendered once per key, and then cached for the given duration.
|
||||||
|
// The element is cached by the unique identifier that is returned by the callback function.
|
||||||
func CachedPerKey[K comparable](duration time.Duration, cb GetElementFuncWithKey[K]) func() *Element {
|
func CachedPerKey[K comparable](duration time.Duration, cb GetElementFuncWithKey[K]) func() *Element {
|
||||||
element := &Element{
|
element := &Element{
|
||||||
tag: CachedNodeTag,
|
tag: CachedNodeTag,
|
||||||
|
|
@ -94,6 +99,8 @@ type ByKeyEntry struct {
|
||||||
parent *Element
|
parent *Element
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CachedPerKeyT caches the given element for the given duration. The element is only rendered once per key, and then cached for the given duration.
|
||||||
|
// The element is cached by the unique identifier that is returned by the callback function.
|
||||||
func CachedPerKeyT[K comparable, T any](duration time.Duration, cb GetElementFuncTWithKey[K, T]) func(T) *Element {
|
func CachedPerKeyT[K comparable, T any](duration time.Duration, cb GetElementFuncTWithKey[K, T]) func(T) *Element {
|
||||||
element := &Element{
|
element := &Element{
|
||||||
tag: CachedNodeTag,
|
tag: CachedNodeTag,
|
||||||
|
|
@ -118,6 +125,8 @@ func CachedPerKeyT[K comparable, T any](duration time.Duration, cb GetElementFun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CachedPerKeyT2 caches the given element for the given duration. The element is only rendered once per key, and then cached for the given duration.
|
||||||
|
// The element is cached by the unique identifier that is returned by the callback function.
|
||||||
func CachedPerKeyT2[K comparable, T any, T2 any](duration time.Duration, cb GetElementFuncT2WithKey[K, T, T2]) func(T, T2) *Element {
|
func CachedPerKeyT2[K comparable, T any, T2 any](duration time.Duration, cb GetElementFuncT2WithKey[K, T, T2]) func(T, T2) *Element {
|
||||||
element := &Element{
|
element := &Element{
|
||||||
tag: CachedNodeTag,
|
tag: CachedNodeTag,
|
||||||
|
|
@ -142,6 +151,8 @@ func CachedPerKeyT2[K comparable, T any, T2 any](duration time.Duration, cb GetE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CachedPerKeyT3 caches the given element for the given duration. The element is only rendered once per key, and then cached for the given duration.
|
||||||
|
// The element is cached by the unique identifier that is returned by the callback function.
|
||||||
func CachedPerKeyT3[K comparable, T any, T2 any, T3 any](duration time.Duration, cb GetElementFuncT3WithKey[K, T, T2, T3]) func(T, T2, T3) *Element {
|
func CachedPerKeyT3[K comparable, T any, T2 any, T3 any](duration time.Duration, cb GetElementFuncT3WithKey[K, T, T2, T3]) func(T, T2, T3) *Element {
|
||||||
element := &Element{
|
element := &Element{
|
||||||
tag: CachedNodeTag,
|
tag: CachedNodeTag,
|
||||||
|
|
@ -166,6 +177,8 @@ func CachedPerKeyT3[K comparable, T any, T2 any, T3 any](duration time.Duration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CachedPerKeyT4 caches the given element for the given duration. The element is only rendered once per key, and then cached for the given duration.
|
||||||
|
// The element is cached by the unique identifier that is returned by the callback function.
|
||||||
func CachedPerKeyT4[K comparable, T any, T2 any, T3 any, T4 any](duration time.Duration, cb GetElementFuncT4WithKey[K, T, T2, T3, T4]) func(T, T2, T3, T4) *Element {
|
func CachedPerKeyT4[K comparable, T any, T2 any, T3 any, T4 any](duration time.Duration, cb GetElementFuncT4WithKey[K, T, T2, T3, T4]) func(T, T2, T3, T4) *Element {
|
||||||
element := &Element{
|
element := &Element{
|
||||||
tag: CachedNodeTag,
|
tag: CachedNodeTag,
|
||||||
|
|
@ -190,6 +203,9 @@ func CachedPerKeyT4[K comparable, T any, T2 any, T3 any, T4 any](duration time.D
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CachedT caches the given element for the given duration. The element is only rendered once, and then cached for the given duration.
|
||||||
|
// Please note this element is globally cached, and not per unique identifier / user.
|
||||||
|
// Use CachedPerKey to cache elements per unqiue identifier.
|
||||||
func CachedT[T any](duration time.Duration, cb GetElementFuncT[T]) func(T) *Element {
|
func CachedT[T any](duration time.Duration, cb GetElementFuncT[T]) func(T) *Element {
|
||||||
element := &Element{
|
element := &Element{
|
||||||
tag: CachedNodeTag,
|
tag: CachedNodeTag,
|
||||||
|
|
@ -208,6 +224,9 @@ func CachedT[T any](duration time.Duration, cb GetElementFuncT[T]) func(T) *Elem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CachedT2 caches the given element for the given duration. The element is only rendered once, and then cached for the given duration.
|
||||||
|
// Please note this element is globally cached, and not per unique identifier / user.
|
||||||
|
// Use CachedPerKey to cache elements per unqiue identifier.
|
||||||
func CachedT2[T any, T2 any](duration time.Duration, cb GetElementFuncT2[T, T2]) func(T, T2) *Element {
|
func CachedT2[T any, T2 any](duration time.Duration, cb GetElementFuncT2[T, T2]) func(T, T2) *Element {
|
||||||
element := &Element{
|
element := &Element{
|
||||||
tag: CachedNodeTag,
|
tag: CachedNodeTag,
|
||||||
|
|
@ -225,6 +244,9 @@ func CachedT2[T any, T2 any](duration time.Duration, cb GetElementFuncT2[T, T2])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CachedT3 caches the given element for the given duration. The element is only rendered once, and then cached for the given duration.
|
||||||
|
// Please note this element is globally cached, and not per unique identifier / user.
|
||||||
|
// Use CachedPerKey to cache elements per unqiue identifier.
|
||||||
func CachedT3[T any, T2 any, T3 any](duration time.Duration, cb GetElementFuncT3[T, T2, T3]) func(T, T2, T3) *Element {
|
func CachedT3[T any, T2 any, T3 any](duration time.Duration, cb GetElementFuncT3[T, T2, T3]) func(T, T2, T3) *Element {
|
||||||
element := &Element{
|
element := &Element{
|
||||||
tag: CachedNodeTag,
|
tag: CachedNodeTag,
|
||||||
|
|
@ -242,6 +264,9 @@ func CachedT3[T any, T2 any, T3 any](duration time.Duration, cb GetElementFuncT3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CachedT4 caches the given element for the given duration. The element is only rendered once, and then cached for the given duration.
|
||||||
|
// Please note this element is globally cached, and not per unique identifier / user.
|
||||||
|
// Use CachedPerKey to cache elements per unqiue identifier.
|
||||||
func CachedT4[T any, T2 any, T3 any, T4 any](duration time.Duration, cb GetElementFuncT4[T, T2, T3, T4]) func(T, T2, T3, T4) *Element {
|
func CachedT4[T any, T2 any, T3 any, T4 any](duration time.Duration, cb GetElementFuncT4[T, T2, T3, T4]) func(T, T2, T3, T4) *Element {
|
||||||
element := &Element{
|
element := &Element{
|
||||||
tag: CachedNodeTag,
|
tag: CachedNodeTag,
|
||||||
|
|
@ -259,6 +284,7 @@ func CachedT4[T any, T2 any, T3 any, T4 any](duration time.Duration, cb GetEleme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClearCache clears the cached HTML of the element. This is called automatically by the framework.
|
||||||
func (c *CachedNode) ClearCache() {
|
func (c *CachedNode) ClearCache() {
|
||||||
c.html = ""
|
c.html = ""
|
||||||
if c.byKeyCache != nil {
|
if c.byKeyCache != nil {
|
||||||
|
|
@ -273,6 +299,7 @@ func (c *CachedNode) ClearCache() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClearExpired clears all expired cached HTML of the element. This is called automatically by the framework.
|
||||||
func (c *CachedNode) ClearExpired() {
|
func (c *CachedNode) ClearExpired() {
|
||||||
c.mutex.Lock()
|
c.mutex.Lock()
|
||||||
defer c.mutex.Unlock()
|
defer c.mutex.Unlock()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package h
|
package h
|
||||||
|
|
||||||
|
// If returns the node if the condition is true, otherwise returns an empty element
|
||||||
func If(condition bool, node Ren) Ren {
|
func If(condition bool, node Ren) Ren {
|
||||||
if condition {
|
if condition {
|
||||||
return node
|
return node
|
||||||
|
|
@ -8,10 +9,12 @@ func If(condition bool, node Ren) Ren {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ternary returns the first argument if the second argument is true, otherwise returns the third argument
|
||||||
func Ternary[T any](value bool, a T, b T) T {
|
func Ternary[T any](value bool, a T, b T) T {
|
||||||
return IfElse(value, a, b)
|
return IfElse(value, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ElementIf returns the element if the condition is true, otherwise returns an empty element
|
||||||
func ElementIf(condition bool, element *Element) *Element {
|
func ElementIf(condition bool, element *Element) *Element {
|
||||||
if condition {
|
if condition {
|
||||||
return element
|
return element
|
||||||
|
|
@ -20,6 +23,7 @@ func ElementIf(condition bool, element *Element) *Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IfElseE returns element if condition is true, otherwise returns element2
|
||||||
func IfElseE(condition bool, element *Element, element2 *Element) *Element {
|
func IfElseE(condition bool, element *Element, element2 *Element) *Element {
|
||||||
if condition {
|
if condition {
|
||||||
return element
|
return element
|
||||||
|
|
@ -28,6 +32,7 @@ func IfElseE(condition bool, element *Element, element2 *Element) *Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IfElse returns node if condition is true, otherwise returns node2
|
||||||
func IfElse[T any](condition bool, node T, node2 T) T {
|
func IfElse[T any](condition bool, node T, node2 T) T {
|
||||||
if condition {
|
if condition {
|
||||||
return node
|
return node
|
||||||
|
|
@ -36,6 +41,10 @@ func IfElse[T any](condition bool, node T, node2 T) T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IfElseLazy returns node if condition is true, otherwise returns the result of cb2
|
||||||
|
// This is useful if you want to lazily evaluate a node based on a condition
|
||||||
|
// For example, If you are rendering a component that requires specific data,
|
||||||
|
// you can use this to only load the component if the data is available
|
||||||
func IfElseLazy[T any](condition bool, cb1 func() T, cb2 func() T) T {
|
func IfElseLazy[T any](condition bool, cb1 func() T, cb2 func() T) T {
|
||||||
if condition {
|
if condition {
|
||||||
return cb1()
|
return cb1()
|
||||||
|
|
@ -44,6 +53,7 @@ func IfElseLazy[T any](condition bool, cb1 func() T, cb2 func() T) T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IfHtmxRequest returns the node if the request is an htmx request, otherwise returns an empty element
|
||||||
func IfHtmxRequest(ctx *RequestContext, node Ren) Ren {
|
func IfHtmxRequest(ctx *RequestContext, node Ren) Ren {
|
||||||
if ctx.isHxRequest {
|
if ctx.isHxRequest {
|
||||||
return node
|
return node
|
||||||
|
|
@ -51,6 +61,7 @@ func IfHtmxRequest(ctx *RequestContext, node Ren) Ren {
|
||||||
return Empty()
|
return Empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClassIf returns the class attribute if the condition is true, otherwise returns an empty element
|
||||||
func ClassIf(condition bool, value string) Ren {
|
func ClassIf(condition bool, value string) Ren {
|
||||||
if condition {
|
if condition {
|
||||||
return Class(value)
|
return Class(value)
|
||||||
|
|
@ -58,6 +69,7 @@ func ClassIf(condition bool, value string) Ren {
|
||||||
return Empty()
|
return Empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AttributeIf returns the attribute if the condition is true, otherwise returns an empty element
|
||||||
func AttributeIf(condition bool, name string, value string) Ren {
|
func AttributeIf(condition bool, name string, value string) Ren {
|
||||||
if condition {
|
if condition {
|
||||||
return Attribute(name, value)
|
return Attribute(name, value)
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ func (l *LifeCycle) OnEvent(event hx.Event, cmd ...Command) *LifeCycle {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnLoad executes the given commands when the element is loaded into the DOM, it also executes when the element is replaced / swapped in.
|
||||||
func OnLoad(cmd ...Command) *LifeCycle {
|
func OnLoad(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.LoadDomEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.LoadDomEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
@ -60,58 +61,73 @@ func (l *LifeCycle) HxBeforeRequest(cmd ...Command) *LifeCycle {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxOnLoad executes the given commands when the element is loaded into the DOM.
|
||||||
|
// Deprecated: Use OnLoad instead.
|
||||||
func HxOnLoad(cmd ...Command) *LifeCycle {
|
func HxOnLoad(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.LoadEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.LoadEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxOnAfterSwap executes the given commands when the element is swapped in.
|
||||||
func HxOnAfterSwap(cmd ...Command) *LifeCycle {
|
func HxOnAfterSwap(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.AfterSwapEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.AfterSwapEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnClick executes the given commands when the element is clicked.
|
||||||
func OnClick(cmd ...Command) *LifeCycle {
|
func OnClick(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.ClickEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.ClickEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnEvent executes the given commands when the given event is triggered.
|
||||||
func OnEvent(event hx.Event, cmd ...Command) *LifeCycle {
|
func OnEvent(event hx.Event, cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(event, cmd...)
|
return NewLifeCycle().OnEvent(event, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxBeforeSseMessage executes the given commands when a message is received from the server via SSE, but before it is processed.
|
||||||
func HxBeforeSseMessage(cmd ...Command) *LifeCycle {
|
func HxBeforeSseMessage(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.SseBeforeMessageEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.SseBeforeMessageEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxAfterSseMessage executes the given commands when a message is received from the server via SSE, and after it is processed.
|
||||||
func HxAfterSseMessage(cmd ...Command) *LifeCycle {
|
func HxAfterSseMessage(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.SseAfterMessageEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.SseAfterMessageEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnSubmit executes the given commands when the form is submitted.
|
||||||
func OnSubmit(cmd ...Command) *LifeCycle {
|
func OnSubmit(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.SubmitEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.SubmitEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxOnSseError executes the given commands when an error occurs while connecting to the server via SSE.
|
||||||
func HxOnSseError(cmd ...Command) *LifeCycle {
|
func HxOnSseError(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.SseErrorEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.SseErrorEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxOnSseClose executes the given commands when the connection to the server via SSE is closed.
|
||||||
func HxOnSseClose(cmd ...Command) *LifeCycle {
|
func HxOnSseClose(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.SseClosedEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.SseClosedEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxOnSseConnecting executes the given commands when the connection to the server via SSE is being established.
|
||||||
func HxOnSseConnecting(cmd ...Command) *LifeCycle {
|
func HxOnSseConnecting(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.SseConnectingEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.SseConnectingEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxOnSseOpen executes the given commands when the connection to the server via SSE is established.
|
||||||
func HxOnSseOpen(cmd ...Command) *LifeCycle {
|
func HxOnSseOpen(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().OnEvent(hx.SseConnectedEvent, cmd...)
|
return NewLifeCycle().OnEvent(hx.SseConnectedEvent, cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxBeforeRequest executes the given commands before the request is sent.
|
||||||
func HxBeforeRequest(cmd ...Command) *LifeCycle {
|
func HxBeforeRequest(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().HxBeforeRequest(cmd...)
|
return NewLifeCycle().HxBeforeRequest(cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxAfterRequest executes the given commands after the request is sent.
|
||||||
func HxAfterRequest(cmd ...Command) *LifeCycle {
|
func HxAfterRequest(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().HxAfterRequest(cmd...)
|
return NewLifeCycle().HxAfterRequest(cmd...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HxOnMutationError executes the given commands when a mutation error of a request occurs.
|
||||||
func HxOnMutationError(cmd ...Command) *LifeCycle {
|
func HxOnMutationError(cmd ...Command) *LifeCycle {
|
||||||
return NewLifeCycle().HxOnMutationError(cmd...)
|
return NewLifeCycle().HxOnMutationError(cmd...)
|
||||||
}
|
}
|
||||||
|
|
@ -137,16 +153,19 @@ type ComplexJsCommand struct {
|
||||||
TempFuncName string
|
TempFuncName string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewComplexJsCommand creates a new complex JavaScript command.
|
||||||
func NewComplexJsCommand(command string) ComplexJsCommand {
|
func NewComplexJsCommand(command string) ComplexJsCommand {
|
||||||
name := fmt.Sprintf("__eval_%s", util.RandSeq(6))
|
name := fmt.Sprintf("__eval_%s", util.RandSeq(6))
|
||||||
return ComplexJsCommand{Command: command, TempFuncName: name}
|
return ComplexJsCommand{Command: command, TempFuncName: name}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetText sets the inner text of the element.
|
||||||
func SetText(text string) SimpleJsCommand {
|
func SetText(text string) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.innerText = '%s'", text)}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.innerText = '%s'", text)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTextOnChildren sets the inner text of all the children of the element that match the selector.
|
||||||
func SetTextOnChildren(selector, text string) ComplexJsCommand {
|
func SetTextOnChildren(selector, text string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJs(fmt.Sprintf(`
|
return EvalJs(fmt.Sprintf(`
|
||||||
|
|
@ -157,26 +176,31 @@ func SetTextOnChildren(selector, text string) ComplexJsCommand {
|
||||||
`, selector, text))
|
`, selector, text))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Increment increments the inner text of the element by the given amount.
|
||||||
func Increment(amount int) SimpleJsCommand {
|
func Increment(amount int) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.innerText = parseInt(this.innerText) + %d", amount)}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.innerText = parseInt(this.innerText) + %d", amount)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetInnerHtml sets the inner HTML of the element.
|
||||||
func SetInnerHtml(r Ren) SimpleJsCommand {
|
func SetInnerHtml(r Ren) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.innerHTML = `%s`", Render(r))}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.innerHTML = `%s`", Render(r))}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetOuterHtml sets the outer HTML of the element.
|
||||||
func SetOuterHtml(r Ren) SimpleJsCommand {
|
func SetOuterHtml(r Ren) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.outerHTML = `%s`", Render(r))}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.outerHTML = `%s`", Render(r))}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddAttribute adds the given attribute to the element.
|
||||||
func AddAttribute(name, value string) SimpleJsCommand {
|
func AddAttribute(name, value string) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.setAttribute('%s', '%s')", name, value)}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.setAttribute('%s', '%s')", name, value)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDisabled sets the disabled attribute on the element.
|
||||||
func SetDisabled(disabled bool) SimpleJsCommand {
|
func SetDisabled(disabled bool) SimpleJsCommand {
|
||||||
if disabled {
|
if disabled {
|
||||||
return AddAttribute("disabled", "true")
|
return AddAttribute("disabled", "true")
|
||||||
|
|
@ -185,26 +209,31 @@ func SetDisabled(disabled bool) SimpleJsCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveAttribute removes the given attribute from the element.
|
||||||
func RemoveAttribute(name string) SimpleJsCommand {
|
func RemoveAttribute(name string) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.removeAttribute('%s')", name)}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.removeAttribute('%s')", name)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddClass adds the given class to the element.
|
||||||
func AddClass(class string) SimpleJsCommand {
|
func AddClass(class string) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.classList.add('%s')", class)}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.classList.add('%s')", class)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveClass removes the given class from the element.
|
||||||
func RemoveClass(class string) SimpleJsCommand {
|
func RemoveClass(class string) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.classList.remove('%s')", class)}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.classList.remove('%s')", class)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToggleClass toggles the given class on the element.
|
||||||
func ToggleClass(class string) SimpleJsCommand {
|
func ToggleClass(class string) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.classList.toggle('%s')", class)}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.classList.toggle('%s')", class)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
return EvalJs(fmt.Sprintf(`
|
return EvalJs(fmt.Sprintf(`
|
||||||
|
|
@ -214,6 +243,7 @@ func ToggleClassOnElement(selector, class string) ComplexJsCommand {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EvalJsOnParent evaluates the given JavaScript code on the parent of the element. Reference the element using 'element'.
|
||||||
func EvalJsOnParent(js string) ComplexJsCommand {
|
func EvalJsOnParent(js string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJs(fmt.Sprintf(`
|
return EvalJs(fmt.Sprintf(`
|
||||||
|
|
@ -223,6 +253,7 @@ func EvalJsOnParent(js string) ComplexJsCommand {
|
||||||
`, js))
|
`, js))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EvalJsOnChildren evaluates the given JavaScript code on the children of the element. Reference the element using 'element'.
|
||||||
func EvalJsOnChildren(selector, js string) ComplexJsCommand {
|
func EvalJsOnChildren(selector, js string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJs(fmt.Sprintf(`
|
return EvalJs(fmt.Sprintf(`
|
||||||
|
|
@ -233,6 +264,7 @@ func EvalJsOnChildren(selector, js string) ComplexJsCommand {
|
||||||
`, selector, js))
|
`, selector, js))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EvalJsOnSibling evaluates the given JavaScript code on the siblings of the element. Reference the element using 'element'.
|
||||||
func EvalJsOnSibling(selector, js string) ComplexJsCommand {
|
func EvalJsOnSibling(selector, js string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJs(fmt.Sprintf(`
|
return EvalJs(fmt.Sprintf(`
|
||||||
|
|
@ -244,66 +276,79 @@ func EvalJsOnSibling(selector, js string) ComplexJsCommand {
|
||||||
`, selector, js))
|
`, selector, js))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetClassOnParent sets the given class on the parent of the element. Reference the element using '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'.
|
||||||
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'.
|
||||||
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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
return EvalJsOnSibling(selector, fmt.Sprintf("element.classList.add('%s')", class))
|
return EvalJsOnSibling(selector, fmt.Sprintf("element.classList.add('%s')", class))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveClassOnSibling removes the given class from the siblings of the element. Reference the element using 'element'.
|
||||||
func RemoveClassOnSibling(selector, class string) ComplexJsCommand {
|
func RemoveClassOnSibling(selector, class string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJsOnSibling(selector, fmt.Sprintf("element.classList.remove('%s')", class))
|
return EvalJsOnSibling(selector, fmt.Sprintf("element.classList.remove('%s')", class))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveClassOnChildren removes the given class from the children of the element. Reference the element using 'element'.
|
||||||
func RemoveClassOnChildren(selector, class string) ComplexJsCommand {
|
func RemoveClassOnChildren(selector, class string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJsOnChildren(selector, fmt.Sprintf("element.classList.remove('%s')", class))
|
return EvalJsOnChildren(selector, fmt.Sprintf("element.classList.remove('%s')", class))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alert displays an alert dialog with the given text.
|
||||||
func Alert(text string) SimpleJsCommand {
|
func Alert(text string) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("alert('%s')", text)}
|
return SimpleJsCommand{Command: fmt.Sprintf("alert('%s')", text)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove removes the element from the DOM.
|
||||||
func Remove() SimpleJsCommand {
|
func Remove() SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: "this.remove()"}
|
return SimpleJsCommand{Command: "this.remove()"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EvalJs evaluates the given JavaScript code.
|
||||||
func EvalJs(js string) ComplexJsCommand {
|
func EvalJs(js string) ComplexJsCommand {
|
||||||
return NewComplexJsCommand(js)
|
return NewComplexJsCommand(js)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PreventDefault prevents the default action of the event.
|
||||||
func PreventDefault() SimpleJsCommand {
|
func PreventDefault() SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: "event.preventDefault()"}
|
return SimpleJsCommand{Command: "event.preventDefault()"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConsoleLog logs a message to the console.
|
||||||
func ConsoleLog(text string) SimpleJsCommand {
|
func ConsoleLog(text string) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("console.log('%s')", text)}
|
return SimpleJsCommand{Command: fmt.Sprintf("console.log('%s')", text)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetValue sets the value of the element.
|
||||||
func SetValue(value string) SimpleJsCommand {
|
func SetValue(value string) SimpleJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return SimpleJsCommand{Command: fmt.Sprintf("this.value = '%s'", value)}
|
return SimpleJsCommand{Command: fmt.Sprintf("this.value = '%s'", value)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SubmitFormOnEnter submits the form when the user presses the enter key.
|
||||||
func SubmitFormOnEnter() ComplexJsCommand {
|
func SubmitFormOnEnter() ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJs(`
|
return EvalJs(`
|
||||||
|
|
@ -316,6 +361,7 @@ func SubmitFormOnEnter() ComplexJsCommand {
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InjectScript injects a script tag into the document.
|
||||||
func InjectScript(src string) ComplexJsCommand {
|
func InjectScript(src string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return NewComplexJsCommand(fmt.Sprintf(`
|
return NewComplexJsCommand(fmt.Sprintf(`
|
||||||
|
|
@ -326,6 +372,7 @@ func InjectScript(src string) ComplexJsCommand {
|
||||||
`, src))
|
`, src))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InjectScriptIfNotExist injects a script tag into the document if it does not already exist.
|
||||||
func InjectScriptIfNotExist(src string) ComplexJsCommand {
|
func InjectScriptIfNotExist(src string) ComplexJsCommand {
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
return EvalJs(fmt.Sprintf(`
|
return EvalJs(fmt.Sprintf(`
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,13 @@ func (q *Qs) ToString() string {
|
||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetQueryParam returns the value of the given query parameter from the request URL.
|
||||||
|
// There are two layers of priority:
|
||||||
|
// 1. The query parameter in the URL
|
||||||
|
// 2. The current browser URL
|
||||||
|
// If the query parameter is not found in the URL from the *RequestContext, it will fall back to the current browser URL if set.
|
||||||
|
// The URL from the *RequestContext would normally be the url from an XHR request through htmx,
|
||||||
|
// which is not the current browser url a visitor may be on.
|
||||||
func GetQueryParam(ctx *RequestContext, key string) string {
|
func GetQueryParam(ctx *RequestContext, key string) string {
|
||||||
value, ok := ctx.Request.URL.Query()[key]
|
value, ok := ctx.Request.URL.Query()[key]
|
||||||
if value == nil || !ok {
|
if value == nil || !ok {
|
||||||
|
|
@ -65,6 +72,11 @@ func GetQueryParam(ctx *RequestContext, key string) string {
|
||||||
return value[0]
|
return value[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetQueryParams sets the query parameters of the given URL.
|
||||||
|
// Given the *Qs passed in, it will set the query parameters of the URL to the given values.
|
||||||
|
// If the value does not exist in *QS, it will remain untouched.
|
||||||
|
// If the value is an empty string, it will be removed from the query parameters.
|
||||||
|
// If the value is not an empty string, it will be set to the given value.
|
||||||
func SetQueryParams(href string, qs *Qs) string {
|
func SetQueryParams(href string, qs *Qs) string {
|
||||||
u, err := url.Parse(href)
|
u, err := url.Parse(href)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ type Ren interface {
|
||||||
Render(context *RenderContext)
|
Render(context *RenderContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render renders the given node recursively, and returns the resulting string.
|
||||||
func Render(node Ren) string {
|
func Render(node Ren) string {
|
||||||
builder := &strings.Builder{}
|
builder := &strings.Builder{}
|
||||||
context := &RenderContext{
|
context := &RenderContext{
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// JsonSerializeOrEmpty serializes the given data as JSON, or returns an empty string if the serialization fails.
|
||||||
func JsonSerializeOrEmpty(data any) string {
|
func JsonSerializeOrEmpty(data any) string {
|
||||||
serialized, err := json.Marshal(data)
|
serialized, err := json.Marshal(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -5,22 +5,27 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Get adds two attributes to the element: hx-get and hx-trigger.
|
||||||
func Get(path string, trigger ...string) *AttributeMapOrdered {
|
func Get(path string, trigger ...string) *AttributeMapOrdered {
|
||||||
return AttributeList(Attribute(hx.GetAttr, path), HxTriggerString(trigger...))
|
return AttributeList(Attribute(hx.GetAttr, path), HxTriggerString(trigger...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPartial adds two attributes to the element: hx-get and hx-trigger, and uses the partial path for the hx-get attribute.
|
||||||
func GetPartial(partial PartialFunc, trigger ...string) *AttributeMapOrdered {
|
func GetPartial(partial PartialFunc, trigger ...string) *AttributeMapOrdered {
|
||||||
return Get(GetPartialPath(partial), trigger...)
|
return Get(GetPartialPath(partial), trigger...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPartialWithQs adds two attributes to the element: hx-get and hx-trigger, and uses the partial path for the hx-get attribute. It also sets the query string parameters.
|
||||||
func GetPartialWithQs(partial PartialFunc, qs *Qs, trigger string) *AttributeMapOrdered {
|
func GetPartialWithQs(partial PartialFunc, qs *Qs, trigger string) *AttributeMapOrdered {
|
||||||
return Get(GetPartialPathWithQs(partial, qs), trigger)
|
return Get(GetPartialPathWithQs(partial, qs), trigger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetWithQs adds two attributes to the element: hx-get and hx-trigger, and uses the path for the hx-get attribute. It also sets the query string parameters.
|
||||||
func GetWithQs(path string, qs *Qs, trigger string) *AttributeMapOrdered {
|
func GetWithQs(path string, qs *Qs, trigger string) *AttributeMapOrdered {
|
||||||
return Get(SetQueryParams(path, qs), trigger)
|
return Get(SetQueryParams(path, qs), trigger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PostPartial adds two attributes to the element: hx-post and hx-trigger, and uses the partial path for the hx-post attribute.
|
||||||
func PostPartial(partial PartialFunc, triggers ...string) *AttributeMapOrdered {
|
func PostPartial(partial PartialFunc, triggers ...string) *AttributeMapOrdered {
|
||||||
path := GetPartialPath(partial)
|
path := GetPartialPath(partial)
|
||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
|
|
@ -29,6 +34,7 @@ func PostPartial(partial PartialFunc, triggers ...string) *AttributeMapOrdered {
|
||||||
return Post(path, triggers...)
|
return Post(path, triggers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PostPartialWithQs adds two attributes to the element: hx-post and hx-trigger, and uses the partial path for the hx-post attribute. It also sets the query string parameters.
|
||||||
func PostPartialWithQs(partial PartialFunc, qs *Qs, trigger ...string) *AttributeMapOrdered {
|
func PostPartialWithQs(partial PartialFunc, qs *Qs, trigger ...string) *AttributeMapOrdered {
|
||||||
path := GetPartialPathWithQs(partial, qs)
|
path := GetPartialPathWithQs(partial, qs)
|
||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
|
|
@ -41,18 +47,22 @@ func Post(url string, trigger ...string) *AttributeMapOrdered {
|
||||||
return AttributeList(Attribute(hx.PostAttr, url), HxTriggerString(trigger...))
|
return AttributeList(Attribute(hx.PostAttr, url), HxTriggerString(trigger...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PostWithQs adds two attributes to the element: hx-post and hx-trigger, and uses the path for the hx-post attribute. It also sets the query string parameters.
|
||||||
func PostWithQs(url string, qs *Qs, trigger string) *AttributeMapOrdered {
|
func PostWithQs(url string, qs *Qs, trigger string) *AttributeMapOrdered {
|
||||||
return Post(SetQueryParams(url, qs), trigger)
|
return Post(SetQueryParams(url, qs), trigger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PostOnClick adds two attributes to the element: hx-post and hx-trigger, and uses the path for the hx-post attribute. It also sets the hx-trigger to hx-click.
|
||||||
func PostOnClick(url string) *AttributeMapOrdered {
|
func PostOnClick(url string) *AttributeMapOrdered {
|
||||||
return Post(url, hx.ClickEvent)
|
return Post(url, hx.ClickEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PostPartialOnClick adds two attributes to the element: hx-post and hx-trigger, and uses the partial path for the hx-post attribute. It also sets the hx-trigger to hx-click.
|
||||||
func PostPartialOnClick(partial PartialFunc) *AttributeMapOrdered {
|
func PostPartialOnClick(partial PartialFunc) *AttributeMapOrdered {
|
||||||
return PostOnClick(GetPartialPath(partial))
|
return PostOnClick(GetPartialPath(partial))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PostPartialOnClickQs adds two attributes to the element: hx-post and hx-trigger, and uses the partial path for the hx-post attribute. It also sets the hx-trigger to hx-click. It also sets the query string parameters.
|
||||||
func PostPartialOnClickQs(partial PartialFunc, qs *Qs) *AttributeMapOrdered {
|
func PostPartialOnClickQs(partial PartialFunc, qs *Qs) *AttributeMapOrdered {
|
||||||
return PostOnClick(GetPartialPathWithQs(partial, qs))
|
return PostOnClick(GetPartialPathWithQs(partial, qs))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue