[Golang] Draggable (Movable) Element by GopherJS


Introduction

It is really cool to run Go code in the browser. GopherJS is a compiler from Go to JavaScript, which makes this possible. In this post, we will give an example of DOM manipulation in Go program. This example shows how to write a draggable/movable HTML element. This example is ported from Dart draggable/movable element [5]. If you are not familiar with basic DOM manipulation in Go, read the posts in GopherJS DOM Example series first.

Install GopherJS and DOM bindings

Run the following command to install GopherJS and GopherJS bindings for the JavaScript DOM APIs:

$ go get -u github.com/gopherjs/gopherjs
$ go get -u honnef.co/go/js/dom

Source Code

First we write a simple HTML for our demo:

index.html | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!doctype html>
<html>
<head>
  <title>Golang Draggable (Movable) Element</title>
</head>
<body>
  <div id="dragMe" style="width: 200px; height: 200px; background: yellow;">Drag Me</div>
<script src="demo.js"></script>
</body>
</html>

The basic idea is that we bind onmousedown event handler to the draggable element. In the onmousedown event handler, we bind onmousemove and onmouseup event handler to document object. In the onmousemove event handler, we calculate the movement and change the CSS property of the draggable element to make it move. In the onmouseup event handler, we remove the onmousemove and onmouseup event handler from document object.

draggable.go | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package main

import "github.com/gopherjs/gopherjs/js"
import "honnef.co/go/js/dom"
import "strconv"

func draggable(elm *dom.HTMLDivElement) {
	var startX, startY, initialMouseX, initialMouseY int
	var fmove, fup func(*js.Object)
	elm.Style().SetProperty("position", "absolute", "")
	d := dom.GetWindow().Document()

	mousemove := func(event dom.Event) {
		event.PreventDefault()
		e := event.(*dom.MouseEvent)
		dx := e.ClientX - initialMouseX
		dy := e.ClientY - initialMouseY
		elm.Style().SetProperty("top", strconv.Itoa(startY+dy)+"px", "")
		elm.Style().SetProperty("left", strconv.Itoa(startX+dx)+"px", "")
	}

	mouseup := func(event dom.Event) {
		d.RemoveEventListener("mousemove", false, fmove)
		d.RemoveEventListener("mouseup", false, fup)
	}

	elm.AddEventListener("mousedown", false, func(event dom.Event) {
		event.PreventDefault()
		e := event.(*dom.MouseEvent)
		startX = int(elm.OffsetLeft())
		startY = int(elm.OffsetTop())
		initialMouseX = e.ClientX
		initialMouseY = e.ClientY
		fmove = d.AddEventListener("mousemove", false, mousemove)
		fup = d.AddEventListener("mouseup", false, mouseup)
	})
}

func main() {
	draggable(dom.GetWindow().Document().GetElementByID("dragMe").(*dom.HTMLDivElement))
}

Compile the Go code to JavaScript by:

$ gopherjs build draggable.go -o demo.js

Put demo.js together with the index.html in the same directory. Open the index.html with your browser, and start to drag the element in the browser!


Tested on: Ubuntu Linux 15.10, Go 1.5.3.