Example #1
0
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
}
Example #2
0
func main() {
	example := dom.GetWindow().Document().GetElementByID("example")
	m.Mount(
		example,
		js.M{
			"view":       js.MakeFunc(View),
			"controller": js.MakeFunc(Controller)},
	)
}
Example #3
0
func init() {
	prompt := js.Global.Get("godebugPrompt")
	if !prompt.Bool() {
		return
	}

	// Expose an input function to javascript for responses to prompts.
	input := make(chan string)
	js.Global.Set("godebugInput", js.MakeFunc(func(this *js.Object, args []*js.Object) interface{} {
		input <- args[0].String()
		return nil
	}))

	// Hook up gopherJS's output function.
	js.Global.Set("goPrintToConsole", js.InternalObject(func(b []byte) {
		js.Global.Call("godebugOutput", string(b))
	}))

	// Override our internal prompt function.
	promptUser = func() (response string, ok bool) {
		prompt.Invoke()
		response = <-input
		return response, true
	}
}
Example #4
0
func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
	if typ.Kind() != Func {
		panic("reflect: call of MakeFunc with non-Func type")
	}

	t := typ.common()
	ftyp := (*funcType)(unsafe.Pointer(t))

	fv := js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
		args := make([]Value, ftyp.NumIn())
		for i := range args {
			argType := ftyp.In(i).common()
			args[i] = makeValue(argType, arguments[i], 0)
		}
		resultsSlice := fn(args)
		switch ftyp.NumOut() {
		case 0:
			return nil
		case 1:
			return resultsSlice[0].object()
		default:
			results := js.Global.Get("Array").New(ftyp.NumOut())
			for i, r := range resultsSlice {
				results.SetIndex(i, r.object())
			}
			return results
		}
	})

	return Value{t, unsafe.Pointer(fv.Unsafe()), flag(Func)}
}
Example #5
0
func init() {
	vue.Component("js-clock", js.M{
		"template": `<canvas></canvas>`,
		"replace":  true,
		"ready": js.MakeFunc(func(this *js.Object, arg []*js.Object) interface{} {
			draw(canvas.NewElement(this.Get("$el")))
			return 0
		}),
	})
}
Example #6
0
func wrap(v, t *js.Object) *js.Object {
	nt := js.Global.Get("Object").New()
	nt.Set("elem", t)
	nt.Set("kind", ptrKind)
	nv := js.Global.Get("Object").New()
	nv.Set("$val", v)
	nv.Set("constructor", nt)
	nv.Set("$get", js.MakeFunc(func(this *js.Object, _ []*js.Object) interface{} {
		return this.Get("$val")
	}))
	return nv
}
Example #7
0
// Bytes returns a slice of the contents of the Blob.
func (b *Blob) Bytes() []byte {
	fileReader := js.Global.Get("FileReader").New()
	var wg sync.WaitGroup
	var buf []byte
	wg.Add(1)
	fileReader.Set("onload", js.MakeFunc(func(this *js.Object, _ []*js.Object) interface{} {
		defer wg.Done()
		buf = js.Global.Get("Uint8Array").New(this.Get("result")).Interface().([]uint8)
		return nil
	}))
	fileReader.Call("readAsArrayBuffer", b)
	wg.Wait()
	return buf
}
Example #8
0
func (m *Module) Controller(name string, cls interface{}) error {
	var err error

	arg, err := buildParams(cls, "ajs-service")
	if err != nil {
		println("Error building controller params: ", err.Error(), "controller: ", name)

		return err
	}

	m.Call("controller", name, arg)
	js.Global.Set(name, js.MakeFunc(makeConstructor(cls)))

	return nil
}
Example #9
0
func TestMakeFunc(t *testing.T) {
	o := js.Global.Get("Object").New()
	o.Set("f", js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
		if this != o {
			t.Fail()
		}
		if len(arguments) != 2 || arguments[0].Int() != 1 || arguments[1].Int() != 2 {
			t.Fail()
		}
		return 3
	}))
	if o.Call("f", 1, 2).Int() != 3 {
		t.Fail()
	}
}
Example #10
0
func makeMethodValue(op string, v Value) Value {
	if v.flag&flagMethod == 0 {
		panic("reflect: internal error: invalid use of makePartialFunc")
	}

	_, _, fn := methodReceiver(op, v, int(v.flag)>>flagMethodShift)
	rcvr := v.object()
	if isWrapped(v.typ) {
		rcvr = jsType(v.typ).New(rcvr)
	}
	fv := js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
		return js.InternalObject(fn).Call("apply", rcvr, arguments)
	})
	return Value{v.Type().common(), unsafe.Pointer(fv.Unsafe()), v.flag&flagRO | flag(Func)}
}
Example #11
0
func buildParams(cb interface{}, name string) (js.S, error) {
	arg := js.S{}

	typ, cls := typeOf(cb)
	if typ.Kind() != reflect.Func {
		return nil, fmt.Errorf("Expected a function, got %q", typ)
	}

	i := 0

	if cls {
		i = 1
	}

	for ; i < typ.NumIn(); i++ {
		argTyp := typ.In(i)
		if argTyp.Kind() != reflect.Struct {
			argTyp = argTyp.Elem()
		}

		param, ok := argTyp.FieldByName("Object")

		if !ok {
			return nil, fmt.Errorf("Invalid paramater type %q (Missing Object)", argTyp)
		}

		if param.Tag.Get(name) == "" {
			if param.Tag.Get("js") == "" {
				return nil, fmt.Errorf("Invalid paramater type %q (Missing tag %s)", argTyp, name)
			} else {
				arg = append(arg, param.Tag.Get("js"))
			}
		} else {
			arg = append(arg, param.Tag.Get(name))
		}
	}

	if cls {
		arg = append(arg, js.MakeFunc(makeConstructor(cb)))
	} else {
		arg = append(arg, cb)
	}

	return arg, nil
}
Example #12
0
func TestMakeFunc(t *testing.T) {
	o := js.Global.Get("Object").New()
	for i := 3; i < 5; i++ {
		x := i
		if i == 4 {
			break
		}
		o.Set("f", js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
			if this != o {
				t.Fail()
			}
			if len(arguments) != 2 || arguments[0].Int() != 1 || arguments[1].Int() != 2 {
				t.Fail()
			}
			return x
		}))
	}
	if o.Call("f", 1, 2).Int() != 3 {
		t.Fail()
	}
}
Example #13
0
func (t *uncommonType) Method(i int) (m Method) {
	if t == nil || i < 0 || i >= len(t.methods) {
		panic("reflect: Method index out of range")
	}
	p := &t.methods[i]
	if p.name != nil {
		m.Name = *p.name
	}
	fl := flag(Func)
	if p.pkgPath != nil {
		m.PkgPath = *p.pkgPath
		fl |= flagStickyRO
	}
	mt := p.typ
	m.Type = mt
	prop := js.Global.Call("$methodSet", js.InternalObject(t).Get("jsType")).Index(i).Get("prop").String()
	fn := js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
		rcvr := arguments[0]
		return rcvr.Get(prop).Call("apply", rcvr, arguments[1:])
	})
	m.Func = Value{mt, unsafe.Pointer(fn.Unsafe()), fl}
	m.Index = i
	return
}
Example #14
0
func (t *rtype) Method(i int) (m Method) {
	if t.Kind() == Interface {
		tt := (*interfaceType)(unsafe.Pointer(t))
		return tt.Method(i)
	}
	methods := t.exportedMethods()
	if i < 0 || i >= len(methods) {
		panic("reflect: Method index out of range")
	}
	p := methods[i]
	pname := t.nameOff(p.name)
	m.Name = pname.name()
	fl := flag(Func)
	mtyp := t.typeOff(p.mtyp)
	ft := (*funcType)(unsafe.Pointer(mtyp))
	in := make([]Type, 0, 1+len(ft.in()))
	in = append(in, t)
	for _, arg := range ft.in() {
		in = append(in, arg)
	}
	out := make([]Type, 0, len(ft.out()))
	for _, ret := range ft.out() {
		out = append(out, ret)
	}
	mt := FuncOf(in, out, ft.IsVariadic())
	m.Type = mt
	prop := js.Global.Call("$methodSet", js.InternalObject(t).Get("jsType")).Index(i).Get("prop").String()
	fn := js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
		rcvr := arguments[0]
		return rcvr.Get(prop).Call("apply", rcvr, arguments[1:])
	})
	m.Func = Value{mt.(*rtype), unsafe.Pointer(fn.Unsafe()), fl}

	m.Index = i
	return m
}
Example #15
0
File: app.go Project: theclapp/js
func main() {
	vue.Component("my-cpnt", js.M{
		"template": "<h1>This is my testing component!</h1>" +
			"<content>This will only be displayed if no content is inserted</content>",
		"created": js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
			println("'An instance of MyComponent has been created!'")
			this.Call("$dispatch", "msg", "hello")
			return 0
		}),
	})
	data := newData()
	datam := structs.New(data).Tag("js").Map()
	println("data:", data)
	println("datam:", datam)
	vm := vue.New(js.M{
		"el": "#demo",
		// "data": js.M{
		// 	"title": "todos",
		// 	"todos": []js.M{
		// 		js.M{
		// 			"done":    true,
		// 			"content": "Learn JavaScript",
		// 		},
		// 		js.M{
		// 			"done":    false,
		// 			"content": "Learn Vue.js",
		// 		},
		// 	},
		// },
		"data": data,
		"methods": js.M{
			"change": func() {
				// data.Title = "Funcked"
			},
		},
		"directives": js.M{
			"showdone": js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
				println("this.expression:", this.Get("expression"))
				return 0
			}),
		},
		"filters": js.M{
			"testf": js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
				println("testf:", this.Get("title"))
				return 0
			}),
		},
		"created": js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
			this.Call("$on", "msg", func(msg interface{}) {
				println("parent got:", msg.(string))
			})
			return 0
		}),
	})
	// v := vue.New(vue.VueOption{
	// 	El: "#demo",
	// 	Data: js.M{
	// 		"title": "todos",
	// 		"todos": []js.M{
	// 			js.M{
	// 				"done":    true,
	// 				"content": "Learn JavaScript",
	// 			},
	// 			js.M{
	// 				"done":    false,
	// 				"content": "Learn Vue.js",
	// 			},
	// 		},
	// 	},
	// })
	println(vm.Object)
	println(vm.Options)
	vm.Watch("todos", func(newVal, oldVal *js.Object) {
		println(newVal.Index(0).Get("done"))
	}, true)

	// vm.On("msg", func(msg interface{}) {
	// 	println("parent got:", msg.(string))
	// })
}
Example #16
0
// Package analytics provides bindings to Google Analytics's analytics.js for
// gopherjs.
package analytics

