dominikh / go-js-dom Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
How would the equivalent of document.execCommand() be achieved in this library?
Currently, we have:
Lines 2460 to 2465 in 662b7b8
It might be helpful and worth considering changing it to have a Bytes() []byte
method:
// File represents files as can be obtained from file choosers or drag
// and drop.
//
// Reference: https://developer.mozilla.org/en-US/docs/Web/API/File.
type File struct {
*js.Object
}
// Bytes reads the file f and returns its contents as a []byte.
func (f *File) Bytes() []byte {
b := make(chan []byte)
fr := js.Global.Get("FileReader").New()
fr.Set("onload", func() {
b <- js.Global.Get("Uint8Array").New(fr.Get("result")).Interface().([]byte)
})
fr.Call("readAsArrayBuffer", f.Object)
return <-b
}
(Extracted from gopherjs/gopherjs#776 and #32. /cc @inkeliz)
Problem:
I am implementing "Mac trackpad" pan and zoom. Mac the way to tell the difference between a pan or zoom is to check ctrlKey
or metaKey
on the WheelEvent. Furthermore - for a zoom, I need to know the offsetX
and offsetY
to calculate the exact point to zoom about. Even though I should, I am not able to accomplish that with this library. The MDN docs suggest that a WheelEvent is a MouseEvent.
Suggested Solution:
Simply embed MouseEvent
in WheelEvent
- I think this solves all my problems.
type WheelEvent struct {
*MouseEvent
DeltaX float64 `js:"deltaX"`
DeltaY float64 `js:"deltaY"`
DeltaZ float64 `js:"deltaZ"`
DeltaMode int `js:"deltaMode"`
}
I think it would be useful if HTMLSelectElement
had Options()
just like HTMLDataListElement
does (which is where I copied the code from):
diff --git a/dom.go b/dom.go
index 78f3e2e..a2fa6e7 100644
--- a/dom.go
+++ b/dom.go
@@ -2401,6 +2401,15 @@ type HTMLScriptElement struct {
type HTMLSelectElement struct{ *BasicHTMLElement }
+func (e *HTMLSelectElement) Options() []*HTMLOptionElement {
+ options := nodeListToElements(e.Get("options"))
+ out := make([]*HTMLOptionElement, len(options))
+ for i, option := range options {
+ out[i] = option.(*HTMLOptionElement)
+ }
+ return out
+}
+
type HTMLSourceElement struct {
*BasicHTMLElement
Media string `js:"media"`
We will want to document all of the public methods and types. For the majority, we should be able to copy existing documentation (for example from the MDN), as long as it's licensed in an acceptable way.
Some methods have behaviour specific to our bindings, which will need handwritten documentation.
This is a long-term goal. It won't happen now, and it doesn't have to happen all at once.
go install honnef.co/go/js/dom/v2@latest yields an error message:
build constraints exclude all Go files in /Users/sergehulne/go/bin/pkg/mod/honnef.co/go/js/dom/[email protected]
I am trying to use CreateTextNode() with GOOS=js GOARCH=wasm and go1.13.9.
// +build js
package main
import "honnef.co/go/js/dom/v2"
func main() {
d := dom.GetWindow().Document().(dom.HTMLDocument)
_ = d.CreateTextNode("foobar")
}
The above code panics with:
panic: interface conversion: dom.Node is dom.Text, not *dom.Text wasm_exec.js:41:14
<empty string> wasm_exec.js:41:14
goroutine 1 [running]: wasm_exec.js:41:14
honnef.co/go/js/dom/v2.document.CreateTextNode(0xc1e018, 0xbade2, 0x6, 0x108be48) wasm_exec.js:41:14
/go/pkg/mod/honnef.co/go/js/dom/[email protected]/dom.go:803 +0x9 wasm_exec.js:41:14
main.main() wasm_exec.js:41:14
/tmp/godomtest/main.go:10 +0xc wasm_exec.js:41:14
exit code: 2 wasm_exec.js:106:14
LookupPrefix expects an argument.
Thanks for the great job!) Today I started to play around with your package and couldn't get it work. The first thing what I did is include compiled main.js file into <head>
tag. However whatever selector I use (dom.GetWindow().Document().querySelector("...")
) - it returned nil. The problem was I need to include the file before body
close tag!) So where is DOM's readyState
property?
"go get" stopped working for packages that import "honnef.co/go/js/dom".
Using int
for those x/y positions/widths/heights truncates the accuracy of returned values (to nearest int). This is not acceptable in some situations. Consider that browsers may have their zoom level set to something like 90% or 125%, so positions/widths may often end up being non-integer even if they are integer in source HTML.
This fixes a real/testable bug in my code where getting the current window position and restoring it later resulted in a minor drift. Switching to float64
fixes it.
I see some APIs already use float64
, like OffsetTop()
, OffsetWidth()
. I propose all other similar APIs should be changed from int
to float64
.
This is a sample patch that I used to test if this would work. It did work. It's an MVP patch that doesn't change all similar APIs, only the ones I needed to run my trial.
From 87d66042d174ce83a0c2a5984c17e8e55965dd75 Mon Sep 17 00:00:00 2001
From: Dmitri Shuralyov <[email protected]>
Date: Sun, 19 Apr 2015 21:57:54 -0700
Subject: [PATCH] WIP: Try out float64 precision for positions and dimensions.
This is an MVP test to see if it makes a difference in fixing slight
drift when saving/restoring window scroll position, etc.
---
dom.go | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/dom.go b/dom.go
index 7ed4e42..18f3200 100644
--- a/dom.go
+++ b/dom.go
@@ -809,14 +809,14 @@ type Window interface {
Location() *Location
Name() string
SetName(string)
- InnerHeight() int
- InnerWidth() int
+ InnerHeight() float64
+ InnerWidth() float64
Length() int
Opener() Window
OuterHeight() int
OuterWidth() int
- ScrollX() int
- ScrollY() int
+ ScrollX() float64
+ ScrollY() float64
Parent() Window
ScreenX() int
ScreenY() int
@@ -852,7 +852,7 @@ type Window interface {
Scroll(x, y int)
ScrollBy(dx, dy int)
ScrollByLines(int)
- ScrollTo(x, y int)
+ ScrollTo(x, y float64)
SetCursor(name string)
SetInterval(fn func(), delay int) int
SetTimeout(fn func(), delay int) int
@@ -890,12 +890,12 @@ func (w *window) SetName(s string) {
w.Set("name", s)
}
-func (w *window) InnerHeight() int {
- return w.Get("innerHeight").Int()
+func (w *window) InnerHeight() float64 {
+ return w.Get("innerHeight").Float()
}
-func (w *window) InnerWidth() int {
- return w.Get("innerWidth").Int()
+func (w *window) InnerWidth() float64 {
+ return w.Get("innerWidth").Float()
}
func (w *window) Length() int {
@@ -914,12 +914,12 @@ func (w *window) OuterWidth() int {
return w.Get("outerWidth").Int()
}
-func (w *window) ScrollX() int {
- return w.Get("scrollX").Int()
+func (w *window) ScrollX() float64 {
+ return w.Get("scrollX").Float()
}
-func (w *window) ScrollY() int {
- return w.Get("scrollY").Int()
+func (w *window) ScrollY() float64 {
+ return w.Get("scrollY").Float()
}
func (w *window) Parent() Window {
@@ -1065,7 +1065,7 @@ func (w *window) ScrollByLines(i int) {
w.Call("scrollByLines", i)
}
-func (w *window) ScrollTo(x, y int) {
+func (w *window) ScrollTo(x, y float64) {
w.Call("scrollTo", x, y)
}
--
2.3.2 (Apple Git-55)
The Element
interface has InnerHTML
and SetInnerHTML
but no equivalents for outerHTML
.
https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
Is there a reason? Is outerHTML
not a first class citizen or is there another reason why it should not be supported unlike innerHTML
?
If there's no reason to avoid adding it, I think it'd be useful. I've been doing:
e.Underlying().Set("outerHTML", html)
One time I accidentally used the wrong variable (type int
rather than string
), and the static type check didn't catch it because js.Object.Set
accepts interface{}
. If I could've used SetOuterHTML
, it'd be caught and save me time (and other people who might make a mistake of this class in the future).
Add a type Error
, which acts as a combination of DOMException and DOMError. It should be returned from methods such as (*HTMLInputElement).StepDown, which are documented to throw exceptions in case of abnormal conditions.
When we catch an exception that isn't of type DOMException¹, we should throw it again, as it's of a different nature.
We should also consider adding one variable per possible error type (e.g. InvalidStateError
), so that one can check directly against those, instead of requiring more constants and comparing fields of Error
to those.
Finally, find out whether all modern browsers have the name
property, or if we need to implement a fallback that looks at code
instead.
¹: Only DOMException will actually be thrown, DOMError is some internal name.
²: https://developer.mozilla.org/en-US/docs/Web/API/DOMError and https://developer.mozilla.org/en/docs/Web/API/DOMException will serve as guidance.
For reference, I'm using dom/v2
with go1.16.6
to build WASM client for a web project.
I have a case when I parse some arbitrary HTML from the server and add individual elements to DOM based on this. I call SetInnerHTML
on some temporary element and then add children one by one. However HTML has whitespaces in it, so returned node may be a text one.
...
newCommentsList := dom.GetWindow().Document().CreateElement("div")
newCommentsList.SetInnerHTML(resp.HTML)
...
for _, commentNode := range newCommentsList.ChildNodes() {
if _, ok := commentNode.(*dom.Text); ok {
//if commentNode.NodeType() == 3 { // or like this
continue
}
...
commentsTop.ParentElement().InsertBefore(commentNode, commentsTop.NextElementSibling())
}
...
I could have avoided checking against node type if I had Children
method:
https://developer.mozilla.org/en-US/docs/Web/API/Element/children. Other *Element
methods, such as ParentElement
or NextElementSibling
works fine for this purpose.
I notice that the HTMLDialogElement
, HTMLSlotElement
and HTMLPictureElement
are missing in the current version of go-js-dom
. Seems all this elements are experimental at this time (the dialog especially).
The following code gives Uncaught TypeError: a.Object.index is not a function
d := dom.GetWindow().Document()
ufoEl := d.GetElementByID("ufo").(*dom.HTMLParagraphElement)
ufoEl.Style().SetProperty("left", "300px", "")
fmt.Println(ufoEl.Style())
fmt.Println(ufoEl.Style().ToMap())
When I run
println(dom.GetWindow().History().Length())
I get the error
Uncaught Error: runtime error: invalid memory address or nil pointer dereference
but if I use
println(js.Global.Get("history").Get("length"))
the output is "2", as expected, both running in Chrome Version 66.0.3359.181 (Official Build) (64-bit), the latest version.
Navigator.Online() is not implemented, which would be very nice to have for my PWA.
Thanks!
When building a v2
-based program with go1.14:
# honnef.co/go/js/dom/v2
..\..\..\..\..\..\pkg\mod\honnef.co\go\js\dom\[email protected]\dom.go:121:7: invalid operation: o == js.Null() (struct containing [0]func() cannot be compared)
..\..\..\..\..\..\pkg\mod\honnef.co\go\js\dom\[email protected]\dom.go:121:25: invalid operation: o == js.Undefined() (struct containing [0]func() cannot be compared)
..\..\..\..\..\..\pkg\mod\honnef.co\go\js\dom\[email protected]\dom.go:144:27: invalid operation: n != js.Undefined() (struct containing [0]func() cannot be compared)
..\..\..\..\..\..\pkg\mod\honnef.co\go\js\dom\[email protected]\dom.go:160:26: invalid operation: o.Get("constructor") == js.Global().Get("Array") (struct containing [0]func() cannot be compared)
..\..\..\..\..\..\pkg\mod\honnef.co\go\js\dom\[email protected]\dom.go:218:2: cannot switch on elementConstructor(o) (type js.Value) (struct containing [0]func() cannot be compared)
..\..\..\..\..\..\pkg\mod\honnef.co\go\js\dom\[email protected]\dom.go:227:2: cannot switch on elementConstructor(o) (type js.Value) (struct containing [0]func() cannot be compared)
..\..\..\..\..\..\pkg\mod\honnef.co\go\js\dom\[email protected]\dom.go:235:7: invalid operation: o == js.Null() (struct containing [0]func() cannot be compared)
..\..\..\..\..\..\pkg\mod\honnef.co\go\js\dom\[email protected]\dom.go:235:25: invalid operation: o == js.Undefined() (struct containing [0]func() cannot be compared)
..\..\..\..\..\..\pkg\mod\honnef.co\go\js\dom\[email protected]\dom.go:238:2: cannot switch on elementConstructor(o) (type js.Value) (struct containing [0]func() cannot be compared)
..\..\..\..\..\..\pkg\mod\honnef.co\go\js\dom\[email protected]\dom.go:248:7: invalid operation: o == js.Null() (struct containing [0]func() cannot be compared)
..\..\..\..\..\..\pkg\mod\honnef.co\go\js\dom\[email protected]\dom.go:248:7: too many errors
For documentation and ease of use, event types could be added to aid users with available event types (these are hard to come across in a complete list on the internet)
const (
EventClick = "click"
EventLoad = "load"
EventAbort = "abort"
// ...
)
package main
// UI events.
const (
// The load event fires when the webpage finishes loading.
// It can also fire on nodes of elements like images, scripts, or objects.
EventLoad = "load"
// Fires when a user leaves the page. Usually because they click on a link.
EventUnload = "unload"
// This event fires when the browser encounters a JavaScript error or an asset that doesn’t exist.
EventError = "error"
// It fires when we resize the browser window. But browsers repeatedly fire this event,
// so avoid using this event to trigger complicated code; it might make the page less responsive.
EventResize = "resize"
// This event fires when the user scrolls up/down on the browser window.
// It can relate to the entire page or a specific element on the page.
EventScroll = "scroll"
)
// Focus and blur events.
const (
// This event fires, for a specific DOM node, when an element gains focus.
EventFocus = "focus"
// This fires, for a specific DOM node, when an element loses focus.
EventBlur = "blur"
)
// Human interface device input events.
const (
// Mouse events or touchpad
// This event fires when the user clicks on the primary mouse button (usually the left button).
// This event also fires if the user presses the Enter key on the keyboard when an element has focus.
// Touch-screen: A tap on the screen acts like a single primary mouse button click.
EventClick = "click"
// It fires when the user clicks down on any mouse button.
EventMouseDown, EventTouchstart = "mousedown", "touchstart"
// We have separate mousedown and mouseup events to add drag-and-drop functionality
// or controls in game development. Don’t forget a click event is the combination
// of mousedown and mouseup events.
// It fires when the user releases a mouse button.
EventMouseUp = "mouseup"
// It fires when the user moves the cursor, which was inside an element before, outside the element.
// We can say that it fires when the cursor moves off the element.
EventMouseOut = "mouseout"
// It fires when the user moves the cursor, which was outside an element before, inside the element.
// We can say that it fires when we move the cursor over the element.
EventMouseOver = "mouseover"
// It fires when the user moves the cursor around the element. This event is frequently triggered.
EventMouseMove = "mousemove"
// Keyboard events
// The keydown and keypress events fire before a character appears on the screen,
// the keyup fires after it shows. To know the key pressed when you use the
// keydown and keypress events, the event object has a keyCode property.
// This property, instead of returning the letter for that key, returns
// the ASCII code of the lowercase for that key.
// The keyup event fires when the user releases a key on the keyboard.
EventKeyUp = "keyup"
// It fires when the user presses any key in the keyboard.
// If the user holds down the key, this event fires repeatedly.
EventKeyDown = "keydown"
// It fires when the user presses a key that results in printing a character on the screen.
// This event fires repeatedly if the user holds down the key.
// This event will not fire for the enter, tab, or arrow keys; the keydown event would.
EventKeyPress = "keypress"
// This event fires when the user clicks the primary mouse button, in quick succession, twice.
EventDoubleClick = "dblclick"
)
// Form events
const (
// This event fires on the node representing the <form> element when a user submits a form.
EventSubmit = "submit"
// It fires when the status of various form elements change.
// This is a better option than using the click event because clicking is not the only way users interact with the form.
EventChange = "change"
// This event fires when the value of an <input> or a <textarea> changes
// (doesn’t fire for deleting in IE9). You can use keydown as a fallback in older browsers.
EventInput = "input"
)
// HTML5 events.
const (
// This event triggers when the DOM tree forms i.e. the script is loading.
// Scripts start to run before all the resources like images, CSS, and JavaScript loads.
// You can attach this event either to the window or the document objects.
EventDOMContentLoaded = "DOMContentLoaded"
// It fires when the URL hash changes without refreshing the entire window.
// Hashes (#) link specific parts (known as anchors) within a page.
// It works on the window object; the event object contains both the oldURL
// and the newURL properties holding the URLs before and after the hashchange.
EventHashChange = "hashchange"
// This event fires on the window object just before the page unloads.
// This event should only be helpful for the user,
// not encouraging them to stay on the page.
// You can add a dialog box to your event, showing a message alerting the users like their changes are not saved.
EventBeforeUnload = "beforeunload"
)
This is one such occurrence that I ran into, but there may be more instances. So we'll want a general solution.
According to https://developer.mozilla.org/en-US/docs/Web/API/Node.insertBefore:
If referenceElement is
null
, orundefined
, newElement is inserted at the end of the list of child nodes.
So it's valid to write the following JavaScript code:
TargetDiv.parentNode.insertBefore(NewDiv, TargetDiv.nextSibling); // Insert after.
Because nextSibling
returns null
if the specified node is the last node in that list.
When we directly translate that to Go with dom package:
TargetDiv.ParentNode().InsertBefore(NewDiv, TargetDiv.NextSibling()) // Insert after.
What happens is TargetDiv.NextSibling()
returns (Node)(nil)
because of wrapNode()
. Then InsertBefore
tries to call Underlying()
on it and we get Uncaught TypeError: undefined is not a function
error.
One solution I can think of, without modifying InsertBefore specifically, since we'd want this situation to be handled okay in other similar cases, would be something like this:
diff --git a/dom.go b/dom.go
index a789bb0..8df66eb 100644
--- a/dom.go
+++ b/dom.go
@@ -164,7 +164,7 @@ func wrapDocument(o js.Object) Document {
func wrapNode(o js.Object) Node {
if o.IsNull() || o.IsUndefined() {
- return nil
+ return &BasicNode{nil}
}
switch o.Get("constructor") {
// TODO all the non-element cases
@@ -1217,6 +1217,9 @@ type BasicNode struct {
}
func (n *BasicNode) Underlying() js.Object {
+ if n == nil {
+ return nil
+ }
return n.Object
}
But I'm not sure if that would cause other unintended side-effects (probably not... but please confirm). Is there a better way or is this the best way? If we use this approach, we'll probably want to apply it to other similar wrap* funcs.
I have: Go 1.7.1, GopherJS 1.7-1.
Can't figure out why i'm receiving: Uncaught RangeError: Maximum call stack size exceeded.
Is it a bug somewhere?
package main
import "honnef.co/go/js/dom"
func main() {
d := dom.GetWindow().Document()
h := d.GetElementByID("app")
h.AddEventListener("click", false, func(event dom.Event) {
event.PreventDefault()
h.SetInnerHTML("I am Clicked")
println("This message is printed in browser console")
})
}
It's the $internalize function producing this error by repeatedly calling the searchJsObject function.
Based on documentation it looks be that you would have to use HTML input events to gather information from input fields. Is there no golang alternative to using a .value in JS terms?
This is my code:
// +build js
package main
import (
"time"
dom "honnef.co/go/js/dom/v2"
)
var window = dom.GetWindow()
var qs = window.Document().QuerySelector
var canvas *dom.HTMLCanvasElement
var ctx *dom.CanvasRenderingContext2D
var lock = false
var currentPuzzle *Puzzle
// Puzzle contains all information about one puzzle and its state
type Puzzle struct {
image *dom.HTMLImageElement
}
func main() {
canvas = qs("#screen").(*dom.HTMLCanvasElement)
ctx = canvas.GetContext2d()
loadImage("assets/puzzles/niagara.jpg", func(img *dom.HTMLImageElement) {
currentPuzzle = &Puzzle{img}
redraw()
})
window.AddEventListener("resize", false, func(e dom.Event) { resize() })
resize()
}
func resize() {
rect := qs("#container").GetBoundingClientRect()
canvas.SetWidth(int(rect.Width()))
canvas.SetHeight(int(rect.Height()))
redraw()
}
func draw(t time.Duration, puzzle *Puzzle) {
ctx.SetFillStyle("#f00")
ctx.FillRect(0, 0, 100, 100)
if puzzle != nil {
ctx.DrawImage(puzzle.image, 0, 0)
}
}
func redraw() {
if !lock {
lock = true
window.RequestAnimationFrame(func(d time.Duration) {
lock = false
draw(d, currentPuzzle)
})
}
}
func loadImage(src string, callback func(img *dom.HTMLImageElement)) {
img := window.Document().CreateElement("img").(*dom.HTMLImageElement)
img.AddEventListener("load", false, func(e dom.Event) { callback(img) })
img.SetSrc(src)
}
On Firefox it gives me: Error: invalid arg: *dom.HTMLImageElement
with the stack trace pointing to convertArgs js.go:174
.
So i've been trying to work with gopherjs and noticed that js-dom does support canvas but not:
https://developer.mozilla.org/it/docs/Web/API/CanvasRenderingContext2D/getImageData
Image data specific functions such as GetImageData, PutImageData, CreateImageData (and then the relative functions for working with imageData.
Would it possible to add these to js-dom?
I would be interested in making a pull request if so. :)
Hi,
Is it possible to use createShadowRoot()
? If not, do you plan to bind createShadowRoot
and everything related to Web components? That would be great and useful for the comunity I guess.
The <template>
have a "attribute" of content
for read the content of the template itself.
It's possible to do using:
template := t.template.QuerySelector("template")
content := dom.WrapDocumentFragment( template.Underlying().Get("content") )
But, the go-js-dom
have a bunch of elements, like HTMLAnchorElement
, HTMLAudioElement
and so on. But actually, don't have seems to have a HTMLTemplateElement
.
the https cert at honnef.co has expired.
Go is getting Wasm support in 1.11: https://tip.golang.org/doc/go1.11#wasm.
A lot of frontend Go code uses this package, so supporting js/wasm
would be very helpful.
I need to be able to get extract what key was pressed (looking for Escape, Enter keys).
I've just looked into the various docs [1][2][3], and they seem to suggest that:
The KeyboardEvent was briefly (from 2003-2010) defined to have keyIdentifier and keyLocation attributes, but these were removed in favor of the current key and location attributes. These attributes were not widely implemented.
But when using the latest stable Chrome and Safari, I'm seeing the opposite. key
is not present at all, but keyIdentifier
is set. With this test page,
<html><body><input onkeydown="console.log(event);"></body></html>
This is what I'm seeing:
The only two fields that I see to identify which key was pressed are keyCode
and keyIdentifier
.
Can you please add one of them? Or if I'm mistaken, suggest how I can determine if Escape or Enter were pressed using existing API.
I think I would prefer keyIdentifier
(over keyCode
) if it indeed is the current "standard". But I'm not opposed to you adding both.
[1] https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent
[2] http://www.w3.org/TR/DOM-Level-3-Events/
[3] http://unixpapa.com/js/key.html
Hi,
First of all, thanks for a great library.
I often find my self needing the underlying *js.Object from an event (to add state information and retrieve the corresponding information if other handlers for the same event). As is the the event interface does not allow me to do this in a type safe way since I do not know the concrete type of the event (may be one f several) I in each function needs to have a large type switch which effectively tests all the event types (and what if more are added, that would lead to a panic/not working).
Thus, my uggestion would be to add a:
Underlying() *js.Object
method to the Event interface.
Any thoughts?
Heya @dominikh ! This is a really broad open-ended question (feel free to ignore / close if you like).. just wondering if you've considered placing this project under e.g. github.com/gopherjs/dom
or something? I think that would help with discovery a bit, as the first place I looked for this was in that organization.
If you dislike the idea / it's already been discussed etc. then I apologize for bringing it up -- I just think it's a nice project and really central to the needs of most gopherjs users and wondered if you'd considered it before or not. (obviously I can't speak for gopherjs maintainers either).
Either way, great package! Cheers!
The current arguments expects a time.Duration
which is an int64
that should measure time deltas in nanoseconds. However requestAnimationFrame
is said to give millisecond time points relative to some variable time origin. Perhaps it is better to change the type into int
(or whatever is best compatible with JS).
Would it be possible to implement Element.ReplaceChildren?
I'd be happy to submit a PR.
dom.CanvasRenderingContext2D
type has a drawImage method, but can not input dom.HTMLImageElement
parameter
Hello, I'm trying to get this project for the first time. I used go mod
for my project.
It's success to get the package mentioned using go get honnef.co/go/js/dom/v2
and when I check the folder it's exist with the following tree :
.
├── honnef.co
│ └── go
│ └── js
│ └── dom
│ └── v2
│ ├── LICENSE
│ ├── dom.go
│ ├── events.go
│ └── go.mod
But when I import it on my simple project it says
build command-line-arguments: cannot load honnef.co/go/js/dom/v2: no Go source files
This is my code
package main
import (
"fmt"
"honnef.co/go/js/dom/v2"
)
func main() {
el := dom.GetWindow().Document().QuerySelector("#number1")
htmlEl := el.(dom.HTMLElement)
pEl := el.(*dom.HTMLParagraphElement)
fmt.Println("Hello", pEl)
}
window.History() returns nil
There is a pull request, from half a year ago.
Using this library is possible to listen the Click
or Change
, like el.AddEventListener("change", false, func(...))
.
However, how can I use the DispatchEvent
? I mean, how I can el.DispatchEvent("change")
to trigger the listener?
Currently, the documentation has this example:
d := dom.GetWindow().Document()
e1 := d.GetElementByID("#my-element")
e2 := d.GetElementByID("#my-element")
e1.SetClass("some-class")
println(e1.Class().String() == e2.Class().String())
That will not compile because Element
interface does not have SetClass
method exposed. So, to access the SetClass
method of BasicElement
struct, one needs to go the long way:
var e dom.HTMLDivElement
e.BasicHTMLElement.BasicElement.SetClass()
Or, if you only have an interface like HTMLElement
given to you, getting to SetClass
is impossible without lots of type assertions.
The example should be rewritten to use correct code that works, for example:
d := dom.GetWindow().Document()
e1 := d.GetElementByID("#my-element")
e2 := d.GetElementByID("#my-element")
e1.Class().SetString("some-class")
println(e1.Class().String() == e2.Class().String())
And since the SetClass
method of BasicElement
struct is redundant, and effectively unusable, it might as well be removed.
Separately, the interface of TokenList
can be improved. Currently, it offers separate methods to set a single string and set a slice:
Set(s []string)
SetString(s string)
I would suggest you consider changing/adding a method with the signature:
Set(s ...string)
It's shorter, one method, and can be used in all situations:
e.Set("single-class")
e.Set("class-a", "class-b", "class-c")
var classes = []string{"foo", "bar"}
e.Set(classes...)
SetClass()
method.TokenList
values.visiting https://honnef.co/go/js/dom?go-get=1 returns 502
The Element.closest()
is already supported by many browsers for a long time, why don't support it?
Hi, is there appetite to add an examples folder to the repo? Or are there already examples of using the package elsewhere that I have missed?
When trying to run "go get honnef.co/go/js/dom" the process crashes with a "signal: killed" message.
Here is the output of "free -m" to show the memory available prior to install and then "go get honnef.co/go/js/dom":
root@recall:~# free -m
total used free shared buffers cached
Mem: 490 87 402 0 10 37
-/+ buffers/cache: 39 450
Swap: 0 0 0
root@recall:~# go get honnef.co/go/js/dom
go build honnef.co/go/js/dom: /usr/local/go/pkg/tool/linux_amd64/6g: signal: killed
When looking up the "signal: killed" error related to 6g, a couple go bug reports say that "What causes the compiler to consume a lot of memory is large static initaliser blocks", eventually getting the process killed (https://code.google.com/p/go/issues/detail?id=6251).
Any way to get around this?
Thanks!
This is an API design issue.
The fillStyle
property of CanvasRenderingContext2D
interface can be assigned any of 3 different types, according to https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle:
However, CanvasRenderingContext2D.FillStyle
field is defined as a string
:
Line 1915 in 790c789
So the following code will fail to compile:
gradient := ctx.CreateRadialGradient(0, 0, 8*1.75, 0, 0, 0)
gradient.AddColorStop(0, "rgba(0, 0, 0, 0)")
gradient.AddColorStop(1, "rgba(0, 0, 0, 0.3)")
ctx.FillStyle = gradient
cannot use gradient (variable of type *honnef.co/go/js/dom.CanvasGradient) as string value in assignment
I can think of some solutions, but I'm not sure which one we should pick. They all have trade-offs.
Don't do anything special. Let users do use *js.Object
API:
ctx.Set("fillStyle", gradient)
This works, but perhaps it's not as nice as one could wish for.
(I'm using this as my current workaround.)
One potential solution is to change FillStyle
type to interface{}
:
FillStyle interface{} `js:"fillStyle"` // Can be assigned one of string, *CanvasGradient, *CanvasPattern.
Then all these are possible:
ctx.FillStyle = "rgb(255, 0, 0)"
ctx.FillStyle = gradient
ctx.FillStyle = pattern
This works, but interface{}
isn't great for APIs. Any other type can be assigned too, and when querying the value of FillStyle
, you get an interface{}
which isn't nice either.
Define 3 fields of 3 different types, all mapping to JS property fillStyle
:
FillStyle string `js:"fillStyle"`
FillStyleGradient *CanvasGradient `js:"fillStyle"`
FillStylePattern *CanvasPattern `js:"fillStyle"`
Then all these are possible:
ctx.FillStyle = "rgb(255, 0, 0)"
ctx.FillStyleGradient = gradient
ctx.FillStylePattern = pattern
This works, but now there are 3 fields for one field... Which may be confusing and creates bloat.
/cc @luckcolors FYI, in case you have ideas on this.
Is it possible to add a method to retrieve the content of a File object to be able to send it with a POST method to the server ?
fileSelect := d.GetElementByID("import-file").(*dom.HTMLInputElement)
file := fileSelect.Files()[0]
...
resp, err := http.Post("/import/", "multipart/form-data", [the-file-content])
...
I currently do this in Javascript with:
var file = fileSelect.files[0];
var formData = new FormData();
formData.append('importFile', file, file.name);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/import/', true);
...
Or any way to do this with another method?
Thanks.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.