UNPKG

@atlassian/aui

Version:

Atlassian User Interface Framework

983 lines (830 loc) 39.4 kB
(function (global, factory) { if (typeof define === "function" && define.amd) { define(['module', 'exports', './jquery', './internal/log', './backbone', './restful-table/class-names', './restful-table/custom-create-view', './restful-table/custom-edit-view', './restful-table/custom-read-view', './restful-table/data-keys', './restful-table/edit-row', './restful-table/entry-model', './restful-table/events', './internal/globalize', './i18n', './restful-table/row', './restful-table/throbber'], factory); } else if (typeof exports !== "undefined") { factory(module, exports, require('./jquery'), require('./internal/log'), require('./backbone'), require('./restful-table/class-names'), require('./restful-table/custom-create-view'), require('./restful-table/custom-edit-view'), require('./restful-table/custom-read-view'), require('./restful-table/data-keys'), require('./restful-table/edit-row'), require('./restful-table/entry-model'), require('./restful-table/events'), require('./internal/globalize'), require('./i18n'), require('./restful-table/row'), require('./restful-table/throbber')); } else { var mod = { exports: {} }; factory(mod, mod.exports, global.jquery, global.log, global.backbone, global.classNames, global.customCreateView, global.customEditView, global.customReadView, global.dataKeys, global.editRow, global.entryModel, global.events, global.globalize, global.i18n, global.row, global.throbber); global.restfulTable = mod.exports; } })(this, function (module, exports, _jquery, _log, _backbone, _classNames, _customCreateView, _customEditView, _customReadView, _dataKeys, _editRow, _entryModel, _events, _globalize, _i18n, _row, _throbber) { 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _jquery2 = _interopRequireDefault(_jquery); var logger = _interopRequireWildcard(_log); var _backbone2 = _interopRequireDefault(_backbone); var _classNames2 = _interopRequireDefault(_classNames); var _customCreateView2 = _interopRequireDefault(_customCreateView); var _customEditView2 = _interopRequireDefault(_customEditView); var _customReadView2 = _interopRequireDefault(_customReadView); var _dataKeys2 = _interopRequireDefault(_dataKeys); var _editRow2 = _interopRequireDefault(_editRow); var _entryModel2 = _interopRequireDefault(_entryModel); var _events2 = _interopRequireDefault(_events); var _globalize2 = _interopRequireDefault(_globalize); var _i18n2 = _interopRequireDefault(_i18n); var _row2 = _interopRequireDefault(_row); var _throbber2 = _interopRequireDefault(_throbber); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Triggers a custom event on the document object * * @param {String} name - name of event * @param {Array} args - args for event handler */ function triggerEvt(name, args) { (0, _jquery2.default)(document).trigger(name, args); } /** * Some generic error handling that fires event in multiple contexts * - on document * - on Instance * - on document with prefixed id. * * @param evt * @param inst * @param args */ function triggerEvtForInst(evt, inst, args) { (0, _jquery2.default)(inst).trigger(evt, args); triggerEvt(evt, args); if (inst.id) { triggerEvt(inst.id + '_' + evt, args); } } /** * A table whose entries/rows can be retrieved, added and updated via REST (CRUD). * It uses backbone.js to sync the table's state back to the server, avoiding page refreshes. * * @class RestfulTable */ var RestfulTable = _backbone2.default.View.extend({ /** * @param {!Object} options * ... {!Object} resources * ... ... {(string|function(function(Array.<Object>)))} all - URL of REST resource OR function that retrieves all entities. * ... ... {string} self - URL of REST resource to sync a single entities state (CRUD). * ... {!(selector|Element|jQuery)} el - Table element or selector of the table element to populate. * ... {!Array.<Object>} columns - Which properties of the entities to render. The id of a column maps to the property of an entity. * ... {Object} views * ... ... {RestfulTable.EditRow} editRow - Backbone view that renders the edit & create row. Your view MUST extend RestfulTable.EditRow. * ... ... {RestfulTable.Row} row - Backbone view that renders the readonly row. Your view MUST extend RestfulTable.Row. * ... {boolean} allowEdit - Is the table editable. If true, clicking row will switch it to edit state. Default true. * ... {boolean} allowDelete - Can entries be removed from the table, default true. * ... {boolean} allowCreate - Can new entries be added to the table, default true. * ... {boolean} allowReorder - Can we drag rows to reorder them, default false. * ... {boolean} autoFocus - Automatically set focus to first field on init, default false. * ... {boolean} reverseOrder - Reverse the order of rows, default false. * ... {boolean} silent - Do not trigger a "refresh" event on sort, default false. * ... {String} id - The id for the table. This id will be used to fire events specific to this instance. * ... {string} createPosition - If set to "bottom", place the create form at the bottom of the table instead of the top. * ... {string} addPosition - If set to "bottom", add new rows at the bottom of the table instead of the top. If undefined, createPosition will be used to define where to add the new row. * ... {string} noEntriesMsg - Text to display under the table header if it is empty, default empty. * ... {string} loadingMsg - Text/HTML to display while loading, default "Loading". * ... {string} submitAccessKey - Access key for submitting. * ... {string} cancelAccessKey - Access key for canceling. * ... {function(Object): (string|function(number, string): string)} deleteConfirmation - HTML to display in popup to confirm deletion. * ... {function(string): (selector|jQuery|Element)} fieldFocusSelector - Element to focus on given a name. * ... {EntryModel} model - Backbone model representing a row, default EntryModel. * ... {Backbone.Collection} Collection - Backbone collection representing the entire table, default Backbone.Collection. */ initialize: function initialize(options) { var instance = this; // combine default and user options instance.options = _jquery2.default.extend(true, instance._getDefaultOptions(options), options); // Prefix events for this instance with this id. instance.id = this.options.id; // faster lookup instance._event = _events2.default; instance.classNames = _classNames2.default; instance.dataKeys = _dataKeys2.default; // shortcuts to popular elements this.$table = (0, _jquery2.default)(options.el).addClass(this.classNames.RESTFUL_TABLE).addClass(this.classNames.ALLOW_HOVER).addClass('aui').addClass(instance.classNames.LOADING); this.$table.wrapAll("<form class='aui' action='#' />"); this.$thead = (0, _jquery2.default)('<thead/>'); this.$theadRow = (0, _jquery2.default)('<tr />').appendTo(this.$thead); this.$tbody = (0, _jquery2.default)('<tbody/>'); if (!this.$table.length) { throw new Error('RestfulTable: Init failed! The table you have specified [' + this.$table.selector + '] cannot be found.'); } if (!this.options.columns) { throw new Error("RestfulTable: Init failed! You haven't provided any columns to render."); } // Let user know the table is loading this.showGlobalLoading(); this.options.columns.forEach(function (column) { var header = _jquery2.default.isFunction(column.header) ? column.header() : column.header; if (typeof header === 'undefined') { logger.warn('You have not specified [header] for column [' + column.id + ']. Using id for now...'); header = column.id; } instance.$theadRow.append('<th>' + header + '</th>'); }); // columns for submit buttons and loading indicator used when editing instance.$theadRow.append('<th></th><th></th>'); // create a new Backbone collection to represent rows (http://documentcloud.github.com/backbone/#Collection) this._models = this._createCollection(); // shortcut to the class we use to create rows this._rowClass = this.options.views.row; this.editRows = []; // keep track of rows that are being edited concurrently this.$table.closest('form').submit(function (e) { if (instance.focusedRow) { // Delegates saving of row. See EditRow.submit instance.focusedRow.trigger(instance._event.SAVE); } e.preventDefault(); }); if (this.options.allowReorder) { // Add allowance for another cell to the <thead> this.$theadRow.prepend('<th />'); // Allow drag and drop reordering of rows this.$tbody.sortable({ handle: '.' + this.classNames.DRAG_HANDLE, helper: function helper(e, elt) { var helper = (0, _jquery2.default)('<div/>').attr('class', elt.attr('class')).addClass(instance.classNames.MOVEABLE); elt.children().each(function (i) { var $td = (0, _jquery2.default)(this); // .offsetWidth/.outerWidth() is broken in webkit for tables, so we do .clientWidth + borders // Need to coerce the border-left-width to an in because IE - http://bugs.jquery.com/ticket/10855 var borderLeft = parseInt(0 + $td.css('border-left-width'), 10); var borderRight = parseInt(0 + $td.css('border-right-width'), 10); var width = $td[0].clientWidth + borderLeft + borderRight; helper.append((0, _jquery2.default)('<div/>').html($td.html()).attr('class', $td.attr('class')).width(width)); }); helper = (0, _jquery2.default)("<div class='aui-restfultable-readonly'/>").append(helper); // Basically just to get the styles. helper.css({ left: elt.offset().left }); // To align with the other table rows, since we've locked scrolling on x. helper.appendTo(document.body); return helper; }, start: function start(event, ui) { var cachedHeight = ui.helper[0].clientHeight; var $this = ui.placeholder.find('td'); // Make sure that when we start dragging widths do not change ui.item.addClass(instance.classNames.MOVEABLE).children().each(function (i) { (0, _jquery2.default)(this).width($this.eq(i).width()); }); // Create a <td> to add to the placeholder <tr> to inherit CSS styles. var td = '<td colspan="' + instance.getColumnCount() + '">&nbsp;</td>'; ui.placeholder.html(td).css({ height: cachedHeight, visibility: 'visible' }); // Stop hover effects etc from occuring as we move the mouse (while dragging) over other rows instance.getRowFromElement(ui.item[0]).trigger(instance._event.MODAL); }, stop: function stop(event, ui) { if ((0, _jquery2.default)(ui.item[0]).is(':visible')) { ui.item.removeClass(instance.classNames.MOVEABLE).children().attr('style', ''); ui.placeholder.removeClass(instance.classNames.ROW); // Return table to a normal state instance.getRowFromElement(ui.item[0]).trigger(instance._event.MODELESS); } }, update: function update(event, ui) { var context = { row: instance.getRowFromElement(ui.item[0]), item: ui.item, nextItem: ui.item.next(), prevItem: ui.item.prev() }; instance.move(context); }, axis: 'y', delay: 0, containment: 'document', cursor: 'move', scroll: true, zIndex: 8000 }); // Prevent text selection while reordering. this.$tbody.bind('selectstart mousedown', function (event) { return !(0, _jquery2.default)(event.target).is('.' + instance.classNames.DRAG_HANDLE); }); } if (this.options.allowCreate !== false) { // Create row responsible for adding new entries ... this._createRow = new this.options.views.editRow({ columns: this.options.columns, isCreateRow: true, model: this.options.model.extend({ url: function url() { return instance.options.resources.self; } }), cancelAccessKey: this.options.cancelAccessKey, submitAccessKey: this.options.submitAccessKey, allowReorder: this.options.allowReorder, fieldFocusSelector: this.options.fieldFocusSelector }).bind(this._event.CREATED, function (values) { if (instance.options.addPosition == undefined && instance.options.createPosition === 'bottom' || instance.options.addPosition === 'bottom') { instance.addRow(values); } else { instance.addRow(values, 0); } }).bind(this._event.VALIDATION_ERROR, function () { this.trigger(instance._event.FOCUS); }).render({ errors: {}, values: {} }); // ... and appends it as the first row this.$create = (0, _jquery2.default)('<tbody class="' + this.classNames.CREATE + '" />').append(this._createRow.el); // Manage which row has focus this._applyFocusCoordinator(this._createRow); // focus create row this._createRow.trigger(this._event.FOCUS); } // when a model is removed from the collection, remove it from the viewport also this._models.bind('remove', function (model) { instance.getRows().forEach(function (row) { if (row.model === model) { if (row.hasFocus() && instance._createRow) { instance._createRow.trigger(instance._event.FOCUS); } instance.removeRow(row); } }); }); this.fetchInitialResources(); }, fetchInitialResources: function fetchInitialResources() { var instance = this; if (_jquery2.default.isFunction(this.options.resources.all)) { this.options.resources.all(function (entries) { instance.populate(entries); }); } else { _jquery2.default.get(this.options.resources.all, function (entries) { instance.populate(entries); }); } }, move: function move(context) { var instance = this; var createRequest = function createRequest(afterElement) { if (!afterElement.length) { return { position: 'First' }; } else { var afterModel = instance.getRowFromElement(afterElement).model; return { after: afterModel.url() }; } }; if (context.row) { var data = instance.options.reverseOrder ? createRequest(context.nextItem) : createRequest(context.prevItem); _jquery2.default.ajax({ url: context.row.model.url() + '/move', type: 'POST', dataType: 'json', contentType: 'application/json', data: JSON.stringify(data), complete: function complete() { // hides loading indicator (spinner) context.row.hideLoading(); }, success: function success(xhr) { triggerEvtForInst(instance._event.REORDER_SUCCESS, instance, [xhr]); }, error: function error(xhr) { var responseData = _jquery2.default.parseJSON(xhr.responseText || xhr.data); triggerEvtForInst(instance._event.SERVER_ERROR, instance, [responseData, xhr, this]); } }); // shows loading indicator (spinner) context.row.showLoading(); } }, _createCollection: function _createCollection() { var instance = this; // create a new Backbone collection to represent rows (http://documentcloud.github.com/backbone/#Collection) var RowsAwareCollection = this.options.Collection.extend({ // Force the collection to re-sort itself. You don't need to call this under normal // circumstances, as the set will maintain sort order as each item is added. sort: function sort(options) { options || (options = {}); if (!this.comparator) { throw new Error('Cannot sort a set without a comparator'); } this.tableRows = instance.getRows(); this.models = this.sortBy(this.comparator); this.tableRows = undefined; if (!options.silent) { this.trigger('refresh', this, options); } return this; }, remove: function remove(models, options) { this.tableRows = instance.getRows(); _backbone2.default.Collection.prototype.remove.apply(this, arguments); this.tableRows = undefined; return this; } }); return new RowsAwareCollection([], { comparator: function comparator(row) { // sort models in collection based on dom ordering var index; var currentTableRows = this.tableRows !== undefined ? this.tableRows : instance.getRows(); currentTableRows.some(function (item, i) { if (item.model.id === row.id) { index = i; return true; } }); return index; } }); }, /** * Refreshes table with entries * * @param entries */ populate: function populate(entries) { if (this.options.reverseOrder) { entries.reverse(); } this.hideGlobalLoading(); if (entries && entries.length) { // Empty the models collection this._models.reset([], { silent: true }); // Add all the entries to collection and render them this.renderRows(entries); // show message to user if we have no entries if (this.isEmpty()) { this.showNoEntriesMsg(); } } else { this.showNoEntriesMsg(); } // Ok, lets let everyone know that we are done... this.$table.append(this.$thead); if (this.options.createPosition === 'bottom') { this.$table.append(this.$tbody).append(this.$create); } else { this.$table.append(this.$create).append(this.$tbody); } this.$table.removeClass(this.classNames.LOADING).trigger(this._event.INITIALIZED, [this]); triggerEvtForInst(this._event.INITIALIZED, this, [this]); if (this.options.autoFocus) { this.$table.find(':input:text:first').focus(); // set focus to first field } }, /** * Shows loading indicator and text * * @return {RestfulTable} */ showGlobalLoading: function showGlobalLoading() { if (!this.$loading) { this.$loading = (0, _jquery2.default)('<div class="aui-restfultable-init">' + (0, _throbber2.default)() + '<span class="aui-restfultable-loading">' + this.options.loadingMsg + '</span></div>'); } if (!this.$loading.is(':visible')) { this.$loading.insertAfter(this.$table); } return this; }, /** * Hides loading indicator and text * @return {RestfulTable} */ hideGlobalLoading: function hideGlobalLoading() { if (this.$loading) { this.$loading.remove(); } return this; }, /** * Adds row to collection and renders it * * @param {Object} values * @param {number} index * @return {RestfulTable} */ addRow: function addRow(values, index) { var view; var model; if (!values.id) { throw new Error('RestfulTable.addRow: to add a row values object must contain an id. ' + 'Maybe you are not returning it from your restend point?' + 'Recieved:' + JSON.stringify(values)); } model = new this.options.model(values); view = this._renderRow(model, index); this._models.add(model); this.removeNoEntriesMsg(); // Let everyone know we added a row triggerEvtForInst(this._event.ROW_ADDED, this, [view, this]); return this; }, /** * Provided a view, removes it from display and backbone collection * * @param row {Row} The row to remove. */ removeRow: function removeRow(row) { this._models.remove(row.model); row.remove(); if (this.isEmpty()) { this.showNoEntriesMsg(); } // Let everyone know we removed a row triggerEvtForInst(this._event.ROW_REMOVED, this, [row, this]); }, /** * Is there any entries in the table * * @return {Boolean} */ isEmpty: function isEmpty() { return this._models.length === 0; }, /** * Gets all models * * @return {Backbone.Collection} */ getModels: function getModels() { return this._models; }, /** * Gets table body * * @return {jQuery} */ getTable: function getTable() { return this.$table; }, /** * Gets table body * * @return {jQuery} */ getTableBody: function getTableBody() { return this.$tbody; }, /** * Gets create Row * * @return {EditRow} */ getCreateRow: function getCreateRow() { return this._createRow; }, /** * Gets the number of table columns, accounting for the number of * additional columns added by RestfulTable itself * (such as the drag handle column, buttons and actions columns) * * @return {Number} */ getColumnCount: function getColumnCount() { var staticFieldCount = 2; // accounts for the columns allocated to submit buttons and loading indicator if (this.allowReorder) { ++staticFieldCount; } return this.options.columns.length + staticFieldCount; }, /** * Get the Row that corresponds to the given <tr> element. * * @param {HTMLElement} tr * * @return {Row} */ getRowFromElement: function getRowFromElement(tr) { return (0, _jquery2.default)(tr).data(this.dataKeys.ROW_VIEW); }, /** * Shows message {options.noEntriesMsg} to the user if there are no entries * * @return {RestfulTable} */ showNoEntriesMsg: function showNoEntriesMsg() { if (this.$noEntries) { this.$noEntries.remove(); } this.$noEntries = (0, _jquery2.default)('<tr>').addClass(this.classNames.NO_ENTRIES).append((0, _jquery2.default)('<td>').attr('colspan', this.getColumnCount()).text(this.options.noEntriesMsg)).appendTo(this.$tbody); return this; }, /** * Removes message {options.noEntriesMsg} to the user if there ARE entries * * @return {RestfulTable} */ removeNoEntriesMsg: function removeNoEntriesMsg() { if (this.$noEntries && this._models.length > 0) { this.$noEntries.remove(); } return this; }, /** * Gets the Row from their associated <tr> elements * * @return {Array} */ getRows: function getRows() { var instance = this; var views = []; this.$tbody.find('.' + this.classNames.READ_ONLY).each(function () { var $row = (0, _jquery2.default)(this); var view = $row.data(instance.dataKeys.ROW_VIEW); if (view) { views.push(view); } }); return views; }, /** * Appends entry to end or specified index of table * * @param {EntryModel} model * @param index * * @return {jQuery} */ _renderRow: function _renderRow(model, index) { var instance = this; var $rows = this.$tbody.find('.' + this.classNames.READ_ONLY); var $row; var view; view = new this._rowClass({ model: model, columns: this.options.columns, allowEdit: this.options.allowEdit, allowDelete: this.options.allowDelete, allowReorder: this.options.allowReorder, deleteConfirmation: this.options.deleteConfirmation }); this.removeNoEntriesMsg(); view.bind(this._event.ROW_EDIT, function (field) { triggerEvtForInst(this._event.EDIT_ROW, {}, [this, instance]); instance.edit(this, field); }); $row = view.render().$el; if (index !== -1) { if (typeof index === 'number' && $rows.length !== 0) { $row.insertBefore($rows[index]); } else { this.$tbody.append($row); } } $row.data(this.dataKeys.ROW_VIEW, view); // deactivate all rows - used in the cases, such as opening a dropdown where you do not want the table editable // or any interactions view.bind(this._event.MODAL, function () { instance.$table.removeClass(instance.classNames.ALLOW_HOVER); instance.$tbody.sortable('disable'); instance.getRows().forEach(function (row) { if (!instance.isRowBeingEdited(row)) { row.delegateEvents({}); // clear all events } }); }); // activate all rows - used in the cases, such as opening a dropdown where you do not want the table editable // or any interactions view.bind(this._event.MODELESS, function () { instance.$table.addClass(instance.classNames.ALLOW_HOVER); instance.$tbody.sortable('enable'); instance.getRows().forEach(function (row) { if (!instance.isRowBeingEdited(row)) { row.delegateEvents(); // rebind all events } }); }); // ensure that when this row is focused no other are this._applyFocusCoordinator(view); this.trigger(this._event.ROW_INITIALIZED, view); return view; }, /** * Returns if the row is edit mode or note. * * @param {Row} row Read-only row to check if being edited. * * @return {Boolean} */ isRowBeingEdited: function isRowBeingEdited(row) { var isBeingEdited = false; this.editRows.some(function (editRow) { if (editRow.el === row.el) { isBeingEdited = true; return true; } }); return isBeingEdited; }, /** * Ensures that when supplied view is focused no others are * * @param {Backbone.View} view * @return {RestfulTable} */ _applyFocusCoordinator: function _applyFocusCoordinator(view) { var instance = this; if (!view.hasFocusBound) { view.hasFocusBound = true; view.bind(this._event.FOCUS, function () { if (instance.focusedRow && instance.focusedRow !== view) { instance.focusedRow.trigger(instance._event.BLUR); } instance.focusedRow = view; if (view instanceof _row2.default && instance._createRow) { instance._createRow.enable(); } }); } return this; }, /** * Remove specified row from collection holding rows being concurrently edited * * @param {EditRow} editView * * @return {RestfulTable} */ _removeEditRow: function _removeEditRow(editView) { var index = _jquery2.default.inArray(editView, this.editRows); this.editRows.splice(index, 1); return this; }, /** * Focuses last row still being edited or create row (if it exists) * * @return {RestfulTable} */ _shiftFocusAfterEdit: function _shiftFocusAfterEdit() { if (this.editRows.length > 0) { this.editRows[this.editRows.length - 1].trigger(this._event.FOCUS); } else if (this._createRow) { this._createRow.trigger(this._event.FOCUS); } return this; }, /** * Evaluate if we save row when we blur. We can only do this when there is one row being edited at a time, otherwise * it causes an infinite loop JRADEV-5325 * * @return {boolean} */ _saveEditRowOnBlur: function _saveEditRowOnBlur() { return this.editRows.length <= 1; }, /** * Dismisses rows being edited concurrently that have no changes */ dismissEditRows: function dismissEditRows() { this.editRows.forEach(function (editRow) { if (!editRow.hasUpdates()) { editRow.trigger(this._event.FINISHED_EDITING); } }, this); }, /** * Converts readonly row to editable view * * @param {Backbone.View} row * @param {String} field - field name to focus * @return {Backbone.View} editRow */ edit: function edit(row, field) { var instance = this; var editRow = new this.options.views.editRow({ el: row.el, columns: this.options.columns, isUpdateMode: true, allowReorder: this.options.allowReorder, fieldFocusSelector: this.options.fieldFocusSelector, model: row.model, cancelAccessKey: this.options.cancelAccessKey, submitAccessKey: this.options.submitAccessKey }); var values = row.model.toJSON(); values.update = true; editRow.render({ errors: {}, update: true, values: values }).bind(instance._event.UPDATED, function (model, focusUpdated) { instance._removeEditRow(this); this.unbind(); row.render().delegateEvents(); // render and rebind events row.trigger(instance._event.UPDATED); // trigger blur fade out if (focusUpdated !== false) { instance._shiftFocusAfterEdit(); } }).bind(instance._event.VALIDATION_ERROR, function () { this.trigger(instance._event.FOCUS); }).bind(instance._event.FINISHED_EDITING, function () { instance._removeEditRow(this); row.render().delegateEvents(); this.unbind(); // avoid any other updating, blurring, finished editing, cancel events being fired }).bind(instance._event.CANCEL, function () { instance._removeEditRow(this); this.unbind(); // avoid any other updating, blurring, finished editing, cancel events being fired row.render().delegateEvents(); // render and rebind events instance._shiftFocusAfterEdit(); }).bind(instance._event.BLUR, function () { instance.dismissEditRows(); // dismiss edit rows that have no changes if (instance._saveEditRowOnBlur()) { this.trigger(instance._event.SAVE, false); // save row, which if successful will call the updated event above } }); // Ensure that if focus is pulled to another row, we blur the edit row this._applyFocusCoordinator(editRow); // focus edit row, which has the flow on effect of blurring current focused row editRow.trigger(instance._event.FOCUS, field); // disables form fields if (instance._createRow) { instance._createRow.disable(); } this.editRows.push(editRow); return editRow; }, /** * Renders all specified rows * * @param rows {Array<Backbone.Model>} array of objects describing Backbone.Model's to render * @return {RestfulTable} */ renderRows: function renderRows() { var _this = this; var rows = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var comparator = this._models.comparator; var els = []; this._models.comparator = undefined; // disable temporarily, assume rows are sorted var models = rows.map(function (row) { var model = new _this.options.model(row); els.push(_this._renderRow(model, -1).el); return model; }); this._models.add(models, { silent: true }); this._models.comparator = comparator; this.removeNoEntriesMsg(); this.$tbody.append(els); return this; }, /** * Gets default options * * @param {Object} options */ _getDefaultOptions: function _getDefaultOptions(options) { return { model: options.model || _entryModel2.default, allowEdit: true, views: { editRow: _editRow2.default, row: _row2.default }, Collection: _backbone2.default.Collection.extend({ url: options.resources.self, model: options.model || _entryModel2.default }), allowReorder: false, fieldFocusSelector: function fieldFocusSelector(name) { return ':input[name=' + name + '], #' + name; }, loadingMsg: options.loadingMsg || AJS.I18n.getText('aui.words.loading') }; } }); RestfulTable.ClassNames = _classNames2.default; RestfulTable.CustomCreateView = _customCreateView2.default; RestfulTable.CustomEditView = _customEditView2.default; RestfulTable.CustomReadView = _customReadView2.default; RestfulTable.DataKeys = _dataKeys2.default; RestfulTable.EditRow = _editRow2.default; RestfulTable.EntryModel = _entryModel2.default; RestfulTable.Events = _events2.default; RestfulTable.Row = _row2.default; RestfulTable.Throbber = _throbber2.default; (0, _globalize2.default)('RestfulTable', RestfulTable); exports.default = RestfulTable; module.exports = exports['default']; }); //# sourceMappingURL=restful-table.js.map