Skip to content

Commit 832daba

Browse files
committed
ME-4 - ditch HTMX
1 parent f599dee commit 832daba

File tree

16 files changed

+460
-376
lines changed

16 files changed

+460
-376
lines changed

index.html

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!DOCTYPE html>
2-
<html lang="en" hx-ext="shadow-host-swap,sse">
2+
<html lang="en">
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -14,11 +14,8 @@
1414

1515
<link rel="icon" href="/static/favicon.ico">
1616
<link rel="stylesheet" href="/static/{{.Css}}">
17-
<script>
18-
// htmx.logAll()
19-
</script>
2017
</head>
21-
<body hx-ext="sse" sse-connect="/sse" sse-swap="oob-update">
18+
<body>
2219
<div class="container">
2320
<header>
2421
<div class="header">

package-lock.json

Lines changed: 252 additions & 278 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,11 @@
99
"preview": "vite preview"
1010
},
1111
"devDependencies": {
12-
"lit": "^3.3.1",
1312
"sass-embedded": "^1.90.0",
1413
"typescript": "~5.8.3",
1514
"vite": "^7.1.2"
1615
},
1716
"dependencies": {
18-
"htmx-ext-sse": "^2.2.3",
19-
"htmx.org": "^2.0.6",
2017
"lucide": "^0.541.0"
2118
}
2219
}

src/components/app/handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
4545
// Create props for the app template
4646
props := AppProps{
4747
BoardComponent: boardComponent,
48-
IsHTMX: h.IsHTMXRequest(r),
48+
IsHTMX: h.IsAJAXRequest(r),
4949
}
5050

5151
// Render using the base handler

src/components/base/handler.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func (h *BaseHandler) RenderTemplate(
4242
}
4343
}
4444

45-
// IsHTMXRequest checks if the request is an HTMX request
46-
func (h *BaseHandler) IsHTMXRequest(r *http.Request) bool {
47-
return r.Header.Get("HX-Request") == "true"
45+
// IsAJAXRequest checks if the request is an AJAX request
46+
func (h *BaseHandler) IsAJAXRequest(r *http.Request) bool {
47+
return r.Header.Get("X-Requested-With") == "XMLHttpRequest"
4848
}

src/components/base/mesh-element.ts

Lines changed: 97 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,8 @@ export class MeshElement extends HTMLElement {
1111
root.appendChild((template as any).content.cloneNode(true));
1212
}
1313
}
14-
if (window.htmx) {
15-
window.htmx.process(this);
16-
if (this.shadowRoot) {
17-
window.htmx.process(this.shadowRoot);
18-
}
19-
}
2014
this.bindListeners();
15+
this.bindFormHandlers();
2116
this.createIcons();
2217
}
2318

@@ -58,6 +53,102 @@ export class MeshElement extends HTMLElement {
5853
});
5954
}
6055

