uhistory
v2.0.0-rc.2
Published
Microscopically small History API based on uevents
Downloads
17
Maintainers
Readme
uhistory
Microscopically small History API based on uevents
Install
npm install --save uhistory
Require
var History = require('uhistory')
Import
import History from 'uhistory'
Use
var history = History()
history.on('change', function(){console.info('Changed!')})
history.pushState({some:'state'}, 'title', '/some/url')
// > 'Changed!'
Why
The standard History object in browsers offers a decent API to change the
history, but is a bit awkward to work with when you want to listen for changes,
because you need to listen to popstate
on the window
object, instead of on
the history object itself, and because 'pushState' and 'replaceState' don't
lead to a popstate
event being emitted...
uhistory
is microscopically small (~0.7kB minified and gzipped) and has only
one dependency, on uevents, which is a
lean version of the widely popular Node JS EventEmitter library. Together, they
create an API that feels natural and standard:
const history = require('uhistory')()
history.on('back', function(){
console.info('Back!')
})
history.on('change', function(location, state, source){
// location = new location
// state = any state associated with the history entry
// source = 'pushState', 'replaceState' or 'popState' (back/forward/go actions)
console.info('Change!')
})
history.pushState({some:'state'}, 'title', '/new/page')
// > Change!
history.back()
// > Back!
// > Change!
History (ctx)
Creates a history object.
ctx
The backing context for the history object.
In browsers, you don't need to pass any arguments. History
will pick up
the native window.history
object automatically:
var History = require('uhistory')
var history = History()
In Node, there is no native history
object. So you need to pass in another
context for History
to use:
var History = require('uhistory')
var MemoryContext = require('uhistory/memorycontext')
var ctx = MemoryContext()
var history = History(ctx)
See MemoryContext for more information.
In browsers, when you create a new history object without passing in an eplicit
context, uhistory will pick up window
as the context and use window.history
and
window.location
as backing mechanism, returning a new object. window.history
is not affected.
var History = require('uhistory')
var history = History()
history === window.history // false
Sometimes, you want window.history
to be affected, so any code that uses it
will trigger events on it. In that case, explicitly pass window
as the context:
var History = require('uhistory')
var history = History(window) // pass in explicitly
history === window.history // true
Events
The following events are emitted by the history object:
change (location, state, source)
The change
event is emitted a a result of calling pushState()
or replaceState()
,
or the popstate
event firing.
location
The location object. location.href
contains the (canonical version of the) url.
state
The state object associated with the current history entry (history.state
)
source
The source of the event. One of 'pushState'
, 'replaceState'
and 'popstate'
.
popstate (event)
As a result of the popstate
event firing on the context.
event
The event object that was received from ctx.popstate
back
As a result of the back()
method being called.
forward
As a result of the forward()
method being called.
go (delta)
As a result of the go()
method being called.
delta
The number of entries to move. Can be negative to move backward.
This is the number that was passed to the go()
method
pushState (state, title, url)
As a result of the pushState()
method being called.
state
The state object that was passed to pushState
, if any
title
The title string that was passed to pushState
, if any
url
The url string that was passed to pushState
, if any
replaceState (state, title, url)
As a result of the replaceState()
method being called.
state
The state object that was passed to pushState
, if any
title
The title string that was passed to pushState
, if any
url
The url string that was passed to pushState
, if any
MemoryContext
To allow you to use uhistory on node, we need to provide the services it depends
on. The context argument you pass to history
mimics the way the history object
operates on browsers and the objects it interacts with:
back
,forward
,go
,pushState
andreplaceState
affectwindow.location
back
,forward
andgo
cause a'popstate'
event to be emitted onwindow
So, including window.history
, three objects are involved in this interaction.
MemoryContext is modeled exactly like this. It provides an object that takes the
place of window
, that has properties location
and history
to replace those
services and it simulates the interaction between those objects to be consistent
with how it happens in the browser.
To use it, require the separate module memorycontext
from the uhistory
package:
var History = require('uhistory')
var MemoryContext = require('uhistory/memorycontext')
Keeping this endpoint separate prevents it from bloating your web bundle
Now, instantiate the context object. It's location.href
property will be set to
'http://localhost'
:
var ctx = MemoryContext()
ctx.location.href // 'http://localhost'
To set a different value, pass it as an argument:
var ctx = MemoryContext('https://www.example.com')
ctx.location.href // 'https://www.example.com'
Now, pass the created context to History
:
var history = History(ctx)
MemoryContext depends on ulocation
Issues
Add an issue in this project's issue tracker to let me know of any problems you find, or questions you may have.
Copyright
Copyright 2017 by Stijn de Witt. Some rights reserved.