| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- /* 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
- ,constrain: true
- ,constrainHeader: true
- ,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: this.config.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);
|