56+
protected bindFormHandlers() {
57+
// Handle forms with mesh-* HTTP attributes
58+
this.all('form[mesh-get], form[mesh-post], form[mesh-put], form[mesh-patch], form[mesh-delete]', form => {
59+
form.addEventListener('submit', this.handleFormSubmit.bind(this));
60+
});
61+
}
62+
63+
protected async handleFormSubmit(event: Event) {
64+
event.preventDefault();
65+
const form = event.target as HTMLFormElement;
66+
67+
// Determine HTTP method from mesh-* attributes
68+
let method = 'GET';
69+
let url = '';
70+
71+
if (form.hasAttribute('mesh-get')) {
72+
method = 'GET';
73+
url = form.getAttribute('mesh-get') || '';
74+
} else if (form.hasAttribute('mesh-post')) {
75+
method = 'POST';
76+
url = form.getAttribute('mesh-post') || '';
77+
} else if (form.hasAttribute('mesh-put')) {
78+
method = 'PUT';
79+
url = form.getAttribute('mesh-put') || '';
80+
} else if (form.hasAttribute('mesh-patch')) {
81+
method = 'PATCH';
82+
url = form.getAttribute('mesh-patch') || '';
83+
} else if (form.hasAttribute('mesh-delete')) {
84+
method = 'DELETE';
85+
url = form.getAttribute('mesh-delete') || '';
86+
}
87+
88+
if (!url) {
89+
console.error('No URL specified for form submission');
90+
return;
91+
}
92+
93+
try {
94+
const formData = new FormData(form);
95+
const response = await this.makeRequest(method, url, formData);
96+
97+
if (response.ok) {
98+
const html = await response.text();
99+
this.handleResponse(html, form);
100+
} else {
101+
console.error('Form submission failed:', response.status, response.statusText);
102+
}
103+
} catch (error) {
104+
console.error('Form submission error:', error);
105+
}
106+
}
107+
108+
protected async makeRequest(method: string, url: string, formData: FormData): Promise<Response> {
109+
const options: RequestInit = {
110+
method,
111+
headers: {
112+
'X-Requested-With': 'XMLHttpRequest',
113+
},
114+
};
115+
116+
if (method === 'GET') {
117+
const params = new URLSearchParams(formData as any);
118+
url += (url.includes('?') ? '&' : '?') + params.toString();
119+
} else {
120+
options.body = formData;
121+
}
122+
123+
return fetch(url, options);
124+
}
125+
126+
protected handleResponse(html: string, form: HTMLFormElement) {
127+
// Check for mesh-target attribute to determine where to place response
128+
const target = form.getAttribute('mesh-target');
129+
130+
if (target) {
131+
const targetElement = this.shadowRoot?.querySelector(target) || document.querySelector(target);
132+
if (targetElement) {
133+
targetElement.innerHTML = html;
134+
return;
135+
}
136+
}
137+
138+
// Check for mesh-swap attribute to determine swap behavior
139+
const swapMode = form.getAttribute('mesh-swap') || 'outerHTML';
140+
141+
switch (swapMode) {
142+
case 'innerHTML':
143+
this.innerHTML = html;
144+
break;
145+
case 'outerHTML':
146+
default:
147+
this.outerHTML = html;
148+
break;
149+
}
150+
}
151+
61152
one(selector: string, cb: (el: HTMLElement) => void) {
62153
const el = this.shadowRoot!.querySelector(selector)
63154
if (el) {

src/components/board/handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
3737
func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
3838
ctx := r.Context()
3939

40-
isHTMX := h.IsHTMXRequest(r)
40+
isHTMX := h.IsAJAXRequest(r)
4141

4242
// Load all columns from service
4343
columnsWithCards := h.CardService.GetColumns()

src/components/card/card.templ

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ templ Card(props CardProps) {
4848
class="create"
4949
}
5050
if ( props.OOB ) {
51-
hx-swap-oob="true"
51+
mesh-swap-oob="true"
5252
}
5353
>
5454
<template shadowrootmode="open">
@@ -67,15 +67,15 @@ templ Card(props CardProps) {
6767
</div>
6868
<div class="actions">
6969
if props.CanDemote {
70-
<form hx-put="/card">
70+
<form mesh-put="/card">
7171
<input type="hidden" name="action" value="demote" />
7272
<input type="hidden" name="cardID" value={props.Card.ID} />
7373
<button type="submit" aria-label="Move to previous column">
7474
<i data-lucide="arrow-left"></i>
7575
</button>
7676
</form>
7777
}
78-
<form hx-delete="/card">
78+
<form mesh-delete="/card">
7979
<input type="hidden" name="cardID" value={props.Card.ID} />
8080
<button type="submit" class="warn">
8181
<i data-lucide="circle-x"></i>
@@ -85,7 +85,7 @@ templ Card(props CardProps) {
8585
<i data-lucide="pencil"></i>
8686
</button>
8787
if props.CanPromote {
88-
<form hx-put="/card">
88+
<form mesh-put="/card">
8989
<input type="hidden" name="action" value="promote" />
9090
<input type="hidden" name="cardID" value={props.Card.ID} />
9191
<button type="submit" aria-label="Move to next column">
@@ -105,9 +105,9 @@ templ Card(props CardProps) {
105105
data-form
106106
class={ "card", templ.KV("hide", !props.IsEditing) }
107107
if (props.Card.ID != 0) {
108-
hx-patch="/card"
108+
mesh-patch="/card"
109109
} else {
110-
hx-post="/card"
110+
mesh-post="/card"
111111
}
112112
>
113113
if ( props.Card.ID != 0 ) {

src/components/card/card.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ export class Card extends MeshElement {
4848
}
4949

5050
createDragImage() {
51-
console.log('piss');
52-
5351
// Clone the card element
5452
const clone = this.cloneNode(true) as HTMLElement;
5553

src/components/card/card_templ.go

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)