I’m undecided what occurred, as soon as I wrote the beneath issues run easily:
// Serve wasm_exec.js file with appropriate MIME kind
http.HandleFunc("/scripts/wasm_exec.js", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content material-Kind", "software/javascript")
http.ServeFile(w, r, "/scripts/wasm_exec.js")
})
// Serve major.wasm file with appropriate MIME kind
http.HandleFunc("/wasm/major.wasm", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content material-Kind", "software/wasm")
http.ServeFile(w, r, "/wasm/major.wasm")
})
Afterward I dedicated them, and the app nonetheless working easily!!
Beneath is my full code:
// major.go
bundle major
import (
"html/template"
"log"
"web/http"
)
// Outline person entry ranges
var userAccessLevels = map[string][]string{
"supervisor": {"edit"},
"auditor": {"readonly"},
"limitedAccessUser": {"readonly"},
"supervisor": {"edit", "no-access"},
}
// Pattern knowledge for the desk
var tableData = []struct {
ID int
Identify string
Position string
Electronic mail string
}{
{1, "John Doe", "supervisor", "john@instance.com"},
{2, "Jane Doe", "auditor", "jane@instance.com"},
{3, "Alice", "limitedAccessUser", "alice@instance.com"},
{4, "Bob", "supervisor", "bob@instance.com"},
}
func major() {
// utilizing GET /{$} imply / solely, however utilizing GET / imply / and something after it which can trigger routes battle
http.Deal with("GET /house", loggingMiddleware(http.HandlerFunc(homePage)))
http.Deal with("GET /base", loggingMiddleware(http.HandlerFunc(baseHandler)))
http.HandleFunc("GET /{$}", handler)
// // Serve wasm_exec.js file with appropriate MIME kind
// http.HandleFunc("/scripts/wasm_exec.js", func(w http.ResponseWriter, r *http.Request) {
// w.Header().Set("Content material-Kind", "software/javascript")
// http.ServeFile(w, r, "/scripts/wasm_exec.js")
// })
// // Serve major.wasm file with appropriate MIME kind
// http.HandleFunc("/wasm/major.wasm", func(w http.ResponseWriter, r *http.Request) {
// w.Header().Set("Content material-Kind", "software/wasm")
// http.ServeFile(w, r, "/wasm/major.wasm")
// })
//http.Deal with("https://discussion board.golangbridge.org/", http.FileServer(http.Dir("./static")))
http.Deal with("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
// Begin the server with CSP headers
http.ListenAndServe(":8080", nil)
}
func baseHandler(w http.ResponseWriter, r *http.Request) {
// Outline templates
//t := template.Should(template.ParseFiles("template/base.html", "template/physique.html"))
t, err := template.ParseFiles("template/base.html", "template/physique.html") //)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Execute base template
if err := t.Execute(w, nil); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func handler(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("template/index.html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
t.Execute(w, nil)
}
func homePage(w http.ResponseWriter, r *http.Request) {
userType := "supervisor"
accessLevels, okay := userAccessLevels[userType]
if !okay {
http.Error(w, "Invalid person kind", http.StatusBadRequest)
return
}
log.Println(accessLevels)
t, err := template.ParseFiles("template/homePage.html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
knowledge := struct {
Title string
Message string
Roles []string
Entry map[string]string
Desk []struct {
ID int
Identify string
Position string
Electronic mail string
}
}{
Title: "Welcome",
Message: "That is the Dwelling Web page",
Roles: accessLevels,
Entry: makeAccessMap(accessLevels),
Desk: tableData,
}
t.Execute(w, knowledge)
}
func loggingMiddleware(subsequent http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("Request acquired: %s %s", r.Methodology, r.URL.Path)
subsequent.ServeHTTP(w, r)
log.Println("Request dealt with efficiently")
})
}
func makeAccessMap(accessLevels []string) map[string]string {
accessMap := make(map[string]string)
for _, degree := vary accessLevels {
accessMap[level] = degree
}
return accessMap
}
And the Net Meeting recordsdata are constructed from:
// base.go
//go:construct js && wasm
bundle major
import (
"encoding/json"
"fmt"
"syscall/js"
)
var (
international js.Worth
doc js.Worth
)
func major() {
international = js.World()
doc = international.Get("doc") // Cache doc for effectivity
international.Set("handleData", js.FuncOf(handleData))
international.Set("notifyme", js.FuncOf(notifyme))
// international.Set("clickCallback", js.FuncOf(clickCallback))
choose {} // Block major thread
}
func handleData(this js.Worth, args []js.Worth) interface{} {
if len(args) < 2 {
return nil // Deal with invalid variety of arguments gracefully
}
num := args[0].Int()
textual content := args[1].String()
knowledge := map[string]interface{}{
"quantity": num,
"textual content": textual content,
}
jsonData, err := json.Marshal(knowledge)
if err != nil {
// Deal with potential marshalling errors (optionally available)
log(fmt.Sprintf("Error: %v", err))
return nil
}
addElement(jsonData)
return string(jsonData)
}
func notifyme(this js.Worth, args []js.Worth) interface{} {
script := `
new perform() {
let knowledge = "only a reminder";
let para = doc.createElement("p");
let node = doc.createTextNode(knowledge);
para.appendChild(node);
doc.physique.appendChild(para);
}();
`
international.Name("eval", script)
log("a Simply reminder ought to be printed on the web page")
return nil
}
func log(message string) {
js.World().Get("console").Name("log", message)
}
func createElement(tagName string) js.Worth {
return js.World().Get("doc").Name("createElement", tagName)
}
func addElement(jsonData []byte) {
var parsedData map[string]interface{}
err := json.Unmarshal(jsonData, &parsedData)
if err != nil {
// Deal with potential unmarshalling errors (optionally available)
return
}
textual content := parsedData["text"].(string)
num := parsedData["number"].(float64)
node := doc.Name("createTextNode", fmt.Sprintf("%v: What's the %.2f?", textual content, num)) // Format quantity with 2 decimal locations
para := createElement("p")
para.Name("appendChild", node)
// Create a js.Func object for clickCallback
clickCallbackFunc := js.FuncOf(clickCallback)
addEventListener(para, "click on", clickCallbackFunc)
physique := doc.Get("physique")
physique.Name("appendChild", para)
}
func addEventListener(el js.Worth, occasion string, callback js.Func) {
el.Name("addEventListener", occasion, callback)
}
func clickCallback(this js.Worth, args []js.Worth) interface{} {
log("Para had been clicked")
return nil
}
// $env:GOOS = "js"
// $env:GOARCH = "wasm"
// $CGO_LDFLAGS="-Wl,-LTO"
// go construct -ldflags="-s -w" -o base.wasm -tags js,wasm base.go
// go construct -o base.wasm -tags js,wasm base.go
And
// physique.go
//go:construct js && wasm
bundle major
import (
"syscall/js"
)
var (
international js.Worth
)
func init() {
international = js.World()
}
func major() {
international.Set("handleClick", js.FuncOf(handleClick))
choose {} // Block major thread
}
func handleClick(this js.Worth, args []js.Worth) interface{} {
alert("Whats up, world!") // Use customized alert perform
return nil
}
func alert(message string) {
international.Name("alert", message)
}
// $env:GOOS = "js"
// $env:GOARCH = "wasm"
// $CGO_LDFLAGS="-Wl,-LTO"
// go construct -ldflags="-s -w" -o physique.wasm -tags js,wasm physique.go
// go construct -o physique.wasm -tags js,wasm physique.go
The generated wasm recordsdata had been moved to the folder static/wasm
And within the static/script
folder I’ve:
// wasm_load.js
const modules = {};
let wasm;
async perform loadWasmModule(module) {
modules[module] = new Go();
strive {
const response = await fetch(`/static/wasm/${module}.wasm`);
const bytes = await response.arrayBuffer();
const result_1 = await WebAssembly.instantiate(bytes, modules[module].importObject);
wasm = result_1.occasion;
modules[module].run(wasm);
} catch (error) {
console.error(`Didn't load wasm module ${module}:`, error);
}
}
The template recordsdata used are:
// template/base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta title="viewport" content material="width=device-width, initial-scale=1.0">
<title>Base Template</title>
<script src="https://discussion board.golangbridge.org/static/scripts/wasm_exec.js"></script>
<script src="/static/scripts/wasm_load.js"></script>
</head>
<physique>
<header>
<h1>Welcome to My Web site</h1>
</header>
<major>
{{template "content material" .}}
</major>
<footer>
<p>© 2024 My Web site. All rights reserved.</p>
<button onclick="notifyme()">notifyme</button>
</footer>
</physique>
<script>
loadWasmModule('base')
</script>
</html>
And
//template/physique.js
{{outline "content material"}}
<h2>Physique Content material</h2>
<button onclick="handleClick()">Click on me</button>
<p>That is the content material of the physique template.</p>
<button onclick="callHandleData()">handleData</button>
<script>
loadWasmModule('physique')
perform callHandleData() {
let knowledge = handleData(46, "Whats up, World!");
// Parse the info utilizing JSON.parse // Parse the info utilizing JSON.parse
let parsedData = JSON.parse(knowledge); // Double stringify for security
// Entry the textual content property from the parsed object
let textual content = parsedData.textual content;
let num = parsedData.quantity;
alert(knowledge)
alert(textual content + " What's the "+ num); // Or use textual content for additional manipulation
}
</script>
{{finish}}
And
//template.index.html
{{outline "content material"}}
<h2>Physique Content material</h2>
<button onclick="handleClick()">Click on me</button>
<p>That is the content material of the physique template.</p>
<button onclick="callHandleData()">handleData</button>
<script>
loadWasmModule('physique')
perform callHandleData() {
let knowledge = handleData(46, "Whats up, World!");
// Parse the info utilizing JSON.parse // Parse the info utilizing JSON.parse
let parsedData = JSON.parse(knowledge); // Double stringify for security
// Entry the textual content property from the parsed object
let textual content = parsedData.textual content;
let num = parsedData.quantity;
alert(knowledge)
alert(textual content + " What's the "+ num); // Or use textual content for additional manipulation
}
</script>
{{finish}}
And
//template/homePage.html
<!DOCTYPE html>
<html>
<head>
<title>{{.Title}}</title>
<model>
/* CSS types right here */
desk {
border-collapse: collapse;
width: 100%;
table-layout: mounted;
}
th, td {
padding: 3px; /* Adjusted padding for narrower rows */
border: 1px strong #ddd;
text-align: left;
width: 150px; /* Set mounted width for cells */
overflow: hidden; /* Conceal overflow content material */
white-space: nowrap; /* Stop wrapping */
}
tr:nth-child(even) {
background-color: #f2f2f2;
}
/* tr:hover {
background-color: #ddd;
} */
th {
background-color: #4CAF50;
coloration: white;
}
.editable {
background-color: #fff;
}
.editable:focus {
background-color: #f0f0f0;
}
/* Outline particular person widths for columns */
.col1 {
width: 100px; /* Width for ID column */
}
.col2 {
width: 200px; /* Width for Identify column */
}
.col3 {
width: 150px; /* Width for Position column */
}
.col4 {
width: 250px; /* Width for Electronic mail column */
}
/* Fashion for the primary column */
.first-column {
background-color: #ffcccb; /* Mild crimson background coloration */
}
/* Hover impact for desk cells */
tbody tr:hover td,
tbody tr td:hover {
background-color: #ffe5cc; /* Mild orange background coloration */
}
@media display and (max-width: 600px) {
desk {
border: 0;
}
th, td {
border: none;
show: block;
padding: 3px; /* Adjusted padding for narrower rows */
width: 100%; /* Set width to 100% for full width in smaller screens */
}
th {
background-color: #4CAF50;
coloration: white;
text-align: left;
}
}
</model>
</head>
<physique>
<h1>{{.Title}}</h1>
<p>{{.Message}}</p>
<p>Person roles are: {{.Roles}}</p>
<div>
{{vary $position, $entry := .Entry}}
<p>Position: {{$position}}, Entry: {{$entry}}</p>
{{finish}}
</div>
{{ $readOnly := false }}
{{ $isVisible := true }}
{{ vary .Roles }}
{{ if eq . "no-access" }}
{{ $isVisible = false }}
{{ finish }}
{{ if eq . "readonly" }}
{{ $readOnly = true }}
{{ finish }}
{{ finish }}
{{ if $isVisible }}
<div data-access="{{if $readOnly}} readonly {{finish}}">
<enter kind="textual content" {{if $readOnly}} readonly {{finish}} placeholder="Enter textual content right here">
</div>
{{ else }}
<p>This content material just isn't accessible.</p>
{{ finish }}
<desk border="1">
<tr>
<th class="col1">ID</th>
<th class="col2">Identify</th>
<th class="col3">Position</th>
{{ if $isVisible }}
<th class="col4" data-access="{{if $readOnly}}readonly{{finish}}">Electronic mail</th>
{{ finish }}
</tr>
{{vary .Desk}}
<tr>
<td contenteditable="true" class="editable col1 first-column">{{.ID}}</td>
<td contenteditable="true" class="editable col2">{{.Identify}}</td>
<td contenteditable="true" class="editable col3">{{.Position}}</td>
{{ if $isVisible }}
<td contenteditable="true" class="editable col4" data-access="{{if $readOnly}}readonly{{finish}}">{{.Electronic mail}}</td>
{{ finish }}
</tr>
{{finish}}
</desk>
<script>
// Add occasion listeners to every editable cell
const editableCells = doc.querySelectorAll('.editable');
editableCells.forEach(cell => {
cell.addEventListener('enter', perform() {
// Add your logic right here to deal with enter modifications
console.log('Cell content material modified:', this.textContent);
});
});
// Add occasion listeners to every cell within the desk physique
const cells = doc.querySelectorAll('tbody td');
cells.forEach(cell => {
cell.addEventListener('mouseover', perform() {
// Add highlighted class to the row
this.parentNode.classList.add('highlighted');
// Add highlighted class to all cells in the identical column
const index = Array.from(this.parentNode.youngsters).indexOf(this);
const allRows = doc.querySelectorAll('tbody tr');
allRows.forEach(row => {
row.youngsters[index].classList.add('highlighted');
});
});
cell.addEventListener('mouseout', perform() {
// Take away highlighted class from the row
this.parentNode.classList.take away('highlighted');
// Take away highlighted class from all cells in the identical column
const index = Array.from(this.parentNode.youngsters).indexOf(this);
const allRows = doc.querySelectorAll('tbody tr');
allRows.forEach(row => {
row.youngsters[index].classList.take away('highlighted');
});
});
});
</script>
</physique>
</html>