    /** * @class Ext.grid.plugin.Editable * * The Editable plugin injects editing at a row level for Modern Toolkit's * Grid. Editing begins by double-tapping a row.  This can be set to any event, which we'll * discuss below. The editor consists of a small positioned dialog that be shown on the right * side of your viewport. * * There is a button to save or cancel all changes for the edit in the toolbar, and the * row is deletable by default. * * The default editable grid can be defined like so: * *     @example *     Ext.create({ *         xtype: 'grid', *         fullscreen: true, *         plugins: 'grideditable', *         store: { *             fields: [], *             data: [{ *                 name: 'Jake' *             }, { *                 name: 'Finn' *             }] *         }, *         columns: [{ *             text: 'Name', *             dataIndex: 'name', *             flex: 1, *             editable: true *         }] *     }); * * By opening up the plugins type as an object (or an array of objects), you can modify your * editor more significantly.  You can see the changeable bits below: * *     @example *     Ext.create({ *         xtype: 'grid', *         fullscreen: true, *         plugins: { *             type: 'grideditable', *             triggerEvent: 'doubletap', *             enableDeleteButton: true, *             formConfig: null, // See more below * *             defaultFormConfig: { *                 xtype: 'formpanel', *                 scrollable: true, *                 items: { *                     xtype: 'fieldset' *                 } *             }, * *             toolbarConfig: { *                 xtype: 'titlebar', *                 docked: 'top', *                 items: [{ *                     xtype: 'button', *                     ui: 'decline', *                     text: 'Cancel', *                     align: 'left', *                     action: 'cancel' *                 }, { *                     xtype: 'button', *                     ui: 'confirm', *                     text: 'Submit', *                     align: 'right', *                     action: 'submit' *                 }] *             }, *         }, *         store: { *             fields: [], *             data: [{ *                 name: 'Jake' *             }, { *                 name: 'Finn' *             }] *         }, *         columns: [{ *             text: 'Name', *             dataIndex: 'name', *             flex: 1, *             editable: true *         }] *     }); * *  As you can see, you can easily modify nearly every bit of the editor window.  As mentioned *  above, the toolbar and delete button are the only components included by default.  That's *  where formConfig comes into play. * *  By adding formConfig, you can hardcode the form that gets created when editing a row. *  There are no fields set on the form initially, so you will need to define them *  yourself.  For example, if you had a "name" column, and you wanted it to be editable, *  you would do something like this in your plugins object: * *     formConfig: { *        items: [{ *           xtype: 'textfield', *           name: 'name', *           label: 'Name' *        }] *     } * *  Now, upon opening the editor, you would see a textfield populated with the editable value from *  its corresponding record. * *  If you want to alter certain form configurations, but still have the default editor fields applied, use *  the defaultFormConfig instead. */Ext.define('Ext.grid.plugin.Editable', {    extend: 'Ext.Component',    alias: 'plugin.grideditable' ,     config: {        /**         * @private         */        grid: null,         /**         * @cfg {String} triggerEvent          * The event used to trigger the showing of the editor form.         */        triggerEvent: 'doubletap',         /**         * @cfg {Object} formConfig          * By changing the formConfig you can hardcode the form that gets created when editing a row.         * Note that the fields are not set on this form, so you will have to define them yourself in this config.         * If you want to alter certain form configurations, but still have the default editor fields applied, use         * the defaultFormConfig instead.         */        formConfig: null,         /**         * Configures the default form appended to the editable panel.         */        defaultFormConfig: {            xtype: 'formpanel',            scrollable: true,            items: {                xtype: 'fieldset'            }        },         /**         * Configures the toolbar appended to the editable panel.         */        toolbarConfig: {            xtype: 'titlebar',            docked: 'top',            items: [{                xtype: 'button',                ui: 'decline',                text: 'Cancel',                align: 'left',                action: 'cancel'            }, {                xtype: 'button',                ui: 'confirm',                text: 'Submit',                align: 'right',                action: 'submit'            }]        },         /**         *  Creates a delete button, which allows the user to delete the selected row.         */        enableDeleteButton: true    },     init: function(grid) {        this.setGrid(grid);    },     updateGrid: function(grid, oldGrid) {        var triggerEvent = this.getTriggerEvent();        if (oldGrid) {            oldGrid.renderElement.un(triggerEvent, 'onTrigger', this);        }         if (grid) {            grid.renderElement.on(triggerEvent, 'onTrigger', this);        }    },     onCancelTap: function() {        this.sheet.hide();    },     onSubmitTap: function() {        this.form.getRecord().set(this.form.getValues());        this.sheet.hide();    },     onSheetHide: function() {        this.sheet.destroy();        this.form = null;        this.sheet = null;    },     getRecordByTriggerEvent: function(e) {        var rowEl = e.getTarget('.' + Ext.baseCSSPrefix + 'gridrow'),            row;         if (rowEl) {            row = Ext.getCmp(rowEl.id);            if (row) {                return row.getRecord();            }        }         return null;    },     getEditorFields: function(columns) {        var fields = [],            ln = columns.length,            i, column, editor;         for (i = 0; i < ln; i++) {            column = columns[i];            if (column.getEditable()) {                editor = Ext.apply({}, column.getEditor() || column.getDefaultEditor());                editor.label = column.getText();                fields.push(editor);            }        }         return fields;    },     onTrigger: function(e) {        var me = this,            grid = me.getGrid(),            formConfig = me.getFormConfig(),            toolbarConfig = me.getToolbarConfig(),            record = me.getRecordByTriggerEvent(e),            fields, form, sheet, toolbar;         if (record) {            if (formConfig) {                this.form = form = Ext.factory(formConfig, Ext.form.Panel);            } else {                this.form = form = Ext.factory(me.getDefaultFormConfig());                 fields = me.getEditorFields(grid.getColumns());                form.down('fieldset').setItems(fields);            }             form.setRecord(record);             toolbar = Ext.factory(toolbarConfig, Ext.form.TitleBar);            toolbar.down('button[action=cancel]').on('tap', 'onCancelTap', this);            toolbar.down('button[action=submit]').on('tap', 'onSubmitTap', this);             this.sheet = sheet = grid.add({                xtype: 'sheet',                items: [toolbar, form],                hideOnMaskTap: true,                enter: 'right',                exit: 'right',                centered: false,                right: 0,                width: 320,                layout: 'fit',                stretchY: true,                hidden: true            });             if (me.getEnableDeleteButton()) {                form.add({                    xtype: 'button',                    text: 'Delete',                    ui: 'decline',                    margin: 10,                    handler: function() {                        grid.getStore().remove(record);                        sheet.hide();                    }                });            }             sheet.on('hide', 'onSheetHide', this);             sheet.show();        }    }});