// TriggerBindEvent connects the giving event with the provided dom target. func (dm *DOMRenderer) TriggerBindEvent(event *gjs.Object, root *gjs.Object, source *trees.Event) { target := event.Get("target") children := root.Call("querySelectorAll", source.Target()) if children == nil || children == gjs.Undefined { return } kids := js.DOMObjectToList(children) var match bool for _, item := range kids { if item != target { continue } match = true break } // if we match then run the listeners registered. if match { dispatch.Dispatch(trees.EventBroadcast{ EventID: source.EventID, Event: trees.NewWrapperEvent(event), }) } }
// QuerySelectorAll returns the result of querySelectorAll on an object func QuerySelectorAll(o *js.Object, sel string) []*js.Object { if sad := o.Get("querySelectorAll"); sad == nil || sad == js.Undefined { return nil } return DOMObjectToList(o.Call("querySelectorAll", sel)) }
// NewContext takes an HTML5 canvas object and optional context attributes. // If an error is returned it means you won't have access to WebGL // functionality. func NewContext(canvas js.Object, ca *ContextAttributes) (*Context, error) { if js.Global.Get("WebGLRenderingContext") == js.Undefined { return nil, errors.New("Your browser doesn't appear to support webgl.") } if ca == nil { ca = DefaultAttributes() } attrs := map[string]bool{ "alpha": ca.Alpha, "depth": ca.Depth, "stencil": ca.Stencil, "antialias": ca.Antialias, "premultipliedAlpha": ca.PremultipliedAlpha, "preserveDrawingBuffer": ca.PreserveDrawingBuffer, } gl := canvas.Call("getContext", "webgl", attrs) if gl == nil { gl = canvas.Call("getContext", "experimental-webgl", attrs) if gl == nil { return nil, errors.New("Creating a webgl context has failed.") } } ctx := new(Context) ctx.Object = gl return ctx, nil }
func MakeWorkspace(canvas *js.Object) *Workspace { doc := js.Global.Get("document") ctx := canvas.Call("getContext", "2d") w := &Workspace{ doc: doc, canvas: canvas, ctx: ctx, x: canvas.Get("offsetLeft").Int(), y: canvas.Get("offsetTop").Int(), dx: canvas.Get("offsetWidth").Int(), dy: canvas.Get("offsetHeight").Int(), images: make(chan schema.ImageManifest), disks: make(chan string), ingresses: make(chan int), draw: make(chan struct{}), mouseDown: make(chan point), mouseMove: make(chan point), mouseUp: make(chan point), makeItSo: make(chan struct{}), cut: make(chan struct{}), } doc.Call("addEventListener", "mousedown", js.MakeFunc(w.onMouseDown), "false") doc.Call("addEventListener", "mousemove", js.MakeFunc(w.onMouseMove), "false") doc.Call("addEventListener", "mouseup", js.MakeFunc(w.onMouseUp), "false") go w.run() return w }
func (ws *webSocket) sendPayload(action *Action) (err error) { defer func() { err = jsError(recover()) }() decodeDataURI := (action.String() == "update_user") for _, frame := range action.Payload { var data *js.Object = frame if decodeDataURI { base64 := data.Call("split", ",").Index(1) binaryString := js.Global.Call("atob", base64) length := binaryString.Length() data = js.Global.Get("ArrayBuffer").New(length) array := js.Global.Get("Uint8Array").New(data) for i := 0; i < length; i++ { array.SetIndex(i, binaryString.Call("charCodeAt", i)) } } ws.impl.Call("send", data) } return }
// DOMObjectToList takes a jsobjects and returns a list of internal objects by calling the item method func DOMObjectToList(o *js.Object) []*js.Object { var out []*js.Object length := o.Get("length").Int() for i := 0; i < length; i++ { out = append(out, o.Call("item", i)) } return out }
func New(el *js.Object) *Canvas { return &Canvas{ Element: el, ctx: el.Call("getContext", "2d"), Width: el.Get("width").Int(), Height: el.Get("height").Int(), } }
// CleanAllTextNode removes all texts nodes within the container root func CleanAllTextNode(o *js.Object) { for _, to := range ChildNodeList(o) { if istx, isem := EmptyTextNode(to); istx { if !isem { o.Call("removeChild", to) } } } }
// SpecialAppendChild takes a list of objects and calls appendNode on the given object, but checks if the objects contain an unknownelement with a text tag then strip the tagname and only apply its content func SpecialAppendChild(o *js.Object, osets ...*js.Object) { for _, onode := range osets { if strings.ToLower(onode.Get("tagName").String()) == "text" { SpecialAppendChild(o, ChildNodeList(onode)...) continue } o.Call("appendChild", onode) } }
func toggleDebugOverlay(e js.Object) { e.Call("preventDefault") d := js.Global.Get("document").Call("getElementById", "debug_overlay") if d.Get("style").Get("display").Str() == "block" { d.Get("style").Set("display", "none") return } d.Get("style").Set("display", "block") }
// BindEvent connects the event with the provided event object and root. func (dm *DOMRenderer) BindEvent(source *trees.Event, root *gjs.Object) { source.Link = func(ev *gjs.Object) { dm.TriggerBindEvent(ev, root, source) } root.Call("addEventListener", source.Type, source.Link, true) source.Handle.AddEnd(func() { root.Call("removeEventListener", source.Type, source.Link, true) }) }
// CleanAllTextNode removes all texts nodes within the container root func CleanAllTextNode(o *js.Object) { for _, to := range ChildNodeList(o) { if istx, isem := EmptyTextNode(to); istx { if !isem { // log.Printf("Cleaning Text Node: %s", to.Get("textContent").String()) o.Call("removeChild", to) } } } }
// New returns a new Canvas that wraps the <canvas> elem. This will // most likely be retrieved using // // js.Global.Get("document").Call("getElementById", id) // // If the browser doesn't support CanvasRenderingContext2D, an error // is returned. func New(elem *js.Object) (*Canvas, error) { if js.Global.Get("CanvasRenderingContext2D") == nil { return nil, errors.New("Browser doesn't support canvas 2D") } return &Canvas{ elem: elem, ctx: elem.Call("getContext", "2d"), }, nil }
func NewCanvas(parent *js.Object, width, height int) *Canvas { document := js.Global.Get("document") canvas := document.Call("createElement", "canvas") parent.Call("appendChild", canvas) canvas.Set("width", width) canvas.Set("height", height) context := canvas.Call("getContext", "2d") return &Canvas{canvas, context, image.Rect(0, 0, width, height)} }
// ContextAppendChild takes a list of objects and calls appendNode on the given object func ContextAppendChild(o *js.Object, osets ...*js.Object) { for _, onode := range osets { if doHeadAppend(onode) { continue } if scripts := QuerySelectorAll(onode, "scripts"); len(scripts) != 0 { for _, script := range scripts { doHeadAppend(script) } } o.Call("appendChild", onode) } }
func createJsWebsocket(scope *js.Object) *Websocket { websocketUrl := fmt.Sprintf("ws://%s/chat", GetWindowHost()) websocket := NewWebsocket(websocketUrl, func(event *js.Object) { stringData := event.Get("data").String() message := chat.MessageData{} json.Unmarshal([]byte(stringData), &message) scope.Call("showMessage", message) // force refresh scope data for async data binding scope.Call("$apply") ScrollToChatBottom() }) return websocket }
func updateScreen(canvas *js.Object, video []byte) { ctx := canvas.Call("getContext", "2d") img := ctx.Call("getImageData", 0, 0, imgWidth, imgHeight) data := img.Get("data") arrBuf := js.Global.Get("ArrayBuffer").New(data.Length()) buf8 := js.Global.Get("Uint8ClampedArray").New(arrBuf) buf32 := js.Global.Get("Uint32Array").New(arrBuf) buf := buf32.Interface().([]uint) for i := 0; i < len(video); i += 3 { buf[i/3] = 0xFF000000 | (uint(video[i]) << 16) | (uint(video[i+1]) << 8) | uint(video[i+2]) } data.Call("set", buf8) ctx.Call("putImageData", img, 0, 0) }
func main() { fmt.Println("gopherjs+electronテスト") fmt.Printf("js: %v\n", js.Global.Get("process").Get("version")) fmt.Printf("electron: %v\n", js.Global.Get("process").Get("versions").Get("electron")) window_options := []byte(` { "width": 1280 , "height": 720 , "web-preferences": { } } `) var window_options_json map[string]interface{} err := json.Unmarshal(window_options, &window_options_json) if err != nil { panic(err) } //init electron app app := js.Global.Call("require", "app") js.Global.Call("require", "crash-reporter").Call("start") browserWindow := js.Global.Call("require", "browser-window") var mainWindow *js.Object app.Call("on", "window-all-closed", func() { if js.Global.Get("process").Get("platform").String() != "darwin" { app.Call("quit") } }) app.Call("on", "ready", func() { mainWindow = browserWindow.New(window_options_json) _, filename, _, _ := runtime.Caller(1) url := "file:///" + path.Join(path.Dir(filename), "index.html") mainWindow.Call("loadUrl", url) mainWindow.Call("on", "closed", func() { mainWindow = nil }) }) }
func unwrap(v, t *js.Object) (*js.Object, *js.Object) { Loop: for { switch t.Get("kind").Int() { case ptrKind: if v.Get("$val") != t.Get("nil") { v = v.Call("$get") t = t.Get("elem") } else { break Loop } case interfaceKind: t = v.Get("constructor") v = v.Get("$val") default: break Loop } } return v, t }
func RenderNode(vnode *VNode) *js.Object { var dnode *js.Object switch vnode.Tag { case tagText: dnode = js.Global.Get("document").Call("createTextNode", vnode.Data) case tagRaw: dnode = js.Global.Get("document").Call("createRange").Call("createContextualFragment", vnode.Data) default: dnode = js.Global.Get("document").Call("createElement", vnode.Tag) for k, v := range vnode.Attributes { dnode.Call("setAttribute", k, v) } for _, child := range vnode.Children { dnode.Call("appendChild", RenderNode(child)) } } return dnode }
func printValueAt(e js.Object, name string, value string) { targets := []js.Object{} if e.Get("name").Str() == name { targets = append(targets, e) } query := fmt.Sprintf("*[name=\"%s\"]", html.EscapeString(name)) es := e.Call("querySelectorAll", query) for i := 0; i < es.Length(); i++ { targets = append(targets, es.Index(i)) } if e.Get("dataset").Get(toDatasetProp(datasetAttrKey)).Str() == name { targets = append(targets, e) } query = fmt.Sprintf( "*[data-%s=\"%s\"]", html.EscapeString(datasetAttrKey), html.EscapeString(name)) es = e.Call("querySelectorAll", query) for i := 0; i < es.Length(); i++ { targets = append(targets, es.Index(i)) } for _, e := range targets { if e.Call("hasAttribute", "value").Bool() { e.Set("value", value) } else { e.Set("textContent", value) } } }
func addEventListenersId(document *js.Object, id string, ls []interface{}) { for _, l := range ls { if v, ok := l.(ClickInterface); ok { x := document.Call("getElementById", id) x.Call("addEventListener", "click", func(e *MouseEvent) { e.Init() v.Click(e) }, false) } if v, ok := l.(LoadInterface); ok { // Fixme event never fires snice main is called from load. w := js.Global.Get("window") // w := document.Call("getElementById", id) // w := document f := func(e *Event) { e.Init() v.Load(e) } w.Call("addEventListener", "load", f, false) } } }
// ShowContextMenu shows the context menu func ShowContextMenu(event *js.Object) { event.Call("stopPropagation") event.Call("preventDefault") ctxMenu := jq("#contextmenu") x := event.Get("pageX").Int() y := event.Get("pageY").Int() width := jq(js.Global.Get("window")).Width() height := jq(js.Global.Get("window")).Height() if x+ctxMenu.Width() > width { x -= ctxMenu.Width() } if y+ctxMenu.Height() > height { y -= ctxMenu.Height() } ctxMenu.SetCss(map[string]interface{}{ "top": y, "left": x, }) ctxMenu.RemoveClass("hidden") }
func newContext(canvas *js.Object, ca *contextAttributes) (context *js.Object, err error) { if js.Global.Get("WebGLRenderingContext") == js.Undefined { return nil, errors.New("Your browser doesn't appear to support WebGL.") } attrs := map[string]bool{ "alpha": ca.Alpha, "depth": ca.Depth, "stencil": ca.Stencil, "antialias": ca.Antialias, "premultipliedAlpha": ca.PremultipliedAlpha, "preserveDrawingBuffer": ca.PreserveDrawingBuffer, "preferLowPowerToHighPerformance": ca.PreferLowPowerToHighPerformance, "failIfMajorPerformanceCaveat": ca.FailIfMajorPerformanceCaveat, } if gl := canvas.Call("getContext", "webgl", attrs); gl != nil { return gl, nil } else if gl := canvas.Call("getContext", "experimental-webgl", attrs); gl != nil { return gl, nil } else { return nil, errors.New("Creating a WebGL context has failed.") } }
func (v *HTMLView) addEventListeners(items Items, form js.Object) { inputDate := form.Call("querySelector", "input[name=Date]") inputDate.Set("onchange", func(e js.Object) { id, err := getIDFromElement(e.Get("target")) if err != nil { v.onErrorFunc(err) return } dateStr := e.Get("target").Get("value").Str() d, err := date.ParseISO8601(dateStr) if err != nil { v.onErrorFunc(err) return } if err := items.UpdateDate(id, d); err != nil { v.onErrorFunc(err) return } }) inputSubject := form.Call("querySelector", "input[name=Subject]") inputSubject.Set("onchange", func(e js.Object) { id, err := getIDFromElement(e.Get("target")) if err != nil { v.onErrorFunc(err) return } subject := e.Get("target").Get("value").Str() if err := items.UpdateSubject(id, subject); err != nil { v.onErrorFunc(err) return } }) inputMoneyAmount := form.Call("querySelector", "input[name=Amount]") inputMoneyAmount.Set("onchange", func(e js.Object) { id, err := getIDFromElement(e.Get("target")) if err != nil { v.onErrorFunc(err) return } amount := int32(e.Get("target").Get("value").Int()) if err := items.UpdateAmount(id, amount); err != nil { v.onErrorFunc(err) return } }) }
func addEventListener(object *js.Object, eventName string, callback func(*js.Object)) { object.Call("addEventListener", eventName, callback) }
func reflectType(typ js.Object) *rtype { return (*rtype)(unsafe.Pointer(typ.Call("reflectType").Unsafe())) }
// SetAttribute calls setAttribute on the js object with the value and key func SetAttribute(o *js.Object, key string, value string) { o.Call("setAttribute", key, value) }
// HasAttribute returns true/false if a key exists using the jsobject func HasAttribute(o *js.Object, key string) bool { return o.Call("hasAttribute", key).Bool() }
// GetAttribute returns a string if a key exists using the jsobject func GetAttribute(o *js.Object, key string) string { return o.Call("getAttribute", key).String() }