<html>
<head>
<meta name="description" content="Chat Guide 3.0 - Real Time">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<chat-app></chat-app>
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
<script src="https://unpkg.com/can@^4.1.0/dist/global/can.all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.8/socket.io.js"></script>
</body>
</html>
chat-home {
display: block;
}
chat-home h1.page-header { margin-top: 0; }
var Message = can.DefineMap.extend({
id: "number",
name: "string",
body: "string",
created_at: "date"
});
Message.List = can.DefineList.extend({
"#": Message
});
Message.connection = can.connect.superMap({
url: {
resource: 'https://chat.donejs.com/api/messages',
contentType: 'application/x-www-form-urlencoded'
},
Map: Message,
List: Message.List,
name: 'message'
});
var socket = io('https://chat.donejs.com');
socket.on('messages created', function(message){
Message.connection.createInstance(message);
});
socket.on('messages updated', function(message){
Message.connection.updateInstance(message);
});
socket.on('messages removed', function(message){
Message.connection.destroyInstance(message);
});
can.Component.extend({
tag: "chat-messages",
view: `
<h1 class="page-header text-center">
Chat Messages
</h1>
<h5><a href="{{routeUrl(page='home')}}">Home</a></h5>
{{#if(messagesPromise.isPending)}}
<div class="list-group-item list-group-item-info">
<h4 class="list-group-item-heading">Loading…</h4>
</div>
{{/if}}
{{#if(messagesPromise.isRejected)}}
<div class="list-group-item list-group-item-danger">
<h4 class="list-group3--item-heading">Error</h4>
<p class="list-group-item-text">{{messagesPromise.reason}}</p>
</div>
{{/if}}
{{#if(messagesPromise.isResolved)}}
{{#each(messagesPromise.value)}}
<div class="list-group-item">
<h4 class="list-group3--item-heading">{{name}}</h4>
<p class="list-group-item-text">{{body}}</p>
</div>
{{else}}
<div class="list-group-item">
<h4 class="list-group-item-heading">No messages</h4>
</div>
{{/each}}
{{/if}}
<form class="row" on:submit="send(scope.event)">
<div class="col-sm-3">
<input type="text" class="form-control" placeholder="Your name"
value:bind="name"/>
</div>
<div class="col-sm-6">
<input type="text" class="form-control" placeholder="Your message"
value:bind="body"/>
</div>
<div class="col-sm-3">
<input type="submit" class="btn btn-primary btn-block" value="Send"/>
</div>
</form>`,
ViewModel: {
messagesPromise: {
default: function(){
return Message.getList({});
}
},
name: "string",
body: "string",
send: function(event) {
event.preventDefault();
new Message({
name: this.name,
body: this.body
}).save().then(function(){
this.body = "";
}.bind(this));
}
}
});
can.Component.extend({
tag: "chat-app",
view: `
<div class="container">
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
{{#eq(page, 'home')}}
<h1 class="page-header text-center" on:click="addExcitement()">
{{message}}
</h1>
<a href="{{routeUrl(page='chat')}}"
class="btn btn-primary btn-block btn-lg">
Start chat
</a>
{{else}}
<chat-messages/>
{{/eq}}
</div>
</div>
</div>`,
ViewModel: {
init(){
can.route.register("{page}",{page: "home"});
can.route.data = this;
can.route.start();
},
page: "string",
message: {
type: "string",
default: "Chat Home",
serialize: false
},
addExcitement: function(){
this.message = this.message + "!";
}
}
});
Output
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. |