Show cool things you have done with our products


Post by praveen.shastri »

I want to override event editor form. How do I do it?

In my case, I want to achieve two things

1. Put a handler on cancel button(to avoid orange box to not appear on timeline in case user clicks cancel instead of save).
2. Remove total hours field and add end date at top of event editor form.

Can you please guide me?

Post by mats »

Try this example, and view the source of the custom plugin:

http://ext-scheduler.com/playpen/evente ... ditor.html

Plugin source: http://ext-scheduler.com/playpen/evente ... yeditor.js

Post by cayenne_08 »

Hi Mats,

When I try http://ext-scheduler.com/playpen/evente ... yeditor.js code, I get the following error:

this.grid.getElementFromEventRecord is not a function

Can you please advise?

Thanks!!

Post by mats »

Please try the regular event-editor demo http://ext-scheduler.com/examples/event ... ditor.html

Does that offer the guidance you need?

Post by cayenne_08 »

>Please try the regular event-editor demo http://ext-scheduler.com/examples/event ... ditor.html

Actually, http://ext-scheduler.com/examples/event ... ditor.html does not show the details of the EditorPanel. I want to see the source of Sch.plugins.EventEditor so that I can create my own custom
EventEditor. How can I get access to the source code for EventEditor?

Post by mats »

Here it is :)
/*
 * Ext Scheduler 1.8
 * Copyright(c) 2009-2011 Mats Bryntse Consulting
 * info@bryntum.com
 * https://www.bryntum.com/license
 *
 */

Ext.ns('Sch.plugins');

/**
 * @class Sch.plugins.EventEditor
 * @extends Ext.form.FormPanel
 * A plugin used to edit event start/end dates as well as any meta data. You can define any fields/layout you want (as it inherits from FormPanel).
<pre><code> 
 var myEditor = new Sch.plugins.EventEditor({
    height : 180,
    width : 270,
    buttonAlign : 'left',
    fieldsPanelConfig : {
        layout : 'form',
        border : false,
        labelAlign : 'top',
        items : [
            this.titleField = new Ext.form.TextField({
                name : 'Title',
                fieldLabel : 'Task'
            }),
                    
            this.locationField = new Ext.form.TextField({
                name : 'Location',
                fieldLabel : 'Location'
            })
        ]
    }
});</code></pre>
 * @requires Ext.ux.form.DateTime
 * @requires Ext.ux.form.SpinnerField
 * @constructor
 * @param {Object} config The configuration options
 */
