react-document-title
Advanced tools
Comparing version 0.1.3 to 1.0.0
150
index.js
@@ -1,69 +0,25 @@ | ||
/** @jsx React.DOM */ | ||
'use strict'; | ||
var React = require('react'), | ||
Children = require('react/addons').Children, | ||
PropTypes = React.PropTypes; | ||
createSideEffect = require('react-side-effect'); | ||
/** | ||
* Provides a declarative way to specify `document.title` in a single-page app. | ||
* This component is only intended for client-side usage. | ||
* | ||
* Because it is just a React component, you can return it in `render` inside | ||
* your own components, and use their `props` or `state` to determine the title. | ||
* | ||
* `DocumentTitle` does not render to DOM itself, not even to a <noscript />. | ||
* In its `render`, it simply returns the only child that was passed to it. | ||
* Being a container itself, it allows title nesting and specificity. | ||
var _serverTitle = null; | ||
* For example, you may put it at the very top of view hierarchy to specify the | ||
* default title, and then you can give some pages their own `DocumentTitle`s | ||
* that depend on their `props` or `state`. | ||
* | ||
* Sample code (assuming you use something like react-router): | ||
* | ||
* var App = React.createClass({ | ||
* render: function () { | ||
* | ||
* // Use "My Web App" if no child overrides this | ||
* | ||
* return ( | ||
* <DocumentTitle title='My Web App'> | ||
* <this.props.activeRouteHandler /> | ||
* </DocumentTitle> | ||
* ); | ||
* } | ||
* }); | ||
* | ||
* var HomePage = React.createClass({ | ||
* render: function () { | ||
* | ||
* // Use "Home" when this component is mounted | ||
* | ||
* return ( | ||
* <DocumentTitle title='Home'> | ||
* <h1>Home, sweet home.</h1> | ||
* </DocumentTitle> | ||
* ); | ||
* } | ||
* }); | ||
* | ||
* var NewArticlePage = React.createClass({ | ||
* mixins: [LinkStateMixin], | ||
* | ||
* render: function () { | ||
* | ||
* // Update using value from state when this component is mounted | ||
* | ||
* return ( | ||
* <DocumentTitle title={this.state.title || 'Untitled'}> | ||
* <div> | ||
* <h1>New Article</h1> | ||
* <input valueLink={this.linkState('title')} /> | ||
* </div> | ||
* </DocumentTitle> | ||
* ); | ||
* } | ||
* }); | ||
*/ | ||
function getTitleFromPropsList(propsList) { | ||
var innermostProps = propsList[propsList.length - 1]; | ||
if (innermostProps) { | ||
return innermostProps.title; | ||
} | ||
} | ||
var SetDocumentTitle = createSideEffect(function handleChange(propsList) { | ||
var title = getTitleFromPropsList(propsList); | ||
if (typeof document !== 'undefined') { | ||
document.title = title || ''; | ||
} else { | ||
_serverTitle = title || null; | ||
} | ||
}); | ||
var DocumentTitle = React.createClass({ | ||
@@ -73,72 +29,22 @@ displayName: 'DocumentTitle', | ||
propTypes: { | ||
title: PropTypes.string | ||
title: React.PropTypes.string.isRequired | ||
}, | ||
statics: { | ||
mountedInstances: [], | ||
peek: function () { | ||
return _serverTitle; | ||
}, | ||
rewind: function () { | ||
var activeInstance = DocumentTitle.getActiveInstance(); | ||
DocumentTitle.mountedInstances.splice(0); | ||
if (activeInstance) { | ||
return activeInstance.props.title; | ||
} | ||
}, | ||
getActiveInstance: function () { | ||
var length = DocumentTitle.mountedInstances.length; | ||
if (length > 0) { | ||
return DocumentTitle.mountedInstances[length - 1]; | ||
} | ||
}, | ||
updateDocumentTitle: function () { | ||
if (typeof document === 'undefined') { | ||
return; | ||
} | ||
var activeInstance = DocumentTitle.getActiveInstance(); | ||
if (activeInstance) { | ||
document.title = activeInstance.props.title; | ||
} | ||
var title = _serverTitle; | ||
SetDocumentTitle.dispose(); | ||
return title; | ||
} | ||
}, | ||
getDefaultProps: function () { | ||
return { | ||
title: '' | ||
}; | ||
}, | ||
isActive: function () { | ||
return this === DocumentTitle.getActiveInstance(); | ||
}, | ||
componentWillMount: function () { | ||
DocumentTitle.mountedInstances.push(this); | ||
DocumentTitle.updateDocumentTitle(); | ||
}, | ||
componentDidUpdate: function (prevProps) { | ||
if (this.isActive() && prevProps.title !== this.props.title) { | ||
DocumentTitle.updateDocumentTitle(); | ||
} | ||
}, | ||
componentWillUnmount: function () { | ||
var index = DocumentTitle.mountedInstances.indexOf(this); | ||
DocumentTitle.mountedInstances.splice(index, 1); | ||
DocumentTitle.updateDocumentTitle(); | ||
}, | ||
render: function () { | ||
if (this.props.children) { | ||
return Children.only(this.props.children); | ||
} else { | ||
return null; | ||
} | ||
return React.createElement(SetDocumentTitle, this.props); | ||
} | ||
}); | ||
module.exports = DocumentTitle; | ||
module.exports = DocumentTitle; |
{ | ||
"name": "react-document-title", | ||
"version": "0.1.3", | ||
"version": "1.0.0", | ||
"description": "A declarative, nested, stateful document.title for React", | ||
@@ -37,3 +37,6 @@ "main": "index.js", | ||
"react": "^0.12.0" | ||
}, | ||
"dependencies": { | ||
"react-side-effect": "~0.1.0" | ||
} | ||
} |
@@ -84,5 +84,5 @@ /*jshint newcap: false */ | ||
); | ||
expect(DocumentTitle.mountedInstances.length).to.be.greaterThan(0); | ||
expect(DocumentTitle.peek()).to.equal('c'); | ||
DocumentTitle.rewind(); | ||
expect(DocumentTitle.mountedInstances.length).to.equal(0); | ||
expect(DocumentTitle.peek()).to.equal(null); | ||
}); | ||
@@ -105,4 +105,4 @@ it('returns the latest document title', function () { | ||
DocumentTitle.rewind(); | ||
expect(DocumentTitle.rewind()).to.equal(undefined); | ||
expect(DocumentTitle.peek()).to.equal(null); | ||
}); | ||
}); |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
0
10750
2
207
+ Addedreact-side-effect@~0.1.0
+ Addedreact-side-effect@0.1.0(transitive)