2017-02-09 17:10:00 -05:00
|
|
|
/**
|
|
|
|
* @license
|
|
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
*/
|
|
|
|
|
2017-02-10 19:29:30 -05:00
|
|
|
import {LocationChangeEvent, LocationChangeListener, PlatformLocation} from '@angular/common';
|
2017-02-14 22:48:48 -05:00
|
|
|
import {Inject, Injectable, Optional} from '@angular/core';
|
2017-02-17 15:55:55 -05:00
|
|
|
import {DOCUMENT, ɵgetDOM as getDOM} from '@angular/platform-browser';
|
2017-02-10 19:29:30 -05:00
|
|
|
import {Subject} from 'rxjs/Subject';
|
2017-02-09 17:10:00 -05:00
|
|
|
import * as url from 'url';
|
2017-02-14 22:48:48 -05:00
|
|
|
import {INITIAL_CONFIG, PlatformConfig} from './tokens';
|
2017-02-09 17:10:00 -05:00
|
|
|
|
|
|
|
|
2017-02-16 13:18:55 -05:00
|
|
|
function parseUrl(urlStr: string): {pathname: string, search: string, hash: string} {
|
|
|
|
const parsedUrl = url.parse(urlStr);
|
|
|
|
return {
|
|
|
|
pathname: parsedUrl.pathname || '',
|
|
|
|
search: parsedUrl.search || '',
|
|
|
|
hash: parsedUrl.hash || '',
|
|
|
|
};
|
|
|
|
}
|
2017-02-09 17:10:00 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Server-side implementation of URL state. Implements `pathname`, `search`, and `hash`
|
|
|
|
* but not the state stack.
|
|
|
|
*/
|
|
|
|
@Injectable()
|
|
|
|
export class ServerPlatformLocation implements PlatformLocation {
|
2017-09-11 15:39:44 -04:00
|
|
|
public readonly pathname: string = '/';
|
|
|
|
public readonly search: string = '';
|
|
|
|
public readonly hash: string = '';
|
2017-02-09 17:10:00 -05:00
|
|
|
private _hashUpdate = new Subject<LocationChangeEvent>();
|
|
|
|
|
2017-02-14 22:48:48 -05:00
|
|
|
constructor(
|
|
|
|
@Inject(DOCUMENT) private _doc: any, @Optional() @Inject(INITIAL_CONFIG) _config: any) {
|
|
|
|
const config = _config as PlatformConfig | null;
|
|
|
|
if (!!config && !!config.url) {
|
2017-02-16 13:18:55 -05:00
|
|
|
const parsedUrl = parseUrl(config.url);
|
2017-09-11 15:39:44 -04:00
|
|
|
this.pathname = parsedUrl.pathname;
|
|
|
|
this.search = parsedUrl.search;
|
|
|
|
this.hash = parsedUrl.hash;
|
2017-02-14 22:48:48 -05:00
|
|
|
}
|
|
|
|
}
|
2017-02-14 19:14:40 -05:00
|
|
|
|
2017-03-24 12:59:41 -04:00
|
|
|
getBaseHrefFromDOM(): string { return getDOM().getBaseHref(this._doc) !; }
|
2017-02-10 19:29:30 -05:00
|
|
|
|
2017-02-09 17:10:00 -05:00
|
|
|
onPopState(fn: LocationChangeListener): void {
|
|
|
|
// No-op: a state stack is not implemented, so
|
|
|
|
// no events will ever come.
|
|
|
|
}
|
2017-02-10 19:29:30 -05:00
|
|
|
|
|
|
|
onHashChange(fn: LocationChangeListener): void { this._hashUpdate.subscribe(fn); }
|
2017-02-09 17:10:00 -05:00
|
|
|
|
2017-02-10 19:29:30 -05:00
|
|
|
get url(): string { return `${this.pathname}${this.search}${this.hash}`; }
|
2017-02-09 17:10:00 -05:00
|
|
|
|
|
|
|
private setHash(value: string, oldUrl: string) {
|
2017-09-11 15:39:44 -04:00
|
|
|
if (this.hash === value) {
|
2017-02-09 17:10:00 -05:00
|
|
|
// Don't fire events if the hash has not changed.
|
|
|
|
return;
|
|
|
|
}
|
2017-09-11 15:39:44 -04:00
|
|
|
(this as{hash: string}).hash = value;
|
2017-02-09 17:10:00 -05:00
|
|
|
const newUrl = this.url;
|
2017-02-10 19:29:30 -05:00
|
|
|
scheduleMicroTask(
|
|
|
|
() => this._hashUpdate.next({ type: 'hashchange', oldUrl, newUrl } as LocationChangeEvent));
|
2017-02-09 17:10:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
replaceState(state: any, title: string, newUrl: string): void {
|
|
|
|
const oldUrl = this.url;
|
2017-02-16 13:18:55 -05:00
|
|
|
const parsedUrl = parseUrl(newUrl);
|
2017-09-11 15:39:44 -04:00
|
|
|
(this as{pathname: string}).pathname = parsedUrl.pathname;
|
|
|
|
(this as{search: string}).search = parsedUrl.search;
|
2017-02-09 17:10:00 -05:00
|
|
|
this.setHash(parsedUrl.hash, oldUrl);
|
|
|
|
}
|
|
|
|
|
|
|
|
pushState(state: any, title: string, newUrl: string): void {
|
|
|
|
this.replaceState(state, title, newUrl);
|
|
|
|
}
|
|
|
|
|
2017-02-10 19:29:30 -05:00
|
|
|
forward(): void { throw new Error('Not implemented'); }
|
2017-02-09 17:10:00 -05:00
|
|
|
|
2017-02-10 19:29:30 -05:00
|
|
|
back(): void { throw new Error('Not implemented'); }
|
2017-02-09 17:10:00 -05:00
|
|
|
}
|
2017-03-01 18:18:10 -05:00
|
|
|
|
|
|
|
export function scheduleMicroTask(fn: Function) {
|
|
|
|
Zone.current.scheduleMicroTask('scheduleMicrotask', fn);
|
|
|
|
}
|