import "github.com/gopherjs/gopherjs/js"

var ga = func() func(...interface{}) {
	// conversion of the code given by Google Analytics as of 2015-06-24
	js.Global.Set("GoogleAnalyticsObject", "ga")
	if js.Global.Get("ga") == js.Undefined {
		js.Global.Set("ga", js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
			if js.Global.Get("ga").Get("q") == js.Undefined {
				js.Global.Get("ga").Set("q", make(js.S, 0))
			}
			js.Global.Get("ga").Get("q").Call("push", arguments)
			return js.Undefined
		}))
	}
	js.Global.Get("ga").Set("l", js.Global.Get("Date").New().Call("valueOf"))
	script := js.Global.Get("document").Call("createElement", "script")
	anchor := js.Global.Get("document").Call("getElementsByTagName", "script").Index(0)
	script.Set("async", true)
	script.Set("src", "//www.google-analytics.com/analytics.js")
	anchor.Get("parentNode").Call("insertBefore", script, anchor)

	return func(args ...interface{}) {
		js.Global.Get("ga").Invoke(args...)
	}
}()

// Create a new default tracker object. The tracking ID starts with "UA-" and
Example #17
0
// wrapComponent creates a React class for the given Component by
// creating a plain js.Object and mapping functions to it, and back.
//
// For example, the React `render()` method is assigned to the object.
// When React calls this method, the given Component's Render() method is
// called. The result of Component.Render() is recursively run through
// Wrap() as well, with the final result being a series of objects given
// to React that map to their respective components.
//
// This means that when a component calls the embedded *React methods,
// such as React.SetState() end up calling the functions in this closure
// which then call the normal React `this.setState()` methods.
//
// A lot of wiring, but the goal is that complexity in a Component is
// isolated from the complexity given to React. So all of the tomfoolery
// that React does to method Binding's are not actually done to the
// methods of your component.
//
// TL;DR: The overhead caused by Wrap() is to avoid React tomfoolery
// multiplying by GopherJS tomfoolery. Resulting in a (in theory)
// net tomfoolery reduction. Science.
//
// TODO: Create the *React pipeline to communicate from the Component
// to the jsObject wrapper.
//
// TODO: Write errors to console.error
//
// TODO: Drop error return. Don't think it's possible to have an error
// outside of the callbacks.
//
// TODO: Handle the following React warning:
//
// 		Warning: Each child in an array or iterator should have a
// 		unique "key" prop. Check the React.render call using <div>.
// 		See https://fb.me/react-warning-keys for more information.
//
// Though, the responsibility of handling this may be better off on the
// Component.
func wrapComponent(c Component) (jsComp *js.Object, err error) {
	fmt.Printf("wrapComponent(<%s>)\n", c.Tag())
	jsObject := js.Global.Get("Object").New()

	// This is a reference to the final, valid React object instance.
	//
	// React does a lot of binding/this tomfoolery, and it heavily
	// screws with GopherJS. As a result, custom functions won't have
	// valid `this` objects.
	//
	// React API functions can get a valid `this`, such as `render` and
	// `setInitialState`, but custom functions fail.
	//
	// Commented out, as it's likely being removed soon (no need for
	// the reference, Components have SetThis()
	//var this *js.Object

	// TODO: Find a way to support sane error handling. It's difficult
	// because the render() method is a callback from JS, and the return
	// value is consumed by React.js itself. Furthermore, even if we could
	// return an error value, we can't get access to it.
	render := func() *js.Object {
		fmt.Printf("<%s>.render\n", c.Tag())

		rendComp := c.Render()

		var jsClass *js.Object
		var content string
		// If a component is Rendered, wrap it and return.
		if rendComp != nil {
			// If this child has Content (String), return it directly.
			content = rendComp.Content()
			if content != "" {
				return reactjs.CreateElement(c.Tag(), c.Props(), content)
			}

			jsClass, _ = wrapComponent(rendComp)

			return reactjs.CreateElement(jsClass)
		}

		// The comp did not render anything, so try to create a Tag with
		// it's children.
		//
		// If it has no tag, we can't do that. Error out.
		if c.Tag() == "" {
			fmt.Println("Error: Component has no Children and no Tag")
			return nil
		}

		children := c.Children()
		childrenCount := len(children)

		// If this comp has no children, create an empty jsComp (eg: <foo />)
		if childrenCount == 0 {
			return reactjs.CreateElement(c.Tag(), c.Props())
		}

		// The == 1 check is done to avoid creating the slice, looping,
		// and (most importantly) avoid returning an array. By doing it
		// here, we can save a bit of overhead.. in theory.
		//
		// Premature optimization without benchmarks? heh
		var childComp Component
		if childrenCount == 1 {
			childComp = children[0]

			// If this child has Content (String), return it directly.
			content = childComp.Content()
			if content != "" {
				return reactjs.CreateElement(c.Tag(), c.Props(), content)
			}

			jsClass, _ = wrapComponent(childComp)

			return reactjs.CreateElement(c.Tag(), c.Props(),
				reactjs.CreateElement(jsClass))
		}

		// A slice of this Element's Childen. Note that in the event of
		// a Content child, string is added to this slice instead of a
		// jsObject.
		jsChildren := make([]interface{}, childrenCount)

		var i int
		for i, childComp = range children {
			// If this child has Content (String), push it onto Children
			// directly.
			content = childComp.Content()
			if content != "" {
				jsChildren[i] = content
				continue
			}

			// Wrap the component, returning it's class
			jsClass, _ = wrapComponent(childComp)
			// And create an element from the class, adding it to the slice.
			jsChildren[i] = reactjs.CreateElement(jsClass)
		}

		return reactjs.CreateElement(c.Tag(), c.Props(), jsChildren)
	}

	jsObject.Set("render", render)
	jsObject.Set("componentDidMount", c.ComponentDidMount)
	jsObject.Set("componentWillUnmount", c.ComponentWillUnmount)

	// Temporary implementation for early testing.
	jsObject.Set("getInitialState", js.MakeFunc(
		func(reactThis *js.Object, _ []*js.Object) interface{} {
			if err := c.SetThis(reactThis); err != nil {
				fmt.Println("Error: ", err.Error())
			}
			return nil
		},
	))

	return reactjs.CreateClass(jsObject), nil
}
Example #18
0
package main

import (
	"github.com/gopherjs/gopherjs/js"
)

var onWordMouseOver = js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
	this.Get("style").Set("color", "red")
	return nil
})

var onWordMouseOut = js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
	this.Get("style").Set("color", "")
	return nil
})

func main() {
	spans := js.Global.Get("document").Call("getElementById", "container").Call("querySelectorAll", "span")
	// access individual span
	length := spans.Get("length").Int()
	for i := 0; i < length; i++ {
		span := spans.Call("item", i)
		span.Set("onmouseover", onWordMouseOver)
		span.Set("onmouseout", onWordMouseOut)
	}
}
Example #19
0
func createFuncWithVisibleDone(fn func(func())) *js.Object {
	return js.MakeFunc(func(this *js.Object, args []*js.Object) interface{} {
		return js.Global.Get("eval").Invoke("var a = function(cb){ return function(done){ return cb(done); }; }; a")
	}).Invoke().Invoke(fn)
}
Example #20
0
func main() {
	js.Global.Set("onmessage", js.MakeFunc(messageHandler))
}