redoc/src/services/HistoryService.ts
2018-01-23 15:04:50 +02:00

76 lines
1.6 KiB
TypeScript

import { bind, debounce } from 'decko';
import { EventEmitter } from 'eventemitter3';
import { isBrowser } from '../utils/';
const EVENT = 'hashchange';
function isSameHash(a: string, b: string): boolean {
return a === b || '#' + a === b || a === '#' + b;
}
class IntHistoryService {
private causedHashChange: boolean = false;
private _emiter;
constructor() {
this._emiter = new EventEmitter();
this.bind();
}
get hash(): string {
return isBrowser ? window.location.hash : '';
}
subscribe(cb): () => void {
const emmiter = this._emiter.addListener(EVENT, cb);
return () => emmiter.removeListener(EVENT, cb);
}
emit = () => {
if (this.causedHashChange) {
this.causedHashChange = false;
return;
}
this._emiter.emit(EVENT, this.hash);
};
bind() {
if (isBrowser) {
window.addEventListener('hashchange', this.emit, false);
}
}
dispose() {
if (isBrowser) {
window.removeEventListener('hashchange', this.emit);
}
this.causedHashChange = false;
}
@bind
@debounce
update(hash: string | null, rewriteHistory: boolean = false) {
if (hash == null || isSameHash(hash, this.hash)) {
return;
}
if (rewriteHistory) {
if (isBrowser) {
window.history.replaceState(null, '', window.location.href.split('#')[0] + '#' + hash);
}
return;
}
this.causedHashChange = true;
if (isBrowser) {
window.location.hash = hash;
}
}
}
export const HistoryService = new IntHistoryService();
if (module.hot) {
module.hot.dispose(() => {
HistoryService.dispose();
});
}