module.exports = LocationHistory function LocationHistory () { if (!new.target) return new LocationHistory() this._history = [] this._forward = [] this._pending = false } LocationHistory.prototype.url = function () { return this.current() && this.current().url } LocationHistory.prototype.current = function () { return this._history[this._history.length - 1] } LocationHistory.prototype.go = function (page, cb) { if (!cb) cb = noop if (this._pending) return cb(null) console.log('go', page) this.clearForward() this._go(page, cb) } LocationHistory.prototype.back = function (cb) { var self = this if (!cb) cb = noop if (self._history.length <= 1 || self._pending) return cb(null) var page = self._history.pop() self._unload(page, done) function done (err) { if (err) return cb(err) self._forward.push(page) self._load(self.current(), cb) } } LocationHistory.prototype.hasBack = function () { return this._history.length > 1 } LocationHistory.prototype.forward = function (cb) { if (!cb) cb = noop if (this._forward.length === 0 || this._pending) return cb(null) var page = this._forward.pop() this._go(page, cb) } LocationHistory.prototype.hasForward = function () { return this._forward.length > 0 } LocationHistory.prototype.clearForward = function (url) { if (url == null) { this._forward = [] } else { console.log(this._forward) console.log(url) this._forward = this._forward.filter(function (page) { return page.url !== url }) } } LocationHistory.prototype.backToFirst = function (cb) { var self = this if (!cb) cb = noop if (self._history.length <= 1) return cb(null) self.back(function (err) { if (err) return cb(err) self.backToFirst(cb) }) } LocationHistory.prototype._go = function (page, cb) { var self = this if (!cb) cb = noop self._unload(self.current(), done1) function done1 (err) { if (err) return cb(err) self._load(page, done2) } function done2 (err) { if (err) return cb(err) self._history.push(page) cb(null) } } LocationHistory.prototype._load = function (page, cb) { var self = this self._pending = true if (page && page.onbeforeload) page.onbeforeload(done) else done(null) function done (err) { self._pending = false cb(err) } } LocationHistory.prototype._unload = function (page, cb) { var self = this self._pending = true if (page && page.onbeforeunload) page.onbeforeunload(done) else done(null) function done (err) { self._pending = false cb(err) } } function noop () {}