This commit is contained in:
thosakwe 2017-03-20 15:46:54 -04:00
parent 45d41c6dac
commit a6835bb900
6 changed files with 72 additions and 31 deletions

View file

@ -1,6 +1,6 @@
# angel_route # angel_route
![version 1.0.2](https://img.shields.io/badge/version-1.0.2-brightgreen.svg) ![version 1.0.3](https://img.shields.io/badge/version-1.0.3-brightgreen.svg)
![build status](https://travis-ci.org/angel-dart/route.svg) ![build status](https://travis-ci.org/angel-dart/route.svg)
A powerful, isomorphic routing library for Dart. A powerful, isomorphic routing library for Dart.
@ -131,6 +131,8 @@ main() {
throw 404; throw 404;
else route.state['foo'] = 'bar'; else route.state['foo'] = 'bar';
}); });
router.listen(); // Start listening
} }
``` ```

View file

@ -1,8 +1,10 @@
import 'dart:async' show Stream, StreamController; import 'dart:async' show Stream, StreamController;
import 'dart:html' show AnchorElement, window; import 'dart:html';
import 'angel_route.dart'; import 'angel_route.dart';
import 'package:path/path.dart' as p;
final RegExp _hash = new RegExp(r'^#/'); final RegExp _hash = new RegExp(r'^#/');
final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
/// A variation of the [Router] support both hash routing and push state. /// A variation of the [Router] support both hash routing and push state.
abstract class BrowserRouter extends Router { abstract class BrowserRouter extends Router {
@ -14,7 +16,7 @@ abstract class BrowserRouter extends Router {
/// Set `hash` to true to use hash routing instead of push state. /// Set `hash` to true to use hash routing instead of push state.
/// `listen` as `true` will call `listen` after initialization. /// `listen` as `true` will call `listen` after initialization.
factory BrowserRouter({bool hash: false, bool listen: true}) { factory BrowserRouter({bool hash: false, bool listen: false}) {
return hash return hash
? new _HashRouter(listen: listen) ? new _HashRouter(listen: listen)
: new _PushStateRouter(listen: listen); : new _PushStateRouter(listen: listen);
@ -30,6 +32,9 @@ abstract class BrowserRouter extends Router {
/// This always navigates to an absolute path. /// This always navigates to an absolute path.
void go(List linkParams); void go(List linkParams);
// Handles a route path, manually.
// void handle(String path);
/// Begins listen for location changes. /// Begins listen for location changes.
void listen(); void listen();
@ -88,8 +93,6 @@ class _HashRouter extends _BrowserRouterImpl {
window.location.hash = '#$uri'; window.location.hash = '#$uri';
} }
@override
void listen() {
void handleHash([_]) { void handleHash([_]) {
final path = window.location.hash.replaceAll(_hash, ''); final path = window.location.hash.replaceAll(_hash, '');
final resolved = resolveAbsolute(path); final resolved = resolveAbsolute(path);
@ -103,19 +106,46 @@ class _HashRouter extends _BrowserRouterImpl {
} }
} }
void handlePath(String path) {
final resolved = resolveAbsolute(path);
if (resolved == null) {
_onResolve.add(null);
_onRoute.add(_current = null);
} else if (resolved != null && resolved.route != _current) {
_onResolve.add(resolved);
_onRoute.add(_current = resolved.route);
}
}
@override
void listen() {
window.onHashChange.listen(handleHash); window.onHashChange.listen(handleHash);
handleHash(); handleHash();
} }
} }
class _PushStateRouter extends _BrowserRouterImpl { class _PushStateRouter extends _BrowserRouterImpl {
String _basePath;
_PushStateRouter({bool listen, Route root}) : super(listen: listen) { _PushStateRouter({bool listen, Route root}) : super(listen: listen) {
var $base = window.document.querySelector('base[href]') as BaseElement;
if ($base?.href?.isNotEmpty != true)
throw new StateError(
'You must have a <base href="<base-url-here>"> element present in your document to run the push state router.');
_basePath = $base.href.replaceAll(_straySlashes, '');
if (listen) this.listen(); if (listen) this.listen();
} }
@override @override
void _goTo(String uri) { void _goTo(String uri) {
final resolved = resolveAbsolute(uri); final resolved = resolveAbsolute(uri);
var relativeUri = uri;
if (_basePath?.isNotEmpty == true) {
relativeUri = p.join(_basePath, uri.replaceAll(_straySlashes, ''));
}
if (resolved == null) { if (resolved == null) {
_onResolve.add(null); _onResolve.add(null);
@ -125,23 +155,25 @@ class _PushStateRouter extends _BrowserRouterImpl {
window.history.pushState( window.history.pushState(
{'path': route.path, 'params': {}, 'properties': properties}, {'path': route.path, 'params': {}, 'properties': properties},
route.name ?? route.path, route.name ?? route.path,
uri); relativeUri);
_onResolve.add(resolved); _onResolve.add(resolved);
_onRoute.add(_current = route); _onRoute.add(_current = route);
} }
} }
@override
void listen() {
void handleState(state) { void handleState(state) {
if (state is Map && state.containsKey('path')) { if (state is Map && state.containsKey('path')) {
final resolved = resolveAbsolute(state['path']); var path = state['path'];
final resolved = resolveAbsolute(path);
if (resolved != null && resolved.route != _current) { if (resolved != null && resolved.route != _current) {
properties.addAll(state['properties'] ?? {}); properties.addAll(state['properties'] ?? {});
_onResolve.add(resolved); _onResolve.add(resolved);
_onRoute.add(_current = resolved.route _onRoute.add(_current = resolved.route
..state.properties.addAll(state['params'] ?? {})); ..state.properties.addAll(state['params'] ?? {}));
} else {
_onResolve.add(null);
_onRoute.add(_current = null);
} }
} else { } else {
_onResolve.add(null); _onResolve.add(null);
@ -149,6 +181,8 @@ class _PushStateRouter extends _BrowserRouterImpl {
} }
} }
@override
void listen() {
window.onPopState.listen((e) { window.onPopState.listen((e) {
handleState(e.state); handleState(e.state);
}); });

View file

@ -1,6 +1,6 @@
name: angel_route name: angel_route
description: A powerful, isomorphic routing library for Dart. description: A powerful, isomorphic routing library for Dart.
version: 1.0.2 version: 1.0.3
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_route homepage: https://github.com/angel-dart/angel_route
dev_dependencies: dev_dependencies:

2
repubspec.yaml Normal file
View file

@ -0,0 +1,2 @@
push_state:
base: push_state/basic.html

View file

@ -1,6 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<base href="/push_state">
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" <meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
@ -25,7 +26,7 @@
<ul id="handlers"> <ul id="handlers">
<li>(empty)</li> <li>(empty)</li>
</ul> </ul>
<script src="basic.dart" type="application/dart"></script> <script src="/push_state/basic.dart" type="application/dart"></script>
<script src="packages/browser/dart.js"></script> <script src="packages/browser/dart.js"></script>
</body> </body>
</html> </html>

View file

@ -31,5 +31,7 @@ basic(BrowserRouter router) {
router.get('c', 'c handler'); router.get('c', 'c handler');
router.dumpTree(); router
..dumpTree()
..listen();
} }