Created
March 19, 2015 17:21
-
-
Save jviereck/9a71734afcfe848ddbe2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var React = require('react'); | |
// EXAMPLE: | |
// | |
// var ExampleComponent = React.createClass({ | |
// render(): any { | |
// // Define the CSS content used by this component. | |
// var styleContent = ` | |
// .chunkTitle { | |
// background: lightgray; | |
// margin-bottom: 4px; | |
// padding: 2px; | |
// }`; | |
// // By using a <StyleDef content="cssContent" /> the CSS definitions get | |
// // added within an <style>cssContent</style> in the header of the page. | |
// return ( | |
// <div className="chunkTitle"> | |
// <StyleDef content={styleContent} /> | |
// ContentGoesHere. | |
// </div> | |
// ); | |
// } | |
// }); | |
// Way to define CSS styles in React components that appear as real <styles> | |
// on the page instead of using the `styles` property. | |
// Defining the CSS string directly inside of a <style> tag does not work as | |
// the parser used by babel.js rejects CSS text like "2px" as invalid JS. Also, | |
// the placeholder like `{someVar}` causes problems with the usage of brakets | |
// in a CSS definition like `.class { color: red }`, where the content between | |
// the brackets should not be replaced by a variable. | |
// The CSS content is defined with the helf of a react component <StyleDef /> | |
// where the actual CSS content is defined as the `content="..."` property. | |
// Instead of creating a <style> element on the page per <StyleDef /> component, | |
// only one <style> element per unique CSS content is created. Reference counting | |
// is used to determine if the CSS content is no longer used in th app and the | |
// corresponding <style> can be removed from the page again. | |
// List of all the physical styles currently mounted in the document's <head>. | |
var mountedDomStyles = []; | |
var DOMStyle = function(content) { | |
this.content = content; | |
this.refCounter = 1; | |
// Create the actual style element and mount it in the document's <head>. | |
this.dom = document.createElement('style'); | |
this.dom.textContent = content; | |
document.head.appendChild(this.dom); | |
} | |
var incrStyleContent = function(content) { | |
for (var i = 0; i < mountedDomStyles.length; i++) { | |
if (mountedDomStyles[i].content === content) { | |
mountedDomStyles[i].refCounter += 1; | |
return; | |
} | |
} | |
mountedDomStyles.push(new DOMStyle(content)); | |
} | |
var decrStyleContent = function(content) { | |
for (var i = 0; i < mountedDomStyles.length; i++) { | |
if (mountedDomStyles[i] === content) { | |
if ((mountedDomStyles[i].refCounter -= 1) == 0) { | |
document.head.remove(mountedDomStyles[i].dom); | |
mountedDomStyles.splice(i, 1); | |
return; | |
} | |
} | |
} | |
} | |
var StyleDef = React.createClass({ | |
componentDidMount: function() { | |
incrStyleContent(this.props.content); | |
}, | |
componentDidUpdate: function(nextProps) { | |
if (nextProps.content !== this.props.content) { | |
decrStyleContent(this.props.content); | |
incrStyleContent(nextProps.content); | |
} | |
}, | |
componentDidUnmount: function() { | |
decrStyleContent(this.props.content); | |
}, | |
render(): any { | |
// The <StyleDef> itself should not appear in the DOM. | |
return null; | |
} | |
}); | |
module.exports = { | |
StyleDef: StyleDef | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment