From 6f8c5bd14126de37b357109795475b27e0c45a94 Mon Sep 17 00:00:00 2001 From: Brandon Cheng Date: Tue, 30 Aug 2016 17:38:55 -0400 Subject: [PATCH] Initial commit --- README.md | 36 ++++++++++++++++ index.js | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 20 +++++++++ 3 files changed, 173 insertions(+) create mode 100644 README.md create mode 100644 index.js create mode 100644 package.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..2f273c2 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# Back Forward History + +This is an addon to the history JavaScript +[history](https://github.com/mjackson/history) library. It enables tracking of +back and forward locations. + +# Setup + +```js +import React from 'react' +import { render } from 'react-dom' +import { Router, Route, browserHistory } from 'react-router' + +import HistoryTracker from './back-forward-history' + +HistoryTracker.listenTo(browserHistory) +``` + +# API + +### listenTo(browserHistory) +Call this method to initialize this addon. Calling it more than once will result +in unexpected behavior + +### canGoBack(n = 1) +Check if you can go back n pages. Defaults to 1. + +### canGoForward(n = 1) +Check if you can go forward n pages. Defaults to 1. + +### setTagForKey(key, tag) +Set a tag for a location you may want to return to. Get a key with +`currentLocationKey`. + +### goToLocationWithTag(tag) +Goes backward or forward to reach a tag. diff --git a/index.js b/index.js new file mode 100644 index 0000000..d41ef85 --- /dev/null +++ b/index.js @@ -0,0 +1,117 @@ +const SESSIONSTORAGE_PREFIX = 'BackForwardHistory_'; + +class BackForwardHistory { + browserHistory + historyStack + currentIndex + titles + tags + + get firstLocationKey() { + return this.historyStack[0]; + } + + get currentLocationKey() { + return this.historyStack[this.currentIndex]; + } + + canGoBack(n = 1) { + return this.currentIndex >= n; + } + + canGoForward(n = 1) { + return this.currentIndex < (this.historyStack.length - n) + } + + get currentlyOnFirstPage() { + return this.currentLocationKey == this.firstLocationKey; + } + + get currentlyOnLastPage() { + return !this.canGoForward() + } + + constructor() { + this.loadStateFromSession(); + } + + listenTo(browserHistory) { + this.browserHistory = browserHistory + browserHistory.listen(this.onHistoryEvent.bind(this)); + } + + loadStateFromSession() { + this.historyStack = JSON.parse(sessionStorage.getItem(SESSIONSTORAGE_PREFIX + 'historyStack')) || []; + this.currentIndex = sessionStorage.getItem(SESSIONSTORAGE_PREFIX + 'currentIndex') || 0; + this.titles = JSON.parse(sessionStorage.getItem(SESSIONSTORAGE_PREFIX + 'titles')) || {}; + this.tags = JSON.parse(sessionStorage.getItem(SESSIONSTORAGE_PREFIX + 'tags')) || {}; + } + + saveStateToSession() { + sessionStorage.setItem(SESSIONSTORAGE_PREFIX + 'historyStack', JSON.stringify(this.historyStack)); + sessionStorage.setItem(SESSIONSTORAGE_PREFIX + 'currentIndex', this.currentIndex); + sessionStorage.setItem(SESSIONSTORAGE_PREFIX + 'titles', JSON.stringify(this.titles)); + sessionStorage.setItem(SESSIONSTORAGE_PREFIX + 'tags', JSON.stringify(this.tags)); + } + + resetState() { + this.historyStack = []; + this.currentIndex = 0; + this.titles = new Map(); + this.tags = new Map(); + saveStateToSession(); + } + + onHistoryEvent({ pathname, key, action }) { + if (this.historyStack.length === 0) { + this.historyStack.push(key); + } + + if (action === 'PUSH') { + if (!this.currentlyOnLastPage) { + this.historyStack = this.historyStack.splice(0, this.currentIndex+1) + } + + this.historyStack.push(key); + this.currentIndex++; + } else if (action === 'POP') { + const potentialIndex = this.historyStack.indexOf(key); + + if (potentialIndex === -1) { + // User hit go on url bar. Reset history stack. + this.historyStack = [key] + } + + this.currentIndex = this.historyStack.indexOf(key); + } + + this.saveStateToSession() + } + + getLastLocationTitle() { + return this.titles[this.historyStack[this.currentIndex-1]] + } + + getTitleForKey(key) { + return this.titles[key] + } + + setTitleForKey(key, title) { + this.titles[key] = title + } + + setTagForKey(key, tag) { + this.tags[tag] = key + } + + goToLocationWithTag(tag) { + const indexOfTag = this.historyStack.indexOf(this.tags[tag]); + if (indexOfTag === -1) { + throw new Error('No index found for key') + } + + this.browserHistory.go(indexOfTag - this.currentIndex) + } +} + +export default new BackForwardHistory() diff --git a/package.json b/package.json new file mode 100644 index 0000000..58f219d --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "back-forward-history", + "version": "1.0.0", + "description": "This is an addon to the history JavaScript library. It enables tracking of back and forward locations.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "UConn Center for Open Research, Resrouces, and Equipment", + "license": "MIT", + "repository": { + "type": "git", + "url": "git@github.uconn.edu:Brandon/BackForwardHistory.git" + }, + "keywords": [ + "history", + "react", + "react-router" + ] +}