Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(router): add link that support only absolute urls
- Loading branch information
Showing
2 changed files
with
131 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import {Tree, TreeNode, UrlSegment, RouteSegment, rootNode} from './segments'; | ||
import {isBlank, isString, isStringMap} from 'angular2/src/facade/lang'; | ||
import {ListWrapper} from 'angular2/src/facade/collection'; | ||
|
||
export function link(segment: RouteSegment, tree: Tree<UrlSegment>, | ||
change: any[]): Tree<UrlSegment> { | ||
if (change.length === 0) return tree; | ||
let normalizedChange = (change.length === 1 && change[0] == "/") ? change : ["/"].concat(change); | ||
return new Tree<UrlSegment>(_update(rootNode(tree), normalizedChange)); | ||
} | ||
|
||
function _update(node: TreeNode<UrlSegment>, changes: any[]): TreeNode<UrlSegment> { | ||
let rest = changes.slice(1); | ||
let outlet = _outlet(changes); | ||
let segment = _segment(changes); | ||
if (isString(segment) && segment[0] == "/") segment = segment.substring(1); | ||
|
||
// reach the end of the tree => create new tree nodes. | ||
if (isBlank(node)) { | ||
let urlSegment = new UrlSegment(segment, null, outlet); | ||
let children = rest.length === 0 ? [] : [_update(null, rest)]; | ||
return new TreeNode<UrlSegment>(urlSegment, children); | ||
|
||
// different outlet => preserve the subtree | ||
} else if (outlet != node.value.outlet) { | ||
return node; | ||
|
||
// same outlet => modify the subtree | ||
} else { | ||
let urlSegment = isStringMap(segment) ? new UrlSegment(null, segment, null) : | ||
new UrlSegment(segment, null, outlet); | ||
if (rest.length === 0) { | ||
return new TreeNode<UrlSegment>(urlSegment, []); | ||
} | ||
|
||
return new TreeNode<UrlSegment>(urlSegment, | ||
_updateMany(ListWrapper.clone(node.children), rest)); | ||
} | ||
} | ||
|
||
function _updateMany(nodes: TreeNode<UrlSegment>[], changes: any[]): TreeNode<UrlSegment>[] { | ||
let outlet = _outlet(changes); | ||
let nodesInRightOutlet = nodes.filter(c => c.value.outlet == outlet); | ||
if (nodesInRightOutlet.length > 0) { | ||
let nodeRightOutlet = nodesInRightOutlet[0]; // there can be only one | ||
nodes[nodes.indexOf(nodeRightOutlet)] = _update(nodeRightOutlet, changes); | ||
} else { | ||
nodes.push(_update(null, changes)); | ||
} | ||
|
||
return nodes; | ||
} | ||
|
||
function _segment(changes: any[]): any { | ||
if (!isString(changes[0])) return changes[0]; | ||
let parts = changes[0].toString().split(":"); | ||
return parts.length > 1 ? parts[1] : changes[0]; | ||
} | ||
|
||
function _outlet(changes: any[]): string { | ||
if (!isString(changes[0])) return null; | ||
let parts = changes[0].toString().split(":"); | ||
return parts.length > 1 ? parts[0] : null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { | ||
ComponentFixture, | ||
AsyncTestCompleter, | ||
TestComponentBuilder, | ||
beforeEach, | ||
ddescribe, | ||
xdescribe, | ||
describe, | ||
el, | ||
expect, | ||
iit, | ||
inject, | ||
beforeEachProviders, | ||
it, | ||
xit | ||
} from 'angular2/testing_internal'; | ||
|
||
import {RouteSegment, UrlSegment, Tree} from 'angular2/src/alt_router/segments'; | ||
import {link} from 'angular2/src/alt_router/link'; | ||
import {DefaultRouterUrlSerializer} from 'angular2/src/alt_router/router_url_serializer'; | ||
|
||
export function main() { | ||
describe('link', () => { | ||
let parser = new DefaultRouterUrlSerializer(); | ||
|
||
it("should return the original tree when given an empty array", () => { | ||
let p = parser.parse("/"); | ||
let t = link(s(p.root), p, []); | ||
expect(t).toBe(p); | ||
}); | ||
|
||
it("should support going to root", () => { | ||
let p = parser.parse("/"); | ||
let t = link(s(p.root), p, ["/"]); | ||
expect(parser.serialize(t)).toEqual(""); | ||
}); | ||
|
||
it("should support positional params", () => { | ||
let p = parser.parse("/"); | ||
let t = link(s(p.root), p, ["/one", 11, "two", 22]); | ||
expect(parser.serialize(t)).toEqual("/one/11/two/22"); | ||
}); | ||
|
||
it("should preserve route siblings when changing the main route", () => { | ||
let p = parser.parse("/a/11/b(c)"); | ||
let t = link(s(p.root), p, ["/a", 11, 'd']); | ||
expect(parser.serialize(t)).toEqual("/a/11/d(aux:c)"); | ||
}); | ||
|
||
it("should preserve route siblings when changing a aux route", () => { | ||
let p = parser.parse("/a/11/b(c)"); | ||
let t = link(s(p.root), p, ["/a", 11, 'aux:d']); | ||
expect(parser.serialize(t)).toEqual("/a/11/b(aux:d)"); | ||
}); | ||
|
||
|
||
it('should update parameters', () => { | ||
let p = parser.parse("/a;aa=11"); | ||
let t = link(s(p.root), p, ["/a", {aa: 22, bb: 33}]); | ||
expect(parser.serialize(t)).toEqual("/a;aa=22;bb=33"); | ||
}); | ||
}); | ||
} | ||
|
||
function s(u: UrlSegment): RouteSegment { | ||
return new RouteSegment([u], {}, null, null, null); | ||
} |