ListView.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. "use strict";
  2. /**
  3. * Licensed Materials - Property of IBM
  4. * IBM Cognos Products: Cognos Analytics
  5. * Copyright IBM Corp. 2015, 2018
  6. * US Government Users Restricted Rights -
  7. * Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  8. */
  9. define(['doT', 'q', 'jquery', 'underscore', 'bi/glass/app/ContentView', 'bi/commons/utils/BidiUtil', 'bacontentnav/utils/WidgetNavigator', 'bi/admin/nls/StringResource', 'bi/admin/common/actions/AddInputRow', 'text!bi/admin/common/ui/listview/templates/ListViewTemplate.html', 'text!bi/admin/common/ui/listview/templates/EmptyListViewTemplate.html', 'datatables', 'bi/commons/utils/Utils', 'bi/glass/utils/ClassFactory'], function (dot, Q, $, _, ContentView, BidiUtil, WidgetNavigator, StringResource, AddInputRow, ListViewTemplate, EmptyListViewTemplate, datatables, Utils, ClassFactory) {
  10. 'use strict'; //NOSONAR: meant to be strict
  11. var ListView = ContentView.extend({
  12. aSelectedRows: [],
  13. multiSelect: true,
  14. touchMultiSelectEnabled: false,
  15. init: function init(options) {
  16. ListView.inherited('init', this, arguments);
  17. if (options !== undefined) {
  18. this.accessibleLabel = options.accessibleLabel || "";
  19. this.formatContent = options.formatContent || true;
  20. } else {
  21. this.accessibleLabel = "";
  22. this.formatContent = true;
  23. }
  24. $.extend(this, options);
  25. this.aSelectedRows = [];
  26. },
  27. createColumnObject: function createColumnObject(columnSpec, ColumnModule) {
  28. return new ColumnModule($.extend(columnSpec, {
  29. 'listControl': this,
  30. 'glassContext': this.glassContext
  31. }));
  32. },
  33. isMultitouchActive: function isMultitouchActive() {
  34. return this.multiSelect;
  35. },
  36. _createColumns: function _createColumns() {
  37. return Promise.all(_.map(this.dataAdaptor.getColumnSpecs(), function (colSpec, index) {
  38. if (colSpec.type || colSpec.module) {
  39. var path = colSpec.module || 'bi/content_apps/common/ui/list_columns/' + colSpec.type;
  40. return ClassFactory.instantiate(path, _.extend({}, colSpec, {
  41. 'listControl': this,
  42. 'glassContext': this.glassContext
  43. })).then(function (col) {
  44. delete col.type;
  45. return col.getSpec().then(function (spec) {
  46. _.extend(col, spec);
  47. col.aTargets = [index];
  48. col.bSortable = !!colSpec.sortable;
  49. if (colSpec.width) {
  50. col.sWidth = colSpec.width;
  51. }
  52. return col;
  53. });
  54. }.bind(this));
  55. } else {
  56. return null;
  57. }
  58. }.bind(this)));
  59. },
  60. setFocus: function setFocus() {
  61. var $firstFocusEl = this.$el.find("td[tabindex='0']");
  62. if ($firstFocusEl.length === 0) {
  63. return false;
  64. } else {
  65. $firstFocusEl.focus();
  66. return true;
  67. }
  68. },
  69. clearShowWorking: function clearShowWorking() {
  70. this.$el.find("tbody tr[role='row']").remove();
  71. this.showWorking();
  72. },
  73. showWorking: function showWorking() {
  74. var loadingAnimation = Utils.getLoadingAnimation(1);
  75. var $container = $('<div class="emptyTableContent bi-admin-working"></div>');
  76. $container.append(loadingAnimation);
  77. this.$el.append($container);
  78. },
  79. hideWorking: function hideWorking() {
  80. var workingEl = this.$el.find(".bi-admin-working");
  81. $(workingEl).remove();
  82. },
  83. render: function render() {
  84. this.showWorking();
  85. return Promise.all([this._createColumns(), this.dataAdaptor.getRows()]).then(function (resp) {
  86. this.$el.empty();
  87. var columns = resp[0];
  88. var rows = resp[1].rows;
  89. if (this.dataAdaptor.checkboxSelection && this.contentView.getSearchTerm) {
  90. var text = this.contentView.getSearchTerm().toLowerCase();
  91. rows = _.filter(rows, function (row) {
  92. return (row['defaultName'] || "").toLowerCase().indexOf(text) !== -1;
  93. });
  94. }
  95. var sHtml;
  96. this.hideWorking();
  97. if (rows.length > 0) {
  98. sHtml = dot.template(ListViewTemplate)({
  99. sortable: this.dataAdaptor.supportSorting,
  100. accessibleLabel: this.accessibleLabel,
  101. tableCaption: StringResource.get('listViewTableCaption'),
  102. columns: columns
  103. });
  104. this.$el.append(sHtml);
  105. return this._renderTable(columns, rows).then(function () {
  106. this.widgetKeyController = new WidgetNavigator({
  107. $el: this.$el.find(".listControl"),
  108. focusClass: "contentListFocusable",
  109. fCallBack: function fCallBack() {}
  110. });
  111. }.bind(this));
  112. } else {
  113. sHtml = '<div class="bi-admin-empty-activities-list-bee wft_bee"></div><div class="bi-admin-empty-activities-list-text">' + StringResource.get('noEntries') + '</div>';
  114. this.$el.append(sHtml);
  115. }
  116. }.bind(this));
  117. },
  118. resize: function resize() {
  119. var sh = this._calcYBound();
  120. var sb = this.$el.find('.dataTables_scrollBody');
  121. if (sb) {
  122. sb.height(sh);
  123. }
  124. },
  125. reload: function reload(append) {
  126. var deferred = Q.defer();
  127. this.showWorking();
  128. if (!this._dTable) {
  129. this.render().done(function () {
  130. this.hideWorking();
  131. deferred.resolve();
  132. }.bind(this));
  133. } else {
  134. if (this._reloading) {
  135. return;
  136. }
  137. this.waitForReload = true;
  138. this._reloading = true;
  139. if (!append) {
  140. this._dTable.clear();
  141. this._dTable.draw();
  142. }
  143. this.dataAdaptor.getRows().done(function (result) {
  144. var rows = result.rows;
  145. if (!append && rows.length === 0) {
  146. var emptyHTML = '<div class="emptyTableContent"><div class="bi-admin-empty-activities-list-bee wft_bee"></div><div class="bi-admin-empty-activities-list-text">' + StringResource.get('noEntries') + '</div></div>';
  147. this.$el.append(emptyHTML);
  148. } else {
  149. this.$el.find(".emptyTableContent").remove();
  150. this._dTable.rows.add(result.rows).draw(false);
  151. this._setTextDirection();
  152. this._clearRows(true);
  153. this.resize();
  154. }
  155. this._reloading = false;
  156. this.hideWorking();
  157. setTimeout(function () {
  158. delete this.waitForReload;
  159. }.bind(this), 1000);
  160. deferred.resolve();
  161. }.bind(this));
  162. }
  163. return deferred.promise;
  164. },
  165. _sortListener: function _sortListener() {},
  166. filter: function filter(text, propertyName) {
  167. if (this.dataAdaptor.checkboxSelection) {
  168. this._clearRows(true);
  169. }
  170. this.removeEmptyTableMessage();
  171. var rows = this.dataAdaptor.getFilteredRows();
  172. if (this._dTable && rows) {
  173. propertyName = propertyName || 'defaultName';
  174. text = text.toLowerCase();
  175. var filteredRows = _.filter(rows, function (row) {
  176. return (row[propertyName] || "").toLowerCase().indexOf(text) !== -1;
  177. });
  178. this._dTable.rows().remove();
  179. this._dTable.rows.add(filteredRows).draw(false);
  180. if (filteredRows.length < 1) {
  181. this._noResults();
  182. } else {
  183. this._setTextDirection();
  184. }
  185. }
  186. },
  187. _renderTable: function _renderTable(columns, rows) {
  188. //NOSONAR
  189. var deferred = Q.defer();
  190. var xbound = this.$el.width();
  191. var datatableSettings = {
  192. 'data': rows,
  193. 'sScrollY': this._calcYBound(),
  194. 'sScrollX': xbound,
  195. 'sDom': 'rtS',
  196. 'bServerSide': false,
  197. 'bFilter': false,
  198. 'bInfo': false,
  199. 'bAutoWidth': false,
  200. 'bPaginate': false,
  201. 'bDeferRender': true,
  202. 'orderClasses': false,
  203. 'bSort': this.dataAdaptor.isServerSorting(),
  204. 'asStripeClasses': [''],
  205. 'aoColumnDefs': columns,
  206. 'fnInitComplete': function (oSettings) {
  207. this.isInitialized = true;
  208. var tabEl = $(oSettings.nScrollHead).find("table");
  209. this._scrollNode = this.$el.find('.dataTables_scrollBody');
  210. var lab = tabEl.attr("aria-label");
  211. tabEl.removeAttr("aria-label");
  212. tabEl.attr("aria-labelledby", "adminTab_tableHeaderLab1 adminTab_tableHeaderLab2 ");
  213. var hiddenDiv1 = $('<div style="position: absolute; left: -999px" aria-hidden="true" id="adminTab_tableHeaderLab1">' + lab + '</div>');
  214. var hiddenDiv2 = $('<div style="position: absolute; left: -999px" aria-hidden="true" id="adminTab_tableHeaderLab2">' + StringResource.get('listControlColumns') + '</div>');
  215. tabEl.parent().append(hiddenDiv1);
  216. tabEl.parent().append(hiddenDiv2);
  217. this._scrollNode.bind('scroll', this._onScroll.bind(this));
  218. deferred.resolve();
  219. }.bind(this),
  220. 'fnDrawCallback': function (oSettings) {
  221. this._drawCallback(oSettings);
  222. }.bind(this)
  223. };
  224. var defaultOrder = this.dataAdaptor.sortOrder;
  225. if (datatableSettings.bSort && defaultOrder) {
  226. datatableSettings.aaSorting = defaultOrder;
  227. }
  228. var $listTable = this.$el.find('table.listControl.bi-admin-table-list'); // cache all indices the selected tr elements
  229. var aSelectedIndices = this._cachedSelectedRows();
  230. this._dTable = $listTable.DataTable(datatableSettings);
  231. $listTable.attr("role", "application");
  232. this._reApplySelections(aSelectedIndices); // process row events
  233. this._dTable.on('click', 'tr', this.handleClick.bind(this));
  234. this._dTable.on('keydown', 'tr', this._handlekeydown.bind(this));
  235. this._dTable.on('hold', this.handleHoldEvent.bind(this));
  236. var self = this; // Locate checkbox header (if supported)
  237. if (this.dataAdaptor.checkboxSelection) {
  238. this._renderSelectAllCheckBox();
  239. } // Customize datatable's sorting behavior
  240. if (this.dataAdaptor.supportSorting && !datatableSettings.bSort) {
  241. var $headers = this.$el.find("thead th");
  242. $headers.each(function () {
  243. var $h = $(this);
  244. var index = $h.attr('colindex') * 1;
  245. var col = columns[index];
  246. if (col && col.sortable) {
  247. $h.removeClass('sorting_disabled');
  248. if (defaultOrder && index === defaultOrder[0]) {
  249. $h.addClass('sorting_' + defaultOrder[1]);
  250. }
  251. $h.on('primaryaction', function () {
  252. var asc = $h.hasClass('sorting_asc');
  253. var nextOrder = asc ? 'desc' : 'asc';
  254. $headers.removeClass('sorting_asc sorting_desc');
  255. $h.addClass('sorting_' + nextOrder);
  256. self.dataAdaptor.setOrder(index, nextOrder);
  257. self.reload();
  258. });
  259. }
  260. });
  261. }
  262. this.$el.find('div.dataTables_scrollBody').on('scroll', function () {
  263. if ($(this).scrollTop() + $(this).innerHeight() >= this.scrollHeight && self.dataAdaptor.hasMore()) {
  264. self.reload(true);
  265. }
  266. });
  267. this._setTextDirection();
  268. return deferred.promise;
  269. },
  270. _isClickableCol: function _isClickableCol(evt) {
  271. var toElem = evt.relatedTarget || evt.toElement || evt.target;
  272. return $(toElem).hasClass('nameColumnDiv');
  273. },
  274. _handlekeydown: function _handlekeydown(evt) {
  275. if (evt.which === 13 || evt.which === 32) {
  276. this.handleClick(evt);
  277. }
  278. },
  279. handleClick: function handleClick(evt) {
  280. //NOSONAR
  281. var trNode = this._findRowNode(evt.currentTarget);
  282. if ($(evt.currentTarget).hasClass("ellipsesButton")) {
  283. if (this.aSelectedRows.length === 0) {
  284. this._selectRow(trNode);
  285. } else if (this.aSelectedRows.length === 1) {
  286. var match = false;
  287. _.each(this.aSelectedRows, function (oRow) {
  288. if ($(oRow)[0].rowIndex === trNode.rowIndex) {
  289. match = true;
  290. }
  291. });
  292. if (!match) {
  293. this._clearRows(true);
  294. this._selectRow(trNode);
  295. }
  296. }
  297. if (this._isClickableCol(evt)) {
  298. this._handleSingleSelect(trNode, evt);
  299. } else {
  300. this._handleContextMenu(evt);
  301. }
  302. return false;
  303. } // click still fired by browser for hold events on iPad, this is to catch and nullify the click
  304. if (evt.type === 'click' && this.multiSelectEvent && this.multiSelectEvent.type === "hold") {
  305. return;
  306. }
  307. if (evt.which === 3 && (evt.shiftKey || evt.ctrlKey || evt.metaKey || $(trNode).hasClass('selected'))) {
  308. return false;
  309. } // process <Shift>click
  310. if (evt.shiftKey && this.multiSelect) {
  311. // get last selected row
  312. var oLastSelectedRow = _.last(this.aSelectedRows);
  313. var iLastSelectedRowIndex = 0;
  314. if (oLastSelectedRow) {
  315. iLastSelectedRowIndex = oLastSelectedRow.rowIndex;
  316. } // clear all rows of 'selected' class
  317. this._clearRows(true);
  318. var iEndRow = Math.max(iLastSelectedRowIndex, trNode.rowIndex);
  319. var iStartRow = Math.min(iLastSelectedRowIndex, trNode.rowIndex); // Get filtered table rows
  320. var aNodes = this._dTable.$('tr', {
  321. "filter": "applied"
  322. });
  323. var i;
  324. for (i = iStartRow; i <= iEndRow; i = i + 1) {
  325. this._handleMultiSelect($(aNodes[i - 1]), evt.target);
  326. }
  327. } // process <Ctrl>click
  328. else if ((evt.ctrlKey || evt.metaKey) && this.multiSelect || evt.type === 'tap' && this.touchMultiSelectEnabled || this.dataAdaptor.checkboxSelection && evt.currentTarget.classList.contains('admin-checkbox')) {
  329. this._handleMultiSelect(trNode, evt.target);
  330. } // process normal mouse click
  331. else if (this._handleSingleSelect(trNode, evt) === false) {
  332. return false;
  333. }
  334. },
  335. _setTextDirection: function _setTextDirection() {
  336. var $divName = this.$el.find('div.nameColumnDiv');
  337. $divName.each(function () {
  338. $(this).attr('dir', BidiUtil.resolveBaseTextDir(this.innerHTML));
  339. });
  340. },
  341. _noResults: function _noResults() {
  342. var emptyHTML = '<div class="emptyTableContent"><div class="bi-admin-empty-activities-list-bee wft_bee"></div><div class="bi-admin-empty-activities-list-text">' + StringResource.get('noEntries') + '</div></div>';
  343. this.$el.append(emptyHTML);
  344. },
  345. _handleMultiSelect: function _handleMultiSelect(trNode, target, fromCheckbox) {
  346. // toggle 'selected' class of current row
  347. if (!($(trNode).hasClass('selected') && $(target).hasClass('forceRowSelection'))) {
  348. $(trNode).toggleClass('selected');
  349. if (this.dataAdaptor.checkboxSelection && !fromCheckbox) {
  350. var $checkbox = $(trNode).find('.admin-checkbox');
  351. $checkbox.prop('checked', !$checkbox.prop('checked'));
  352. }
  353. } // maintain the array of selected rows
  354. var iIndex = this.aSelectedRows.indexOf(trNode);
  355. if (iIndex > -1) {
  356. if (!$(target).hasClass('forceRowSelection')) {
  357. this._updateSelectedRows('-', iIndex);
  358. }
  359. } else {
  360. this._updateSelectedRows('+', trNode);
  361. }
  362. },
  363. _handleSingleSelect: function _handleSingleSelect(trNode, evt) {
  364. if (this.aSelectedRows.length === 1 && trNode.rowIndex === this.aSelectedRows[0].rowIndex) {
  365. if (this.deselectCallback) {
  366. this.deselectCallback();
  367. }
  368. $(trNode).removeClass('selected');
  369. this._checkRow(trNode, true);
  370. this._updateSelectedRows('c');
  371. }
  372. this._selectSingleRow(trNode, evt);
  373. },
  374. getActionPayload: function getActionPayload() {
  375. //method required by content apps column class...need to return a payload I guess
  376. var deferred = Q.defer(); //don't want the content apps column to do a thing....
  377. deferred.reject();
  378. return deferred.promise;
  379. },
  380. _selectSingleRow: function _selectSingleRow(trNode, evt) {
  381. this._clearRows(true);
  382. this._selectRow(trNode); //trigger event when row is highlighted
  383. this.$el.trigger('com.ibm.admin.listItemHighlighted', this.getSelectedObjects()[0]);
  384. if (this.singleSelectCallback && this._isClickableCol(evt)) {
  385. this.singleSelectCallback(this.getSelectedObjects()[0]);
  386. }
  387. },
  388. _handleContextMenu: function _handleContextMenu(evt) {
  389. var position = {};
  390. if (evt.pageX === undefined || evt.gesture === undefined || evt.gesture.center === undefined || evt.gesture.center.pageX === undefined) {
  391. position = $(evt.target).offset();
  392. } else {
  393. position.left = evt.pageX || evt.gesture.center.pageX;
  394. position.top = evt.pageY || evt.gesture.center.pageY;
  395. }
  396. var data = {
  397. 'position': {
  398. "pageX": position.left,
  399. "pageY": position.top
  400. },
  401. 'selectedObject': this.getSelectedObjects()
  402. };
  403. if (this.contextMenuCallback) {
  404. this.contextMenuCallback(data);
  405. }
  406. },
  407. handleHoldEvent: function handleHoldEvent(evt) {
  408. this._clearRows(true);
  409. this.touchMultiSelectEnabled = true;
  410. var node = this._findRowNode(evt.target.parentNode);
  411. $(node).addClass('selected');
  412. this._updateSelectedRows('+', node);
  413. this.multiSelectEvent = evt;
  414. },
  415. _findRowNode: function _findRowNode(node) {
  416. while (node.nodeName.toLowerCase() !== 'tr') {
  417. node = node.parentNode;
  418. }
  419. return node;
  420. },
  421. /**
  422. Clear all selected rows in dataTable
  423. **/
  424. _clearRows: function _clearRows(isFromAdmin) {
  425. if (isFromAdmin) {
  426. if (this.dataAdaptor.checkboxSelection) {
  427. var $checkboxHeader = this.$el.find('thead th .admin-header-checkbox input');
  428. $checkboxHeader.prop('checked', false);
  429. }
  430. _.each(this.aSelectedRows, function (oRow) {
  431. $(oRow).removeClass('selected');
  432. this._checkRow(oRow, false);
  433. }.bind(this));
  434. this._updateSelectedRows('c'); // clear button and counter for multi-select on touch devices
  435. this.touchMultiSelectEnabled = false;
  436. }
  437. },
  438. /**
  439. Returns an array of objects that are being represented by the selected rows
  440. **/
  441. getSelectedObjects: function getSelectedObjects() {
  442. var i;
  443. var rowObjects = [];
  444. for (i = 0; i < this.aSelectedRows.length; i += 1) {
  445. var obj = this._dTable.row(this.aSelectedRows[i]).data();
  446. rowObjects.push(obj);
  447. }
  448. return rowObjects;
  449. },
  450. /**
  451. Select a row in dataTable
  452. **/
  453. _selectRow: function _selectRow(trNode) {
  454. $(trNode).addClass('selected');
  455. this._updateSelectedRows('+', trNode);
  456. if (this.dataAdaptor.checkboxSelection) {
  457. var $checkbox = $(trNode).find('.admin-checkbox');
  458. $checkbox.prop('checked', true);
  459. }
  460. },
  461. _formatContentHelper: function _formatContentHelper(oSettings, i, rowData) {
  462. //add in the role of gridcell to the td's
  463. if (rowData.anCells) {
  464. for (var cellIndex = 0; cellIndex < rowData.anCells.length; cellIndex += 1) {
  465. var $cell = $(rowData.anCells[cellIndex]);
  466. var scope = oSettings.aoColumns[cellIndex].scope;
  467. if (scope === 'row') {
  468. $cell.attr("role", "rowheader");
  469. } else {
  470. $cell.attr("role", "gridcell");
  471. }
  472. $cell.attr("tabindex", "-1");
  473. }
  474. }
  475. this._processColumnWeights(oSettings);
  476. if (this.formatContent && rowData.anCells && rowData.anCells[i]) {
  477. oSettings.aoColumns[i].formatContent(rowData.anCells[i]);
  478. }
  479. },
  480. _drawCallback: function _drawCallback(oSettings) {
  481. for (var i = 0; i < oSettings.aoColumns.length; i++) {
  482. if (oSettings.aoColumns[i].formatContent) {
  483. oSettings.aoData.forEach(this._formatContentHelper.bind(this, oSettings, i));
  484. }
  485. }
  486. if (this.widgetKeyController) {
  487. this.widgetKeyController.setInitialTabIndex();
  488. }
  489. },
  490. _processColumnWeights: function _processColumnWeights(oSettings) {
  491. var weightSum = 0;
  492. var percentSum = 0;
  493. oSettings.aoColumns.forEach(function (column) {
  494. if (column.weight) {
  495. weightSum += column.weight;
  496. } else if (column.sWidth && column.sWidth.slice(-1) === '%') {
  497. percentSum += parseInt(column.sWidth.slice(0, -1), 10);
  498. }
  499. });
  500. oSettings.aoColumns.forEach(function (column) {
  501. if (column.weight) {
  502. column.sWidth = Math.floor(column.weight / weightSum * (100 - percentSum)) + '%';
  503. }
  504. });
  505. },
  506. _calcYBound: function _calcYBound() {
  507. var headerHeight = this.$el.find('th').height();
  508. if (this.$el.height() - headerHeight < headerHeight) {
  509. return "70%";
  510. } else {
  511. return this.$el.height() - headerHeight;
  512. }
  513. },
  514. addInput: function addInput(type, pid, accountExplorer, listAdaptor) {
  515. //running multiple instances of AddInputRow simultaneously leads to unnecessary bugs,
  516. //therefore, only manage one instance at a time, instances will terminate when finished
  517. if (this.activeInputForm === null) {
  518. this.activeInputForm = new AddInputRow({
  519. 'oListControl': this,
  520. 'glassContext': this.glassContext,
  521. 'data': this._dTable.rows().data(),
  522. 'accountExplorer': accountExplorer,
  523. 'listAdaptor': listAdaptor
  524. });
  525. this.activeInputForm.execute(type, pid);
  526. }
  527. },
  528. insertToTable: function insertToTable(rowObj) {
  529. this._dTable.rows.add([rowObj]).draw(true);
  530. },
  531. removeEmptyTableMessage: function removeEmptyTableMessage() {
  532. this.$el.find('.emptyTableContent').remove();
  533. },
  534. adjustScrollForPageDown: function adjustScrollForPageDown() {
  535. var $sb = $(this.$el.find('.dataTables_scrollBody'));
  536. $sb.scrollTop($sb.scrollTop() + 50);
  537. },
  538. _clearTable: function _clearTable() {
  539. this._dTable.clear().draw();
  540. },
  541. setPaging: function setPaging(isPaged) {
  542. this.pagingOn = isPaged;
  543. },
  544. _onScroll: function _onScroll(event) {
  545. if (!this.scrollIgnore && !this.waitForReload) {
  546. var $target = $(event.target); // If we've scrolled to the bottom
  547. if ($target.scrollTop() + $target.innerHeight() >= $target[0].scrollHeight - 20) {
  548. $(this).trigger("nextPage", event);
  549. this.scrollIgnore = true;
  550. setTimeout(function () {
  551. delete this.scrollIgnore;
  552. }.bind(this), 500);
  553. } else if ($target.scrollTop() === 0) {
  554. $(this).trigger("previousPage", event);
  555. this.scrollIgnore = true;
  556. setTimeout(function () {
  557. delete this.scrollIgnore;
  558. }.bind(this), 500);
  559. }
  560. }
  561. },
  562. _isShortTable: function _isShortTable() {
  563. var listContainer = this.$el.find('.ca-listContainer');
  564. return listContainer.height() < 200;
  565. },
  566. _updateSelectedRows: function _updateSelectedRows(action, options) {
  567. switch (action) {
  568. case '-':
  569. var removeAtIndex = this.aSelectedRows.indexOf(options);
  570. if (removeAtIndex !== -1) {
  571. this.aSelectedRows.splice(removeAtIndex, 1);
  572. }
  573. break;
  574. case '+':
  575. this.aSelectedRows.push(options);
  576. break;
  577. case 'c':
  578. this.aSelectedRows = [];
  579. break;
  580. case '=':
  581. this.aSelectedRows = options;
  582. break;
  583. default:
  584. break;
  585. }
  586. if (this.onSelectionChange) {
  587. this.onSelectionChange();
  588. }
  589. },
  590. _cachedSelectedRows: function _cachedSelectedRows() {
  591. // cache all indices the selected tr elements
  592. var aSelectedIndices = [];
  593. if (this._dTable && this.aSelectedRows.length > 0) {
  594. var selectedRows = this._dTable.$('tr.selected');
  595. for (var index = 0; index < selectedRows.length; ++index) {
  596. aSelectedIndices.push($(selectedRows[index]).index());
  597. }
  598. }
  599. return aSelectedIndices;
  600. },
  601. _reApplySelections: function _reApplySelections(aSelectedIndices) {
  602. this.aSelectedRows = []; // reapply previous selections
  603. for (var index = 0; index < aSelectedIndices.length; ++index) {
  604. var trNode = this._dTable.$('tr')[aSelectedIndices[index]];
  605. trNode.classList.add('selected');
  606. this._checkRow(trNode, true);
  607. this._updateSelectedRows('+', trNode);
  608. }
  609. },
  610. _renderSelectAllCheckBox: function _renderSelectAllCheckBox() {
  611. var $checkboxHeader = this.$el.find('thead th .admin-header-checkbox:not(:has(input))');
  612. $checkboxHeader.html('<input role="checkbox" tabindex="-1" type="checkbox" class="admin-clickable admin-checkbox"></input>');
  613. $checkboxHeader.find('input').click(this._toggleSelectAll.bind(this));
  614. },
  615. _toggleSelectAll: function _toggleSelectAll(evt) {
  616. if (evt.currentTarget.checked) {
  617. var rows = this._dTable.$('tr:not(.selected)');
  618. for (var index = 0; index < rows.length; ++index) {
  619. this._selectRow(rows[index]);
  620. }
  621. } else {
  622. this._clearRows(true);
  623. }
  624. },
  625. _deselectRow: function _deselectRow(trNode) {
  626. if (this.deselectCallback) {
  627. this.deselectCallback();
  628. }
  629. $(trNode).removeClass('selected');
  630. this._checkRow(trNode, false);
  631. this._updateSelectedRows('-', trNode);
  632. },
  633. _checkRow: function _checkRow(trNode, check) {
  634. if (this.dataAdaptor.checkboxSelection) {
  635. var $checkbox = $(trNode).find('.admin-checkbox');
  636. $checkbox.prop('checked', check);
  637. }
  638. }
  639. });
  640. return ListView;
  641. });