Skip to content

Commit

Permalink
feat(router): add configuration for use browser fragment hash
Browse files Browse the repository at this point in the history
  • Loading branch information
jwx committed Aug 25, 2019
1 parent 5ac5891 commit 4b2f0c1
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 35 deletions.
34 changes: 19 additions & 15 deletions packages/__tests__/router/browser-navigator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe('BrowserNavigator', function () {
it('can be activated', async function () {
const { sut, tearDown, callback } = setup();

await sut.activate(callback);
await sut.activate({ callback });

assert.strictEqual(sut['isActive'], true, `sut.isActive`);
// assert.strictEqual(addEventListener.calls.length, 1, `addEventListener.calls.length`);
Expand All @@ -82,7 +82,7 @@ describe('BrowserNavigator', function () {
it('can be deactivated', async function () {
const { sut, tearDown, callback } = setup();

await sut.activate(callback);
await sut.activate({ callback });
assert.strictEqual(sut['isActive'], true, `sut.isActive`);
// assert.strictEqual(addEventListener.calls.length, 1, `addEventListener.calls.length`);

Expand All @@ -97,12 +97,12 @@ describe('BrowserNavigator', function () {
it('throws when activated while active', async function () {
const { sut, tearDown, callback } = setup();

await sut.activate(callback);
await sut.activate({ callback });
assert.strictEqual(sut['isActive'], true, `sut.isActive`);

let err;
try {
await sut.activate(callback);
await sut.activate({ callback });
} catch (e) {
err = e;
}
Expand All @@ -117,11 +117,13 @@ describe('BrowserNavigator', function () {
const { sut, tearDown, callback } = setup();

let counter = 0;
await sut.activate(
// Called once for each url/location change (no longer in as part of activation)
function () {
counter++;
});
await sut.activate({
callback:
// Called once for each url/location change (no longer in as part of activation)
function () {
counter++;
}
});

await sut.pushNavigatorState(toNavigatorState('one'));
assert.strictEqual(sut.history.state.currentEntry.instruction, 'one', `sut.history.state.currentEntry.instruction`);
Expand All @@ -141,7 +143,7 @@ describe('BrowserNavigator', function () {
it('queues consecutive calls', async function () {
const { sut, tearDown, callback } = setup();

await sut.activate(callback);
await sut.activate({ callback });
await wait();

const length = sut['pendingCalls'].length;
Expand All @@ -163,11 +165,13 @@ describe('BrowserNavigator', function () {
const { sut, tearDown, callback } = setup();

let counter = 0;
await sut.activate(
// Called once for each url/location change (no longer in as part of activation)
function () {
counter++;
});
await sut.activate({
callback:
// Called once for each url/location change (no longer in as part of activation)
function () {
counter++;
}
});

await sut.pushNavigatorState(toNavigatorState('one'));
assert.strictEqual(sut.history.state.currentEntry.instruction, 'one', `sut.history.state.currentEntry.instruction`);
Expand Down
43 changes: 25 additions & 18 deletions packages/router/src/browser-navigator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Key, Reporter } from '@aurelia/kernel';
import { IDOM, ILifecycle } from '@aurelia/runtime';
import { HTMLDOM } from '@aurelia/runtime-html';
import { INavigatorState, INavigatorStore, INavigatorViewer, INavigatorViewerEvent } from './navigator';
import { INavigatorState, INavigatorStore, INavigatorViewer, INavigatorViewerEvent, INavigatorViewerOptions } from './navigator';
import { Queue, QueueItem } from './queue';

interface Call {
Expand All @@ -16,19 +16,26 @@ interface ForwardedState {
suppressPopstate?: boolean;
resolve?: ((value: void | PromiseLike<void>) => void) | null;
}

export interface IBrowserNavigatorOptions extends INavigatorViewerOptions {
useBrowserFragmentHash?: boolean;
}

export class BrowserNavigator implements INavigatorStore, INavigatorViewer {
public static readonly inject: readonly Key[] = [ILifecycle, IDOM];

public window: Window;
public history: History;
public location: Location;

public useHash: boolean = true;
public allowedExecutionCostWithinTick: number = 2; // Limit no of executed actions within the same RAF (due to browser limitation)

private readonly pendingCalls: Queue<Call>;
private isActive: boolean = false;
private callback: ((ev: INavigatorViewerEvent) => void) | null = null;
private options: IBrowserNavigatorOptions = {
useBrowserFragmentHash: true,
callback: () => { },
};

private forwardedState: ForwardedState = {};

Expand All @@ -42,12 +49,12 @@ export class BrowserNavigator implements INavigatorStore, INavigatorViewer {
this.pendingCalls = new Queue<Call>(this.processCalls);
}

public activate(callback: (ev: INavigatorViewerEvent) => void): void {
public activate(options: IBrowserNavigatorOptions): void {
if (this.isActive) {
throw new Error('Browser navigation has already been activated');
}
this.isActive = true;
this.callback = callback;
this.options = { ...this.options, ...options };
this.pendingCalls.activate({ lifecycle: this.lifecycle, allowedExecutionCostWithinTick: this.allowedExecutionCostWithinTick });
this.window.addEventListener('popstate', this.handlePopstate);
}
Expand All @@ -62,7 +69,7 @@ export class BrowserNavigator implements INavigatorStore, INavigatorViewer {
}
this.window.removeEventListener('popstate', this.handlePopstate);
this.pendingCalls.deactivate();
this.callback = null;
this.options = { useBrowserFragmentHash: true, callback: () => { } };
this.isActive = false;
}

Expand All @@ -79,12 +86,14 @@ export class BrowserNavigator implements INavigatorStore, INavigatorViewer {

public pushNavigatorState(state: INavigatorState): Promise<void> {
const { title, path } = state.currentEntry;
return this.enqueue(this.history, 'pushState', [state, title, `#${path}`]);
const fragment = this.options.useBrowserFragmentHash ? '#' : '';
return this.enqueue(this.history, 'pushState', [state, title, `${fragment}${path}`]);
}

public replaceNavigatorState(state: INavigatorState): Promise<void> {
const { title, path } = state.currentEntry;
return this.enqueue(this.history, 'replaceState', [state, title, `#${path}`]);
const fragment = this.options.useBrowserFragmentHash ? '#' : '';
return this.enqueue(this.history, 'replaceState', [state, title, `${fragment}${path}`]);
}

public popNavigatorState(): Promise<void> {
Expand All @@ -98,16 +107,14 @@ export class BrowserNavigator implements INavigatorStore, INavigatorViewer {
private popstate(ev: PopStateEvent, resolve: ((value?: void | PromiseLike<void>) => void), suppressPopstate: boolean = false): void {
if (!suppressPopstate) {
const { pathname, search, hash } = this.location;
if (this.callback) {
this.callback({
event: ev,
state: this.history.state,
path: pathname,
data: search,
hash,
instruction: this.useHash ? hash.slice(1) : pathname,
});
}
this.options.callback({
event: ev,
state: this.history.state,
path: pathname,
data: search,
hash,
instruction: this.options.useBrowserFragmentHash ? hash.slice(1) : pathname,
});
}
if (resolve) {
resolve();
Expand Down
5 changes: 4 additions & 1 deletion packages/router/src/navigator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ export interface INavigatorStore {
}

export interface INavigatorViewer {
activate(callback: (ev?: INavigatorViewerEvent) => void): void;
activate(options: INavigatorViewerOptions): void;
deactivate(): void;
}
export interface INavigatorViewerOptions {
callback(ev: INavigatorViewerEvent): void;
}

export interface INavigatorViewerEvent {
event: PopStateEvent;
Expand Down
6 changes: 5 additions & 1 deletion packages/router/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const IRouteTransformer = DI.createInterface<IRouteTransformer>('IRouteTr

export interface IRouterOptions extends INavigatorOptions, IRouteTransformer {
separators?: IRouteSeparators;
useBrowserFragmentHash?: boolean;
reportCallback?(instruction: INavigatorInstruction): void;
}

Expand Down Expand Up @@ -127,7 +128,10 @@ export class Router implements IRouter {
store: this.navigation,
});
this.linkHandler.activate({ callback: this.linkCallback });
this.navigation.activate(this.browserNavigatorCallback);
this.navigation.activate({
callback: this.browserNavigatorCallback,
useBrowserFragmentHash: this.options.useBrowserFragmentHash
});
}

public loadUrl(): Promise<void> {
Expand Down

0 comments on commit 4b2f0c1

Please sign in to comment.