@@ -13,17 +13,48 @@ import (
13
13
"github.com/gopherjs/gopherjs/compiler"
14
14
"github.com/gopherjs/gopherjs/js"
15
15
"github.com/neelance/go-angularjs"
16
+ "honnef.co/go/js/dom"
17
+ "honnef.co/go/js/xhr"
16
18
)
17
19
18
20
type Line map [string ]string
19
21
20
22
var output []Line
21
23
24
+ const snippetStoreHost = "snippets.gotools.org"
25
+
22
26
func main () {
27
+ codeReady := make (chan struct {}) // Used to synchronize when "code" value is ready.
28
+
23
29
app := angularjs .NewModule ("playground" , nil , nil )
24
30
25
31
app .NewController ("PlaygroundCtrl" , func (scope * angularjs.Scope ) {
26
- scope .Set ("code" , "package main\n \n import (\n \t \" fmt\" \n \t \" github.com/gopherjs/gopherjs/js\" \n )\n \n func main() {\n \t fmt.Println(\" Hello, playground\" )\n \t js.Global.Call(\" alert\" , \" Hello, JavaScript\" )\n \t println(\" Hello, JS console\" )\n }\n " )
32
+ if strings .HasPrefix (dom .GetWindow ().Location ().Hash , "#/" ) {
33
+ id := dom .GetWindow ().Location ().Hash [2 :]
34
+
35
+ req := xhr .NewRequest ("GET" , "http://" + snippetStoreHost + "/p/" + id )
36
+ req .ResponseType = xhr .ArrayBuffer
37
+ go func () {
38
+ err := req .Send (nil )
39
+ if err != nil || req .Status != 200 {
40
+ scope .Apply (func () {
41
+ scope .Set ("output" , []Line {Line {"type" : "err" , "content" : `failed to load snippet "` + id + `"` }})
42
+ })
43
+ return
44
+ }
45
+
46
+ data := js .Global .Get ("Uint8Array" ).New (req .Response ).Interface ().([]byte )
47
+ scope .Apply (func () {
48
+ scope .Set ("code" , string (data ))
49
+ close (codeReady )
50
+ })
51
+ }()
52
+ } else {
53
+ scope .Set ("code" , "package main\n \n import (\n \t \" fmt\" \n \t \" github.com/gopherjs/gopherjs/js\" \n )\n \n func main() {\n \t fmt.Println(\" Hello, playground\" )\n \t js.Global.Call(\" alert\" , \" Hello, JavaScript\" )\n \t println(\" Hello, JS console\" )\n }\n " )
54
+ close (codeReady )
55
+ }
56
+ scope .Set ("shareUrl" , "" )
57
+ scope .Set ("showShareUrl" , false )
27
58
scope .Set ("showGenerated" , false )
28
59
scope .Set ("generated" , `(generated code will be shown here after clicking "Run")` )
29
60
@@ -42,6 +73,10 @@ func main() {
42
73
setupEnvironment (scope )
43
74
44
75
codeArea := angularjs .ElementById ("code" )
76
+ codeArea .On ("input" , func (e * angularjs.Event ) {
77
+ scope .Set ("showShareUrl" , false )
78
+ dom .GetWindow ().Location ().Hash = ""
79
+ })
45
80
codeArea .On ("keydown" , func (e * angularjs.Event ) {
46
81
toInsert := ""
47
82
switch e .KeyCode {
@@ -62,6 +97,9 @@ func main() {
62
97
}
63
98
}
64
99
if toInsert != "" {
100
+ scope .Set ("showShareUrl" , false )
101
+ dom .GetWindow ().Location ().Hash = ""
102
+
65
103
start := codeArea .Prop ("selectionStart" ).Int ()
66
104
end := codeArea .Prop ("selectionEnd" ).Int ()
67
105
code := scope .Get ("code" ).Str ()
@@ -118,18 +156,18 @@ func main() {
118
156
for _ , p := range pkgsToLoad {
119
157
path := p
120
158
121
- req := js . Global . Get ( "XMLHttpRequest" ). New ( )
122
- req .Call ( "open" , "GET" , "pkg/" + path + ".a.js" , true )
123
- req . Set ( "responseType" , "arraybuffer" )
124
- req .Set ( "onload" , func () {
125
- if req .Get ( "status" ). Int () != 200 {
159
+ req := xhr . NewRequest ( "GET" , "pkg/" + path + ".a.js" )
160
+ req .ResponseType = xhr . ArrayBuffer
161
+ go func () {
162
+ err := req .Send ( nil )
163
+ if err != nil || req .Status != 200 {
126
164
scope .Apply (func () {
127
- scope .Set ("output" , []Line {Line {"type" : "err" , "content" : `cannot load package "` + path + `"` }})
165
+ scope .Set ("output" , []Line {Line {"type" : "err" , "content" : `failed to load package "` + path + `"` }})
128
166
})
129
167
return
130
168
}
131
169
132
- data := js .Global .Get ("Uint8Array" ).New (req .Get ( "response" ) ).Interface ().([]byte )
170
+ data := js .Global .Get ("Uint8Array" ).New (req .Response ).Interface ().([]byte )
133
171
packages [path ], err = compiler .ReadArchive (path + ".a" , path , bytes .NewReader (data ), importContext .Packages )
134
172
if err != nil {
135
173
scope .Apply (func () {
@@ -141,8 +179,7 @@ func main() {
141
179
if pkgsReceived == len (pkgsToLoad ) {
142
180
run (loadOnly )
143
181
}
144
- })
145
- req .Call ("send" )
182
+ }()
146
183
}
147
184
return
148
185
}
@@ -163,7 +200,10 @@ func main() {
163
200
js .Global .Call ("eval" , js .InternalObject (jsCode .String ()))
164
201
}
165
202
scope .Set ("run" , run )
166
- run (true )
203
+ go func () {
204
+ <- codeReady // Wait for "code" value to be ready.
205
+ run (true )
206
+ }()
167
207
168
208
scope .Set ("format" , func () {
169
209
out , err := format .Source ([]byte (scope .Get ("code" ).Str ()))
@@ -174,6 +214,37 @@ func main() {
174
214
scope .Set ("code" , string (out ))
175
215
scope .Set ("output" , []Line {})
176
216
})
217
+
218
+ scope .Set ("share" , func () {
219
+ req := xhr .NewRequest ("POST" , "http://" + snippetStoreHost + "/share" )
220
+ req .ResponseType = xhr .ArrayBuffer
221
+ go func () {
222
+ // TODO: Send as binary?
223
+ err := req .Send (scope .Get ("code" ).Str ())
224
+ if err != nil || req .Status != 200 {
225
+ scope .Apply (func () {
226
+ scope .Set ("output" , []Line {Line {"type" : "err" , "content" : `failed to share snippet` }})
227
+ })
228
+ return
229
+ }
230
+
231
+ data := js .Global .Get ("Uint8Array" ).New (req .Response ).Interface ().([]byte )
232
+ scope .Apply (func () {
233
+ id := string (data )
234
+
235
+ dom .GetWindow ().Location ().Hash = "#/" + id
236
+
237
+ scope .Set ("shareUrl" , dom .GetWindow ().Location ().Str ())
238
+ scope .Set ("showShareUrl" , true )
239
+ // TODO: Do this better using AngularJS.
240
+ // Perhaps using http://stackoverflow.com/questions/14833326/how-to-set-focus-on-input-field/18295416.
241
+ go func () {
242
+ time .Sleep (time .Millisecond )
243
+ dom .GetWindow ().Document ().GetElementByID ("share-url" ).(* dom.HTMLInputElement ).Select ()
244
+ }()
245
+ })
246
+ }()
247
+ })
177
248
})
178
249
}
179
250
0 commit comments