ExtJs MODX REVOLUTION - объект MODx.Windows
Вертикальные линии обозначают столбцы.
Действие | Описание | по умолчанию | Возможные | |
---|---|---|---|---|
action | Если baseParams не установлен, будет использоваться это как действие для контроллера. | |||
allowDrop | Разрешить или запретить удаление элементов дерева в поля формы. | 1 | ||
baseParams | Объект параметров для отправки вместе с формой окна при сохранении. | {} | ||
blankValues | Если true, каждый раз, когда он будет показан, будут сброшены значения формы. | 0 | ||
cancelBtnText | Текст кнопки "Отменить" | Отменить | ||
fields | Перечисления полей фомрмы | [] | ||
fileUpload | Если true, форма будет построена для приема файлов | 0 | ||
formFrame | Добавление к окну внешних стилей | 1 | ||
labelAlign | Выравнивание подписи поля на форме | top | right,left,top,bottom | |
labelWidth | Ширина подписи поля | 100 | 100, '100%' | |
record | запись объекта JSON значений по умолчанию (в формате name: value) для установки в форму при первой загрузке окна. | {pagetitle: 'Название страницы'} | ||
saveBtnText | Текст кнопки сохранить | Сохранить | ||
url | ссылка на контроллер |
События
Наименование | Описание |
---|---|
success | Если представление формы возвращает успешный ответ. |
failure | Если представление формы возвращает ответ об отказе. |
beforeSubmit | Событие перед отправкой формы, но после проверки |
Код формы
/* override default Ext.Window component properties */
// these also apply for Windows that do not extend MODx.Window (like console for ex.)
// we use CSS3 box-shadows in 2014, removes clutter from the DOM
Ext.Window.prototype.floating = { shadow: false };
/* override default Ext.Window component methods */
Ext.override(Ext.Window, {
// prevents ugly slow js animations when opening a window
// we cannot do the CSS3 animations stuff in these overrides, as not all windows are animated!
// so they just prevent the normal JS animation to take effect
animShow: function() {
this.afterShow();
// some windows (like migx) don't seem to call onShow
// so we have to do a check here after onShow should have finished
var win = this; // we need a reference to this for setTimeout
// wait for onShow to finish and check if the window is already visible then, if not, try to do that
setTimeout(function() {
if (!win.el.hasClass('anim-ready')) {
win.el.addClass('anim-ready');
setTimeout(function() {
if (win.mask !== undefined) {
// respect that the mask is not always the same object
if (win.mask instanceof Ext.Element) {
win.mask.addClass('fade-in');
} else {
win.mask.el.addClass('fade-in');
}
}
win.el.addClass('zoom-in');
}, 250);
}
}, 300);
}
,animHide: function() {
//this.el.hide(); // dont hide the window here, we'll do that onHide when the animation is finished!
this.afterHide();
}
,onShow: function() {
// skip MODx.msg windows, the animations do not work with them as they are always the same element!
if (!this.el.hasClass('x-window-dlg')) {
// first set the class that scales the window down a bit
// this has to be done after the full window is positioned correctly by extjs
this.addClass('anim-ready');
// let the scale transformation to 0.7 finish before animating in
var win = this; // we need a reference to this for setTimeout
setTimeout(function() {
if (win.mask !== undefined) {
// respect that the mask is not always the same object
if (win.mask instanceof Ext.Element) {
win.mask.addClass('fade-in');
} else {
win.mask.el.addClass('fade-in');
}
}
win.el.addClass('zoom-in');
}, 250);
} else {
// we need to handle MODx.msg windows (Ext.Msg singletons, e.g. always the same element, no multiple instances) differently
this.mask.addClass('fade-in');
this.el.applyStyles({'opacity': 1});
}
}
,onHide: function() {
// for some unknown (to me) reason, onHide() get's called when a window is initialized, e.g. before onShow()
// so we need to prevent the following routine be applied prematurely
if (this.el.hasClass('zoom-in')) {
this.el.removeClass('zoom-in');
if (this.mask !== undefined) {
// respect that the mask is not always the same object
if (this.mask instanceof Ext.Element) {
this.mask.removeClass('fade-in');
} else {
this.mask.el.removeClass('fade-in');
}
}
this.addClass('zoom-out');
// let the CSS animation finish before hiding the window
var win = this; // we need a reference to this for setTimeout
setTimeout(function() {
// we have an unsolved problem with windows that are destroyed on hide
// the zoom-out animation cannot be applied for such windows, as they
// get destroyed too early, if someone knows a solution, please tell =)
if (!win.isDestroyed) {
win.el.hide();
// and remove the CSS3 animation classes
win.el.removeClass('zoom-out');
win.el.removeClass('anim-ready');
}
}, 250);
} else if (this.el.hasClass('x-window-dlg')) {
// we need to handle MODx.msg windows (Ext.Msg singletons, e.g. always the same element, no multiple instances) differently
this.el.applyStyles({'opacity': 0});
if (this.mask !== undefined) {
// respect that the mask is not always the same object
if (this.mask instanceof Ext.Element) {
this.mask.removeClass('fade-in');
} else {
this.mask.el.removeClass('fade-in');
}
}
}
}
});
/**
* Abstract class for Ext.Window creation in MODx
*
* @class MODx.Window
* @extends Ext.Window
* @constructor
* @param {Object} config An object of options.
* @xtype modx-window
*/
MODx.Window = function(config) {
config = config || {};
Ext.applyIf(config,{
modal: false
,layout: 'auto'
,closeAction: 'hide'
,shadow: true
,resizable: true
,collapsible: true
,maximizable: true
// ,autoHeight: true // this messes up many windows on smaller screens (e.g. too much height), ex. macbook air 11"
,autoHeight: false
,autoScroll: true
,allowDrop: true
,width: 400
,cls: 'modx-window'
,buttons: [{
text: config.cancelBtnText || _('cancel')
,scope: this
,handler: function() { config.closeAction !== 'close' ? this.hide() : this.close(); }
},{
text: config.saveBtnText || _('save')
,cls: 'primary-button'
,scope: this
,handler: this.submit
}]
,record: {}
,keys: [{
key: Ext.EventObject.ENTER
,fn: function(keyCode, event) {
var elem = event.getTarget();
var component = Ext.getCmp(elem.id);
if (component instanceof Ext.form.TextArea) {
return component.append("\n");
} else {
this.submit();
}
}
,scope: this
}]
});
MODx.Window.superclass.constructor.call(this,config);
this.options = config;
this.config = config;
this.addEvents({
success: true
,failure: true
,beforeSubmit: true
});
this._loadForm();
this.on('show',function() {
if (this.config.blankValues) { this.fp.getForm().reset(); }
if (this.config.allowDrop) { this.loadDropZones(); }
this.syncSize();
this.focusFirstField();
},this);
this.on('afterrender', function() {
this.originalHeight = this.el.getHeight();
this.toolsHeight = this.originalHeight - this.body.getHeight() + 50;
this.resizeWindow();
});
Ext.EventManager.onWindowResize(this.resizeWindow, this);
};
Ext.extend(MODx.Window,Ext.Window,{
_loadForm: function() {
if (this.checkIfLoaded(this.config.record || null)) { return false; }
var r = this.config.record;
/* set values here, since setValue after render seems to be broken */
if (this.config.fields) {
var l = this.config.fields.length;
for (var i=0;i<l;i++) {
var f = this.config.fields[i];
if (r[f.name]) {
if (f.xtype == 'checkbox' || f.xtype == 'radio') {
f.checked = r[f.name];
} else {
f.value = r[f.name];
}
}
}
}
this.fp = this.createForm({
url: this.config.url
,baseParams: this.config.baseParams || { action: this.config.action || '' }
,items: this.config.fields || []
});
var w = this;
this.fp.getForm().items.each(function(f) {
f.on('invalid', function(){
w.doLayout();
});
});
this.renderForm();
}
,focusFirstField: function() {
if (this.fp && this.fp.getForm() && this.fp.getForm().items.getCount() > 0) {
var fld = this.findFirstTextField();
if (fld) { fld.focus(false,200); }
}
}
,findFirstTextField: function(i) {
i = i || 0;
var fld = this.fp.getForm().items.itemAt(i);
if (!fld) return false;
if (fld.isXType('combo') || fld.isXType('checkbox') || fld.isXType('radio') || fld.isXType('displayfield') || fld.isXType('statictextfield') || fld.isXType('hidden')) {
i = i+1;
fld = this.findFirstTextField(i);
}
return fld;
}
,submit: function(close) {
close = close === false ? false : true;
var f = this.fp.getForm();
if (f.isValid() && this.fireEvent('beforeSubmit',f.getValues())) {
f.submit({
waitMsg: _('saving')
,submitEmptyText: this.config.submitEmptyText !== false
,scope: this
,failure: function(frm,a) {
if (this.fireEvent('failure',{f:frm,a:a})) {
MODx.form.Handler.errorExt(a.result,frm);
}
this.doLayout();
}
,success: function(frm,a) {
if (this.config.success) {
Ext.callback(this.config.success,this.config.scope || this,[frm,a]);
}
this.fireEvent('success',{f:frm,a:a});
if (close) { this.config.closeAction !== 'close' ? this.hide() : this.close(); }
this.doLayout();
}
});
}
}
,createForm: function(config) {
Ext.applyIf(this.config,{
formFrame: true
,border: false
,bodyBorder: false
,autoHeight: true
});
config = config || {};
Ext.applyIf(config,{
labelAlign: this.config.labelAlign || 'top'
,labelWidth: this.config.labelWidth || 100
,labelSeparator: this.config.labelSeparator || ''
,frame: this.config.formFrame
,border: this.config.border
,bodyBorder: this.config.bodyBorder
,autoHeight: this.config.autoHeight
,anchor: '100% 100%'
,errorReader: MODx.util.JSONReader
,defaults: this.config.formDefaults || {
msgTarget: this.config.msgTarget || 'under'
}
,url: this.config.url
,baseParams: this.config.baseParams || {}
,fileUpload: this.config.fileUpload || false
});
return new Ext.FormPanel(config);
}
,renderForm: function() {
this.fp.on('destroy', function() {
Ext.EventManager.removeResizeListener(this.resizeWindow, this);
}, this);
this.add(this.fp);
}
,checkIfLoaded: function(r) {
r = r || {};
if (this.fp && this.fp.getForm()) { /* so as not to duplicate form */
this.fp.getForm().reset();
this.fp.getForm().setValues(r);
return true;
}
return false;
}
,setValues: function(r) {
if (r === null) { return false; }
this.fp.getForm().setValues(r);
}
,reset: function() {
this.fp.getForm().reset();
}
,hideField: function(f) {
f.disable();
f.hide();
var d = f.getEl().up('.x-form-item');
if (d) { d.setDisplayed(false); }
}
,showField: function(f) {
f.enable();
f.show();
var d = f.getEl().up('.x-form-item');
if (d) { d.setDisplayed(true); }
}
,loadDropZones: function() {
if (this._dzLoaded) return false;
var flds = this.fp.getForm().items;
flds.each(function(fld) {
if (fld.isFormField && (
fld.isXType('textfield') || fld.isXType('textarea')
) && !fld.isXType('combo')) {
new MODx.load({
xtype: 'modx-treedrop'
,target: fld
,targetEl: fld.getEl().dom
});
}
});
this._dzLoaded = true;
}
,resizeWindow: function(){
var viewHeight = Ext.getBody().getViewSize().height;
var el = this.fp.getForm().el;
if(viewHeight < this.originalHeight){
el.setStyle('overflow-y', 'scroll');
el.setHeight(viewHeight - this.toolsHeight);
}else{
el.setStyle('overflow-y', 'auto');
el.setHeight('auto');
}
}
});
Ext.reg('modx-window',MODx.Window);
Управление
// Отправить форму и затем закрыть её
var w = Ext.getCmp('my-window-id');
w.submit(true); /* submit and then close window */
// Установить значения после загрузки формы
var w = Ext.getCmp('my-window-id');
w.setValues({
name: 'John'
,email: 'my@email.com'
});
// Сброс значений в форме
var w = Ext.getCmp('my-window-id');
w.reset();
// Показать скрыть поле в форме
var w = Ext.getCmp('my-window-id');
w.hideField('email');
w.showField('comments');
23 февраля 2021, 15:17 3120
Вы должны авторизоваться, чтобы оставлять комментарии.
Комментарии ()