[Golang] GopherJS DOM Example - Dropdown Menu


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 a simple example of DOM manipulation in Go program. This example shows how to write a dropdown menu. This example is ported from the Dart dropdown menu [5] and JavaScript dropdown menu [6]. 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 and CSS for our demo:

index.html | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<!doctype html>
<html>
<head>
  <title>Golang Dropdown Menu by GopherJS</title>
  <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
  <div id="menu-dropdown">Menu&#9660;</div>
  <div id="menuDiv-dropdown" class="invisible">
    line1<br>line2<br>line3
  </div>


<script src="demo.js"></script>
</body>
</html>
style.css | repository | view raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#menu-dropdown {
  font-size: 3em;
  color: blue;
}

#menu-dropdown:hover {
  cursor: pointer;
}

#menuDiv-dropdown {
  font-size: 3em;
  position: absolute;
  border: 1px solid blue;
}

.invisible {
  display: none;
}

We will bind a onclick event handler to the HTML DOM document object. When users click inside the browser, we will check which DOM element is clicked. According to the clicked element and visibility of the dropdown menu, the dropdown menu will show up or disappear.

dropdown.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
package main

import "honnef.co/go/js/dom"

func checkParent(target, elm dom.Element) bool {
	for target.ParentElement() != nil {
		if target.IsEqualNode(elm) {
			return true
		}
		target = target.ParentElement()
	}
	return false
}

func main() {
	d := dom.GetWindow().Document()

	toggle := d.GetElementByID("menu-dropdown").(*dom.HTMLDivElement)
	menu := d.GetElementByID("menuDiv-dropdown").(*dom.HTMLDivElement)

	d.AddEventListener("click", false, func(event dom.Event) {
		if !checkParent(event.Target(), menu) {
			// click NOT on the menu
			if checkParent(event.Target(), toggle) {
				// click on the link
				menu.Class().Toggle("invisible")
			} else {
				// click both outside link and outside menu, hide menu
				menu.Class().Add("invisible")
			}
		}
	})
}

Compile the Go code to JavaScript by:

$ gopherjs build dropdown.go -o demo.js

Put demo.js together with the index.html and style.css in the same directory. Open the index.html with your browser. Click on the Menu text to toggle the visibility of the menu. Also try to click outside the dropdown menu, the dropdown menu will disappear.


Tested on: Ubuntu Linux 15.10, Go 1.5.3.