Chromium Code Reviews| 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 /// Utility class to decode and encode the fragment (starts with '#') portion |
| 8 final _initialPath = '/vm'; | 8 /// of a url, including any query parameters. |
| 9 class FragmentUri { | |
|
turnidge
2015/04/07 21:24:31
Do we need to introduce this class? What if we ju
Cutch
2015/04/14 21:45:15
I've redone this part of the CL.
| |
| 10 String _path; | |
| 11 String get path => _path; | |
| 12 final Map<String, String> parameters = new Map<String, String>(); | |
| 13 | |
| 14 FragmentUri(String url) { | |
| 15 // Chop off leading '#'. | |
| 16 if (url.startsWith('#')) { | |
| 17 url = url.substring(1); | |
| 18 } | |
| 19 var queryStringIndex = url.indexOf('?'); | |
| 20 if (queryStringIndex == -1) { | |
| 21 _path = url; | |
| 22 } else { | |
| 23 _path = url.substring(0, queryStringIndex); | |
| 24 parameters.addAll( | |
| 25 Uri.splitQueryString(url.substring(queryStringIndex + 1))); | |
| 26 } | |
| 27 } | |
| 28 | |
| 29 FragmentUri.from(FragmentUri other) { | |
| 30 _path = other._path; | |
| 31 parameters.addAll(other.parameters); | |
| 32 } | |
| 33 | |
| 34 String toString() { | |
| 35 if (parameters.isEmpty) { | |
| 36 return '#$_path'; | |
| 37 } | |
| 38 var encodedParameters = new Uri(queryParameters: parameters).query; | |
| 39 return '#${_path}?${encodedParameters}'; | |
| 40 } | |
| 41 } | |
| 42 | |
| 43 class LocationManager extends Observable { | |
| 44 final _defaultPath = '/vm'; | |
| 9 ObservatoryApplication _app; | 45 ObservatoryApplication _app; |
| 10 | 46 FragmentUri _fragment; |
| 11 String _lastUrl; | 47 FragmentUri get fragment => _fragment; |
| 48 String _url; | |
| 12 | 49 |
| 13 void _init(ObservatoryApplication app) { | 50 void _init(ObservatoryApplication app) { |
| 14 // Called once. | 51 // Called once. |
| 15 assert(_app == null); | 52 assert(_app == null); |
| 16 _app = app; | 53 _app = app; |
| 17 // Register for history events. | 54 // Register for history events. |
| 18 window.onPopState.listen(_onLocationChange); | 55 window.onPopState.listen(_onLocationChange); |
| 19 _onStartup(); | 56 |
| 57 var applicationPath = '${window.location.hash}'; | |
| 58 if ((window.location.hash == '') || (window.location.hash == '#')) { | |
| 59 // Observatory has loaded but no application path has been specified, | |
| 60 // use the default. | |
| 61 applicationPath = '#${_defaultPath}'; | |
| 62 } | |
| 63 // Update current application path. | |
| 64 window.history.replaceState(applicationPath, | |
| 65 document.title, | |
| 66 applicationPath); | |
| 67 _updateCurrent(applicationPath); | |
| 68 _go(applicationPath); | |
| 20 } | 69 } |
| 21 | 70 |
| 22 void _onStartup(); | 71 void _updateCurrent(String url) { |
| 23 void _onLocationChange(PopStateEvent event); | 72 _url = url; |
| 73 _fragment = new FragmentUri(url); | |
| 74 } | |
| 24 | 75 |
| 25 void _pushUrl(String url) { | 76 void _pushUrl(String url) { |
| 26 if (_lastUrl != url) { | 77 if (_url != url) { |
| 27 Logger.root.info('Navigated to ${url}'); | 78 Logger.root.info('Navigated to ${url}'); |
| 28 window.history.pushState(url, document.title, url); | 79 window.history.pushState(url, document.title, url); |
| 29 _lastUrl = url; | 80 _updateCurrent(url); |
| 30 } | 81 } |
| 31 } | 82 } |
| 32 | 83 |
| 33 /// Go to a specific url. | |
| 34 void go(String 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 | |
| 46 void _go(String url) { | 84 void _go(String url) { |
| 47 // Chop off leading '#'. | 85 // Chop off leading '#'. |
| 48 if (url.startsWith('#')) { | 86 if (url.startsWith('#')) { |
| 49 url = url.substring(1); | 87 url = url.substring(1); |
| 50 } | 88 } |
| 51 // Fall through handles '#/' | 89 // Fall through handles '#/' |
| 52 // Chop off leading '/'. | 90 // Chop off leading '/'. |
| 53 if (url.startsWith('/')) { | 91 if (url.startsWith('/')) { |
| 54 url = url.substring(1); | 92 url = url.substring(1); |
| 55 } | 93 } |
| 56 var args; | 94 var args; |
| 57 // Parse out arguments. | 95 // Parse out arguments. |
| 58 if (url.contains('---')) { | 96 if (url.contains('---')) { |
| 59 var chunks = url.split('---'); | 97 var chunks = url.split('---'); |
| 60 url = chunks[0]; | 98 url = chunks[0]; |
| 61 if ((chunks.length > 1) && (chunks[1] != '')) { | 99 if ((chunks.length > 1) && (chunks[1] != '')) { |
| 62 args = chunks[1]; | 100 args = chunks[1]; |
| 63 } | 101 } |
| 64 } | 102 } |
| 65 _app._visit(url, args); | 103 _app._visit(url, args); |
| 66 } | 104 } |
| 67 | 105 |
| 68 /// Go back. | 106 /// Go to a specific url. |
| 69 void back() { | 107 void go(String url) { |
| 70 window.history.go(-1); | 108 if ((url != makeLink('/vm-connect/')) && _app.vm == null) { |
| 109 if (!window.confirm('Connection with VM has been lost. ' | |
| 110 'Proceeding will lose current page.')) { | |
| 111 return; | |
| 112 } | |
| 113 url = makeLink('/vm-connect/'); | |
| 114 } | |
| 115 _pushUrl(url); | |
| 116 _go(url); | |
| 71 } | 117 } |
| 72 | 118 |
| 73 /// Go forward. | 119 /// Starting with the current url, update all parameters present in |
| 74 void forward() { | 120 /// [updatedParameters], then generate a new url and navigate to that. |
| 75 window.history.go(1); | 121 goParameter(Map updatedParameters) { |
| 122 var fragment = new FragmentUri.from(_fragment); | |
| 123 updatedParameters.forEach((k, v) { | |
| 124 fragment.parameters[k] = v; | |
| 125 }); | |
| 126 go(fragment.toString()); | |
| 76 } | 127 } |
| 77 | 128 |
| 78 /// Handle clicking on an application url link. | 129 /// Handle clicking on an application url link. |
| 79 void onGoto(MouseEvent event) { | 130 void onGoto(MouseEvent event) { |
| 80 var target = event.target; | 131 var target = event.target; |
| 81 var href = target.attributes['href']; | 132 var href = target.attributes['href']; |
| 82 if (event.button > 0 || event.metaKey || event.ctrlKey || | 133 if (event.button > 0 || event.metaKey || event.ctrlKey || |
| 83 event.shiftKey || event.altKey) { | 134 event.shiftKey || event.altKey) { |
| 84 // Not a left-click or a left-click with a modifier key: | 135 // Not a left-click or a left-click with a modifier key: |
| 85 // Let browser handle. | 136 // Let browser handle. |
| 86 return; | 137 return; |
| 87 } | 138 } |
| 88 go(href); | 139 go(href); |
| 89 event.preventDefault(); | 140 event.preventDefault(); |
| 90 } | 141 } |
| 91 | 142 |
| 92 /// Given an application url, generate a link. | 143 /// Called whenever the browser changes the location bar (e.g. back button). |
| 93 String makeLink(String url); | 144 void _onLocationChange(PopStateEvent event) { |
| 94 } | 145 _updateCurrent(window.location.hash); |
| 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); | 146 _go(window.location.hash); |
| 105 } | 147 } |
| 106 | 148 |
| 107 void _onLocationChange(PopStateEvent _) { | 149 /// Given an application url, generate a link. |
| 108 _go(window.location.hash); | 150 String makeLink(String url) => '#$url'; |
| 109 } | |
| 110 | |
| 111 /// Given an application url, generate a link for an anchor tag. | |
| 112 String makeLink(String url) { | |
| 113 return '#$url'; | |
| 114 } | |
| 115 } | 151 } |
| 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 |