See a working demo here:
http://jsbin.com/ceseku/3/edit?html,css,js,output
Component
Logic
/**
* Notifications Manager of Notifications Widget
* Object which manages incoming transactions and provides
* access to App.Notification which can not be directly
* accessed.
*
* @example
* App.NotificationsManager.push({type: 'error', msg: 'Unable to persist comment'});
* App.NotificationsManager.push({msg: 'Unable to persist comment'});
* App.NotificationsManager.push('Plain message');
*/
App.NotificationsManager = Ember.Object.create({
/**
* Array store for message objects
* type {Array}
*/
content: Ember.A(),
/**
* @param options {Object} the message object containing msg and type
*/
push: function(options) {
var self = this,
message,
type; // success|warning|error|info
if (!Boolean(arguments)) return;
if (typeof options === 'object' && options.msg) {
message = options.msg;
type = options.type || 'warning';
} else if (typeof options === 'string') {
message = options;
type = 'warning';
} else {
return false;
}
self.get('content').pushObject({
type: type,
message: message
});
}
});
/**
* A collection of Notification Items of Notification Widget
* @requires App.NotificationsManager
*/
App.NotificationsListComponent = Ember.Component.extend({
classNames: ['Notifications'],
tagName: 'section',
content: App.NotificationsManager.get('content')
});
/**
* A Notification Item of Notification Widget
* @requires App.NotificationsListComponent
*/
App.NotificationsListItemComponent = Ember.Component.extend({
classNames: ['Notifications__item', 'alert', 'alert-dismissible'],
classNameBindings: ['typeClass'],
item: null,
typeClass: function() {
return 'alert-' + this.get('item.type');
}.property('item.type'),
isSuccess: function() {
return this.get('item.type') === 'success';
}.property('item.type'),
duration: 6000,
timer: null,
showNotification: function(time) {
var self = this;
self.set('timer', window.setTimeout(function() {
self.clearNotification();
self.clearTimeout();
}, time));
},
clearNotification: function() {
this.$().fadeOut();
App.NotificationsManager.get('content').removeObject(this.get('content'));
this.set('timer', null);
},
clearTimeout: function() {
var self = this;
if (self.get('timer') !== null) {
window.clearTimeout(self.get('timer'));
self.set('timer', null);
}
},
didInsertElement: function() {
var self = this;
this.showNotification(self.get('duration'));
},
mouseEnter: function() {
this.clearTimeout();
},
mouseLeave: function() {
var halfSpeedTime = this.get('duration') / 2;
this.showNotification(halfSpeedTime);
},
actions: {
clear: function() {
this.clearNotification();
}
}
// willDestroyElement: function() {
// }
});
Templates
<script type="text/x-handlebars" data-template-name="components/notifications-list">
{{#each notification in content}}
{{notifications-list-item item=notification}}
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="components/notifications-list-item">
<div class="Notifications__item__icon">
{{#if isSuccess}}
<i class="glyphicon glyphicon-ok-sign info-icon"></i>
{{else}}
<i class="glyphicon glyphicon-question-sign info-icon"></i>
{{/if}}
</div>
<div class="Notifications__item__main">
<span>{{item.message}}</span>
</div>
<button type="button" class="Notifications__item__close close" {{action "clear"}}><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
</script>
Styles
.Notifications {
position: fixed;
top: 20px;
right: 50%;
left: 50%;
margin-left: -200px;
z-index: $zindex-navbar-fixed;
width: 400px;
}
.Notifications .info-icon {
margin-right: 6px;
}
.Notifications__item {
display: table;
cursor: pointer;
box-shadow: 0 3px 3px rgba(black, .16), 0 3px 3px rgba(black, .23);
width: 90%;
margin-left: auto;
margin-right: auto;
}
.Notifications__item__icon,
.Notifications__item__main,
.Notifications__item__close {
display: table-cell;
vertical-align: top;
}
.Notifications__item__icon {
width: 26px;
}
.Notifications__item__main span {
word-wrap: break-word;
text-wrap:none;
}
}
.Notifications__item__close {
width: 20px;
text-align: right;
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…