<html>
<head>
<script src="//fb.me/react-0.12.0.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
</body>
</html>
var Input = React.createFactory(React.createClass({
render: function () {
var inputClass = this.props.invalid ?
"react-tagsinput-input react-tagsinput-invalid" :
"react-tagsinput-input";
return this.transferPropsTo(
React.DOM.input({
type: "text"
, className: inputClass
, placeholder: this.props.placeholder
})
);
}
}));
var Tag = React.createFactory(React.createClass({
render: function () {
return (
React.DOM.span({
className: "react-tagsinput-tag"
}, this.props.tag + " ", React.DOM.a({
onClick: this.props.remove
, className: "react-tagsinput-remove"
}))
);
}
}));
var TagsInput = React.createClass({
getDefaultProps: function () {
return {
tags: []
, placeholder: "Add a tag"
, validate: function (tag) { return tag !== ""; }
, addKeys: [13, 9]
, removeKeys: [8]
, onTagAdd: function () { }
, onTagRemove: function () { }
, onChange: function () { }
};
}
, getInitialState: function () {
return {
tags: []
, tag: ""
, invalid: false
};
}
, componentWillMount: function () {
this.setState({
tags: this.props.tags.slice(0)
});
}
, getTags: function () {
return this.state.tags;
}
, addTag: function () {
var tag = this.state.tag.trim();
if (this.state.tags.indexOf(tag) !== -1 || !this.props.validate(tag)) {
return this.setState({
invalid: true
});
}
this.setState({
tags: this.state.tags.concat([tag])
, tag: ""
, invalid: false
}, function () {
this.props.onTagAdd(tag);
this.props.onChange(this.state.tags);
this.inputFocus();
});
}
, removeTag: function (i) {
var tags = this.state.tags.slice(0);
var tag = tags.splice(i, 1);
this.setState({
tags: tags
, invalid: false
}, function () {
this.props.onTagRemove(tag[0]);
this.props.onChange(this.state.tags);
});
}
, onKeyDown: function (e) {
var add = this.props.addKeys.indexOf(e.keyCode) !== -1
, remove = this.props.removeKeys.indexOf(e.keyCode) !== -1;
if (add) {
e.preventDefault();
this.addTag();
}
if (remove && this.state.tags.length > 0 && this.state.tag === "") {
this.removeTag(this.state.tags.length - 1);
}
}
, onChange: function (e) {
this.setState({
tag: e.target.value
, invalid: false
});
}
, onBlur: function (e) {
if (this.state.tag !== "" && !this.state.invalid) {
this.addTag();
}
}
, inputFocus: function () {
this.refs.input.getDOMNode().focus();
}
, render: function() {
var tagNodes = this.state.tags.map(function (tag, i) {
return Tag({
key: i
, tag: tag
, remove: this.removeTag.bind(null, i)
});
}.bind(this));
return (
React.DOM.div({
className: "react-tagsinput"
}, tagNodes, Input({
ref: "input"
, placeholder: this.props.placeholder
, value: this.state.tag
, invalid: this.state.invalid
, onKeyDown: this.onKeyDown
, onChange: this.onChange
, onBlur: this.onBlur
}))
);
}
});
var TagsComponent = React.createClass({
displayName: "TagsComponent",
saveTags: function () {
console.log('tags: ', this.refs.tags.getTags().join(', '));
},
render: function () {
return (
React.createElement("div", null,
React.createElement(TagsInput, {ref: "tags", tags: ["tag1", "tag2"]}),
React.createElement("button", {onClick: this.saveTags}, "Save")
)
);
}
});
React.render(React.createElement(TagsComponent, null), document.body);
Output
300px
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |