diff --git a/.travis/RouteChange.js b/.travis/RouteChange.js new file mode 100644 index 0000000..b0ecde3 --- /dev/null +++ b/.travis/RouteChange.js @@ -0,0 +1,154 @@ +/* eslint-env mocha */ +const { expect } = require('chai'); +const istanbulVM = require('./istanbulVM'); +const RouteChangeType = require('../testable/lib/RouteChangeType').default; + +describe('RouteChange', () => { + const validTestRegExp = /^\/test\/([^\/#?]+)\/page\/([^\/#?]+)\/dialog\/([^\/#?]+)$/; + const vm = istanbulVM(); + let result = null; + + describe('::transfromPathToRegExp', () => { + + it('should return an object', () => { + vm.runModule('../testable/lib/RouteChange'); + result = vm.runModule('./tests/RouteChange_transformPathToRegExp'); + + expect(result.global.result).to.have.property('regExp'); + expect(result.global.result).to.have.property('paramsCollector'); + }); + + it('should return the right regEx', () => { + expect(result.global.result.regExp.source) + .to.be.equal(validTestRegExp.source); + }); + + it('should collect all params', () => { + expect(Object.keys(result.global.result.paramsCollector)).to.have.lengthOf(3, 3); + }); + }); + + describe('::populateStateParamValues', () => { + it('should populate the route params', () => { + result = vm.runModule('./tests/RouteChange_populateStateParamValues_1'); + + expect(result.global.result).to.have.property('param1', '108978234'); + expect(result.global.result).to.have.property('param2', 'id-24397876'); + expect(result.global.result).to.have.property('param3', 'BigWhiteThing'); + }); + + it('should work fine if there are no params to collect', () => { + result = vm.runModule('./tests/RouteChange_populateStateParamValues_2'); + + expect(result.global.result).to.be.empty; + }); + }); + + describe('::routeItemWasEntered', () => { + it('should not enter if the path doesn\'t match!', () => { + result = vm.runModule('./tests/RouteChange_routeItemWasEntered_1'); + + expect(result.global.result).to.not.be.ok; + }); + + it('should enter if the path matches', () => { + result = vm.runModule('./tests/RouteChange_routeItemWasEntered_2'); + + expect(result.global.result).to.be.ok; + }); + + it('should not enter if the path matches, is persistent and active', () => { + result = vm.runModule('./tests/RouteChange_routeItemWasEntered_3'); + + expect(result.global.result).to.not.be.ok; + }); + }); + + describe('::routeItemWasLost', () => { + it('should be lost if the path matches', () => { + result = vm.runModule('./tests/RouteChange_routeItemWasLost_1'); + + expect(result.global.result).to.be.ok; + }); + }); + + const executedActions = [false, false, false]; + + const state = { actions : [{ + path: '/home/rooms/place/1', + persistent: false, + active: false, + enter() { executedActions[0] = 'enter_0'; }, + leave() { executedActions[0] = 'leave_0'; } + }, { + path: '/home/rooms/place/1/info', + persistent: true, + active: false, + enter() { executedActions[1] = 'enter_1'; }, + leave() { executedActions[1] = 'leave_1'; }, + }, { + path: '/work/about', + persistent: true, + active: true, + enter() { executedActions[2] = 'enter_2'; }, + leave() { executedActions[2] = 'leave_2'; }, + }], overrides : {}, }; + + describe('constructor', () => { + const type = RouteChangeType.ADD; + const path = '/home/rooms/place/1'; + + vm._context.global.params = { type: type, path : path, state: state }; + + it('should construct a new RouteChange object', () => { + result = vm.runModule('./tests/RouteChange_constructor'); + + expect(result.global.routeChange).to.have.property('type', type); + expect(result.global.routeChange).to.have.property('path', path); + expect(result.global.routeChange).to.have.property('state', state); + }); + }); + + describe('trigger', () => { + it('should enter the action that matches the current path', () => { + executedActions[0] = executedActions[1] = executedActions[2] = false; + + vm.runModule('./tests/RouteChange_trigger_1'); + + expect(executedActions).to.be.eql(['enter_0', false, false]); + }); + + it('should enter the persistent state, but not if it already active', () => { + const path = '/home/rooms/place/1/info'; + + vm._context.global.routeChange.path = path; + executedActions[0] = executedActions[1] = executedActions[2] = false; + + vm.runModule('./tests/RouteChange_trigger_1'); + + expect(executedActions).to.be.eql([false, 'enter_1', false]); + }); + + it('should not enter a persistent and already active state', () => { + const path = '/home/rooms/place/1/info'; + executedActions[0] = executedActions[1] = executedActions[2] = false; + + vm._context.global.routeChange.path = path; + vm.runModule('./tests/RouteChange_trigger_1'); + + expect(executedActions).to.be.eql([false, false, false]); + }); + + it('should error if an invalid change type was set', () => { + const path = '/home/rooms/place/1'; + executedActions[0] = executedActions[1] = executedActions[2] = false; + + vm._context.routeChange.type = 123; + vm._context.routeChange.path = path; + result = vm.runModule('./tests/RouteChange_trigger_1'); + + expect(executedActions).to.be.eql([false, false, false]); + expect(result.console.stats.error).to.be.equal(1); + }); + }); +}); diff --git a/.travis/Router.js b/.travis/Router.js new file mode 100644 index 0000000..15502ee --- /dev/null +++ b/.travis/Router.js @@ -0,0 +1,214 @@ +/* eslint-env mocha */ + +const { expect } = require('chai'); +const istanbulVM = require('./istanbulVM'); + +describe('Router', () => { + const triggerTracker = [false, false, false]; + + const vm = istanbulVM({ + testActions: [{ + path: '/home/pages/p1', + onEnter() { triggerTracker[0] = 'enter_0'; }, + onLeave() { triggerTracker[0] = 'leave_0'; }, + isPersistent: false, + }, { + path: '/home/pages/p1/info', + onEnter() { triggerTracker[1] = 'enter_1'; }, + onLeave() { triggerTracker[1] = 'leave_1'; }, + isPersistent: true, + }, { + path: ['/', '/home'], + onEnter() { triggerTracker[2] = 'enter_2'; }, + onLeave() { triggerTracker[2] = 'leave_2'; }, + isPersistent: false, + }], + + Event: function() {}, + + window: { + location: { hash: '/start' }, + localStorage: { + store: {}, + setItem(key, value) { + this.store[key] = value; + }, + + getItem(key) { + return this.store[key]; + } + }, + + eventDispatched: false, + + dispatchEvent() { this.eventDispatched = true; }, + + addEventListener(name, fn) { + this[name] = fn; + } + } + }); + + describe('init', () => { + it('should init all submitted states', () => { + vm.runModule('../testable/lib/Router'); + const result = vm.runModule('./tests/Router/init'); + + expect(result.Router.state.actions).to.have.lengthOf(4); + expect(result.window.hashchange).to.be.a('function'); + }); + }); + + describe('addRoutable', () => { + it('should add a new Routable object', () => { + const result = vm.runModule('./tests/Router/addRoutable'); + + expect(result.Router.state.actions[result.Router.state.actions.length - 1].path) + .to.be.equal('/home/routable/page/1'); + }); + }); + + describe('down', () => { + it('should append a new segment to the path', () => { + expect(vm._context.window.location.hash).to.be.equal('/start'); + + const result = vm.runModule('./tests/Router/down'); + + expect(result.window.location.hash).to.be.equal('/start/second'); + }); + }); + + describe('remove', () => { + it('should remove the action at the given id', () => { + expect(vm._context.Router.state.actions).to.have.lengthOf(5); + + const result = vm.runModule('./tests/Router/remove'); + + expect(result.Router.state.actions).to.have.lengthOf(4); + }); + }); + + describe('routeChanged', () => { + it('should enter the first and third state', () => { + vm.runModule('./tests/Router/routeChanged_1'); + + expect(triggerTracker).to.be.eql(['enter_0', false, 'enter_2']); + }); + + it('should leave the first state when navigating up', () => { + triggerTracker[0] = triggerTracker[1] = triggerTracker[2] = false; + + vm.runModule('./tests/Router/routeChanged_2'); + + expect(triggerTracker).to.be.eql(['leave_0', false, false]); + }); + + it('should not leave persistent states', () => { + vm.runModule('./tests/Router/routeChanged_3'); + + triggerTracker[0] = triggerTracker[1] = triggerTracker[2] = false; + + vm.runModule('./tests/Router/routeChanged_2'); + + expect(triggerTracker).to.be.eql(['leave_0', false, false]); + }); + + it('should redirect when trying to navigate into an overwritten state', () => { + triggerTracker[0] = triggerTracker[1] = triggerTracker[2] = false; + + expect(vm._context.window.location.hash).to.be.equal('#!/home'); + + vm.runModule('./tests/Router/routeChanged_1'); + const result = vm.runModule('./tests/Router/routeChanged_4'); + + expect(triggerTracker).to.be.eql(['enter_0', false, false]); + expect(result.window.location.hash).to.be.equal('#!/home/pages/p1/info'); + }); + + it('should leave a persistent state if we actively navigate out of it', () => { + triggerTracker[0] = triggerTracker[1] = triggerTracker[2] = false; + + vm.runModule('./tests/Router/routeChanged_1'); + + expect(triggerTracker).to.be.eql([false, 'leave_1', false]); + }); + }); + + describe('up', () => { + it('should dop the lowest element in the path', () => { + vm._context.window.location.hash = '#!/home/pages/p2'; + + const result = vm.runModule('./tests/Router/up'); + + expect(result.window.location.hash).to.be.equal('#!/home/pages'); + }); + }); + + describe('validateRoutePath', () => { + it('should throw if the hash path is invalid', () => { + const result = vm.runModule('./tests/Router/validateRoutePath'); + + expect(result.console.stats.error).to.be.equal(1); + }); + }); + + describe('switchTo', () => { + it('should switch to the given path', () => { + const result = vm.runModule('./tests/Router/switchTo'); + + expect(result.window.location.hash).to.be.equal('#!/test/path'); + }); + }); + + describe('restore', () => { + it('should restore the last path if no path is currently set', () => { + vm._context.window.location.hash = ''; + vm._context.window.localStorage.store['af.router.backup'] = '/backed/path/in/storage'; + + const result = vm.runModule('./tests/Router/restore'); + + expect(result.window.location.hash).to.be.equal('#!/backed/path/in/storage'); + }); + + it('should not restore from backup if there is already a path set', () => { + vm._context.window.location.hash = '#!/test/path/a1'; + + const result = vm.runModule('./tests/Router/restore'); + + expect(result.window.eventDispatched).to.be.true; + }); + + it('should just simply trigger if there is no backup', () => { + vm._context.window.location.hash = ''; + vm._context.window.localStorage.store = {}; + vm._context.window.eventDispatched = false; + + let result = vm.runModule('./tests/Router/restore'); + + expect(result.window.location.hash).to.be.empty; + expect(result.window.eventDispatched).to.be.true; + + result = vm.runModule('./tests/Router/getCurrentPath'); + + expect(result.currentPath).to.be.eql(['#!', '']); + }); + }); + + describe('triggerGoogleAnalytics', () => { + it('should trigger google analytics if available', () => { + vm._context.window.location = { + protocol: 'https:', + host: 'example.org', + pathname: '/test/', + search: '?test=1', + hash: '#test' + }; + + vm._context.window.ga = function() { vm._context.window.ga.triggered = true; }; + + const result = vm.runModule('./tests/Router/triggerGoogleAnalytics'); + + expect(result.window.ga.triggered).to.be.true; + }); + }); +}); diff --git a/.travis/istanbulVM.js b/.travis/istanbulVM.js index 6c982e1..fcb358b 100644 --- a/.travis/istanbulVM.js +++ b/.travis/istanbulVM.js @@ -5,7 +5,7 @@ const Path = require('path'); const instrumenter = new istanbul.Instrumenter(); -module.exports = function() { +module.exports = function(data = {}) { const coverage = Object.keys(global).find(key => key.indexOf('$$cov_') === 0); const context = { @@ -20,7 +20,8 @@ module.exports = function() { stats: { error: 0, warn: 0, log: 0, }, log() { this.stats.log += 1; }, error() { this.stats.error += 1; }, - warn() { this.stats.warn += 1; } + warn() { this.stats.warn += 1; }, + write(...args) { console.log(...args); } }, exports: {}, global: null, @@ -28,16 +29,21 @@ module.exports = function() { }; context.global = context; + Object.assign(context, data); const vm = Object.create(VM).constructor(context); - vm.addLoadHook((code, filename) => { - if (filename.indexOf('.travis') < 0) { - code = instrumenter.instrumentSync(code, filename); - } + vm._hooks = []; - return code; - }); + if (coverage) { + vm.addLoadHook((code, filename) => { + if (filename.indexOf('.travis') < 0) { + code = instrumenter.instrumentSync(code, filename); + } + + return code; + }); + } return vm; }; diff --git a/.travis/main.js b/.travis/main.js index 3f83fb5..9005178 100644 --- a/.travis/main.js +++ b/.travis/main.js @@ -1,155 +1,2 @@ -/* eslint-env mocha */ -const { expect } = require('chai'); -const istanbulVM = require('./istanbulVM'); -const RouteChangeType = require('../testable/lib/RouteChangeType').default; - - -describe('RouteChange', () => { - const validTestRegExp = /^\/test\/([^\/#?]+)\/page\/([^\/#?]+)\/dialog\/([^\/#?]+)$/; - const vm = istanbulVM(); - let result = null; - - describe('::transfromPathToRegExp', () => { - - it('should return an object', () => { - vm.runModule('../testable/lib/RouteChange'); - result = vm.runModule('./tests/RouteChange_transformPathToRegExp'); - - expect(result.global.result).to.have.property('regExp'); - expect(result.global.result).to.have.property('paramsCollector'); - }); - - it('should return the right regEx', () => { - expect(result.global.result.regExp.source) - .to.be.equal(validTestRegExp.source); - }); - - it('should collect all params', () => { - expect(Object.keys(result.global.result.paramsCollector)).to.have.lengthOf(3, 3); - }); - }); - - describe('::populateStateParamValues', () => { - it('should populate the route params', () => { - result = vm.runModule('./tests/RouteChange_populateStateParamValues_1'); - - expect(result.global.result).to.have.property('param1', '108978234'); - expect(result.global.result).to.have.property('param2', 'id-24397876'); - expect(result.global.result).to.have.property('param3', 'BigWhiteThing'); - }); - - it('should work fine if there are no params to collect', () => { - result = vm.runModule('./tests/RouteChange_populateStateParamValues_2'); - - expect(result.global.result).to.be.empty; - }); - }); - - describe('::routeItemWasEntered', () => { - it('should not enter if the path doesn\'t match!', () => { - result = vm.runModule('./tests/RouteChange_routeItemWasEntered_1'); - - expect(result.global.result).to.not.be.ok; - }); - - it('should enter if the path matches', () => { - result = vm.runModule('./tests/RouteChange_routeItemWasEntered_2'); - - expect(result.global.result).to.be.ok; - }); - - it('should not enter if the path matches, is persistent and active', () => { - result = vm.runModule('./tests/RouteChange_routeItemWasEntered_3'); - - expect(result.global.result).to.not.be.ok; - }); - }); - - describe('::routeItemWasLost', () => { - it('should be lost if the path matches', () => { - result = vm.runModule('./tests/RouteChange_routeItemWasLost_1'); - - expect(result.global.result).to.be.ok; - }); - }); - - const executedActions = [false, false, false]; - - const state = { actions : [{ - path: '/home/rooms/place/1', - persistent: false, - active: false, - enter() { executedActions[0] = 'enter_0'; }, - leave() { executedActions[0] = 'leave_0'; } - }, { - path: '/home/rooms/place/1/info', - persistent: true, - active: false, - enter() { executedActions[1] = 'enter_1'; }, - leave() { executedActions[1] = 'leave_1'; }, - }, { - path: '/work/about', - persistent: true, - active: true, - enter() { executedActions[2] = 'enter_2'; }, - leave() { executedActions[2] = 'leave_2'; }, - }], overrides : {}, }; - - describe('constructor', () => { - const type = RouteChangeType.ADD; - const path = '/home/rooms/place/1'; - - vm._context.global.params = { type: type, path : path, state: state }; - - it('should construct a new RouteChange object', () => { - result = vm.runModule('./tests/RouteChange_constructor'); - - expect(result.global.routeChange).to.have.property('type', type); - expect(result.global.routeChange).to.have.property('path', path); - expect(result.global.routeChange).to.have.property('state', state); - }); - }); - - describe('trigger', () => { - it('should enter the action that matches the current path', () => { - executedActions[0] = executedActions[1] = executedActions[2] = false; - - vm.runModule('./tests/RouteChange_trigger_1'); - - expect(executedActions).to.be.eql(['enter_0', false, false]); - }); - - it('should enter the persistent state, but not if it already active', () => { - const path = '/home/rooms/place/1/info'; - - vm._context.global.routeChange.path = path; - executedActions[0] = executedActions[1] = executedActions[2] = false; - - vm.runModule('./tests/RouteChange_trigger_1'); - - expect(executedActions).to.be.eql([false, 'enter_1', false]); - }); - - it('should not enter a persistent and already active state', () => { - const path = '/home/rooms/place/1/info'; - executedActions[0] = executedActions[1] = executedActions[2] = false; - - vm._context.global.routeChange.path = path; - vm.runModule('./tests/RouteChange_trigger_1'); - - expect(executedActions).to.be.eql([false, false, false]); - }); - - it('should error if an invalid change type was set', () => { - const path = '/home/rooms/place/1'; - executedActions[0] = executedActions[1] = executedActions[2] = false; - - vm._context.routeChange.type = 123; - vm._context.routeChange.path = path; - result = vm.runModule('./tests/RouteChange_trigger_1'); - - expect(executedActions).to.be.eql([false, false, false]); - expect(result.console.stats.error).to.be.equal(1); - }); - }); -}); +require('./RouteChange'); +require('./Router'); diff --git a/.travis/tests/Router/addRoutable.js b/.travis/tests/Router/addRoutable.js new file mode 100644 index 0000000..f418574 --- /dev/null +++ b/.travis/tests/Router/addRoutable.js @@ -0,0 +1,11 @@ +/* global Router */ + +(() => { + const routable = { + onRouteEnter() { }, + onRouteLeave() { }, + isRoutedPeristently: false, + }; + + Router.addRoutable('/home/routable/page/1', routable); +})(); diff --git a/.travis/tests/Router/down.js b/.travis/tests/Router/down.js new file mode 100644 index 0000000..70ec0ef --- /dev/null +++ b/.travis/tests/Router/down.js @@ -0,0 +1,5 @@ +/* global Router */ + +(() => { + Router.down('second'); +})(); diff --git a/.travis/tests/Router/getCurrentPath.js b/.travis/tests/Router/getCurrentPath.js new file mode 100644 index 0000000..f0ad3b4 --- /dev/null +++ b/.travis/tests/Router/getCurrentPath.js @@ -0,0 +1,5 @@ +/* global Router */ + +(() => { + global.currentPath = Router.getCurrentPath(); +})(); diff --git a/.travis/tests/Router/init.js b/.travis/tests/Router/init.js new file mode 100644 index 0000000..8af0d11 --- /dev/null +++ b/.travis/tests/Router/init.js @@ -0,0 +1,6 @@ +/* global Router */ + +(() => { + global.Router = global.exports.default; + Router.init(global.testActions); +})(); diff --git a/.travis/tests/Router/remove.js b/.travis/tests/Router/remove.js new file mode 100644 index 0000000..ba6b360 --- /dev/null +++ b/.travis/tests/Router/remove.js @@ -0,0 +1,5 @@ +/* global Router */ + +(() => { + Router.remove(4); +})(); diff --git a/.travis/tests/Router/restore.js b/.travis/tests/Router/restore.js new file mode 100644 index 0000000..f881dc5 --- /dev/null +++ b/.travis/tests/Router/restore.js @@ -0,0 +1,5 @@ +/* global Router */ + +(() => { + Router.restore(); +})(); diff --git a/.travis/tests/Router/routeChanged_1.js b/.travis/tests/Router/routeChanged_1.js new file mode 100644 index 0000000..3be5b4b --- /dev/null +++ b/.travis/tests/Router/routeChanged_1.js @@ -0,0 +1,7 @@ +/* global Router */ + +(() => { + window.location.hash = '#!/home/pages/p1'; + + Router.routeChanged(); +})(); diff --git a/.travis/tests/Router/routeChanged_2.js b/.travis/tests/Router/routeChanged_2.js new file mode 100644 index 0000000..3820501 --- /dev/null +++ b/.travis/tests/Router/routeChanged_2.js @@ -0,0 +1,7 @@ +/* global Router */ + +(() => { + window.location.hash = '#!/home'; + + Router.routeChanged(); +})(); diff --git a/.travis/tests/Router/routeChanged_3.js b/.travis/tests/Router/routeChanged_3.js new file mode 100644 index 0000000..0072055 --- /dev/null +++ b/.travis/tests/Router/routeChanged_3.js @@ -0,0 +1,7 @@ +/* global Router */ + +(() => { + window.location.hash = '#!/home/pages/p1/info'; + + Router.routeChanged(); +})(); diff --git a/.travis/tests/Router/routeChanged_4.js b/.travis/tests/Router/routeChanged_4.js new file mode 100644 index 0000000..2a2a2bb --- /dev/null +++ b/.travis/tests/Router/routeChanged_4.js @@ -0,0 +1,5 @@ +/* global Router */ + +(() => { + Router.routeChanged(); +})(); diff --git a/.travis/tests/Router/switchTo.js b/.travis/tests/Router/switchTo.js new file mode 100644 index 0000000..23c2ee5 --- /dev/null +++ b/.travis/tests/Router/switchTo.js @@ -0,0 +1,5 @@ +/* global Router */ + +(() => { + Router.swichTo('/test/path'); +})(); diff --git a/.travis/tests/Router/triggerGoogleAnalytics.js b/.travis/tests/Router/triggerGoogleAnalytics.js new file mode 100644 index 0000000..1c3bd96 --- /dev/null +++ b/.travis/tests/Router/triggerGoogleAnalytics.js @@ -0,0 +1,5 @@ +/* global Router */ + +(() => { + Router.triggerGoogleAnalytics(); +})(); diff --git a/.travis/tests/Router/up.js b/.travis/tests/Router/up.js new file mode 100644 index 0000000..b9e0f7f --- /dev/null +++ b/.travis/tests/Router/up.js @@ -0,0 +1,5 @@ +/* global Router */ + +(() => { + Router.up(); +})(); diff --git a/.travis/tests/Router/validateRoutePath.js b/.travis/tests/Router/validateRoutePath.js new file mode 100644 index 0000000..9b3c394 --- /dev/null +++ b/.travis/tests/Router/validateRoutePath.js @@ -0,0 +1,9 @@ +/* global Router */ + +(() => { + try { + Router.validateRoutePath('/stuff happens here!'); + } catch (e) { + console.error(e); + } +})(); diff --git a/README.md b/README.md index 2390855..69a4f5f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # AF Router [![Build Status](https://travis-ci.org/TitanNanoDE/af-router.svg?branch=master)](https://travis-ci.org/TitanNanoDE/af-router) +[![Coverage Status](https://coveralls.io/repos/github/TitanNanoDE/af-router/badge.svg?branch=master)](https://coveralls.io/github/TitanNanoDE/af-router?branch=master) ## Instalation @@ -15,9 +16,9 @@ import Router from '@af-modules/router'; Router.init([ { path: ['/', '/home'], - onEnter: (path) => {...}, - onLeave: (path) => {...}, - isPersistent: true, + onEnter: (path) => {...}, + onLeave: (path) => {...}, + isPersistent: true, }, { path: '/home/details', diff --git a/lib/RouteChange.js b/lib/RouteChange.js index 01a7f3b..7e049e0 100755 --- a/lib/RouteChange.js +++ b/lib/RouteChange.js @@ -56,7 +56,7 @@ const processEnterActions = function(items, path) { }); }; -const processLeaveActions = function(items, path, count) { +const processLeaveActions = function(items, path, count, state) { items.forEach((item) => { const { regExp, paramsCollector } = transfromPathToRegExp(item.path); @@ -70,14 +70,14 @@ const processLeaveActions = function(items, path, count) { if (item.persistent) { path = path.split('/'); path.pop(); - delete this.state.overrides[path.join('/')]; + delete state.overrides[path.join('/')]; item.active = false; } } else { path = path.split('/'); path.pop(); - this.state.overrides[path.join('/')] = path; + state.overrides[path.join('/')] = item.path.split('/'); } } }); @@ -108,7 +108,7 @@ const RouteChange = { let type = Object.values(RouteChangeType).find(type => type === this.type); if (type) { - processingMap.get(type)(this.state.actions, path, count); + processingMap.get(type)(this.state.actions, path, count, this.state); } else { console.error('[AF-Router]', 'unknown RouteChangeType!', this.type); diff --git a/lib/Router.js b/lib/Router.js index 5abe8b2..4d5749e 100755 --- a/lib/Router.js +++ b/lib/Router.js @@ -47,15 +47,15 @@ const Router = { let hash = window.location.hash.split('/'); hash.shift(); hash.pop(); - window.location.hash = '!/' + hash.join('/'); + window.location.hash = '#!/' + hash.join('/'); }, swichTo(path) { - window.location.hash = '!' + path; + window.location.hash = '#!' + path; }, trigger() { - let e= new Event('hashchange'); + let e = new Event('hashchange'); window.dispatchEvent(e); }, @@ -64,7 +64,7 @@ const Router = { let fullRoute = '#!' + route; if(route && window.location.hash === '') - window.location.hash= fullRoute; + window.location.hash = fullRoute; else this.trigger(); }, @@ -77,8 +77,6 @@ const Router = { // remove first item, we don't need it currentPath.shift(); - this.backupPath(currentPath); - let { added, lost } = this.diffPaths(currentPath); //trigger lost events first @@ -88,8 +86,9 @@ const Router = { // check for overrides let path = '/' + currentPath.join('/'); + if(this.state.overrides[path]){ - this.location.hash= '#!' + this.state.overrides[path]; + window.location.hash = '#!' + this.state.overrides[path].join('/'); return; } @@ -100,6 +99,10 @@ const Router = { // store the new path this.state.path = currentPath; + this.backupPath(currentPath); + + // trigger google analytics + this.triggerGoogleAnalytics(); }, /** @@ -112,7 +115,7 @@ const Router = { validateRoutePath(path) { if (path[0] != '#!'){ - throw 'error in your hash path!'; + throw `error in your hash path! ${path}`; } }, @@ -151,7 +154,7 @@ const Router = { } if (difference) { - added.push(Object.create(RouteChange).constructor(RouteChangeType.ADD, path)); + added.push(Object.create(RouteChange).constructor(RouteChangeType.ADD, path, this.state)); } }); }, @@ -168,14 +171,14 @@ const Router = { }, backupPath(currentPath) { - this.localStorage.setItem('af.hash.backup', `/${currentPath.join('/')}`); + window.localStorage.setItem('af.hash.backup', `/${currentPath.join('/')}`); }, triggerGoogleAnalytics() { // Google Analytics Support (only analytics.js) - if(this.ga){ - let location = `${this.location.protocol}//${this.location.hostname}${this.location.pathname}${this.location.search}${this.location.hash}`; - this.ga('send', 'pageview', location); + if(window.ga){ + let location = `${window.location.protocol}//${window.location.hostname}${window.location.pathname}${window.location.search}${window.location.hash}`; + window.ga('send', 'pageview', location); } },