Sch.plugins.EventEditor = Ext.extend(Ext.form.FormPanel, {
    
    /**
     * @cfg {String} durationText The text to show after the duration spinner field
     */
    durationText : 'hrs',
    
    /**
     * @cfg {String} saveText The text to show on the save button
     */
    saveText: 'Save',

    /**
     * @cfg {String} deleteText The text to show on the delete button
     */
    deleteText: 'Delete',
    
    /**
     * @cfg {String} cancelText The text to show on the cancel button
     */
    cancelText: 'Cancel',

    /**
     * @cfg {Boolean} hideOnBlur True to hide this panel if a click is detected outside the panel (defaults to true)
     */
    hideOnBlur : true,
     
    /**
     * This property provides access to the start date field (which is a UX by Saki)
     * @property startDateField
     * @type Ext.ux.form.DateTime
     */
     
    /**
     * This property provides access to the duration spinner field (which is a UX)
     * @property durationField
     * @type Ext.ux.form.SpinnerField   
     */
                 
    /**
     * @cfg {Object} timeConfig Config for the TimeField constructor.
     */
    timeConfig : {
         allowBlank:false,
         editable : false,
         forceSelection : true,
         value : '11:00'    // Dummy value required for IE
    },
    
    /**
     * @cfg {Object} dateConfig Config for the DateField constructor.
     */
    dateConfig: {
        allowBlank:false
    },

    /**
     * @cfg {String} fieldsPanelConfig A panel config representing your fields that is associated with a scheduled event
     * 
     * Example:
     *  
     * <pre><code>
        fieldsPanelConfig : {
                        layout : 'form',
                        style:'background:#fff',
                        border : false,
                        cls : 'editorpanel',
                        labelAlign : 'top',
                        defaults : {
                            width : 135
                        },
                        items : [
                            titleField = new Ext.form.TextField({
                                name : 'Title',
                                fieldLabel : 'Task'
                            }),
                            
                            locationField = new Ext.form.TextField({
                                name : 'Location',
                                fieldLabel : 'Location'
                            })
                        ]
                    }
     * </pre></code>
     * 
     */
    
    /**
     * @cfg {String} dateFormat This config parameter is passed to the Ext.ux.form.DateTime constructor.
     */
    dateFormat:'Y-m-d',
    
    /**
     * @cfg {String} timeFormat This config parameter is passed to the Ext.ux.form.DateTime constructor.
     */
    timeFormat:'H:i',
    
    constructor : function(config) {
        this.addEvents(
            /**
            * @event beforeeventdelete
            * Fires before an event is deleted (return false to cancel the operation)
            * @param {Sch.plugins.EventEditor} editor The editor instance
            * @param {Ext.data.Record} eventRecord The record about to be deleted
            */
            'beforeeventdelete',

            /**
            * @event beforeeventsave
            * Fires before an event is saved (return false to cancel the operation)
            * @param {Sch.plugins.EventEditor} editor The editor instance
            * @param {Ext.data.Record} eventRecord The record about to be saved
            */
            'beforeeventsave'
        );

        Sch.plugins.EventEditor.superclass.constructor.apply(this, arguments);
    },

    /* 
     * Expands the editor
     * @param {Record} eventRecord The record to show in the editor panel
     */
    show : function(eventRecord, alignToEl) {
        
        // Only show delete button if the event belongs to a store
        if (this.deleteButton) {
            this.deleteButton.setVisible(!!eventRecord.store);
        }

        this.eventRecord = eventRecord;
        
        // Manually set the duration field value
        var duration = Sch.util.Date.getDurationInHours(eventRecord.get('StartDate'), eventRecord.get('EndDate'));
        this.durationField.setValue(duration);
        
        // Load form panel fields
        this.getForm().loadRecord(eventRecord);
        alignToEl = alignToEl || this.scheduler.view.getElementFromEventRecord(eventRecord);
        this.el.alignTo(alignToEl, 'bl', this.getConstrainOffsets(alignToEl));
        this.expand();
    },
    
    // Override this to add support for constraining the editor panel to the viewport or scheduler
    getConstrainOffsets : function(eventEl) {
        return [0, 0];
    },
    
    cls : 'sch-eventeditor',
    layout : 'border',
    border : false,
    
    onSaveClick : function() {
        var formPanel = this,
            record = formPanel.eventRecord,
            form = formPanel.getForm();
        
        if (form.isValid() && this.fireEvent('beforeeventsave', this, record) !== false) {

            var start = formPanel.startDateField.getValue(),
                hours = formPanel.durationField.getValue();

            if (start && hours >= 0) {
                end = Sch.util.Date.add(start, Sch.util.Date.MINUTE, hours * 60);
            } else {
                return;
            }

            var values = form.getValues();

            record.beginEdit();
            form.updateRecord(record);
            record.set('StartDate', start);
            record.set('EndDate', end);
            record.endEdit();

            // Check if this is a new record
            if (!this.eventRecord.store) {
                if (this.scheduler.fireEvent('beforeeventadd', this.scheduler, record) !== false) {
                    this.eventStore.add(record);
                }
            }
            formPanel.collapse();
        }
    },

    onDeleteClick : function() {
        if (this.fireEvent('beforeeventdelete', this, this.eventRecord) !== false) {
            this.eventStore.remove(this.eventRecord);
        }
        this.collapse();
    },

    onCancelClick : function() {
        this.collapse();
    },

    buildButtons : function() {
        this.saveButton = new Ext.Button({
            text : this.saveText,
            scope : this,
            handler : this.onSaveClick
        });

        this.deleteButton = new Ext.Button({
            text : this.deleteText,
            scope : this,
            handler : this.onDeleteClick
        });
        
        this.cancelButton = new Ext.Button({
            text : this.cancelText,
            scope : this,
            handler : this.onCancelClick
        });

        return [this.saveButton, this.deleteButton, this.cancelButton];
    },

    buildDurationFields : function() {
        this.startDateField = new Ext.ux.form.DateTime({
            name : 'StartDate',
            x:10,
            y:7,
            width:160,
            timeFormat:this.timeFormat,
            timeWidth : 60,
            timeConfig: this.timeConfig,
            dateFormat:this.dateFormat,
            dateConfig : this.dateConfig
        });
                    
        this.durationField = new Ext.ux.form.SpinnerField({
            x:180,
            y:7,
            width:55,
            minValue : 0,
            allowNegative:false
        });
                    
        this.durationLabel = new Ext.form.Label({
            y:7,
            x:240,
            xtype : 'label',
            text : this.durationText
        });

        return [this.startDateField, this.durationField, this.durationLabel];
    },

    initComponent : function() {
        
        if (!this.fieldsPanelConfig) throw 'Must define a fieldsPanelConfig property';
        
        this.fieldsPanelConfig.region = 'center';

        Ext.apply(this, {
            fbar : this.buildButtons(),
            items : [{
                region : 'north',
                layout : 'absolute',
                height :35,
                border : false,
                cls : 'sch-eventeditor-timefields',
                items : this.buildDurationFields()
            },
            this.fieldsPanelConfig]
        });
        Sch.plugins.EventEditor.superclass.initComponent.call(this);
    },
    
    init : function(scheduler) {
        this.scheduler = scheduler;
        this.eventStore = scheduler.getEventStore();

        this.scheduler.on({
            eventdblclick : this.onEventDblClick, 
            afterrender : this.onSchedulerRender,
            destroy : this.onSchedulerDestroy,
            dragcreateend : this.onDragCreateEnd, 
            scope : this
        });
        
        this.scheduler.registerEventEditor(this);
    },
    
    onEventDblClick : function(g, evtRecord) {
        this.show(evtRecord);
    },
    
    onSchedulerRender : function() {
        this.render(Ext.getBody());

        // Collapse after render, otherwise rendering is messed up
        this.collapse();
         
        if (this.hideOnBlur) {
            // Hide when clicking outside panel
            this.mon(Ext.getBody(), 'mousedown', this.onMouseDown, this);
        }
    },

    onMouseDown : function(e){
        var sd = this.startDateField;
                        
        if (!this.collapsed && 
            !e.within(this.getEl()) &&
            (!sd.tf.view || !e.within(sd.tf.view.el)) &&
            (!sd.df.menu || !e.within(sd.df.menu.el))) {        // HACK, reading private/undocumented property 'menu'
            this.collapse(false);
        }
    },

    onSchedulerDestroy : function() {
        this.scheduler.un('eventdblclick', this.onEventDblClick, this);
    },

    onDragCreateEnd : function(s, eventRecord) {
        if (!this.dragProxyEl && this.scheduler.dragCreator) {
            this.dragProxyEl = this.scheduler.dragCreator.getProxy();
        }

        // Call scheduler template method
        this.scheduler.onEventCreated(eventRecord);

        this.show(eventRecord, this.dragProxyEl);
    },

    // Always hide drag proxy on collapse
    onCollapse : function() {
        var dpEl = this.dragProxyEl;
        if (dpEl) {
            dpEl.hide();
        }
        Sch.plugins.EventEditor.superclass.onCollapse.apply(this, arguments);
    }
});


