From 9545dc88552c6dc3132a3454a6490c68fb73802a Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Sat, 10 Jan 2015 14:50:21 -0800 Subject: [PATCH] Reload snippet on hash change. Due to the way browsers work, if the user manually edits the URL to change the hash to another snippet ID and presses enter, the first time it will cause a hash change event (typically scrolls page to the matching anchor, without reloading page). Second time the user presses enter, since the hash has not changed, it will instead reload the page, and in our case reload the snippet. Therefore, before this PR, if the user manually edits the URL in browser to another snippet ID, first time it did not actually load it. After this PR, it will always try to load the snippet whose ID is in the URL box. I think this leads to a better user experience as it eliminates a possible confusing behavior. It's also more efficient than reloading entire page, since that is not necessary. --- playground/playground.go | 26 ++++++++++++++++++++++++++ playground/playground.js | 27 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/playground/playground.go b/playground/playground.go index e9c0dd21..321927fe 100644 --- a/playground/playground.go +++ b/playground/playground.go @@ -247,6 +247,32 @@ func main() { }) }() }) + + // Start watching for hashchange events, and reload snippet if it happens. + dom.GetWindow().Top().AddEventListener("hashchange", false, func(event dom.Event) { + event.PreventDefault() + + if strings.HasPrefix(location.Hash, "#/") { + id := location.Hash[2:] + + req := xhr.NewRequest("GET", "https://"+snippetStoreHost+"/p/"+id) + req.ResponseType = xhr.ArrayBuffer + go func() { + err := req.Send(nil) + if err != nil || req.Status != 200 { + scope.Apply(func() { + scope.Set("output", []Line{Line{"type": "err", "content": `failed to load snippet "` + id + `"`}}) + }) + return + } + + data := js.Global.Get("Uint8Array").New(req.Response).Interface().([]byte) + scope.Apply(func() { + scope.Set("code", string(data)) + }) + }() + } + }) }) } diff --git a/playground/playground.js b/playground/playground.js index 34fdb4db..4f154306 100644 --- a/playground/playground.js +++ b/playground/playground.js @@ -64848,6 +64848,33 @@ $packages["main"] = (function() { /* */ case -1: } return; } }; $f.$blocking = true; return $f; }), []); }), funcType$1); + dom.GetWindow().Top().AddEventListener("hashchange", false, (function(event) { + var id$1, req$1; + event.PreventDefault(); + if (strings.HasPrefix($internalize(location.URLUtils.Object.hash, $String), "#/")) { + id$1 = $internalize(location.URLUtils.Object.hash, $String).substring(2); + req$1 = xhr.NewRequest("GET", "http://snippets.gotools.org/p/" + id$1); + req$1.Object.responseType = $externalize("arraybuffer", $String); + $go((function($b) { + var $this = this, $args = arguments, $r, $s = 0, _r, err, data; + /* */ if($b !== $BLOCKING) { $nonblockingCall(); }; var $f = function() { s: while (true) { switch ($s) { case 0: + _r = req$1.Send($ifaceNil, $BLOCKING); /* */ $s = 1; case 1: if (_r && _r.$blocking) { _r = _r(); } + err = _r; + if (!($interfaceIsEqual(err, $ifaceNil)) || !((($parseInt(req$1.Object.status) >> 0) === 200))) { + scope.Apply((function() { + var _map, _key; + scope.Object.output = $externalize(new sliceType([(_map = new $Map(), _key = "type", _map[_key] = { k: _key, v: "err" }, _key = "content", _map[_key] = { k: _key, v: "failed to load snippet \"" + id$1 + "\"" }, _map)]), sliceType); + })); + return; + } + data = $assertType($internalize(new ($global.Uint8Array)(req$1.Object.response), $emptyInterface), sliceType$2); + scope.Apply((function() { + scope.Object.code = $externalize($bytesToString(data), $String); + })); + /* */ case -1: } return; } }; $f.$blocking = true; return $f; + }), []); + } + })); })); }; setupEnvironment = function(scope) {