/** * @ngdoc directive * @name Bastion.components.directive:bstTable * @restrict A * * @requires $window * * @description * * @example */ angular.module('Bastion.components') .directive('bstTable', function () { return { restrict: 'A', replace: true, scope: { 'table': '=bstTable', 'rowSelect': '@', 'rowChoice': '@' }, controller: 'BstTableController', link: function (scope, element) { function checkForResults(rows) { var table = scope.table, tableElement = element.find('table'), tableBody = tableElement.find('tbody'), existingTr, numberOfColumns, messageTd, message; tableBody.find('#noRowsTr').remove(); if (rows.length === 0 && !table.working) { existingTr = tableBody.find('#noRowsTr'); numberOfColumns = tableElement.find('th').length; if (table.searchTerm || table.searchCompleted) { message = element.find("#noSearchResultsMessage").html(); } else { message = element.find("#noRowsMessage").html(); } messageTd = $('').attr('colspan', numberOfColumns); messageTd.html(message); if (existingTr.length > 0) { existingTr.html(messageTd); } else { tableBody.append($('')); tableBody.find('tr').html(messageTd); } } } // Check for results and handle no rows message scope.$watch('table.rows', checkForResults); } }; }) .controller('BstTableController', ['$scope', function ($scope) { var rows = $scope.rows = [], headers = $scope.headers = [], self = this; this.selection = {allSelected: false, selectAllDisabled: false}; if (!$scope.table.numSelected) { $scope.table.numSelected = 0; } $scope.table.chosenRow = null; $scope.table.getSelected = function () { var selectedRows = []; angular.forEach($scope.table.rows, function (row, rowIndex) { if (row.selected === true) { selectedRows.push($scope.table.rows[rowIndex]); } }); return selectedRows; }; $scope.table.selectAllDisabled = false; this.disableSelectAll = $scope.table.disableSelectAll = function () { self.selection.selectAllDisabled = true; }; this.enableSelectAll = $scope.table.enableSelectAll = function () { self.selection.selectAllDisabled = false; }; $scope.table.allSelected = function () { return self.selection.allSelected; }; this.addRow = function (row) { rows.push(row); if (headers.length) { angular.forEach(headers[0].columns, function (column, columnIndex) { if (row.cells[columnIndex]) { row.cells[columnIndex].show = column.show; } }); } }; this.addHeader = function (columns) { headers.push(columns); }; this.itemSelected = function (row) { $scope.table.numSelected += row.selected ? 1 : -1; self.selection.allSelected = false; }; this.itemChosen = function (row) { $scope.table.chosenRow = row; }; this.selectAll = $scope.table.selectAll = function (selected) { var table = $scope.table, rowsSelected = 0; self.selection.allSelected = selected; angular.forEach(table.rows, function (row) { if (!row.unselectable) { row.selected = self.selection.allSelected; rowsSelected = rowsSelected + 1; } }); $scope.table.numSelected = selected ? rowsSelected : 0; }; }]) .directive('bstTableHead', [function () { var rowSelectTemplate = function () { return '' + '' + ''; }, rowChoiceTemplate = function () { return ''; }; return { require: '^bstTable', restrict: 'A', scope: true, controller: 'BstTableHeadController', compile: function (tElement, tAttrs) { if (angular.isDefined(tAttrs.rowSelect)) { tElement.prepend(rowSelectTemplate()); } else if (angular.isDefined(tAttrs.rowChoice)) { tElement.prepend(rowChoiceTemplate()); } return function (scope, element, attrs, bstTableController) { if (angular.isDefined(tAttrs.rowSelect) && angular.isDefined(scope.table)) { scope.table.rowSelect = true; } else if (angular.isDefined(tAttrs.rowChoice)) { scope.table.rowChoice = true; } bstTableController.addHeader(scope.header); scope.selection = bstTableController.selection; scope.allSelected = function () { bstTableController.selectAll(scope.selection.allSelected); }; }; } }; }]) .controller('BstTableHeadController', ['$scope', function ($scope) { $scope.header = { columns: [] }; this.addColumn = function (column) { $scope.header.columns.push(column); }; }]) .directive('bstTableColumn', ['$compile', function ($compile) { var sortIconTemplate = '' + '' + ''; return { require: '^bstTableHead', restrict: 'A', scope: true, controller: ['$scope', function ($scope) { $scope.column = { show: true }; }], compile: function (tElement, tAttributes) { var newElement; if (tAttributes.hasOwnProperty("sortable")) { newElement = angular.element(sortIconTemplate); newElement.find('.sort-icon').before(tElement.html()); newElement.addClass('sortable'); newElement.addClass(tElement.attr('class')); tElement.replaceWith(newElement); } return function (scope, element, attributes, bstTableHeadController) { if (attributes.hasOwnProperty("sortable")) { $compile(element)(scope); } scope.column.id = attributes.bstTableColumn; bstTableHeadController.addColumn(scope.column); scope.$watch('column.show', function (show) { var display = show ? '' : 'none'; element.css('display', display); }); }; } }; }]) .directive('bstTableRow', ['$parse', function ($parse) { var rowSelectTemplate, rowChoiceTemplate, activeRowTemplate; rowSelectTemplate = function (model) { return '' + '' + ''; }; rowChoiceTemplate = function (model) { return '' + '' + ''; }; activeRowTemplate = function (activeTest) { return ''; }; return { require: '^bstTable', restrict: 'A', scope: true, controller: 'BstTableRowController', compile: function (tElement, tAttrs) { if (angular.isDefined(tAttrs.activeRow)) { tElement.find('td:first-child').append(activeRowTemplate(tAttrs.activeRow)); } if (angular.isDefined(tAttrs.rowSelect)) { tElement.prepend(rowSelectTemplate(tAttrs.rowSelect)); } if (angular.isDefined(tAttrs.rowChoice)) { tElement.prepend(rowChoiceTemplate(tAttrs.rowChoice)); } if (angular.isDefined(tAttrs.activeRow)) { tElement.find('td').attr('ng-class', '{ "active-row": ' + tAttrs.activeRow + ' }'); } return function (scope, element, attrs, bstTableController) { bstTableController.addRow(scope.row); if (attrs.rowSelect) { scope.model = $parse(attrs.rowSelect)(scope); if ($parse(attrs.rowSelectIf)(scope)) { scope.model.unselectable = true; } scope.$watch('model.selected', function (selected) { if (selected) { element.addClass('selected-row'); } else { element.removeClass('selected-row'); } }); } else if (attrs.rowChoice) { scope.model = $parse(attrs.rowChoice)(scope); } if (attrs.activeRow) { scope.activeTest = $parse(attrs.activeRow)(scope); } scope.itemSelected = function (row) { bstTableController.itemSelected(row); }; scope.itemChosen = function (row) { element.parent().find('.selected-row').removeClass('selected-row'); element.addClass('selected-row'); bstTableController.itemChosen(row); }; }; } }; }]) .controller('BstTableRowController', ['$scope', function ($scope) { $scope.row = { cells: [] }; this.addCell = function (cell) { $scope.row.cells.push(cell); }; }]) .directive('bstTableCell', [function () { return { require: '^bstTableRow', restrict: 'A', scope: true, controller: ['$scope', function ($scope) { $scope.cell = { show: true }; }], link: function (scope, element, attrs, bstTableRowController) { bstTableRowController.addCell(scope.cell); scope.$watch('cell.show', function (show) { var display = show ? '' : 'none'; element.css('display', display); }); } }; }]);