add DOMTitleChange event (#525)

This commit is contained in:
Yoshua Wuyts
2017-07-03 10:43:44 +02:00
committed by GitHub
parent 711f92a7c1
commit 38a875a0d6
2 changed files with 22 additions and 1 deletions
+10
View File
@@ -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.
+12 -1
View File
@@ -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)
}) })