<html>
<head>
<script src="//code.jquery.com/jquery.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<meta charset="utf-8">
<title>Ember Starter Kit</title>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/2.1.0/normalize.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ember.js/1.9.1/ember.min.js"></script>
</head>
<body>
<script type="text/x-handlebars">
<h2>Ember Flash Messages demo <small>by @sugarpirate_</small></h2>
<p>Add flash messages with different types by clicking on the buttons below. You can also clear all messages on screen. To remove a single message, click on it.</p>
{{outlet}}
{{#each flash in flashes.queue}}
{{#flash-message flash=flash}}
<h5>{{flash.type}}</h5>
<p>{{flash.message}}</p>
{{/flash-message}}
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<div class="btn-group" role="group" aria-label="...">
<button class="btn btn-success" {{action 'success' on='click'}}>Success</button>
<button class="btn btn-warning" {{action 'warning' on='click'}}>Warning</button>
<button class="btn btn-info" {{action 'info' on='click'}}>Info</button>
<button class="btn btn-danger" {{action 'danger' on='click'}}>Danger</button>
<button class="btn btn" {{action 'clearMessages' on='click'}}>Clear</button>
</div>
</script>
<script type="text/x-handlebars" data-template-name="components/flash-message">
{{#if template}}
{{yield}}
{{else}}
{{flash.message}}
{{/if}}
</script>
</body>
</html>
var get = Ember.get;
var set = Ember.set;
var computed = Ember.computed;
var getWithDefault = Ember.getWithDefault;
var run = Ember.run;
var on = Ember.on;
var assert = Ember.assert;
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ['red', 'yellow', 'blue'];
}
});
App.IndexController = Ember.ArrayController.extend({
actions: {
success: function() {
get(this, 'flashes').success('Your work was saved.');
},
warning: function() {
get(this, 'flashes').warning('You went offline. Restoring connection...');
},
info: function() {
get(this, 'flashes').info('Did you know that cats use their tails for balance, and have nearly 30 individual bones in them?');
},
danger: function() {
get(this, 'flashes').danger('Embarassing comment deleted.');
},
clearMessages: function() {
get(this, 'flashes').clearMessages();
}
}
});
Ember.Application.initializer({
name: 'flash-messages',
initialize: function(container, application){
application.register('service:flash-messages', application.FlashMessagesService, { singleton: true });
application.inject('controller', 'flashes', 'service:flash-messages');
application.inject('route', 'flashes', 'service:flash-messages');
}
});
App.FlashMessagesService = Ember.Object.extend({
queue : Ember.A([]),
isEmpty : computed.equal('queue.length', 0),
defaultTimeout : 2000,
success: function(message, timeout) {
timeout = (timeout === undefined) ? get(this, 'defaultTimeout') : timeout;
return this._addToQueue(message, 'success', timeout);
},
info: function(message, timeout) {
timeout = (timeout === undefined) ? get(this, 'defaultTimeout') : timeout;
return this._addToQueue(message, 'info', timeout);
},
warning: function(message, timeout) {
timeout = (timeout === undefined) ? get(this, 'defaultTimeout') : timeout;
return this._addToQueue(message, 'warning', timeout);
},
danger: function(message, timeout) {
timeout = (timeout === undefined) ? get(this, 'defaultTimeout') : timeout;
return this._addToQueue(message, 'danger', timeout);
},
addMessage: function(message, type, timeout) {
type = (type === undefined) ? 'info' : type;
timeout = (timeout === undefined) ? get(this, 'defaultTimeout') : timeout;
return this._addToQueue(message, type, timeout);
},
clearMessages: function() {
var flashes = get(this, 'queue');
flashes.clear();
return flashes;
},
// private
_addToQueue: function(message, type, timeout) {
var flashes = get(this, 'queue');
var flash = this._newFlashMessage(this, message, type, timeout);
flashes.pushObject(flash);
return flash;
},
_newFlashMessage: function(service, message, type, timeout) {
type = (type === undefined) ? 'info' : type;
timeout = (timeout === undefined) ? get(this, 'defaultTimeout') : timeout;
Ember.assert('Must pass a valid flash service', service);
Ember.assert('Must pass a valid flash message', message);
return App.FlashMessage.create({
type : type,
message : message,
timeout : timeout,
flashService : service
});
}
});
App.FlashMessage = Ember.Object.extend({
isSuccess : computed.equal('type', 'success'),
isInfo : computed.equal('type', 'info'),
isWarning : computed.equal('type', 'warning'),
isDanger : computed.equal('type', 'danger'),
defaultTimeout : computed.alias('flashService.defaultTimeout'),
queue : computed.alias('flashService.queue'),
timer : null,
destroyMessage: function() {
this._destroyMessage();
},
willDestroy: function() {
this._super();
var timer = get(this, 'timer');
if (timer) {
run.cancel(timer);
set(this, 'timer', null);
}
},
// private
_destroyLater: function() {
var defaultTimeout = get(this, 'defaultTimeout');
var timeout = getWithDefault(this, 'timeout', defaultTimeout);
var destroyTimer = run.later(this, '_destroyMessage', timeout);
set(this, 'timer', destroyTimer);
}.on('init'),
_destroyMessage: function() {
var queue = get(this, 'queue');
if (queue) {
queue.removeObject(this);
}
this.destroy();
}
});
App.FlashMessageComponent = Ember.Component.extend({
classNames: [ 'alert', 'flashMessage' ],
classNameBindings: [ 'alertType' ],
alertType: computed('flash.type', function() {
var flashType = get(this, 'flash.type');
return 'alert-' + flashType;
}),
click: function() {
this._destroyFlashMessage();
},
//private
// _destroyOnTeardown: on('willDestroyElement', function() {
// this._destroyFlashMessage();
// }),
_destroyFlashMessage: function() {
var flash = get(this, 'flash');
flash.destroyMessage();
}
});
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. |