1 | import $ from './jquery';
|
2 | import 'jquery-ui/ui/core';
|
3 | import 'jquery-ui/ui/widget';
|
4 | import 'jquery-ui/ui/widgets/mouse';
|
5 | import 'jquery-ui/ui/widgets/draggable';
|
6 | import 'jquery-ui/ui/widgets/sortable';
|
7 | import * as logger from './internal/log';
|
8 | import Backbone from 'backbone';
|
9 | import classNames from './restful-table/class-names';
|
10 | import CustomCreateView from './restful-table/custom-create-view';
|
11 | import CustomEditView from './restful-table/custom-edit-view';
|
12 | import CustomReadView from './restful-table/custom-read-view';
|
13 | import dataKeys from './restful-table/data-keys';
|
14 | import EditRow from './restful-table/edit-row';
|
15 | import EntryModel from './restful-table/entry-model';
|
16 | import {triggerEvtForInst} from './restful-table/event-handlers';
|
17 | import events from './restful-table/event-names';
|
18 | import globalize from './internal/globalize';
|
19 | import Row from './restful-table/row';
|
20 | import { I18n } from './i18n';
|
21 | import {spinner} from './restful-table/spinner';
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | var RestfulTable = Backbone.View.extend({
|
30 | |
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 | initialize: function (options) {
|
61 | var instance = this;
|
62 |
|
63 |
|
64 | instance.options = $.extend(true, instance._getDefaultOptions(options), options);
|
65 |
|
66 |
|
67 | instance.id = this.options.id;
|
68 |
|
69 |
|
70 | instance._event = events;
|
71 | instance.classNames = classNames;
|
72 | instance.dataKeys = dataKeys;
|
73 |
|
74 |
|
75 | this.$table = $(options.el)
|
76 | .addClass(this.classNames.RESTFUL_TABLE)
|
77 | .addClass(this.classNames.ALLOW_HOVER)
|
78 | .addClass('aui');
|
79 |
|
80 | this.$table.wrapAll("<form class='aui' action='#' />");
|
81 |
|
82 | this.$thead = $('<thead/>');
|
83 | this.$theadRow = $('<tr />').appendTo(this.$thead);
|
84 | this.$tbody = $('<tbody/>');
|
85 |
|
86 | if (!this.$table.length) {
|
87 | throw new Error('RestfulTable: Init failed! The table you have specified [' + this.$table.selector + '] cannot be found.');
|
88 | }
|
89 |
|
90 | if (!this.options.columns) {
|
91 | throw new Error("RestfulTable: Init failed! You haven't provided any columns to render.");
|
92 | }
|
93 |
|
94 | if (this.options.deleteConfirmationCallback && !(this.options.deleteConfirmationCallback instanceof Function)) {
|
95 | throw new Error('RestfulTable: Init failed! deleteConfirmationCallback is not a function');
|
96 | }
|
97 |
|
98 |
|
99 | this.showGlobalLoading();
|
100 | this.options.columns.forEach(function (column) {
|
101 | var header = $.isFunction(column.header) ? column.header() : column.header;
|
102 | if (typeof header === 'undefined') {
|
103 | logger.warn('You have not specified [header] for column [' + column.id + ']. Using id for now...');
|
104 | header = column.id;
|
105 | }
|
106 |
|
107 | instance.$theadRow.append('<th>' + header + '</th>');
|
108 | });
|
109 |
|
110 |
|
111 | instance.$theadRow.append('<th></th><th></th>');
|
112 |
|
113 |
|
114 | this._models = this._createCollection();
|
115 |
|
116 |
|
117 | this._rowClass = this.options.views.row;
|
118 |
|
119 | this.editRows = [];
|
120 |
|
121 | this.$table.closest('form').submit(function (e) {
|
122 | if (instance.focusedRow) {
|
123 |
|
124 | instance.focusedRow.trigger(instance._event.SAVE);
|
125 | }
|
126 | e.preventDefault();
|
127 | });
|
128 |
|
129 | if (this.options.allowReorder) {
|
130 |
|
131 | this.$theadRow.prepend('<th />');
|
132 |
|
133 |
|
134 | this.$tbody.sortable({
|
135 | handle: '.' + this.classNames.DRAG_HANDLE,
|
136 | helper: function (e, elt) {
|
137 | var helper = $('<div/>').attr('class', elt.attr('class')).addClass(instance.classNames.MOVEABLE);
|
138 | elt.children().each(function () {
|
139 | var $td = $(this);
|
140 |
|
141 |
|
142 |
|
143 | var borderLeft = parseInt(0 + $td.css('border-left-width'), 10);
|
144 | var borderRight = parseInt(0 + $td.css('border-right-width'), 10);
|
145 | var width = $td[0].clientWidth + borderLeft + borderRight;
|
146 |
|
147 | helper.append($('<div/>').html($td.html()).attr('class', $td.attr('class')).width(width));
|
148 | });
|
149 |
|
150 | helper = $("<div class='aui-restfultable-readonly'/>").append(helper);
|
151 | helper.css({left: elt.offset().left});
|
152 | helper.appendTo(document.body);
|
153 |
|
154 | return helper;
|
155 | },
|
156 | start: function (event, ui) {
|
157 | var cachedHeight = ui.helper[0].clientHeight;
|
158 | var $this = ui.placeholder.find('td');
|
159 |
|
160 |
|
161 | ui.item
|
162 | .addClass(instance.classNames.MOVEABLE)
|
163 | .children().each(function (i) {
|
164 | $(this).width($this.eq(i).width());
|
165 | });
|
166 |
|
167 |
|
168 | var td = '<td colspan="' + instance.getColumnCount() + '"> </td>';
|
169 |
|
170 | ui.placeholder.html(td).css({
|
171 | height: cachedHeight,
|
172 | visibility: 'visible'
|
173 | });
|
174 |
|
175 |
|
176 | instance.getRowFromElement(ui.item[0]).trigger(instance._event.MODAL);
|
177 | },
|
178 | stop: function (event, ui) {
|
179 | if ($(ui.item[0]).is(':visible')) {
|
180 | ui.item
|
181 | .removeClass(instance.classNames.MOVEABLE)
|
182 | .children().attr('style', '');
|
183 |
|
184 | ui.placeholder.removeClass(instance.classNames.ROW);
|
185 |
|
186 |
|
187 | instance.getRowFromElement(ui.item[0]).trigger(instance._event.MODELESS);
|
188 | }
|
189 | },
|
190 | update: function (event, ui) {
|
191 | var context = {
|
192 | row: instance.getRowFromElement(ui.item[0]),
|
193 | item: ui.item,
|
194 | nextItem: ui.item.next(),
|
195 | prevItem: ui.item.prev()
|
196 | };
|
197 |
|
198 | instance.move(context);
|
199 | },
|
200 | axis: 'y',
|
201 | delay: 0,
|
202 | containment: 'document',
|
203 | cursor: 'move',
|
204 | scroll: true,
|
205 | zIndex: 8000
|
206 | });
|
207 |
|
208 |
|
209 | this.$tbody.on('selectstart mousedown', function (event) {
|
210 | return !$(event.target).is('.' + instance.classNames.DRAG_HANDLE);
|
211 | });
|
212 | }
|
213 |
|
214 | if (this.options.allowCreate !== false) {
|
215 |
|
216 |
|
217 | this._createRow = new this.options.views.editRow({
|
218 | columns: this.options.columns,
|
219 | isCreateRow: true,
|
220 | model: this.options.model.extend({
|
221 | url: function () {
|
222 | return instance.options.resources.self;
|
223 | }
|
224 | }),
|
225 | cancelAccessKey: this.options.cancelAccessKey,
|
226 | submitAccessKey: this.options.submitAccessKey,
|
227 | allowReorder: this.options.allowReorder,
|
228 | fieldFocusSelector: this.options.fieldFocusSelector
|
229 | });
|
230 | this._createRow.on(this._event.CREATED, function (values) {
|
231 | if ((typeof instance.options.addPosition === 'undefined' && instance.options.createPosition === 'bottom') ||
|
232 | instance.options.addPosition === 'bottom') {
|
233 | instance.addRow(values);
|
234 | } else {
|
235 | instance.addRow(values, 0);
|
236 | }
|
237 | });
|
238 | this._createRow.on(this._event.VALIDATION_ERROR, function () {
|
239 | this.trigger(instance._event.FOCUS);
|
240 | });
|
241 | this._createRow.render({
|
242 | errors: {},
|
243 | values: {}
|
244 | });
|
245 |
|
246 |
|
247 | this.$create = $('<tbody class="' + this.classNames.CREATE + '" />')
|
248 | .append(this._createRow.el);
|
249 |
|
250 |
|
251 | this._applyFocusCoordinator(this._createRow);
|
252 |
|
253 |
|
254 | if (this.options.autoFocus) {
|
255 | this._createRow.trigger(this._event.FOCUS);
|
256 | }
|
257 | }
|
258 |
|
259 |
|
260 | this._models.on('remove', function (model) {
|
261 | instance.getRows().forEach(function (row) {
|
262 | if (row.model === model) {
|
263 | if (row.hasFocus() && instance._createRow) {
|
264 | instance._createRow.trigger(instance._event.FOCUS);
|
265 | }
|
266 | instance.removeRow(row);
|
267 | }
|
268 | });
|
269 | });
|
270 |
|
271 | this.fetchInitialResources();
|
272 | },
|
273 |
|
274 | fetchInitialResources: function () {
|
275 | var instance = this;
|
276 | if ($.isFunction(this.options.resources.all)) {
|
277 | this.options.resources.all(function (entries) {
|
278 | instance.populate(entries);
|
279 | });
|
280 | } else {
|
281 | $.get(this.options.resources.all, function (entries) {
|
282 | instance.populate(entries);
|
283 | });
|
284 | }
|
285 | },
|
286 |
|
287 | move: function (context) {
|
288 |
|
289 | var instance = this;
|
290 |
|
291 | var createRequest = function (afterElement) {
|
292 | if (!afterElement.length) {
|
293 | return {
|
294 | position: 'First'
|
295 | };
|
296 | } else {
|
297 | var afterModel = instance.getRowFromElement(afterElement).model;
|
298 | return {
|
299 | after: afterModel.url()
|
300 | };
|
301 | }
|
302 | };
|
303 |
|
304 | if (context.row) {
|
305 |
|
306 | var data = instance.options.reverseOrder ? createRequest(context.nextItem) : createRequest(context.prevItem);
|
307 |
|
308 | $.ajax({
|
309 | url: context.row.model.url() + '/move',
|
310 | type: 'POST',
|
311 | dataType: 'json',
|
312 | contentType: 'application/json',
|
313 | data: JSON.stringify(data),
|
314 | complete: function () {
|
315 |
|
316 | context.row.hideLoading();
|
317 | },
|
318 | success: function (xhr) {
|
319 | triggerEvtForInst(instance._event.REORDER_SUCCESS, instance, [xhr]);
|
320 | },
|
321 | error: function (xhr) {
|
322 | var responseData = $.parseJSON(xhr.responseText || xhr.data);
|
323 | triggerEvtForInst(instance._event.SERVER_ERROR, instance, [responseData, xhr, this]);
|
324 | }
|
325 | });
|
326 |
|
327 |
|
328 | context.row.showLoading();
|
329 | }
|
330 | },
|
331 |
|
332 | _createCollection: function () {
|
333 | var instance = this;
|
334 |
|
335 |
|
336 | var RowsAwareCollection = this.options.Collection.extend({
|
337 |
|
338 |
|
339 | sort: function (options) {
|
340 | options || (options = {});
|
341 | if (!this.comparator) {
|
342 | throw new Error('Cannot sort a set without a comparator');
|
343 | }
|
344 | this.tableRows = instance.getRows();
|
345 | this.models = this.sortBy(this.comparator, this);
|
346 | this.tableRows = undefined;
|
347 | if (!options.silent) {
|
348 | this.trigger('refresh', this, options);
|
349 | }
|
350 | return this;
|
351 | },
|
352 | remove: function (...args) {
|
353 | this.tableRows = instance.getRows();
|
354 | Backbone.Collection.prototype.remove.apply(this, args);
|
355 | this.tableRows = undefined;
|
356 | return this;
|
357 | }
|
358 | });
|
359 |
|
360 | return new RowsAwareCollection([], {
|
361 | comparator: function (row) {
|
362 |
|
363 | var index;
|
364 |
|
365 | var currentTableRows = (this && this.tableRows !== undefined) ? this.tableRows : instance.getRows();
|
366 | currentTableRows.some(function (item, i) {
|
367 | if (item.model.id === row.id) {
|
368 | index = i;
|
369 | return true;
|
370 | }
|
371 | });
|
372 | return index;
|
373 | }
|
374 | });
|
375 | },
|
376 |
|
377 | |
378 |
|
379 |
|
380 |
|
381 |
|
382 | populate: function (entries) {
|
383 | if (this.options.reverseOrder) {
|
384 | entries.reverse();
|
385 | }
|
386 |
|
387 | this.hideGlobalLoading();
|
388 | if (entries && entries.length) {
|
389 |
|
390 | this._models.reset([], {silent: true});
|
391 |
|
392 | this.renderRows(entries);
|
393 |
|
394 | if (this.isEmpty()) {
|
395 | this.showNoEntriesMsg();
|
396 | }
|
397 | } else {
|
398 | this.showNoEntriesMsg();
|
399 | }
|
400 |
|
401 |
|
402 | this.$table
|
403 | .append(this.$thead);
|
404 |
|
405 | if (this.options.createPosition === 'bottom') {
|
406 | this.$table.append(this.$tbody)
|
407 | .append(this.$create);
|
408 | } else {
|
409 | this.$table
|
410 | .append(this.$create)
|
411 | .append(this.$tbody);
|
412 | }
|
413 |
|
414 | this.$table.trigger(this._event.INITIALIZED, [this]);
|
415 |
|
416 | triggerEvtForInst(this._event.INITIALIZED, this, [this]);
|
417 |
|
418 | if (this.options.autoFocus) {
|
419 | this.$table.find(':input:text:first').focus();
|
420 | }
|
421 | },
|
422 |
|
423 | |
424 |
|
425 |
|
426 |
|
427 |
|
428 | showGlobalLoading: function () {
|
429 | if (!this.$loading) {
|
430 | this.$loading = $('<div class="aui-restfultable-init">' +
|
431 | '<span class="aui-restfultable-loading">' + spinner + this.options.loadingMsg + '</span></div>');
|
432 | }
|
433 |
|
434 | if (!this.$loading.is(':visible')) {
|
435 | this.$loading.insertAfter(this.$table);
|
436 | }
|
437 |
|
438 | return this;
|
439 | },
|
440 |
|
441 | |
442 |
|
443 |
|
444 |
|
445 | hideGlobalLoading: function () {
|
446 | if (this.$loading) {
|
447 | this.$loading.remove();
|
448 | }
|
449 | return this;
|
450 | },
|
451 |
|
452 |
|
453 | |
454 |
|
455 |
|
456 |
|
457 |
|
458 |
|
459 |
|
460 | addRow: function (values, index) {
|
461 | var view;
|
462 | var model;
|
463 |
|
464 | if (!values.id) {
|
465 | throw new Error('RestfulTable.addRow: to add a row values object must contain an id. ' +
|
466 | 'Maybe you are not returning it from your restend point?' +
|
467 | 'Recieved:' + JSON.stringify(values));
|
468 | }
|
469 |
|
470 | model = new this.options.model(values);
|
471 |
|
472 |
|
473 | view = this._renderRow(model, index);
|
474 |
|
475 | this._models.add(model);
|
476 | this.removeNoEntriesMsg();
|
477 |
|
478 |
|
479 | triggerEvtForInst(this._event.ROW_ADDED, this, [view, this]);
|
480 | return this;
|
481 | },
|
482 |
|
483 | |
484 |
|
485 |
|
486 |
|
487 |
|
488 | removeRow: function (row) {
|
489 | this._models.remove(row.model);
|
490 | row.remove();
|
491 |
|
492 | if (this.isEmpty()) {
|
493 | this.showNoEntriesMsg();
|
494 | }
|
495 |
|
496 |
|
497 | triggerEvtForInst(this._event.ROW_REMOVED, this, [row, this]);
|
498 | },
|
499 |
|
500 | |
501 |
|
502 |
|
503 |
|
504 |
|
505 | isEmpty: function () {
|
506 | return this._models.length === 0;
|
507 | },
|
508 |
|
509 | |
510 |
|
511 |
|
512 |
|
513 |
|
514 | getModels: function () {
|
515 | return this._models;
|
516 | },
|
517 |
|
518 | |
519 |
|
520 |
|
521 |
|
522 |
|
523 | getTable: function () {
|
524 | return this.$table;
|
525 | },
|
526 |
|
527 | |
528 |
|
529 |
|
530 |
|
531 |
|
532 | getTableBody: function () {
|
533 | return this.$tbody;
|
534 | },
|
535 |
|
536 | |
537 |
|
538 |
|
539 |
|
540 |
|
541 | getCreateRow: function () {
|
542 | return this._createRow;
|
543 | },
|
544 |
|
545 | |
546 |
|
547 |
|
548 |
|
549 |
|
550 |
|
551 |
|
552 | getColumnCount: function () {
|
553 | var staticFieldCount = 2;
|
554 | if (this.allowReorder) {
|
555 | ++staticFieldCount;
|
556 | }
|
557 | return this.options.columns.length + staticFieldCount;
|
558 | },
|
559 |
|
560 | |
561 |
|
562 |
|
563 |
|
564 |
|
565 |
|
566 |
|
567 | getRowFromElement: function (tr) {
|
568 | return $(tr).data(this.dataKeys.ROW_VIEW);
|
569 | },
|
570 |
|
571 | |
572 |
|
573 |
|
574 |
|
575 |
|
576 | showNoEntriesMsg: function () {
|
577 |
|
578 | if (this.$noEntries) {
|
579 | this.$noEntries.remove();
|
580 | }
|
581 |
|
582 | this.$noEntries = $('<tr>')
|
583 | .addClass(this.classNames.NO_ENTRIES)
|
584 | .append($('<td>')
|
585 | .attr('colspan', this.getColumnCount())
|
586 | .text(this.options.noEntriesMsg)
|
587 | )
|
588 | .appendTo(this.$tbody);
|
589 |
|
590 | return this;
|
591 | },
|
592 |
|
593 | |
594 |
|
595 |
|
596 |
|
597 |
|
598 | removeNoEntriesMsg: function () {
|
599 | if (this.$noEntries && this._models.length > 0) {
|
600 | this.$noEntries.remove();
|
601 | }
|
602 | return this;
|
603 | },
|
604 |
|
605 | |
606 |
|
607 |
|
608 |
|
609 |
|
610 | getRows: function () {
|
611 | var instance = this;
|
612 | var views = [];
|
613 |
|
614 | this.$tbody.find('.' + this.classNames.READ_ONLY).each(function () {
|
615 | var $row = $(this);
|
616 | var view = $row.data(instance.dataKeys.ROW_VIEW);
|
617 |
|
618 | if (view) {
|
619 | views.push(view);
|
620 | }
|
621 | });
|
622 |
|
623 | return views;
|
624 | },
|
625 |
|
626 | |
627 |
|
628 |
|
629 |
|
630 |
|
631 |
|
632 |
|
633 |
|
634 | _renderRow: function (model, index) {
|
635 | var instance = this;
|
636 | var $rows = this.$tbody.find('.' + this.classNames.READ_ONLY);
|
637 | var $row;
|
638 | var view;
|
639 |
|
640 | view = new this._rowClass({
|
641 | model: model,
|
642 | columns: this.options.columns,
|
643 | allowEdit: this.options.allowEdit,
|
644 | allowDelete: this.options.allowDelete,
|
645 | allowReorder: this.options.allowReorder,
|
646 | deleteConfirmationCallback: this.options.deleteConfirmationCallback
|
647 | });
|
648 |
|
649 | this.removeNoEntriesMsg();
|
650 |
|
651 | view.on(this._event.ROW_EDIT, function (field) {
|
652 | triggerEvtForInst(this._event.EDIT_ROW, {}, [this, instance]);
|
653 | instance.edit(this, field);
|
654 | });
|
655 |
|
656 | $row = view.render().$el;
|
657 |
|
658 | if (index !== -1) {
|
659 |
|
660 | if (typeof index === 'number' && $rows.length !== 0) {
|
661 | $row.insertBefore($rows[index]);
|
662 | } else {
|
663 | this.$tbody.append($row);
|
664 | }
|
665 | }
|
666 |
|
667 | $row.data(this.dataKeys.ROW_VIEW, view);
|
668 |
|
669 |
|
670 |
|
671 | view.on(this._event.MODAL, function () {
|
672 | instance.$table.removeClass(instance.classNames.ALLOW_HOVER);
|
673 | instance.$tbody.sortable('disable');
|
674 | instance.getRows().forEach(function (row) {
|
675 | if (!instance.isRowBeingEdited(row)) {
|
676 | row.delegateEvents({});
|
677 | }
|
678 | });
|
679 | });
|
680 |
|
681 |
|
682 |
|
683 | view.on(this._event.MODELESS, function () {
|
684 | instance.$table.addClass(instance.classNames.ALLOW_HOVER);
|
685 | instance.$tbody.sortable('enable');
|
686 | instance.getRows().forEach(function (row) {
|
687 | if (!instance.isRowBeingEdited(row)) {
|
688 | row.delegateEvents();
|
689 | }
|
690 | });
|
691 | });
|
692 |
|
693 |
|
694 | this._applyFocusCoordinator(view);
|
695 |
|
696 | this.trigger(this._event.ROW_INITIALIZED, view);
|
697 |
|
698 | return view;
|
699 | },
|
700 |
|
701 | |
702 |
|
703 |
|
704 |
|
705 |
|
706 |
|
707 |
|
708 | isRowBeingEdited: function (row) {
|
709 |
|
710 | var isBeingEdited = false;
|
711 |
|
712 | this.editRows.some(function (editRow) {
|
713 | if (editRow.el === row.el) {
|
714 | isBeingEdited = true;
|
715 | return true;
|
716 | }
|
717 | });
|
718 |
|
719 | return isBeingEdited;
|
720 | },
|
721 |
|
722 | |
723 |
|
724 |
|
725 |
|
726 |
|
727 |
|
728 | _applyFocusCoordinator: function (view) {
|
729 | var instance = this;
|
730 |
|
731 | if (!view.hasFocusBound) {
|
732 | view.hasFocusBound = true;
|
733 |
|
734 | view.on(this._event.FOCUS, function () {
|
735 | if (instance.focusedRow && instance.focusedRow !== view) {
|
736 | instance.focusedRow.trigger(instance._event.BLUR);
|
737 | }
|
738 | instance.focusedRow = view;
|
739 | if (view instanceof Row && instance._createRow) {
|
740 | instance._createRow.enable();
|
741 | }
|
742 | });
|
743 | }
|
744 |
|
745 | return this;
|
746 | },
|
747 |
|
748 | |
749 |
|
750 |
|
751 |
|
752 |
|
753 |
|
754 |
|
755 | _removeEditRow: function (editView) {
|
756 | var index = $.inArray(editView, this.editRows);
|
757 | this.editRows.splice(index, 1);
|
758 | return this;
|
759 | },
|
760 |
|
761 | |
762 |
|
763 |
|
764 |
|
765 |
|
766 | _shiftFocusAfterEdit: function () {
|
767 |
|
768 | if (this.editRows.length > 0) {
|
769 | this.editRows[this.editRows.length - 1].trigger(this._event.FOCUS);
|
770 | } else if (this._createRow) {
|
771 | this._createRow.trigger(this._event.FOCUS);
|
772 | }
|
773 |
|
774 | return this;
|
775 | },
|
776 |
|
777 | |
778 |
|
779 |
|
780 |
|
781 |
|
782 |
|
783 | _saveEditRowOnBlur: function () {
|
784 | return this.editRows.length <= 1;
|
785 | },
|
786 |
|
787 | |
788 |
|
789 |
|
790 | dismissEditRows: function () {
|
791 | this.editRows.forEach(function (editRow) {
|
792 | if (!editRow.hasUpdates()) {
|
793 | editRow.trigger(this._event.FINISHED_EDITING);
|
794 | }
|
795 | }, this);
|
796 | },
|
797 |
|
798 | |
799 |
|
800 |
|
801 |
|
802 |
|
803 |
|
804 |
|
805 | edit: function (row, field) {
|
806 | var instance = this;
|
807 | var editRow = new this.options.views.editRow({
|
808 | el: row.el,
|
809 | columns: this.options.columns,
|
810 | isUpdateMode: true,
|
811 | allowReorder: this.options.allowReorder,
|
812 | fieldFocusSelector: this.options.fieldFocusSelector,
|
813 | model: row.model,
|
814 | cancelAccessKey: this.options.cancelAccessKey,
|
815 | submitAccessKey: this.options.submitAccessKey
|
816 | });
|
817 | var values = row.model.toJSON();
|
818 |
|
819 | values.update = true;
|
820 | editRow.render({
|
821 | errors: {},
|
822 | update: true,
|
823 | values: values
|
824 | })
|
825 | .on(instance._event.UPDATED, function (model, focusUpdated) {
|
826 | instance._removeEditRow (this);
|
827 | this.off();
|
828 | row.render().delegateEvents();
|
829 | row.trigger(instance._event.UPDATED);
|
830 | if (focusUpdated !== false) {
|
831 | instance._shiftFocusAfterEdit();
|
832 | }
|
833 | })
|
834 | .on(instance._event.VALIDATION_ERROR, function () {
|
835 | this.trigger(instance._event.FOCUS);
|
836 | })
|
837 | .on(instance._event.FINISHED_EDITING, function () {
|
838 | instance._removeEditRow(this);
|
839 | row.render().delegateEvents();
|
840 | this.off();
|
841 | })
|
842 | .on(instance._event.CANCEL, function () {
|
843 | instance._removeEditRow(this);
|
844 | this.off();
|
845 | row.render().delegateEvents();
|
846 | instance._shiftFocusAfterEdit();
|
847 | })
|
848 | .on(instance._event.BLUR, function () {
|
849 | instance.dismissEditRows();
|
850 | if (instance._saveEditRowOnBlur()) {
|
851 | this.trigger(instance._event.SAVE, false);
|
852 | }
|
853 | });
|
854 |
|
855 |
|
856 | this._applyFocusCoordinator(editRow);
|
857 |
|
858 |
|
859 | editRow.trigger(instance._event.FOCUS, field);
|
860 |
|
861 |
|
862 | if (instance._createRow) {
|
863 | instance._createRow.disable();
|
864 | }
|
865 |
|
866 | this.editRows.push(editRow);
|
867 |
|
868 | return editRow;
|
869 | },
|
870 |
|
871 |
|
872 | |
873 |
|
874 |
|
875 |
|
876 |
|
877 |
|
878 | renderRows: function (rows = []) {
|
879 | var comparator = this._models.comparator;
|
880 | var els = [];
|
881 |
|
882 | this._models.comparator = undefined;
|
883 |
|
884 | var models = rows.map((row) => {
|
885 | var model = new this.options.model(row);
|
886 | els.push(this._renderRow(model, -1).el);
|
887 | return model;
|
888 | });
|
889 |
|
890 | this._models.add(models, {silent: true});
|
891 | this._models.comparator = comparator;
|
892 | this.removeNoEntriesMsg();
|
893 | this.$tbody.append(els);
|
894 |
|
895 | return this;
|
896 | },
|
897 |
|
898 | |
899 |
|
900 |
|
901 |
|
902 |
|
903 | _getDefaultOptions: function (options) {
|
904 | return {
|
905 | model: options.model || EntryModel,
|
906 | allowEdit: true,
|
907 | views: {
|
908 | editRow: EditRow,
|
909 | row: Row
|
910 | },
|
911 | Collection: Backbone.Collection.extend({
|
912 | url: options.resources.self,
|
913 | model: options.model || EntryModel
|
914 | }),
|
915 | allowReorder: false,
|
916 | fieldFocusSelector: function (name) {
|
917 | return ':input[name=' + name + '], #' + name;
|
918 | },
|
919 | loadingMsg: options.loadingMsg || I18n.getText('aui.words.loading')
|
920 | };
|
921 | }
|
922 | });
|
923 |
|
924 | RestfulTable.ClassNames = classNames;
|
925 | RestfulTable.CustomCreateView = CustomCreateView;
|
926 | RestfulTable.CustomEditView = CustomEditView;
|
927 | RestfulTable.CustomReadView = CustomReadView;
|
928 | RestfulTable.DataKeys = dataKeys;
|
929 | RestfulTable.EditRow = EditRow;
|
930 | RestfulTable.EntryModel = EntryModel;
|
931 | RestfulTable.Events = events;
|
932 | RestfulTable.Row = Row;
|
933 |
|
934 | globalize('RestfulTable', RestfulTable);
|
935 |
|
936 | export default RestfulTable;
|