/**
*弹出一个窗口
* Ext.create('Ext.ux.Notification', {
title : 'Notification',
position : 'b',
manager : 'demo1',
stickWhileHover : false,
iconCls : 'ux-notification-icon-information',
html : '慢慢 的出来了'
}).show();
*/
Ext.define('Ext.ux.Notification', {
extend: 'Ext.window.Window',
alias: 'widget.uxNotification',
cls: 'ux-notification-window',
autoClose: true,
autoHeight: true,
plain: false,
draggable: false,
shadow: false,
focus: Ext.emptyFn,
// For alignment and to store array of rendered notifications. Defaults to document if not set.
manager: null,
useXAxis: false,
// Options: br, bl, tr, tl, t, l, b, r
position: 'br',
// Pixels between each notification
spacing: 6,
// Pixels from the managers borders to start the first notification
paddingX: 30,
paddingY: 10,
slideInAnimation: 'easeIn',
slideBackAnimation: 'bounceOut',
slideInDuration: 1500,
slideBackDuration: 1000,
hideDuration: 500,
autoCloseDelay: 7000,
stickOnClick: true,
stickWhileHover: true,
// Private. Do not override!
isHiding: false,
isFading: false,
destroyAfterHide: false,
closeOnMouseOut: false,
// Caching coordinates to be able to align to final position of siblings being animated
xPos: 0,
yPos: 0,
statics: {
defaultManager: {
el: null
}
},
farhigh~~(499184414) 22:50:29
initComponent: function() {
var me = this;
// Backwards compatibility
if (Ext.isDefined(me.corner)) {
me.position = me.corner;
}
if (Ext.isDefined(me.slideDownAnimation)) {
me.slideBackAnimation = me.slideDownAnimation;
}
if (Ext.isDefined(me.autoDestroyDelay)) {
me.autoCloseDelay = me.autoDestroyDelay;
}
if (Ext.isDefined(me.autoHideDelay)) {
me.autoCloseDelay = me.autoHideDelay;
}
if (Ext.isDefined(me.autoHide)) {
me.autoClose = me.autoHide;
}
if (Ext.isDefined(me.slideInDelay)) {
me.slideInDuration = me.slideInDelay;
}
if (Ext.isDefined(me.slideDownDelay)) {
me.slideBackDuration = me.slideDownDelay;
}
if (Ext.isDefined(me.fadeDelay)) {
me.hideDuration = me.fadeDelay;
}
// 'bc', lc', 'rc', 'tc' compatibility
me.position = me.position.replace(/c/, '');
me.updateAlignment(me.position);
me.setManager(me.manager);
me.callParent(arguments);
},
onRender: function() {
var me = this;
me.callParent(arguments);
me.el.hover(
function () {
me.mouseIsOver = true;
},
function () {
me.mouseIsOver = false;
if (me.closeOnMouseOut) {
me.closeOnMouseOut = false;
me.close();
}
},
me
);
},
updateAlignment: function (position) {
var me = this;
switch (position) {
case 'br':
me.paddingFactorX = -1;
me.paddingFactorY = -1;
me.siblingAlignment = "br-br";
if (me.useXAxis) {
me.managerAlignment = "bl-br";
} else {
me.managerAlignment = "tr-br";
}
break;
case 'bl':
me.paddingFactorX = 1;
me.paddingFactorY = -1;
me.siblingAlignment = "bl-bl";
if (me.useXAxis) {
me.managerAlignment = "br-bl";
} else {
me.managerAlignment = "tl-bl";
}
break;
case 'tr':
me.paddingFactorX = -1;
me.paddingFactorY = 1;
me.siblingAlignment = "tr-tr";
if (me.useXAxis) {
me.managerAlignment = "tl-tr";
} else {
me.managerAlignment = "br-tr";
}
break;
case 'tl':
me.paddingFactorX = 1;
me.paddingFactorY = 1;
me.siblingAlignment = "tl-tl";
if (me.useXAxis) {
me.managerAlignment = "tr-tl";
} else {
me.managerAlignment = "bl-tl";
}
break;
case 'b':
me.paddingFactorX = 0;
me.paddingFactorY = -1;
me.siblingAlignment = "b-b";
me.useXAxis = 0;
me.managerAlignment = "t-b";
break;
case 't':
me.paddingFactorX = 0;
me.paddingFactorY = 1;
me.siblingAlignment = "t-t";
me.useXAxis = 0;
me.managerAlignment = "b-t";
break;
case 'l':
me.paddingFactorX = 1;
me.paddingFactorY = 0;
me.siblingAlignment = "l-l";
me.useXAxis = 1;
me.managerAlignment = "r-l";
break;
case 'r':
me.paddingFactorX = -1;
me.paddingFactorY = 0;
me.siblingAlignment = "r-r";
me.useXAxis = 1;
me.managerAlignment = "l-r";
break;
}
},
getXposAlignedToManager: function () {
var me = this;
var xPos = 0;
// Avoid error messages if the manager does not have a dom element
if (me.manager && me.manager.el && me.manager.el.dom) {
if (!me.useXAxis) {
// Element should already be aligned vertically
return me.el.getLeft();
} else {
// Using getAnchorXY instead of getTop/getBottom should give a correct placement when document is used
// as the manager but is still 0 px high. Before rendering the viewport.
if (me.position == 'br' || me.position == 'tr' || me.position == 'r') {
xPos += me.manager.el.getAnchorXY('r')[0];
xPos -= (me.el.getWidth() + me.paddingX);
} else {
xPos += me.manager.el.getAnchorXY('l')[0];
xPos += me.paddingX;
}
}
}
return xPos;
},
getYposAlignedToManager: function () {
var me = this;
var yPos = 0;
// Avoid error messages if the manager does not have a dom element
if (me.manager && me.manager.el && me.manager.el.dom) {
if (me.useXAxis) {
// Element should already be aligned horizontally
return me.el.getTop();
} else {
// Using getAnchorXY instead of getTop/getBottom should give a correct placement when document is used
// as the manager but is still 0 px high. Before rendering the viewport.
if (me.position == 'br' || me.position == 'bl' || me.position == 'b') {
yPos += me.manager.el.getAnchorXY('b')[1];
yPos -= (me.el.getHeight() + me.paddingY);
} else {
yPos += me.manager.el.getAnchorXY('t')[1];
yPos += me.paddingY;
}
}
}
return yPos;
},
getXposAlignedToSibling: function (sibling) {
var me = this;
if (me.useXAxis) {
if (me.position == 'tl' || me.position == 'bl' || me.position == 'l') {
// Using sibling's width when adding
return (sibling.xPos + sibling.el.getWidth() + sibling.spacing);
} else {
// Using own width when subtracting
return (sibling.xPos - me.el.getWidth() - me.spacing);
}
} else {
return me.el.getLeft();
}
},
getYposAlignedToSibling: function (sibling) {
var me = this;
if (me.useXAxis) {
return me.el.getTop();
} else {
if (me.position == 'tr' || me.position == 'tl' || me.position == 't') {
// Using sibling's width when adding
return (sibling.yPos + sibling.el.getHeight() + sibling.spacing);
} else {
// Using own width when subtracting
return (sibling.yPos - me.el.getHeight() - sibling.spacing);
}
}
},
getNotifications: function (alignment) {
var me = this;
if (!me.manager.notifications[alignment]) {
me.manager.notifications[alignment] = [];
}
return me.manager.notifications[alignment];
},
setManager: function (manager) {
var me = this;
me.manager = manager;
if (typeof me.manager == 'string') {
me.manager = Ext.getCmp(me.manager);
}
// If no manager is provided or found, then the static object is used and the el property pointed to the body document.
if (!me.manager) {
me.manager = me.statics().defaultManager;
if (!me.manager.el) {
me.manager.el = Ext.getBody();
}
}
if (typeof me.manager.notifications == 'undefined') {
me.manager.notifications = {};
}
},
beforeShow: function () {
var me = this;
if (me.stickOnClick) {
if (me.body && me.body.dom) {
Ext.fly(me.body.dom).on('click', function () {
me.cancelAutoClose();
me.addCls('notification-fixed');
}, me);
}
}
if (me.autoClose) {
me.task = new Ext.util.DelayedTask(me.doAutoClose, me);
me.task.delay(me.autoCloseDelay);
}
// Shunting offscreen to avoid flicker
me.el.setX(-10000);
me.el.setOpacity(1);
},
afterShow: function () {
var me = this;
me.callParent(arguments);
var notifications = me.getNotifications(me.managerAlignment);
if (notifications.length) {
me.el.alignTo(notifications[notifications.length - 1].el, me.siblingAlignment, [0, 0]);
me.xPos = me.getXposAlignedToSibling(notifications[notifications.length - 1]);
me.yPos = me.getYposAlignedToSibling(notifications[notifications.length - 1]);
} else {
me.el.alignTo(me.manager.el, me.managerAlignment, [(me.paddingX * me.paddingFactorX), (me.paddingY * me.paddingFactorY)], false);
me.xPos = me.getXposAlignedToManager();
me.yPos = me.getYposAlignedToManager();
}
Ext.Array.include(notifications, me);
// Repeating from coordinates makes sure the windows does not flicker into the center of the viewport during animation
me.el.animate({
from: {
x: me.el.getX(),
y: me.el.getY()
},
to: {
x: me.xPos,
y: me.yPos,
opacity: 1
},
easing: me.slideInAnimation,
duration: me.slideInDuration,
dynamic: true
});
},
slideBack: function () {
var me = this;
var notifications = me.getNotifications(me.managerAlignment);
var index = Ext.Array.indexOf(notifications, me);
// Not animating the element if it already started to hide itself or if the manager is not present in the dom
if (!me.isHiding && me.el && me.manager && me.manager.el && me.manager.el.dom && me.manager.el.isVisible()) {
if (index) {
me.xPos = me.getXposAlignedToSibling(notifications[index - 1]);
me.yPos = me.getYposAlignedToSibling(notifications[index - 1]);
} else {
me.xPos = me.getXposAlignedToManager();
me.yPos = me.getYposAlignedToManager();
}
me.stopAnimation();
me.el.animate({
to: {
x: me.xPos,
y: me.yPos
},
easing: me.slideBackAnimation,
duration: me.slideBackDuration,
dynamic: true
});
}
},
cancelAutoClose: function() {
var me = this;
if (me.autoClose) {
me.task.cancel();
}
},
doAutoClose: function () {
var me = this;
if (!(me.stickWhileHover && me.mouseIsOver)) {
// Close immediately
me.close();
} else {
// Delayed closing when mouse leaves the component.
me.closeOnMouseOut = true;
}
},
removeFromManager: function () {
var me = this;
if (me.manager) {
var notifications = me.getNotifications(me.managerAlignment);
var index = Ext.Array.indexOf(notifications, me);
if (index != -1) {
// Requires Ext JS 4.0.2
Ext.Array.erase(notifications, index, 1);
// Slide "down" all notifications "above" the hidden one
for (;index < notifications.length; index++) {
notifications[index].slideBack();
}
}
}
},
hide: function () {
var me = this;
if (me.isHiding) {
if (!me.isFading) {
me.callParent(arguments);
// Must come after callParent() since it will pass through hide() again triggered by destroy()
me.isHiding = false;
}
} else {
// Must be set right away in case of double clicks on the close button
me.isHiding = true;
me.isFading = true;
me.cancelAutoClose();
if (me.el) {
me.el.fadeOut({
opacity: 0,
easing: 'easeIn',
duration: me.hideDuration,
remove: me.destroyAfterHide,
listeners: {
afteranimate: function () {
me.isFading = false;
me.removeCls('notification-fixed');
me.removeFromManager();
me.hide(me.animateTarget, me.doClose, me);
}
}
});
}
}
return me;
},
destroy: function () {
var me = this;
if (!me.hidden) {
me.destroyAfterHide = true;
me.hide(me.animateTarget, me.doClose, me);
} else {
me.callParent(arguments);
}
}
});