Post by cayenne_08 »

Thanks a lot Mats for the quick response!!

Post by cayenne_08 »

Hi Mats,

When I run the source code for EventEditor,

I get the following error:

"Sch.util.Date is undefined"

var duration = Sch.util.Date.getDurationInHours(eventRecord.get('StartDate'), eventRecord.get('EndDate'));

Can you please send me the source code for Sch.util.Date?

Thanks!!

Post by mats »

Are you using the 1.7 version of scheduler? Then use this version instead:
/*
 * Ext Scheduler 1.7
 * Copyright(c) 2009-2010 Mats Bryntse Consulting
 * mats@ext-scheduler.com
 * http://ext-scheduler.com/license.html
 *
 */

Ext.ns('Sch.plugins');

/**
 * @class Sch.plugins.EventEditor
 * @extends Ext.FormPanel
 * A FormPanel used to edit scheduled events
 * @constructor
 * Create a new instance of this plugin
 * @param {Object} config The configuration options
 */
Sch.plugins.EventEditor = Ext.extend(Ext.FormPanel, {
    
    /**
     * @cfg {String} saveText The text to show on the save button
     */
    saveText : 'Save',
    
    /**
     * @cfg {String} cancelText The text to show on the cancel button
     */
    cancelText : 'Cancel',
    
    /**
     * @cfg {String} hoursText The text to show after the hour spinner field
     */
    hoursText : 'hrs',
    
    /**
     * @cfg {Object} hideOnBlur True to hide this panel if a click is detected outside the panel
     */
    hideOnBlur : true,
     
    /**
     * @cfg {Object} timeConfig Config for the TimeField constructor.
     */
    timeConfig : {
         allowBlank:false,
         editable : false,
         forceSelection : true
    },
    
    /**
     * @cfg {String} fieldsPanel Panel representing your data that is associated with a scheduler event
     * 
     * Example:
     *  
     * <pre><code>
        fieldsPanel : {
                        layout : 'form',
                        style:'background:#fff',
                        border : false,
                        cls : 'editorpanel',
                        labelAlign : 'top',
                        defaults : {
                            width : 135
                        },
                        items : [
                            titleField = new Ext.form.TextField({
                                name : 'Title',
                                fieldLabel : 'Task'
                            }),
                            
                            locationField = new Ext.form.TextField({
                                name : 'Location',
                                fieldLabel : 'Location'
                            })
                        ]
                    }
     * </pre></code>
     * 
     */
    fieldsPanel : null,
    
    /**
     * @cfg {String} dateFormat This config parameter is passed to the TimeField constructor.
     */
    dateFormat:'Y-m-d',
    
    /**
     * @cfg {String} timeFormat This config parameter is passed to the TimeField constructor.
     */
    timeFormat:'H:i',
    
    /* 
     * Expands the editor
     * @param {Record} eventRecord The record to show in the editor panel
     */
    show : function(eventRecord) {
        
        this.eventRecord = eventRecord;
        
        // Manually set the duration field value
        var duration = Date.getDurationInHours(eventRecord.get('StartDate'), eventRecord.get('EndDate'));
        this.durationField.setValue(duration);
        
        // Load form panel fields
        this.getForm().loadRecord(eventRecord);
        var eventEl = this.grid.getElementFromEventRecord(eventRecord);
        this.el.anchorTo(eventEl, 'bl', this.getConstrainOffsets(eventEl));
        this.expand();
    },
    
    // TODO implement support for constraining the editor panel to the viewport
    getConstrainOffsets : function(eventEl) {
        return [0, 0];
    },
    
    cls : 'sch-eventeditor',
    layout : 'border',
    border : false,
    
    initComponent : function() {
        
        if (!this.fieldsPanelConfig) throw 'Must define a fieldsPanelConfig property';
        
        if (this.hideOnBlur) {
            // Hide when clicking outside panel
            this.mon(Ext.getBody(), 'click', function(e){
                if (!this.collapsed && !e.within(this.getEl()) && !Ext.fly(e.getTarget()).is('.x-combo-list-item')) {
                  this.collapse(false);
                }
            }, this);
        }
        
        // Collapse after render, otherwise rendering is messed up
        this.on('render', this.collapse, this);
        
        this.fieldsPanelConfig.region = 'center';
        
        Ext.apply(this, {
            buttons : [
                {
                    text : this.saveText,
                    scope : this,
                    handler : function() {
                        if (this.getForm().isValid()) {
                            var start = this.startDateField.getValue(),
                                hours = this.durationField.getValue();
                                
                            if (start && hours) {
                                end = start.add(Date.MINUTE, hours * 60);
                            }
                            this.saveHandler.call(this.saveHandlerScope || this, this, start, end, this.eventRecord);
                        }
                    }
                },
                {
                    text : this.cancelText,
                    scope : this,
                    handler : this.collapse
                }
            ],
            items : [{
                region : 'north',
                layout : 'absolute',
                height :35,
                border : false,
                cls : 'sch-eventeditor-timefields',
                items : [
                    this.startDateField = new Ext.ux.form.DateTime({
                        name : 'StartDate',
                        x:10,
                        y:7,
                        width:160,
                        timeFormat:this.timeFormat,
                        timeWidth : 60,
                        timeConfig: this.timeConfig,
                        dateFormat:this.dateFormat,
                        dateConfig: {
                             allowBlank:false
                        }
                    }),
                    
                    this.durationField = new Ext.ux.form.SpinnerField({
                        x:180,
                        y:7,
                        width:55,
                        allowBlank:false
                    }),
                    
                    new Ext.form.Label({
                        y:7,
                        x:240,
                        xtype : 'label',
                        text : this.hoursText
                    })
                ]
            },
            this.fieldsPanelConfig]
        });
        Sch.plugins.EventEditor.superclass.initComponent.call(this);
    },
    
    init : function(grid) {
        grid.on('eventdblclick', this.onEventDblClick, this);
        grid.on('render', this.onGridRender, this);
        
        grid.on('beforedestroy', function() {
            grid.un('eventdblclick', this.onEventDblClick, this);
        });
        
        this.grid = grid;
    },
    
    onEventDblClick : function(g, evtRecord) {
        this.show(evtRecord);
    },
    
    onGridRender : function() {
        this.render(Ext.getBody());
    }
});

Post by cayenne_08 »

How do I check the version of Ext Scheduler?

Post Reply