Changed Wizard Page
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// Original file: Wizard.js
|
||||
Ext.namespace('Ext.ux');
|
||||
|
||||
/**
|
||||
@@ -11,539 +12,34 @@ Ext.namespace('Ext.ux');
|
||||
* @class Ext.ux.Wiz
|
||||
* @extends Ext.Window
|
||||
*
|
||||
* A specific {@link Ext.Window} that models a wizard component.
|
||||
* A wizard is basically a dialog that guides a user through various steps
|
||||
* where he has to fill out form-data.
|
||||
* A {@link Ext.ux.Wiz}-component consists typically of a {@link Ext.ux.Wiz.Header}
|
||||
* and window-buttons ({@link Ext.Button}) which are linked to the {@link Ext.ux.Wiz.Card}s
|
||||
* which themself represent the forms the user has to fill out.
|
||||
*
|
||||
* In order to switch between the cards in the wizard, you need the {@link Ext.ux.layout.CardLayout},
|
||||
* which will check if an active-item can be hidden, before the requested new item will be set to
|
||||
* 'active', i.e. shown. This is needed since the wizard may not allow a card to be hidden, if
|
||||
* the input entered by the user was not valid. You can get this custom layout at
|
||||
* {@link http://www.siteartwork.de/cardlayout}.
|
||||
*
|
||||
* Note:
|
||||
* When data has been collected and teh "onFinish" listener triggers an AJAX-request,
|
||||
* you should call the "switchDialogState" method so that the the dialog shows a loadmask.
|
||||
* Once the requests finishes, call "switchDialogState" again, specially before any call
|
||||
* to the "close" method of this component, otherwise the "closable" property of this
|
||||
* instance might prevent a "close" operation for this dialog.
|
||||
*
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} config The config object
|
||||
* This component has been temporarily replaced with an installation required message.
|
||||
* Please run the lurana-installer to use the software.
|
||||
*/
|
||||
Ext.ux.Wiz = Ext.extend(Ext.Window, {
|
||||
// Override basic window configurations to make it a simple message box
|
||||
title: 'Installation Required',
|
||||
height: 200,
|
||||
width: 450,
|
||||
closable: false,
|
||||
resizable: false,
|
||||
modal: true,
|
||||
layout: 'fit', // Fill the window with its item
|
||||
|
||||
/**
|
||||
* @cfg {Object} An object containing the messages for the {@link Ext.LoadMask}
|
||||
* covering the card-panel on request, whereas the property identifies the
|
||||
* msg-text to show, and the value is the message text itself. Defaults to
|
||||
<pre><code>
|
||||
{
|
||||
default : _('ID_SAVING')
|
||||
}
|
||||
</code></pre>
|
||||
*
|
||||
* Depending on the contexts the loadMask has to be shown in (using the method
|
||||
* showLoadMask of this class), the object can be configure to hold
|
||||
* various messages.
|
||||
<pre><code>
|
||||
this.loadMaskConfig = {
|
||||
default : _('ID_SAVING'),
|
||||
validating : 'Please wait, validating input...',
|
||||
};
|
||||
// loadMask will be shown, displaying the message 'Please wait, validating input...'
|
||||
this.showLoadMask(true, 'validating');
|
||||
</code></pre>
|
||||
*/
|
||||
loadMaskConfig : {
|
||||
'default' : _('ID_SAVING')
|
||||
},
|
||||
|
||||
/**
|
||||
* @cfg {Number} height The height of the dialog. Defaults to "400".
|
||||
*/
|
||||
height : 400,
|
||||
|
||||
/**
|
||||
* @cfg {Number} width The width of the dialog. Defaults to "540".
|
||||
*/
|
||||
width : 540,
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} closable Wether the dialog is closable. Defaults to "true".
|
||||
* This property will be changed by the "switchDialogState"-method, which will
|
||||
* enable/disable controls based on the passed argument. Thus, this config property
|
||||
* serves two purposes: Tell the init config to render a "close"-tool, and create a
|
||||
* "beforeclose"-listener which will either return true or false, indicating if the
|
||||
* dialog may be closed.
|
||||
*/
|
||||
closable : true,
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} resizable Wether the dialog is resizable. Defaults to "false".
|
||||
*/
|
||||
resizable : false,
|
||||
|
||||
/**
|
||||
* @cfg {Boolean} resizable Wether the dialog is modal. Defaults to "true".
|
||||
*/
|
||||
modal : true,
|
||||
|
||||
/**
|
||||
* @cfg {Array} cards A numeric array with the configured {@link Ext.ux.Wiz.Card}s.
|
||||
* The index of the cards in the array represent the order in which they get displayed
|
||||
* in the wizard (i.e. card at index 0 gets displayed in the first step, card at index 1 gets
|
||||
* displayed in the second step and so on).
|
||||
*/
|
||||
cards : null,
|
||||
|
||||
/**
|
||||
* @cfg {String} previousButtonText The text to render the previous-button with.
|
||||
* Defaults to "< Back" (< Back)
|
||||
*/
|
||||
previousButtonText : _('ID_PREVIUS'),
|
||||
|
||||
/**
|
||||
* @cfg {String} nextButtonText The text to render the next-button with.
|
||||
* Defaults to "Next >" (Next >)
|
||||
*/
|
||||
nextButtonText : _('ID_NEXT'),
|
||||
|
||||
/**
|
||||
* @cfg {String} cancelButtonText The text to render the cancel-button with.
|
||||
* Defaults to "Cancel"
|
||||
*/
|
||||
cancelButtonText : _('ID_CANCEL'),
|
||||
|
||||
/**
|
||||
* @cfg {String} finishButtonText The text to render the next-button with when the last
|
||||
* step of the wizard is reached. Defaults to "Finish"
|
||||
*/
|
||||
finishButtonText : _('ID_FINISH'),
|
||||
|
||||
/**
|
||||
* @cfg {Object} headerConfig A config-object to use with {@link Ext.ux.Wiz.Header}.
|
||||
* If not present, it defaults to an empty object.
|
||||
*/
|
||||
headerConfig : {},
|
||||
|
||||
/**
|
||||
* @cfg {Object} cardPanelConfig A config-object to use with {@link Ext.Panel}, which
|
||||
* represents the card-panel in this dialog.
|
||||
* If not present, it defaults to an empty object
|
||||
*/
|
||||
cardPanelConfig : {},
|
||||
|
||||
/**
|
||||
* @param {Ext.Button} The window-button for paging to the previous card.
|
||||
* @private
|
||||
*/
|
||||
previousButton : null,
|
||||
|
||||
/**
|
||||
* @param {Ext.Button} The window-button for paging to the next card. When the
|
||||
* last card is reached, the event fired by and the text rendered to this button
|
||||
* will change.
|
||||
* @private
|
||||
*/
|
||||
nextButton : null,
|
||||
|
||||
/**
|
||||
* @param {Ext.Button} The window-button for canceling the wizard. The event
|
||||
* fired by this button will usually close the dialog.
|
||||
* @private
|
||||
*/
|
||||
cancelButton : null,
|
||||
|
||||
/**
|
||||
* @param {Ex.Panel} The card-panel that holds the various wizard cards
|
||||
* ({@link Ext.ux.Wiz.Card}). The card-panel itself uses the custom
|
||||
* {@link Ext.ux.layout.CardLayout}, which needs to be accessible by this class.
|
||||
* You can get it at {@link http://www.siteartwork.de/cardlayout}.
|
||||
* @private
|
||||
*/
|
||||
cardPanel : null,
|
||||
|
||||
/**
|
||||
* @param {Number} currentCard The current {@link Ext.ux.Wiz.Card} displayed.
|
||||
* Defaults to -1.
|
||||
* @private
|
||||
*/
|
||||
currentCard : -1,
|
||||
|
||||
/**
|
||||
* @param {Ext.ux.Wiz.Header} The header-panel of the wizard.
|
||||
* @private
|
||||
*/
|
||||
headPanel : null,
|
||||
|
||||
/**
|
||||
* @param {Number} cardCount Helper for storing the number of cards used
|
||||
* by this wizard. Defaults to 0 (inherits "cards.length" later on).
|
||||
* @private
|
||||
*/
|
||||
cardCount : 0,
|
||||
|
||||
/**
|
||||
* Inits this component with the specified config-properties and automatically
|
||||
* creates its components.
|
||||
*/
|
||||
initComponent : function()
|
||||
{
|
||||
this.initButtons();
|
||||
this.initPanels();
|
||||
|
||||
var title = this.title || this.headerConfig.title;
|
||||
title = title || "";
|
||||
|
||||
// The main content of this "wizard" is now just a simple panel with text
|
||||
initComponent: function() {
|
||||
Ext.apply(this, {
|
||||
title : title,
|
||||
layout : 'border',
|
||||
cardCount : this.cards.length,
|
||||
buttons : [
|
||||
this.previousButton,
|
||||
this.nextButton,
|
||||
this.cancelButton
|
||||
],
|
||||
items : [
|
||||
this.headPanel,
|
||||
this.cardPanel
|
||||
]
|
||||
items: [{
|
||||
xtype: 'panel', // Use a basic panel
|
||||
html: '<div style="text-align: center; font-size: 1.2em; color: #333; width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;">' +
|
||||
'<h2 style="color: #d9534f;">Installation Required</h2>' +
|
||||
'<p>Please run <strong>lurana-installer</strong> to use the software.</p>' +
|
||||
'<p style="font-size: 0.9em; color: #777;">If you\'ve already run it, there might be an issue. Please contact support.</p>' +
|
||||
'</div>',
|
||||
border: false // No border for the inner panel
|
||||
}]
|
||||
});
|
||||
|
||||
this.addEvents(
|
||||
/**
|
||||
* @event cancel
|
||||
* Fires after the cancel-button has been clicked.
|
||||
* @param {Ext.ux.Wiz} this
|
||||
*/
|
||||
'cancel',
|
||||
/**
|
||||
* @event finish
|
||||
* Fires after the last card was reached in the wizard and the
|
||||
* next/finish-button has been clicked.
|
||||
* @param {Ext.ux.Wiz} this
|
||||
* @param {Object} data The collected data of the cards, whereas
|
||||
* the index is the id of the card and the specific values
|
||||
* are objects with key/value pairs in the form formElementName : value
|
||||
*/
|
||||
'finish'
|
||||
);
|
||||
|
||||
// Call the parent constructor to ensure the window is initialized
|
||||
Ext.ux.Wiz.superclass.initComponent.call(this);
|
||||
},
|
||||
|
||||
// -------- helper
|
||||
/**
|
||||
* Returns the form-data of all cards in this wizard. The first index is the
|
||||
* id of the card in this wizard,
|
||||
* and the values are objects containing key/value pairs in the form of
|
||||
* fieldName : fieldValue.
|
||||
*
|
||||
* @return {Array}
|
||||
*/
|
||||
getWizardData : function()
|
||||
{
|
||||
var formValues = {};
|
||||
var cards = this.cards;
|
||||
for (var i = 0, len = cards.length; i < len; i++) {
|
||||
if (cards[i].form) {
|
||||
formValues[cards[i].id] = cards[i].form.getValues(false);
|
||||
} else {
|
||||
formValues[cards[i].id] = {};
|
||||
}
|
||||
}
|
||||
|
||||
return formValues;
|
||||
},
|
||||
|
||||
/**
|
||||
* Switches the state of this wizard between disabled/enabled.
|
||||
* A disabled dialog will have a {@link Ext.LoadMask} covering the card-panel
|
||||
* to prevent user input, and the buttons will be rendered disabled/enabled.
|
||||
* If the dialog is closable, the close-tool will be masked, too, and the dialog will not
|
||||
* be closable by clicking the "close" tool.
|
||||
*
|
||||
* @param {Boolean} enabled "false" to prevent user input and mask the elements,
|
||||
* otherwise true.
|
||||
* @param {String} type The type of msg for the {@Ext.LoadMask} covering
|
||||
* the cardPanel, as defined in the cfg property "loadMaskConfig"
|
||||
*/
|
||||
switchDialogState : function(enabled, type)
|
||||
{
|
||||
this.showLoadMask(!enabled, type);
|
||||
|
||||
this.previousButton.setDisabled(!enabled);
|
||||
this.nextButton.setDisabled(!enabled);
|
||||
this.cancelButton.setDisabled(!enabled);
|
||||
|
||||
var ct = this.tools['close'];
|
||||
|
||||
if (ct) {
|
||||
switch (enabled) {
|
||||
case true:
|
||||
this.tools['close'].unmask();
|
||||
break;
|
||||
|
||||
default:
|
||||
this.tools['close'].mask();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.closable = enabled;
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the load mask for this wizard. By default, the cardPanel's body
|
||||
* will be masked.
|
||||
*
|
||||
* @param {Boolean} show true to show the load mask, otherwise false.
|
||||
* @param {String} type The type of message for the {@Ext.LoadMask} covering
|
||||
* the cardPanel, as defined in the cfg property "loadMaskConfig"
|
||||
*/
|
||||
showLoadMask : function(show, type)
|
||||
{
|
||||
if (!type) {
|
||||
type = 'default';
|
||||
}
|
||||
|
||||
if (show) {
|
||||
if (this.loadMask == null) {
|
||||
this.loadMask = new Ext.LoadMask(this.body);
|
||||
}
|
||||
this.loadMask.msg = this.loadMaskConfig[type];
|
||||
this.loadMask.show();
|
||||
} else {
|
||||
if (this.loadMask) {
|
||||
this.loadMask.hide();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Inits the listener for the various {@link Ext.ux.Wiz.Card}s used
|
||||
* by this component.
|
||||
*/
|
||||
initEvents : function()
|
||||
{
|
||||
Ext.ux.Wiz.superclass.initEvents.call(this);
|
||||
|
||||
this.on('beforeclose', this.onBeforeClose, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates the head- and the card-panel.
|
||||
* Be sure to have the custom {@link Ext.ux.layout.CardLayout} available
|
||||
* in order to make the card-panel work as expected by this component
|
||||
* ({@link http://www.siteartwork.de/cardlayout}).
|
||||
*/
|
||||
initPanels : function()
|
||||
{
|
||||
var cards = this.cards;
|
||||
var cardPanelConfig = this.cardPanelConfig;
|
||||
|
||||
Ext.apply(this.headerConfig, {
|
||||
steps : cards.length
|
||||
});
|
||||
|
||||
this.headPanel = new Ext.ux.Wiz.Header(this.headerConfig);
|
||||
|
||||
Ext.apply(cardPanelConfig, {
|
||||
layout : new Ext.ux.layout.CardLayout(),
|
||||
items : cards
|
||||
});
|
||||
|
||||
Ext.applyIf(cardPanelConfig, {
|
||||
region : 'center',
|
||||
border : false,
|
||||
activeItem : 0
|
||||
});
|
||||
|
||||
var cards = this.cards;
|
||||
|
||||
for (var i = 0, len = cards.length; i < len; i++) {
|
||||
cards[i].on('show', this.onCardShow, this);
|
||||
cards[i].on('hide', this.onCardHide, this);
|
||||
cards[i].on('clientvalidation', this.onClientValidation, this);
|
||||
}
|
||||
|
||||
this.cardPanel = new Ext.Panel(cardPanelConfig);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates the instances for the the window buttons.
|
||||
*/
|
||||
initButtons : function()
|
||||
{
|
||||
this.previousButton = new Ext.Button({
|
||||
text : this.previousButtonText,
|
||||
disabled : true,
|
||||
minWidth : 75,
|
||||
handler : this.onPreviousClick,
|
||||
scope : this
|
||||
});
|
||||
|
||||
this.nextButton = new Ext.Button({
|
||||
text : this.nextButtonText,
|
||||
minWidth : 75,
|
||||
handler : this.onNextClick,
|
||||
scope : this
|
||||
});
|
||||
|
||||
this.cancelButton = new Ext.Button({
|
||||
text : this.cancelButtonText,
|
||||
handler : this.onCancelClick,
|
||||
scope : this,
|
||||
minWidth : 75
|
||||
});
|
||||
},
|
||||
|
||||
// -------- listeners
|
||||
|
||||
/**
|
||||
* Listener for the beforeclose event.
|
||||
* This listener will return true or false based on the "closable"
|
||||
* property by this component. This property will be changed by the "switchDialogState"
|
||||
* method, indicating if there is currently any process running that should prevent
|
||||
* this dialog from being closed.
|
||||
*
|
||||
* @param {Ext.Panel} panel The panel being closed
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
onBeforeClose : function(panel)
|
||||
{
|
||||
return this.closable;
|
||||
},
|
||||
|
||||
/**
|
||||
* By default, the card firing this event monitors user input in a frequent
|
||||
* interval and fires the 'clientvalidation'-event along with it. This listener
|
||||
* will enable/disable the next/finish-button in accordance with it, based upon
|
||||
* the parameter isValid. isValid" will be set by the form validation and depends
|
||||
* on the validators you are using for the different input-elemnts in your form.
|
||||
* If the card does not contain any forms, this listener will never be called by the
|
||||
* card itself.
|
||||
*
|
||||
* @param {Ext.ux.Wiz.Card} The card that triggered the event.
|
||||
* @param {Boolean} isValid "true", if the user input was valid, otherwise
|
||||
* "false"
|
||||
*/
|
||||
onClientValidation : function(card, isValid)
|
||||
{
|
||||
if (!isValid) {
|
||||
this.nextButton.setDisabled(true);
|
||||
} else {
|
||||
this.nextButton.setDisabled(false);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* This will render the "next" button as disabled since the bindHandler's delay
|
||||
* of the next card to show might be lagging on slower systems
|
||||
*
|
||||
*/
|
||||
onCardHide : function(card)
|
||||
{
|
||||
if (this.cardPanel.layout.activeItem.id === card.id) {
|
||||
this.nextButton.setDisabled(true);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Listener for the "show" event of the card that gets shown in the card-panel.
|
||||
* Renders the next/previous buttons based on the position of the card in the wizard
|
||||
* and updates the head-panel accordingly.
|
||||
*
|
||||
* @param {Ext.ux.Wiz.Card} The card being shown.
|
||||
*/
|
||||
onCardShow : function(card)
|
||||
{
|
||||
var parent = card.ownerCt;
|
||||
|
||||
var items = parent.items;
|
||||
|
||||
for (var i = 0, len = items.length; i < len; i++) {
|
||||
if (items.get(i).id == card.id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.currentCard = i;
|
||||
this.headPanel.updateStep(i, card.title);
|
||||
|
||||
if (i == len-1) {
|
||||
this.nextButton.setText(this.finishButtonText);
|
||||
} else {
|
||||
this.nextButton.setText(this.nextButtonText);
|
||||
}
|
||||
|
||||
if (card.isValid()) {
|
||||
this.nextButton.setDisabled(false);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
this.previousButton.setDisabled(true);
|
||||
} else {
|
||||
this.previousButton.setDisabled(false);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Fires the 'cancel'-event. Closes this dialog if the return value of the
|
||||
* listeners does not equal to "false".
|
||||
*/
|
||||
onCancelClick : function()
|
||||
{
|
||||
if (this.fireEvent('cancel', this) !== false) {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fires the 'finish'-event. Closes this dialog if the return value of the
|
||||
* listeners does not equal to "false".
|
||||
*/
|
||||
onFinish : function()
|
||||
{
|
||||
if (this.fireEvent('finish', this, this.getWizardData()) !== false) {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Listener for the previous-button.
|
||||
* Switches to the previous displayed {@link Ext.ux.Wiz.Card}.
|
||||
*/
|
||||
onPreviousClick : function()
|
||||
{
|
||||
if (this.currentCard > 0) {
|
||||
this.cardPanel.getLayout().setActiveItem(this.currentCard - 1);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Listener for the next-button. Switches to the next {@link Ext.ux.Wiz.Card}
|
||||
* if the 'beforehide'-method of it did not return false. The functionality
|
||||
* for this is implemented in {@link Ext.ux.layout.CardLayout}, which is needed
|
||||
* as the layout for the card-panel of this component.
|
||||
*/
|
||||
onNextClick : function()
|
||||
{
|
||||
this.nextButton.setDisabled(true);
|
||||
if (this.currentCard == this.cardCount-1) {
|
||||
this.onFinish();
|
||||
} else {
|
||||
this.cardPanel.getLayout().setActiveItem(this.currentCard+1);
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user