add DOMTitleChange event (#525)
This commit is contained in:
@@ -209,6 +209,13 @@ will be a previous entry in the browser's history stack, and will emit
|
|||||||
`'navigate'` and `'render'`. Similar to
|
`'navigate'` and `'render'`. Similar to
|
||||||
[history.popState](http://devdocs.io/dom_events/popstate).
|
[history.popState](http://devdocs.io/dom_events/popstate).
|
||||||
|
|
||||||
|
### `'DOMTitleChange'`|`state.events.DOMTITLECHANGE`
|
||||||
|
This event should be emitted whenever the `document.title` needs to be updated.
|
||||||
|
It will set both `document.title` and `state.title`. This value can be used
|
||||||
|
when server rendering to accurately include a `<title>` tag in the header.
|
||||||
|
This is derived from the
|
||||||
|
[DOMTitleChanged event](https://developer.mozilla.org/en-US/docs/Web/Events/DOMTitleChanged).
|
||||||
|
|
||||||
## State
|
## State
|
||||||
Choo comes with a shared state object. This object can be mutated freely, and
|
Choo comes with a shared state object. This object can be mutated freely, and
|
||||||
is passed into the view functions whenever `'render'` is emitted. The state
|
is passed into the view functions whenever `'render'` is emitted. The state
|
||||||
@@ -232,6 +239,9 @@ An object containing the current queryString. `/foo?bin=baz` becomes `{ bin:
|
|||||||
### `state.route`
|
### `state.route`
|
||||||
The current name of the route used in the router (e.g. `/foo/:bar`).
|
The current name of the route used in the router (e.g. `/foo/:bar`).
|
||||||
|
|
||||||
|
### `state.title`
|
||||||
|
The current page title. Can be set using the `DOMTitleChange` event.
|
||||||
|
|
||||||
## Routing
|
## Routing
|
||||||
Choo is an application level framework. This means that it takes care of
|
Choo is an application level framework. This means that it takes care of
|
||||||
everything related to routing and pathnames for you.
|
everything related to routing and pathnames for you.
|
||||||
|
|||||||
@@ -20,9 +20,12 @@ function Choo (opts) {
|
|||||||
|
|
||||||
assert.equal(typeof opts, 'object', 'choo: opts should be type object')
|
assert.equal(typeof opts, 'object', 'choo: opts should be type object')
|
||||||
|
|
||||||
|
var self = this
|
||||||
|
|
||||||
// define events used by choo
|
// define events used by choo
|
||||||
this._events = {
|
this._events = {
|
||||||
DOMCONTENTLOADED: 'DOMContentLoaded',
|
DOMCONTENTLOADED: 'DOMContentLoaded',
|
||||||
|
DOMTITLECHANGE: 'DOMTitleChange',
|
||||||
REPLACESTATE: 'replaceState',
|
REPLACESTATE: 'replaceState',
|
||||||
PUSHSTATE: 'pushState',
|
PUSHSTATE: 'pushState',
|
||||||
NAVIGATE: 'navigate',
|
NAVIGATE: 'navigate',
|
||||||
@@ -33,6 +36,7 @@ function Choo (opts) {
|
|||||||
// properties for internal use only
|
// properties for internal use only
|
||||||
this._historyEnabled = opts.history === undefined ? true : opts.history
|
this._historyEnabled = opts.history === undefined ? true : opts.history
|
||||||
this._hrefEnabled = opts.href === undefined ? true : opts.href
|
this._hrefEnabled = opts.href === undefined ? true : opts.href
|
||||||
|
this._hasWindow = typeof window !== 'undefined'
|
||||||
this._createLocation = nanolocation
|
this._createLocation = nanolocation
|
||||||
this._tree = null
|
this._tree = null
|
||||||
|
|
||||||
@@ -40,6 +44,13 @@ function Choo (opts) {
|
|||||||
this.router = nanorouter({ curry: true })
|
this.router = nanorouter({ curry: true })
|
||||||
this.emitter = nanobus('choo.emit')
|
this.emitter = nanobus('choo.emit')
|
||||||
this.state = { events: this._events }
|
this.state = { events: this._events }
|
||||||
|
|
||||||
|
// listen for title changes; available even when calling .toString()
|
||||||
|
this.emitter.prependListener(this._events.DOMTITLECHANGE, function (title) {
|
||||||
|
assert.equal(typeof title, 'string', 'events.DOMTitleChange: title should be type string')
|
||||||
|
self.state.title = title
|
||||||
|
if (self._hasWindow) document.title = title
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Choo.prototype.route = function (route, handler) {
|
Choo.prototype.route = function (route, handler) {
|
||||||
@@ -72,7 +83,6 @@ Choo.prototype.start = function () {
|
|||||||
assert.equal(typeof window, 'object', 'choo.start: window was not found. .start() must be called in a browser, use .toString() if running in Node')
|
assert.equal(typeof window, 'object', 'choo.start: window was not found. .start() must be called in a browser, use .toString() if running in Node')
|
||||||
|
|
||||||
var self = this
|
var self = this
|
||||||
|
|
||||||
if (this._historyEnabled) {
|
if (this._historyEnabled) {
|
||||||
this.emitter.prependListener(this._events.NAVIGATE, function () {
|
this.emitter.prependListener(this._events.NAVIGATE, function () {
|
||||||
self.emitter.emit(self._events.RENDER)
|
self.emitter.emit(self._events.RENDER)
|
||||||
@@ -133,6 +143,7 @@ Choo.prototype.start = function () {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
documentReady(function () {
|
documentReady(function () {
|
||||||
|
self.state.title = document.title
|
||||||
self.emitter.emit(self._events.DOMCONTENTLOADED)
|
self.emitter.emit(self._events.DOMCONTENTLOADED)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user