265 lines
6.2 KiB
JavaScript
265 lines
6.2 KiB
JavaScript
/**
|
|
* A 'Toast' is a simple modal message that is displayed on the screen and then automatically closed by a timeout or by a user tapping
|
|
* outside of the toast itself. Think about it like a text only alert box that will self destruct. **A Toast should not be instantiated manually**
|
|
* but creating by calling 'Ext.toast(message, timeout)'. This will create one reusable toast container and content will be swapped out as
|
|
* toast messages are queued or displayed.
|
|
*
|
|
* # Simple Toast
|
|
*
|
|
* @example miniphone
|
|
* Ext.toast('Hello Sencha!'); // Toast will close in 1000 milliseconds (default)
|
|
*
|
|
* # Toast with Timeout
|
|
*
|
|
* @example miniphone
|
|
* Ext.toast('Hello Sencha!', 5000); // Toast will close in 5000 milliseconds
|
|
*
|
|
* # Toast with config
|
|
*
|
|
* @example miniphone
|
|
* Ext.toast({message: 'Hello Sencha!', timeout: 2000}); // Toast will close in 2000 milliseconds
|
|
*
|
|
* # Multiple Toasts queued
|
|
*
|
|
* @example miniphone
|
|
* Ext.toast('Hello Sencha!');
|
|
* Ext.toast('Hello Sencha Again!');
|
|
* Ext.toast('Hello Sencha One More Time!');
|
|
*/
|
|
Ext.define('Ext.Toast', {
|
|
extend: 'Ext.Sheet',
|
|
requires: [
|
|
'Ext.util.InputBlocker'
|
|
],
|
|
|
|
config: {
|
|
/**
|
|
* @cfg
|
|
* @inheritdoc
|
|
*/
|
|
ui: 'dark',
|
|
|
|
/**
|
|
* @cfg
|
|
* @inheritdoc
|
|
*/
|
|
baseCls: Ext.baseCSSPrefix + 'toast',
|
|
|
|
/**
|
|
* @cfg
|
|
* @inheritdoc
|
|
*/
|
|
showAnimation: {
|
|
type: 'popIn',
|
|
duration: 250,
|
|
easing: 'ease-out'
|
|
},
|
|
|
|
/**
|
|
* @cfg
|
|
* @inheritdoc
|
|
*/
|
|
hideAnimation: {
|
|
type: 'popOut',
|
|
duration: 250,
|
|
easing: 'ease-out'
|
|
},
|
|
|
|
/**
|
|
* Override the default `zIndex` so it is normally always above floating components.
|
|
*/
|
|
zIndex: 999,
|
|
|
|
/**
|
|
* @cfg {String} message
|
|
* The message to be displayed in the {@link Ext.Toast}.
|
|
* @accessor
|
|
*/
|
|
message: null,
|
|
|
|
/**
|
|
* @cfg {Number} timeout
|
|
* The amount of time in milliseconds to wait before destroying the toast automatically
|
|
*/
|
|
timeout: 1000,
|
|
|
|
/**
|
|
* @cfg{Boolean/Object} animation
|
|
* The animation that should be used between toast messages when they are queued up
|
|
*/
|
|
messageAnimation: true,
|
|
|
|
/**
|
|
* @cfg
|
|
* @inheritdoc
|
|
*/
|
|
hideOnMaskTap: true,
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
modal: true,
|
|
|
|
/**
|
|
* @cfg
|
|
* @inheritdoc
|
|
*/
|
|
layout: {
|
|
type: 'vbox',
|
|
pack: 'center'
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
applyMessage: function(config) {
|
|
config = {
|
|
html: config,
|
|
cls: this.getBaseCls() + '-text'
|
|
};
|
|
|
|
return Ext.factory(config, Ext.Component, this._message);
|
|
},
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
updateMessage: function(newMessage) {
|
|
if (newMessage) {
|
|
this.add(newMessage);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
applyTimeout: function(timeout) {
|
|
if (this._timeoutID) {
|
|
clearTimeout(this._timeoutID);
|
|
if (!Ext.isEmpty(timeout)) {
|
|
this._timeoutID = setTimeout(Ext.bind(this.onTimeout, this), timeout);
|
|
}
|
|
}
|
|
return timeout;
|
|
},
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
next: Ext.emptyFn,
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
show: function(config) {
|
|
var me = this,
|
|
timeout = config.timeout,
|
|
msgAnimation = me.getMessageAnimation(),
|
|
message = me.getMessage();
|
|
|
|
if (me.isRendered() && me.isHidden() === false) {
|
|
config.timeout = null;
|
|
message.onAfter({
|
|
hiddenchange: function() {
|
|
me.setMessage(config.message);
|
|
message = me.getMessage();
|
|
message.onAfter({
|
|
hiddenchange: function() {
|
|
|
|
// Forces applyTimeout to create a timer
|
|
this._timeoutID = true;
|
|
me.setTimeout(timeout);
|
|
},
|
|
scope: me,
|
|
single: true
|
|
});
|
|
message.show(msgAnimation);
|
|
},
|
|
scope: me,
|
|
single: true
|
|
});
|
|
|
|
message.hide(msgAnimation);
|
|
} else {
|
|
Ext.util.InputBlocker.blockInputs();
|
|
me.setConfig(config);
|
|
|
|
//if it has not been added to a container, add it to the Viewport.
|
|
if (!me.getParent() && Ext.Viewport) {
|
|
Ext.Viewport.add(me);
|
|
}
|
|
|
|
if (!Ext.isEmpty(timeout)) {
|
|
me._timeoutID = setTimeout(Ext.bind(me.onTimeout, me), timeout);
|
|
}
|
|
|
|
me.callParent(arguments);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
hide: function(animation) {
|
|
clearTimeout(this._timeoutID);
|
|
if (!this.next()) {
|
|
this.callParent(arguments);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
onTimeout: function() {
|
|
this.hide();
|
|
}
|
|
}, function(Toast) {
|
|
var _queue = [], _isToasting = false;
|
|
|
|
function next() {
|
|
var config = _queue.shift();
|
|
|
|
if (config) {
|
|
_isToasting = true;
|
|
this.show(config);
|
|
} else {
|
|
_isToasting = false;
|
|
}
|
|
|
|
return _isToasting;
|
|
}
|
|
|
|
function getInstance() {
|
|
if (!Ext.Toast._instance) {
|
|
Ext.Toast._instance = Ext.create('Ext.Toast');
|
|
Ext.Toast._instance.next = next;
|
|
}
|
|
return Ext.Toast._instance;
|
|
}
|
|
|
|
Ext.toast = function(message, timeout) {
|
|
var toast = getInstance(),
|
|
config = message;
|
|
|
|
if (Ext.isString(message)) {
|
|
config = {
|
|
message: message,
|
|
timeout: timeout
|
|
};
|
|
}
|
|
|
|
if (config.timeout === undefined) {
|
|
config.timeout = Ext.Toast.prototype.config.timeout;
|
|
}
|
|
|
|
_queue.push(config);
|
|
if (!_isToasting) {
|
|
toast.next();
|
|
}
|
|
|
|
return toast;
|
|
}
|
|
});
|
|
|