<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<!DOCTYPE html><html class=''>
<head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/pauloelias/pen/kkYaWr?depth=everything&order=popularity&page=26&q=react&show_forks=false" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<style class="cp-pen-styles">/* Blatantly stolen, and unmodified, from https://teamtreehouse.com/library/react-basics */
body {
background: #d5d5d5;
font-family: arial;
color: #FAFAFA;
text-transform: uppercase;
}
.scoreboard {
background: #333;
width: 700px;
margin: 70px auto;
box-shadow: 0 4px 0px #333;
border-radius: 15px;
}
.header {
padding: 5px 10px;
text-align: center;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
background-color: #222;
border-radius: 15px 15px 0 0;
border-bottom: solid 2px #444;
}
.header h1 {
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
font-size: 1.5em;
letter-spacing: 3px;
font-weight: normal;
}
.header .stats,
.header .stopwatch {
width: 170px;
}
.stats {
margin-top: 0;
font-weight: normal;
}
.stats td:first-child {
text-align: right;
font-weight: normal;
letter-spacing: 2px;
color: #666;
font-size: .7em;
}
.stats td:last-child {
text-align: left;
}
.stopwatch {
padding: 15px 10px 5px 10px;
margin: -5px -10px -5px 10px;
background: #2f2f2f;
border-radius: 0 15px 0 0;
}
.stopwatch-time {
font-family: monospace;
font-size: 2em;
}
.stopwatch button {
margin: 8px 5px;
background-color: #222;
border-radius: 5px;
padding: 7px 8px;
border: none;
color: #999;
letter-spacing: 2px;
font-weight: bold;
text-shadow: none;
text-transform: uppercase;
}
.stopwatch button:hover {
background: #4b71b5;
color: #fafafa;
cursor: pointer;
}
.stopwatch h2 {
font-size: .6em;
margin: 0;
font-weight: normal;
letter-spacing: 2px;
color: #666;
}
.player {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
font-size: 1.2em;
border-bottom: solid 2px #444;
letter-spacing: 2px;
}
.remove-player {
visibility: hidden;
margin-right: 10px;
color: #e57373;
cursor: pointer;
}
.player-name:hover .remove-player {
visibility: visible;
}
.player-name {
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
padding: 20px 10px 10px 10px;
}
.player-score {
width: 190px;
background: blue;
}
.counter {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
.counter-action {
border: none;
font-weight: bold;
color: #FAFAFA;
display: block;
padding: 20px 20px;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.counter-action.increment {
background: #66BB6A;
}
.counter-action.increment:hover {
background: #549d59;
cursor: pointer;
}
.counter-action.decrement {
background: #ef5350;
}
.counter-action.decrement:hover {
background: #c44442;
cursor: pointer;
}
.counter-score {
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
background: #2b2b2b;
color: #FAFAFA;
text-align: center;
font-family: monospace;
padding: 10px;
font-size: 2em;
}
.add-player-form form {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
background-color: #222;
border-radius: 0 0 20px 20px
}
.add-player-form input[type=text] {
-webkit-box-flex: 1;
-ms-flex-positive: 1;
flex-grow: 1;
border-width: 0 0 1px 0;
margin: 15px 10px 15px 15px;
padding: 10px;
border-radius: 5px;
background-color: #333;
border-style: none;
text-shadow: none;
text-transform: uppercase;
color: #999;
letter-spacing: 2px;
outline: none;
}
.add-player-form input[type=text]::-webkit-input-placeholder{
color: #666;
letter-spacing: 2px;
}
.add-player-form input[type=text]:focus{
background-color: #444;
}
.add-player-form input[type=submit] {
display: block;
font-size: .6em;
margin: 15px 15px 15px 0;
padding: 10px;
background-color: #333;
border-radius: 5px;
border: none;
color: #999;
letter-spacing: 2px;
font-weight: bold;
text-shadow: none;
text-transform: uppercase;
}
.add-player-form input[type=submit]:hover{
background: #4b71b5;
color: #fafafa;
cursor: pointer;
}</style></head><body>
<div id="App">Loading...</div>
<script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script><script src='https://npmcdn.com/react@15.3.0/dist/react.min.js'></script><script src='https://npmcdn.com/react-dom@15.3.0/dist/react-dom.min.js'></script>
<script >"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/*
All code here is blatantly stolen from Treehouse's React Basics workshop found at https://teamtreehouse.com/library/react-basics
The difference is, after completing the worksjop I ES2015-ified the react components and javascript as an exercise to practice more ES2015.
*/
var PLAYERS = [{
name: "Jim Hoskins",
score: 31,
id: 1
}, {
name: "Andrew Chalkley",
score: 35,
id: 2
}, {
name: "Alena Holligan",
score: 42,
id: 3
}];
// This should be a random number that does not conflict with
// `player.id` defined in PLAYERS
var nextId = 4;
var Stopwatch = function (_React$Component) {
_inherits(Stopwatch, _React$Component);
function Stopwatch(props) {
_classCallCheck(this, Stopwatch);
// Set default state
var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));
_this.state = {
running: false,
elapsedTime: 0,
previousTime: 0
};
// Bind custom methods
_this._onTick = _this._onTick.bind(_this);
_this._onStart = _this._onStart.bind(_this);
_this._onStop = _this._onStop.bind(_this);
_this._onReset = _this._onReset.bind(_this);
return _this;
}
Stopwatch.prototype.componentDidMount = function componentDidMount() {
this.interval = setInterval(this._onTick, 100);
};
Stopwatch.prototype.componentWillUnmount = function componentWillUnmount() {
clearInterval(this.interval);
};
Stopwatch.prototype._onTick = function _onTick() {
if (this.state.running) {
var now = Date.now();
this.setState({
previousTime: now,
elapsedTime: this.state.elapsedTime + (now - this.state.previousTime)
});
}
};
Stopwatch.prototype._onStart = function _onStart() {
this.setState({
running: true,
previousTime: Date.now()
});
};
Stopwatch.prototype._onStop = function _onStop() {
this.setState({ running: false });
};
Stopwatch.prototype._onReset = function _onReset() {
this.setState({
elapsedTime: 0,
previousTime: Date.now()
});
};
Stopwatch.prototype.render = function render() {
var seconds = Math.floor(this.state.elapsedTime / 1000);
return React.createElement(
"div",
{ className: "stopwatch" },
React.createElement(
"h2",
null,
"Stopwatch"
),
React.createElement(
"div",
{ className: "stopwatch-time" },
seconds
),
this.state.running ? React.createElement(
"button",
{ onClick: this._onStop },
"Stop"
) : React.createElement(
"button",
{ onClick: this._onStart },
"Start"
),
React.createElement(
"button",
{ onClick: this._onReset },
"Reset"
)
);
};
return Stopwatch;
}(React.Component);
var AddPlayerForm = function (_React$Component2) {
_inherits(AddPlayerForm, _React$Component2);
function AddPlayerForm(props) {
_classCallCheck(this, AddPlayerForm);
// Set default state
var _this2 = _possibleConstructorReturn(this, _React$Component2.call(this, props));
_this2.state = { name: '' };
// Bind custom methods
_this2._onNameChange = _this2._onNameChange.bind(_this2);
_this2._onSubmit = _this2._onSubmit.bind(_this2);
return _this2;
}
AddPlayerForm.prototype._onNameChange = function _onNameChange(e) {
this.setState({ name: e.target.value });
};
AddPlayerForm.prototype._onSubmit = function _onSubmit(e) {
e.preventDefault();
this.props.onAdd(this.state.name);
this.setState({ name: '' });
};
AddPlayerForm.prototype.render = function render() {
return React.createElement(
"div",
{ className: "add-player-form" },
React.createElement(
"form",
{ onSubmit: this._onSubmit },
React.createElement("input", { type: "text", value: this.state.name, onChange: this._onNameChange }),
React.createElement("input", { type: "submit", value: "Add Player" })
)
);
};
return AddPlayerForm;
}(React.Component);
// Define proptypes fpr a stateless component
AddPlayerForm.propTypes = {
onAdd: React.PropTypes.func.isRequired
};
// Es6 Stateless component
var Stats = function Stats(props) {
var totalPlayers = props.players.length;
var totalPoints = props.players.reduce(function (total, player) {
return total + player.score;
}, 0);
return React.createElement(
"table",
{ className: "stats" },
React.createElement(
"tbody",
null,
React.createElement(
"tr",
null,
React.createElement(
"td",
null,
"Players:"
),
React.createElement(
"td",
null,
totalPlayers
)
),
React.createElement(
"tr",
null,
React.createElement(
"td",
null,
"Total Points:"
),
React.createElement(
"td",
null,
totalPoints
)
)
)
);
};
// Define proptypes fpr a stateless component
Stats.propTypes = {
players: React.PropTypes.array.isRequired
};
// Es6 Stateless component
var Header = function Header(props) {
return React.createElement(
"div",
{ className: "header" },
React.createElement(Stats, { players: props.players }),
React.createElement(
"h1",
null,
props.title
),
React.createElement(Stopwatch, null)
);
};
// Define proptypes fpr a stateless component
Header.propTypes = {
title: React.PropTypes.string.isRequired,
players: React.PropTypes.array.isRequired
};
// Es6 Stateless component
var Counter = function Counter(props) {
return React.createElement(
"div",
{ className: "counter" },
React.createElement(
"button",
{ className: "counter-action decrement", onClick: function onClick() {
props.onChange(-1);
} },
" - "
),
React.createElement(
"div",
{ className: "counter-score" },
" ",
props.score,
" "
),
React.createElement(
"button",
{ className: "counter-action increment", onClick: function onClick() {
props.onChange(1);
} },
" + "
)
);
};
// Define proptypes fpr a stateless component
Counter.propTypes = {
score: React.PropTypes.number.isRequired,
onChange: React.PropTypes.func.isRequired
};
// Es6 Stateless component
var Player = function Player(props) {
return React.createElement(
"div",
{ className: "player" },
React.createElement(
"div",
{ className: "player-name" },
React.createElement(
"a",
{ className: "remove-player", onClick: props.onRemove },
"✖"
),
props.name
),
React.createElement(
"div",
{ className: "player-score" },
React.createElement(Counter, { score: props.score, onChange: props.onScoreChange })
)
);
};
// Define proptypes fpr a stateless component
Player.propTypes = {
name: React.PropTypes.string.isRequired,
score: React.PropTypes.number.isRequired,
onScoreChange: React.PropTypes.func.isRequired,
onRemove: React.PropTypes.func.isRequired
};
var Application = function (_React$Component3) {
_inherits(Application, _React$Component3);
function Application(props) {
_classCallCheck(this, Application);
// Set the initial state
var _this3 = _possibleConstructorReturn(this, _React$Component3.call(this, props));
_this3.state = { players: _this3.props.initialPlayers };
// Bind custom methods
_this3._onScoreChange = _this3._onScoreChange.bind(_this3);
_this3._onPlayerAdd = _this3._onPlayerAdd.bind(_this3);
_this3._onRemovePlayer = _this3._onRemovePlayer.bind(_this3);
return _this3;
}
Application.prototype._onScoreChange = function _onScoreChange(index, delta) {
this.state.players[index].score += delta;
this.setState(this.state);
};
Application.prototype._onPlayerAdd = function _onPlayerAdd(name) {
this.state.players.push({
name: name,
score: 0,
id: nextId
});
this.setState(this.state);
nextId += 1;
};
Application.prototype._onRemovePlayer = function _onRemovePlayer(index) {
this.state.players.splice(index, 1);
this.setState(this.state);
};
Application.prototype.render = function render() {
var _this4 = this;
return React.createElement(
"div",
{ className: "scoreboard" },
React.createElement(Header, { title: this.props.title, players: this.state.players }),
React.createElement(
"div",
{ className: "players" },
this.state.players.map(function (player, index) {
return React.createElement(Player, {
onScoreChange: function onScoreChange(delta) {
return _this4._onScoreChange(index, delta);
},
onRemove: function onRemove() {
return _this4._onRemovePlayer(index);
},
name: player.name,
score: player.score,
key: player.id });
})
),
React.createElement(AddPlayerForm, { onAdd: this._onPlayerAdd })
);
};
return Application;
}(React.Component);
Application.propTypes = {
title: React.PropTypes.string,
initialPlayers: React.PropTypes.arrayOf(React.PropTypes.shape({
name: React.PropTypes.string.isRequired,
score: React.PropTypes.number.isRequired,
id: React.PropTypes.number.isRequired
})).isRequired
};
Application.defaultProps = {
title: "Scoreboard"
};
// Load the app into the DOM
ReactDOM.render(React.createElement(Application, { initialPlayers: PLAYERS }), document.getElementById('App'));
//# sourceURL=pen.js
</script>
</body></html>