ref: 09b964472704c60ee0aa9a34d00e82316b94f952
parent: ba613e27cf2a4a29fc5a8955f3f782d1881205f8
author: Philip Silva <philip.silva@protonmail.com>
date: Thu Mar 20 10:13:15 EDT 2025
unglobal browser variable
--- a/browser/browser.go
+++ b/browser/browser.go
@@ -64,7 +64,6 @@
)
var (
- browser *Browser
Style = style.Map{}dui *duit.DUI
scroller *duitx.Scroll
@@ -94,7 +93,7 @@
}
}
-func NewText(content []string, n *nodes.Node) (el []*Element) {+func NewText(b *Browser, content []string, n *nodes.Node) (el []*Element) {tt := strings.Join(content, " ")
// '\n' is nowhere visible
@@ -111,6 +110,7 @@
}
l := &Element{+ b: b,
UI: NewLabel(t, n),
n: n,
}
@@ -170,8 +170,8 @@
src string
}
-func NewImage(n *nodes.Node) duit.UI {- img, err := newImage(n)
+func NewImage(b *Browser, n *nodes.Node) duit.UI {+ img, err := newImage(b, n)
if err != nil { log.Errorf("could not load image: %v", err) return &duit.Label{}@@ -179,7 +179,7 @@
return img
}
-func newImage(n *nodes.Node) (ui duit.UI, err error) {+func newImage(b *Browser, n *nodes.Node) (ui duit.UI, err error) {var i *draw.Image
var cached bool
src := attr(*n.DomSubtree, "src")
@@ -223,7 +223,7 @@
mw = dui.Scale(mw)
w := dui.Scale(n.Width())
h := dui.Scale(n.Height())
- i, err = img.Load(dui, browser, src, mw, w, h, false)
+ i, err = img.Load(dui, b, src, mw, w, h, false)
if err != nil { return nil, fmt.Errorf("load image: %w", err)}
@@ -232,6 +232,7 @@
img_elem:
return NewElement(
+ b,
&Image{ Image: &duit.Image{Image: i,
@@ -299,6 +300,7 @@
type Element struct {duit.UI
+ b *Browser
n *nodes.Node
orig image.Point
IsLink bool
@@ -309,7 +311,7 @@
rect image.Rectangle
}
-func NewElement(ui duit.UI, n *nodes.Node) *Element {+func NewElement(b *Browser, ui duit.UI, n *nodes.Node) *Element { if ui == nil {return nil
}
@@ -328,6 +330,7 @@
}
el := &Element{+ b: b,
UI: ui,
n: n,
}
@@ -524,10 +527,10 @@
Font: n.Font(),
Click: click,
}
- return NewElement(btn, n)
+ return NewElement(b, btn, n)
}
-func NewInputField(n *nodes.Node) *Element {+func NewInputField(b *Browser, n *nodes.Node) *Element {t := attr(*n.DomSubtree, "type")
if n.Css("width") == "" && n.Css("max-width") == "" { n.SetCss("max-width", "200px")@@ -548,9 +551,9 @@
if f == nil {return
}
- if !browser.loading {- browser.loading = true
- go browser.submit(f.DomSubtree, nil)
+ if !b.loading {+ b.loading = true
+ go b.submit(f.DomSubtree, nil)
}
return duit.Event{Consumed: true,
@@ -561,10 +564,10 @@
return
},
}
- return NewElement(f, n)
+ return NewElement(b, f, n)
}
-func NewSelect(n *nodes.Node) *Element {+func NewSelect(b *Browser, n *nodes.Node) *Element {var l *duit.List
l = &duit.List{Values: make([]*duit.ListValue, 0, len(n.Children)),
@@ -597,10 +600,10 @@
if n.Css("height") == "" { n.SetCss("height", fmt.Sprintf("%vpx", 4*n.Font().Height))}
- return NewElement(duit.NewScroll(l), n)
+ return NewElement(b, duit.NewScroll(l), n)
}
-func NewTextArea(n *nodes.Node) *Element {+func NewTextArea(b *Browser, n *nodes.Node) *Element {t := n.ContentString(true)
lines := len(strings.Split(t, "\n"))
edit := &duit.Edit{@@ -616,7 +619,7 @@
n.SetCss("height", fmt.Sprintf("%vpx", (int(n.FontHeight())*(lines+2))))}
- el := NewElement(edit, n)
+ el := NewElement(b, edit, n)
el.Changed = func(e *Element) {ed := e.UI.(*duitx.Box).Kids[0].UI.(*duit.Edit)
@@ -775,7 +778,7 @@
dui.WriteSnarf([]byte(s))
}
} else if selected > 0 && m.Buttons == 1 {- TraverseTree(browser.Website.UI, func(ui duit.UI) {+ TraverseTree(el.b.Website.UI, func(ui duit.UI) {l, ok := ui.(*duitx.Label)
if ok && l.Selected {selected--
@@ -822,7 +825,7 @@
log.Errorf("trigger click %v: %v", q, err) } else if consumed {offset := scroller.Offset
- browser.Website.layout(browser, res, ClickRelayout)
+ el.b.Website.layout(el.b, res, ClickRelayout)
scroller.Offset = offset
dui.MarkLayout(dui.Top.UI)
dui.MarkDraw(dui.Top.UI)
@@ -844,12 +847,12 @@
return
}
- u, err := browser.LinkedUrl(href)
+ u, err := el.b.LinkedUrl(href)
if err != nil { log.Errorf("makeLink from %v: %v", href, err)return
}
- f := browser.SetAndLoadUrl(u)
+ f := el.b.SetAndLoadUrl(u)
TraverseTree(el, func(ui duit.UI) {el, ok := ui.(*Element)
if ok && el != nil {@@ -932,7 +935,7 @@
}
// arrangeAbsolute positioned elements, if any
-func arrangeAbsolute(n *nodes.Node, elements ...*Element) (ael *Element, ok bool) {+func arrangeAbsolute(b *Browser, n *nodes.Node, elements ...*Element) (ael *Element, ok bool) {absolutes := make([]*Element, 0, 1)
other := make([]*Element, 0, len(elements))
@@ -954,7 +957,7 @@
log.Fatalf("%v", err)}
uis := make([]duit.UI, 0, len(other)+1)
- na := Arrange(n, other...)
+ na := Arrange(b, n, other...)
if na != nil {uis = append(uis, na)
}
@@ -967,19 +970,20 @@
}
pl.Place = placeFunc(n.QueryRef(), pl)
- return NewElement(pl, n), true
+ return NewElement(b, pl, n), true
}
-func Arrange(n *nodes.Node, elements ...*Element) *Element {- if ael, ok := arrangeAbsolute(n, elements...); ok {+func Arrange(b *Browser, n *nodes.Node, elements ...*Element) *Element {+ if ael, ok := arrangeAbsolute(b, n, elements...); ok {return ael
}
- ui := horizontalSeq(n, true, elements)
+ ui := horizontalSeq(b, n, true, elements)
if ui == nil {return nil
}
el := &Element{+ b: b,
n: n,
UI: ui,
}
@@ -987,7 +991,7 @@
return el
}
-func horizontalSeq(parent *nodes.Node, wrap bool, es []*Element) duit.UI {+func horizontalSeq(b *Browser, parent *nodes.Node, wrap bool, es []*Element) duit.UI { if len(es) == 0 {return nil
}
@@ -998,7 +1002,7 @@
if isLabel {tts := strings.Split(label.Text, " ")
for _, t := range tts {- finalUis = append(finalUis, NewElement(&duit.Label{+ finalUis = append(finalUis, NewElement(b, &duit.Label{Text: t,
Font: label.Font,
}, el.n))
@@ -1010,11 +1014,11 @@
}
}
- b, ok := newBoxElement(parent, true, finalUis...)
+ box, ok := newBoxElement(parent, true, finalUis...)
if !ok {return nil
}
- return b
+ return box
}
func duitDisplay(n *nodes.Node) duitx.Display {@@ -1173,6 +1177,7 @@
}
return NewElement(
+ b,
&duitx.Grid{Columns: numCols,
Rows: len(t.rows),
@@ -1193,17 +1198,17 @@
for _, col := range row.columns {ui := NodeToBox(r+1, b, col)
if ui != nil {- el := NewElement(ui, col)
+ el := NewElement(b, ui, col)
rowEls = append(rowEls, el)
}
}
if len(rowEls) > 0 {- seq := horizontalSeq(nil, false, rowEls)
- seqs = append(seqs, NewElement(seq, row.n))
+ seq := horizontalSeq(b, nil, false, rowEls)
+ seqs = append(seqs, NewElement(b, seq, row.n))
}
}
- return NewElement(verticalSeq(seqs), n)
+ return NewElement(b, verticalSeq(seqs), n)
}
}
@@ -1272,14 +1277,14 @@
case "input":
t := n.Attr("type") if t == "" || t == "text" || t == "email" || t == "search" || t == "password" {- return NewInputField(n)
+ return NewInputField(b, n)
} else if t == "submit" {return NewSubmitButton(b, n)
}
case "select":
- return NewSelect(n)
+ return NewSelect(b, n)
case "textarea":
- return NewTextArea(n)
+ return NewTextArea(b, n)
case "button":
if t := n.Attr("type"); t == "" || t == "submit" {return NewSubmitButton(b, n)
@@ -1290,13 +1295,14 @@
Font: n.Font(),
}
- return NewElement(btn, n)
+ return NewElement(b, btn, n)
case "table":
return NewTable(n).Element(r+1, b, n)
case "picture", "img", "svg":
- return NewElement(NewImage(n), n)
+ return NewElement(b, NewImage(b, n), n)
case "pre":
return NewElement(
+ b,
NewCodeView(n.ContentString(true), n.Map),
n,
)
@@ -1316,7 +1322,7 @@
return InnerNodesToBox(r+1, b, n)
}
- return NewElement(innerContent, n)
+ return NewElement(b, innerContent, n)
case "a":
var href = n.Attr("href")var innerContent duit.UI
@@ -1331,7 +1337,7 @@
if innerContent == nil {return nil
}
- el := NewElement(innerContent, n)
+ el := NewElement(b, innerContent, n)
el.makeLink(href)
return el
case "noscript":
@@ -1348,7 +1354,7 @@
if text := n.ContentString(false); text != "" {ui := NewLabel(text, n)
- return NewElement(ui, n)
+ return NewElement(b, ui, n)
}
}
@@ -1375,15 +1381,15 @@
continue
}
if isWrapped(c) {- ls := NewText(c.Content(false), c)
+ ls := NewText(b, c.Content(false), c)
els = append(els, ls...)
} else if nodes.IsPureTextContent(*n) && n.IsInline() {// Handle text wrapped in unwrappable tags like p, div, ...
- ls := NewText(c.Content(false), items[0])
+ ls := NewText(b, c.Content(false), items[0])
if len(ls) == 0 {continue
}
- el := NewElement(horizontalSeq(c, true, ls), c)
+ el := NewElement(b, horizontalSeq(b, c, true, ls), c)
if el == nil {continue
}
@@ -1397,7 +1403,7 @@
return nil
}
- return Arrange(n, els...)
+ return Arrange(b, n, els...)
}
func TraverseTree(ui duit.UI, f func(ui duit.UI)) {@@ -1536,16 +1542,15 @@
Transport: tr,
},
dui: _dui,
- Website: &Website{},LocCh: make(chan string, 10),
StatusCh: make(chan string, 10),
}
+ b.Website = &Website{b: b}u, err := url.Parse(initUrl)
if err != nil { log.Fatalf("parse: %v", err)}
b.History.Push(u, 0)
- browser = b
b.Website.UI = &duit.Label{}style.SetFetcher(b)
dui = _dui
@@ -1558,7 +1563,7 @@
if ExperimentalJsInsecure { fs.Client = &http.Client{}- fs.Fetcher = browser
+ fs.Fetcher = b
}
go fs.Srv9p()
--- a/browser/browser_test.go
+++ b/browser/browser_test.go
@@ -46,6 +46,7 @@
}
func TestArrange(t *testing.T) {+ b := &Browser{}htm := `
<div>
<h1>title 1</h1>
@@ -83,7 +84,7 @@
&Element{n: h2}, &Element{n: h3},}
- v := Arrange(nt, es...)
+ v := Arrange(b, nt, es...)
for _, e := range es { if e.n.IsInline() != (d == "inline") { t.Fatalf("%+v", e)@@ -174,7 +175,6 @@
body := grep(doc, "body")
b := &Browser{} b.client = &http.Client{}- browser = b
u, err := url.Parse("https://example.com") if err != nil { log.Fatalf("parse: %v", err)@@ -204,7 +204,6 @@
body := grep(doc, "body")
b := &Browser{} b.client = &http.Client{}- browser = b
u, err := url.Parse("https://example.com") if err != nil { return nil, nil, fmt.Errorf("parse url: %w", err)@@ -441,6 +440,7 @@
}
func TestTextArea(t *testing.T) {+ b := &Browser{}htm := `
<textarea height="100">
</textarea>
@@ -451,7 +451,7 @@
}
ta := nt.Find("textarea")- el := NewTextArea(ta)
+ el := NewTextArea(b, ta)
// Trigger key press to trigger call to changed
el.Key(nil, nil, 'a', draw.Mouse{}, image.Point{})}
--- a/browser/website.go
+++ b/browser/website.go
@@ -21,6 +21,7 @@
)
type Website struct {+ b *Browser
duit.UI
mycel.ContentType
}
@@ -27,7 +28,7 @@
func (w *Website) layout(f mycel.Fetcher, htm string, layouting int) { defer func() {- browser.StatusCh <- ""
+ w.b.StatusCh <- ""
}()
pass := func(htm string, csss ...string) (*html.Node, map[*html.Node]style.Map) { if f.Ctx().Err() != nil {@@ -143,7 +144,7 @@
scroller.Free()
scroller = nil
}
- scroller = duitx.NewScroll(dui, NodeToBox(0, browser, nt))
+ scroller = duitx.NewScroll(dui, NodeToBox(0, w.b, nt))
numElements := 0
TraverseTree(scroller, func(ui duit.UI) {numElements++
@@ -153,7 +154,7 @@
if numElements < 10 { log.Errorf("Less than 10 elements layouted, seems css processing failed. Will layout without css") nt = nodes.NewNodeTree(body, style.Map{}, make(map[*html.Node]style.Map), nil)- scroller = duitx.NewScroll(dui, NodeToBox(0, browser, nt))
+ scroller = duitx.NewScroll(dui, NodeToBox(0, w.b, nt))
w.UI = scroller
}
--
⑨