UNPKG

editable-grid

Version:
237 lines (191 loc) 7.21 kB
var $ = require('jquery'), _ = require('underscore'), rowFactory = require('./rowFactory'), utils = require('./gridUtils'), listeners = require('./gridListeners'), depthFirstTreeTraversal = require('./depthFirstTreeTraversal'), Ears = require('elephant-ears'); var Grid = function (options) { var grid = this; grid.ears = new Ears(); grid.ears.on('editable-delete-mode', function (activate) { if (activate) { grid._createDeleteRows(); } else { grid._removeDeleteRows(); } }); // add default props and funcs to options options = _.defaults(options, { sortConfig: [], id: 'id', borders: true, rows: { link: false, newRow: false, totalRow: false }, stateManager: { isEditable: function () { return false; } }, addListeners: function () { }, treeMode: false, childData: function () { return $.Deferred().resolve([]); }, launchLinksNewTab: false }); // add default props and fncs to columns options.columns = _.map(options.columns, function (column) { var formatter = function (id, value) { return value; }; var parser = function (id, value) { return value; }; var validate = function () { return ''; }; return _.defaults(column, { formatter: formatter, parser: parser, validate: validate, sortable: false, sortCompare: null, sortType: null, nullable: false, type: 'text', link: null, alignment: 'left', titleAlignment: 'left', classes: [], preCreateCallback: function () { } }); }); // store the original order of the data grid.dataOrder = _.clone(options.data); var createHeaderTable = function (columns) { return '<div class="editable-header-table">' + '<table class="table table-bordered">' + '<thead>' + rowFactory.createTableHeaderRow( { columns: columns, isColumnSorted: grid._isColumnSorted }) + '</thead>' + '</table>' + '</div>'; }; var createBodyTable = function () { var hasTreeState = ('_treeState' in grid) && _.keys(grid._treeState); var rowsMarkup = depthFirstTreeTraversal.call(grid, options, options.data, hasTreeState, 0); var tableClazzes = 'table table-bordered'; if (options.rows.link) { tableClazzes += ' table-hover'; } return '<div class="editable-body-table">' + '<table class="' + tableClazzes + '">' + '<tbody>' + rowsMarkup + '</tbody>' + '</table>' + '</div>'; }; var createFooterTable = function (options) { // opening tags var markup = '<div class="editable-footer-table">'; markup += '<table class="table table-bordered"><tfoot>'; if (options.rows.totalRow) { markup += rowFactory.createTableFooterTotalRow({ columns: options.columns, data: options.data }); } if (options.rows.newRow) { markup += rowFactory.createTableFooterAddRow({columns: options.columns}); } // closing tags markup += '</tfoot></table>'; if (options.rows.newRow) { markup += '<div>'; markup += '<button type="button" class="new-row pull-right btn btn-link">Add</button>'; markup += '</div>'; } markup += '</div>'; return markup; }; // attach grid functions _.extend(grid, utils.call(grid, options)); _.extend(grid, { trigger: function (name, params) { grid.ears.trigger(name, params); }, on: function (name, callback) { grid.ears.on(name, callback); }, off: function (name) { grid.ears.off(name); }, destroy: function () { // remove any previous content options.el.empty(); }, get options () { return options; }, clearAllValidation: function () { this.bodyTableContainer.find('.validation-error').remove(); this.bodyTableContainer.find('.has-error').removeClass('has-error'); }, addValidation: function (recordId, propertyName, message) { var td = this.bodyTableContainer.find('tr[data-row-id="' + recordId + '"] ' + 'td[data-col-id="' + propertyName + '"]'); td.addClass('has-error'); td.append('<span class="validation-error help-block small">' + message + '</div>'); }, render: function () { grid.ears.trigger('editable-pre-render'); this.destroy(); // get the height before any contents is rendered var height = options.el.height(); var markup = createHeaderTable(options.columns); markup += createBodyTable(); markup += createFooterTable(options); options.el.append(markup); this.headerTableContainer = options.el.find('.editable-header-table'); this.headerTable = this.headerTableContainer.find('table'); this.bodyTableContainer = options.el.find('.editable-body-table'); this.bodyTable = this.bodyTableContainer.find('table'); this.footerTableContainer = options.el.find('.editable-footer-table'); this.footerTable = this.footerTableContainer.find('table'); if (options.borders === false) { this.headerTable.addClass('no-borders'); this.bodyTable.addClass('no-borders'); this.footerTable.addClass('no-borders'); } if (height > 0) { // only set the body height if the outer containing div has a height set this.bodyTableContainer.height(options.el.height() - this.headerTableContainer.height() - this.footerTableContainer.height()); this.headerTable.width(this.bodyTable.width() + 1); } // the below line enforces the browser to calculate heights and widths if (options.data.length > 0) { this.bodyTableContainer.get(0).scrollHeight > this.bodyTableContainer.get(0).clientHeight; } else { this.bodyTableContainer.height(0); } // attach grid listeners listeners.call(grid, this.headerTableContainer, this.bodyTableContainer, this.footerTableContainer, options); // allow the user to add custom listeners options.addListeners(options.el); grid.ears.trigger('editable-post-render'); } }); }; module.exports = Grid;