OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of app; | 5 part of app; |
6 | 6 |
7 abstract class LocationManager extends Observable { | 7 class LocationManager extends Observable { |
8 final _initialPath = '/vm'; | 8 final _defaultPath = '/vm'; |
9 ObservatoryApplication _app; | 9 final ObservatoryApplication _app; |
10 /// [internalArguments] are parameters specified after a '---' in the | |
11 /// application URL. | |
12 final Map<String, String> internalArguments = new Map<String, String>(); | |
13 Uri _uri; | |
14 /// [uri] is the application uri. Application uris consist of a path and | |
15 /// the queryParameters map. | |
16 Uri get uri => _uri; | |
turnidge
2015/04/16 17:23:44
Maybe some blank lines between decls?
Cutch
2015/04/22 14:05:09
Done.
| |
10 | 17 |
11 String _lastUrl; | 18 LocationManager(this._app) { |
12 | 19 window.onPopState.listen(_onBrowserNavigation); |
13 void _init(ObservatoryApplication app) { | 20 // Determine initial application path. |
14 // Called once. | 21 var applicationPath = '${window.location.hash}'; |
15 assert(_app == null); | 22 if ((window.location.hash == '') || (window.location.hash == '#')) { |
16 _app = app; | 23 // Observatory has loaded but no application path has been specified, |
17 // Register for history events. | 24 // use the default. |
18 window.onPopState.listen(_onLocationChange); | 25 applicationPath = makeLink(_defaultPath); |
19 _onStartup(); | 26 } |
27 // Update current application path. | |
28 window.history.replaceState(applicationPath, | |
29 document.title, | |
30 applicationPath); | |
31 _updateApplicationLocation(applicationPath); | |
20 } | 32 } |
21 | 33 |
22 void _onStartup(); | 34 /// Called whenever the browser changes the location bar (e.g. forward or |
23 void _onLocationChange(PopStateEvent event); | 35 /// back button press). |
24 | 36 void _onBrowserNavigation(PopStateEvent event) { |
25 void _pushUrl(String url) { | 37 _updateApplicationLocation(window.location.hash); |
26 if (_lastUrl != url) { | 38 _visit(); |
27 Logger.root.info('Navigated to ${url}'); | |
28 window.history.pushState(url, document.title, url); | |
29 _lastUrl = url; | |
30 } | |
31 } | 39 } |
32 | 40 |
33 /// Go to a specific url. | 41 /// Given an application url, generate an href link. |
34 void go(String url) { | 42 String makeLink(String url) => '#$url'; |
35 if ((url != makeLink('/vm-connect/')) && _app.vm == null) { | |
36 if (!window.confirm('Connection with VM has been lost. ' | |
37 'Proceeding will lose current page.')) { | |
38 return; | |
39 } | |
40 url = makeLink('/vm-connect/'); | |
41 } | |
42 _pushUrl(url); | |
43 _go(url); | |
44 } | |
45 | 43 |
46 void _go(String url) { | 44 /// Update the application location. After this function returns, |
45 /// [uri] and [debugArguments] will be updated. | |
46 _updateApplicationLocation(String url) { | |
47 // Chop off leading '#'. | 47 // Chop off leading '#'. |
48 if (url.startsWith('#')) { | 48 if (url.startsWith('#')) { |
49 url = url.substring(1); | 49 url = url.substring(1); |
50 } | 50 } |
51 // Fall through handles '#/' | 51 // Fall through handles '#/' |
52 // Chop off leading '/'. | 52 // Chop off leading '/'. |
53 if (url.startsWith('/')) { | 53 if (url.startsWith('/')) { |
54 url = url.substring(1); | 54 url = url.substring(1); |
55 } | 55 } |
56 var args; | 56 // Parse out debug arguments. |
57 // Parse out arguments. | |
58 if (url.contains('---')) { | 57 if (url.contains('---')) { |
59 var chunks = url.split('---'); | 58 var chunks = url.split('---'); |
60 url = chunks[0]; | 59 url = chunks[0]; |
61 if ((chunks.length > 1) && (chunks[1] != '')) { | 60 if ((chunks.length > 1) && (chunks[1] != '')) { |
62 args = chunks[1]; | 61 internalArguments.clear(); |
62 try { | |
63 internalArguments.addAll(Uri.splitQueryString(chunks[1])); | |
64 } catch (e) { | |
65 Logger.root.warning('Could not parse debug arguments ${e}'); | |
66 } | |
63 } | 67 } |
64 } | 68 } |
65 _app._visit(url, args); | 69 _uri = Uri.parse(url); |
66 } | 70 } |
67 | 71 |
68 /// Go back. | 72 /// Add [url] to the browser history. |
69 void back() { | 73 _addToBrowserHistory(String url) { |
70 window.history.go(-1); | 74 window.history.pushState(url, document.title, url); |
71 } | 75 } |
72 | 76 |
73 /// Go forward. | 77 /// Notify the current page that something has changed. |
74 void forward() { | 78 _visit() { |
75 window.history.go(1); | 79 _app._visit(_uri, internalArguments); |
76 } | 80 } |
77 | 81 |
78 /// Handle clicking on an application url link. | 82 /// Navigate to [url]. |
83 void go(String url, [bool addToBrowserHistory = true]) { | |
84 if ((url != makeLink('/vm-connect/')) && _app.vm == null) { | |
85 if (!window.confirm('Connection with VM has been lost. ' | |
86 'Proceeding will lose current page.')) { | |
87 return; | |
88 } | |
89 url = makeLink('/vm-connect/'); | |
90 } | |
91 if (addToBrowserHistory) { | |
92 _addToBrowserHistory(url); | |
93 } | |
94 _updateApplicationLocation(url); | |
95 _visit(); | |
96 } | |
97 | |
98 /// Starting with the current uri path and queryParameters, update | |
99 /// queryParameters present in [updateParameters], then generate a new uri | |
100 /// and navigate to that. | |
101 goParameter(Map updatedParameters, [bool addToBrowserHistory = true]) { | |
102 var parameters = new Map.from(_uri.queryParameters); | |
103 updatedParameters.forEach((k, v) { | |
104 parameters[k] = v; | |
105 }); | |
106 // Ensure path starts with a slash. | |
107 var path = uri.path.startsWith('/') ? uri.path : '/${uri.path}'; | |
108 var generatedUri = new Uri(path: path, queryParameters: parameters); | |
109 go(makeLink(generatedUri.toString()), addToBrowserHistory); | |
110 } | |
111 | |
112 /// Utility event handler when clicking on application url link. | |
79 void onGoto(MouseEvent event) { | 113 void onGoto(MouseEvent event) { |
80 var target = event.target; | 114 if ((event.button > 0) || |
81 var href = target.attributes['href']; | 115 event.metaKey || |
82 if (event.button > 0 || event.metaKey || event.ctrlKey || | 116 event.ctrlKey || |
83 event.shiftKey || event.altKey) { | 117 event.shiftKey || |
84 // Not a left-click or a left-click with a modifier key: | 118 event.altKey) { |
85 // Let browser handle. | 119 // Mouse event is not a left-click OR |
120 // mouse event is a left-click with a modifier key: | |
121 // let browser handle. | |
86 return; | 122 return; |
87 } | 123 } |
88 go(href); | |
89 event.preventDefault(); | 124 event.preventDefault(); |
90 } | 125 var target = event.target; |
91 | 126 go(target.attributes['href']); |
92 /// Given an application url, generate a link. | |
93 String makeLink(String url); | |
94 } | |
95 | |
96 /// Uses location.hash to encode application urls. | |
97 class HashLocationManager extends LocationManager { | |
98 void _onStartup() { | |
99 String initialPath = '${window.location.hash}'; | |
100 if ((window.location.hash == '') || (window.location.hash == '#')) { | |
101 initialPath = '#${_initialPath}'; | |
102 } | |
103 window.history.pushState(initialPath, document.title, initialPath); | |
104 _go(window.location.hash); | |
105 } | |
106 | |
107 void _onLocationChange(PopStateEvent _) { | |
108 _go(window.location.hash); | |
109 } | |
110 | |
111 /// Given an application url, generate a link for an anchor tag. | |
112 String makeLink(String url) { | |
113 return '#$url'; | |
114 } | 127 } |
115 } | 128 } |
116 | |
117 /// Uses location.pathname to encode application urls. Requires server side | |
118 /// rewriting to support copy and paste linking. pub serve makes this hard. | |
119 /// STATUS: Work in progress. | |
120 class LinkLocationManager extends LocationManager { | |
121 void _onStartup() { | |
122 Logger.root.warning('Using untested LinkLocationManager'); | |
123 String initialPath = window.location.pathname; | |
124 if ((window.location.pathname == '/index.html') || | |
125 (window.location.pathname == '/')) { | |
126 initialPath = '/vm'; | |
127 } | |
128 window.history.replaceState(initialPath, document.title, initialPath); | |
129 _go(window.location.pathname); | |
130 } | |
131 | |
132 void _onLocationChange(PopStateEvent _) { | |
133 _go(window.location.pathname); | |
134 } | |
135 | |
136 /// Given an application url, generate a link for an anchor tag. | |
137 String makeLink(String url) => url; | |
138 } | |
OLD | NEW |