diff --git a/app/modules/main/features/ColumnFilterFeature/ColumnFilterFeature.js b/app/modules/main/features/ColumnFilterFeature/ColumnFilterFeature.js index ecb6ce1..b303b3b 100644 --- a/app/modules/main/features/ColumnFilterFeature/ColumnFilterFeature.js +++ b/app/modules/main/features/ColumnFilterFeature/ColumnFilterFeature.js @@ -121,6 +121,19 @@ } }; + service.resetFiltersForColumn = function(dataStorage, index){ + if(dataStorage.header[index].columnFilter + && dataStorage.header[index].columnFilter.isEnabled + && dataStorage.header[index].columnFilter.filtersApplied.length){ + + dataStorage.header[index].columnFilter.filtersApplied = []; + + return true; + } + + return false; + }; + /** * Set the position of the column filter panel. It's required to attach it to the outer container * of the component because otherwise some parts of the panel can became partially or fully hidden diff --git a/app/modules/main/features/ColumnSelectorFeature/ColumnSelectorFeature.js b/app/modules/main/features/ColumnSelectorFeature/ColumnSelectorFeature.js index 4e8570a..62f5fda 100644 --- a/app/modules/main/features/ColumnSelectorFeature/ColumnSelectorFeature.js +++ b/app/modules/main/features/ColumnSelectorFeature/ColumnSelectorFeature.js @@ -72,7 +72,7 @@ var rt = ($(window).width() - (elementPosition.left + elementToPosition.outerWidth())); var targetMetrics = { - top: elementPosition.top + 60, + top: elementPosition.top + 55, right: rt }; diff --git a/app/modules/main/features/ColumnSelectorFeature/directives/mdtColumnSelectorDirective.js b/app/modules/main/features/ColumnSelectorFeature/directives/mdtColumnSelectorDirective.js index 129a67e..1be2905 100644 --- a/app/modules/main/features/ColumnSelectorFeature/directives/mdtColumnSelectorDirective.js +++ b/app/modules/main/features/ColumnSelectorFeature/directives/mdtColumnSelectorDirective.js @@ -1,7 +1,7 @@ (function() { 'use strict'; - function mdtColumnSelectorDirective(ColumnSelectorFeature){ + function mdtColumnSelectorDirective(ColumnSelectorFeature, ColumnFilterFeature, PaginatorTypeProvider){ return{ restrict: 'E', templateUrl: '/main/templates/mdtColumnSelector.html', @@ -79,12 +79,31 @@ return result ? false : true; }; - $scope.confirmCallback = function(){ + $scope.confirmCallback = function(params){ + var paginator = params.paginator; + var isAnyResetHappened = false; + _.each($scope.dataStorage.header, function(item, index){ item.columnSelectorFeature.isVisible = $scope.headerRowsData[index].isVisible; + + if(!item.columnSelectorFeature.isVisible){ + var result = ColumnFilterFeature.resetFiltersForColumn($scope.dataStorage, index); + + if(result){ + isAnyResetHappened = true; + } + } }); $scope.columnSelectorFeature.isActive = false; + + if(isAnyResetHappened){ + if(paginator.paginatorType === PaginatorTypeProvider.AJAX){ + paginator.getFirstPage(); + }else{ + // no support for non-ajax yet + } + } }; $scope.cancelCallback = function(){ diff --git a/app/modules/main/templates/mdtColumnSelector.html b/app/modules/main/templates/mdtColumnSelector.html index a8d7132..d019881 100644 --- a/app/modules/main/templates/mdtColumnSelector.html +++ b/app/modules/main/templates/mdtColumnSelector.html @@ -22,7 +22,7 @@
- *- */ - mdtTableDirective.$inject = ['TableDataStorageFactory', 'EditCellFeature', 'SelectableRowsFeature', 'PaginationFeature', 'ColumnSelectorFeature', '_']; - function mdtTableDirective(TableDataStorageFactory, - EditCellFeature, - SelectableRowsFeature, - PaginationFeature, - ColumnSelectorFeature, - _){ - return { - restrict: 'E', - templateUrl: '/main/templates/mdtTable.html', - transclude: true, - scope: { - tableCard: '=', - selectableRows: '=', - alternateHeaders: '=', - deleteRowCallback: '&', - selectedRowCallback: '&', - saveRowCallback: '&', - animateSortIcon: '=', - rippleEffect: '=', - paginatedRows: '=', - mdtRow: '=', - mdtRowPaginator: '&?', - mdtRowPaginatorErrorMessage:'@', - mdtRowPaginatorNoResultsMessage:'@', - virtualRepeat: '=', - mdtTriggerRequest: '&?', - mdtTranslations: '=?', - mdtLoadingIndicator: '=?' - }, - controller: ['$scope', function mdtTable($scope){ - var vm = this; - - $scope.rippleEffectCallback = function(){ - return $scope.rippleEffect ? $scope.rippleEffect : false; - }; - - _setDefaultTranslations(); - _initTableStorage(); - - PaginationFeature.initFeature($scope, vm); - ColumnSelectorFeature.initFeature($scope, vm); - - _processData(); - - // initialization of the storage service - function _initTableStorage(){ - vm.dataStorage = TableDataStorageFactory.getInstance(); - } - - // set translations or fallback to a default value - function _setDefaultTranslations(){ - $scope.mdtTranslations = $scope.mdtTranslations || {}; - - $scope.mdtTranslations.rowsPerPage = $scope.mdtTranslations.rowsPerPage || 'Rows per page:'; - - $scope.mdtTranslations.largeEditDialog = $scope.mdtTranslations.largeEditDialog || {}; - $scope.mdtTranslations.largeEditDialog.saveButtonLabel = $scope.mdtTranslations.largeEditDialog.saveButtonLabel || 'Save'; - $scope.mdtTranslations.largeEditDialog.cancelButtonLabel = $scope.mdtTranslations.largeEditDialog.cancelButtonLabel || 'Cancel'; - } - - // fill storage with values if set - function _processData(){ - if(_.isEmpty($scope.mdtRow)) { - return; - } - - //local search/filter - if (angular.isUndefined($scope.mdtRowPaginator)) { - $scope.$watch('mdtRow', function (mdtRow) { - vm.dataStorage.storage = []; - - _addRawDataToStorage(mdtRow['data']); - }, true); - }else{ - //if it's used for 'Ajax pagination' - } - } - - function _addRawDataToStorage(data){ - var rowId; - var columnValues = []; - _.each(data, function(row){ - rowId = _.get(row, $scope.mdtRow['table-row-id-key']); - columnValues = []; - - _.each($scope.mdtRow['column-keys'], function(columnKey){ - columnValues.push({ - attributes: { - editableField: false - }, - rowId: rowId, - columnKey: columnKey, - value: _.get(row, columnKey) - }); - }); - - vm.dataStorage.addRowData(rowId, columnValues); - }); - } - }], - link: function($scope, element, attrs, ctrl, transclude){ - $scope.dataStorage = ctrl.dataStorage; - - _injectContentIntoTemplate(); - - _initEditCellFeature(); - _initSelectableRowsFeature(); - - PaginationFeature.startFeature(ctrl); - ColumnSelectorFeature.initFeatureHeaderValues($scope.dataStorage.header, ctrl.columnSelectorFeature); - - function _injectContentIntoTemplate(){ - transclude(function (clone) { - var headings = []; - var body = []; - var customCell = []; - - // Use plain JS to append content - _.each(clone, function (child) { - - if ( child.classList !== undefined ) { - if ( child.classList.contains('theadTrRow')) { - headings.push(child); - } - else if( child.classList.contains('customCell') ) { - customCell.push(child); - } - else { - body.push(child); - } - } else { - body.push(child); - } - }); - - var reader = element[0].querySelector('.mdtTable-reader'); - - _.each(headings, function (heading) { - reader.appendChild( heading ); - }); - - _.each(body, function (item) { - reader.appendChild( item ); - }); - }); - } - - function _initEditCellFeature(){ - //TODO: make it possible to only register feature if there is at least - // one column which requires it. - // for that we need to change the place where we register edit-row. - // Remove mdt-row attributes --> do it in mdt-row attribute directive on mdtTable - EditCellFeature.addRequiredFunctions($scope, ctrl); - } - - function _initSelectableRowsFeature(){ - SelectableRowsFeature.getInstance({ - $scope: $scope, - ctrl: ctrl - }); - } - } - }; - } - - angular - .module('mdDataTable') - .directive('mdtTable', mdtTableDirective); -}()); - (function(){ 'use strict'; @@ -675,160 +360,475 @@ }; return { - getInstance: function(dataStorage, isEnabled){ - return new mdtPaginationHelper(dataStorage, isEnabled); - } - }; - } - - angular - .module('mdDataTable') - .service('mdtPaginationHelperFactory', mdtPaginationHelperFactory); -}()); -(function(){ - 'use strict'; + getInstance: function(dataStorage, isEnabled){ + return new mdtPaginationHelper(dataStorage, isEnabled); + } + }; + } + + angular + .module('mdDataTable') + .service('mdtPaginationHelperFactory', mdtPaginationHelperFactory); +}()); +(function(){ + 'use strict'; + + TableDataStorageFactory.$inject = ['$log', '_']; + function TableDataStorageFactory($log, _){ + + function TableDataStorageService(){ + this.storage = []; + this.header = []; + this.customCells = {}; + } + + TableDataStorageService.prototype.addHeaderCellData = function(ops){ + this.header.push(ops); + }; + + TableDataStorageService.prototype.addRowData = function(explicitRowId, rowArray, className){ + if(!(rowArray instanceof Array)){ + $log.error('`rowArray` parameter should be array'); + return; + } + + this.storage.push({ + rowId: explicitRowId, + optionList: { + selected: false, + deleted: false, + visible: true, + className: className || false + }, + data: rowArray + }); + }; + + TableDataStorageService.prototype.getRowData = function(index){ + if(!this.storage[index]){ + $log.error('row is not exists at index: '+index); + return; + } + + return this.storage[index].data; + }; + + TableDataStorageService.prototype.getRowOptions = function(index){ + if(!this.storage[index]){ + $log.error('row is not exists at index: '+index); + return; + } + + return this.storage[index].optionList; + }; + + TableDataStorageService.prototype.setAllRowsSelected = function(isSelected, isPaginationEnabled){ + if(typeof isSelected === 'undefined'){ + $log.error('`isSelected` parameter is required'); + return; + } + + _.each(this.storage, function(rowData){ + if(isPaginationEnabled) { + if (rowData.optionList.visible) { + rowData.optionList.selected = isSelected ? true : false; + } + }else{ + rowData.optionList.selected = isSelected ? true : false; + } + }); + }; + + TableDataStorageService.prototype.isAnyRowSelected = function(){ + return _.some(this.storage, function(rowData){ + return rowData.optionList.selected === true && rowData.optionList.deleted === false; + }); + }; + + TableDataStorageService.prototype.getNumberOfSelectedRows = function(){ + var res = _.countBy(this.storage, function(rowData){ + return rowData.optionList.selected === true && rowData.optionList.deleted === false ? 'selected' : 'unselected'; + }); + + return res.selected ? res.selected : 0; + }; + + TableDataStorageService.prototype.deleteSelectedRows = function(){ + var deletedRows = []; + + _.each(this.storage, function(rowData){ + if(rowData.optionList.selected && rowData.optionList.deleted === false){ + + if(rowData.rowId){ + deletedRows.push(rowData.rowId); + + //Fallback when no id was specified + } else{ + deletedRows.push(rowData.data); + } + + rowData.optionList.deleted = true; + } + }); + + return deletedRows; + }; + + TableDataStorageService.prototype.getSelectedRows = function(){ + var selectedRows = []; + + _.each(this.storage, function(rowData){ + if(rowData.optionList.selected && rowData.optionList.deleted === false){ + + if(rowData.rowId){ + selectedRows.push(rowData.rowId); + + //Fallback when no id was specified + } else{ + selectedRows.push(rowData.data); + } + } + }); + + return selectedRows; + }; + + TableDataStorageService.prototype.getSavedRowData = function(rowData){ + var rawRowData = []; + + _.each(rowData.data, function(aCell){ + rawRowData.push(aCell.value); + }); + + return rawRowData; + }; + + return { + getInstance: function(){ + return new TableDataStorageService(); + } + }; + } + + angular + .module('mdDataTable') + .factory('TableDataStorageFactory', TableDataStorageFactory); +}()); +(function(){ + 'use strict'; + + mdtAlternateHeadersDirective.$inject = ['_']; + function mdtAlternateHeadersDirective(_){ + return { + restrict: 'E', + templateUrl: '/main/templates/mdtAlternateHeaders.html', + transclude: true, + replace: true, + scope: true, + require: '^mdtTable', + link: function($scope, element, attrs, ctrl){ + $scope.deleteSelectedRows = deleteSelectedRows; + $scope.getNumberOfSelectedRows = _.bind(ctrl.dataStorage.getNumberOfSelectedRows, ctrl.dataStorage); + + function deleteSelectedRows(){ + var deletedRows = ctrl.dataStorage.deleteSelectedRows(); + + $scope.deleteRowCallback({rows: deletedRows}); + } + } + }; + } + + angular + .module('mdDataTable') + .directive('mdtAlternateHeaders', mdtAlternateHeadersDirective); +}()); +(function(){ + 'use strict'; + + /** + * @ngdoc directive + * @name mdtTable + * @restrict E + * + * @description + * The base HTML tag for the component. + * + * @param {object=} tableCard when set table will be embedded within a card, with data manipulation tools available + * at the top and bottom. + * + * Properties: + * + * - `{boolean=}` `visible` - enable/disable table card explicitly + * - `{string}` `title` - the title of the card + * - `{boolean=}` `columnSelector` - enables the column selection for the table (you can disable certain columns from the list selection, using `exclude-from-column-selector`, see the related docs) + * - `{array=}` `actionIcons` - (not implemented yet) + * + * @param {boolean=} selectableRows when set each row will have a checkbox + * @param {boolean=} virtualRepeat when set, virtual scrolling will be applied to the table. You must set a fixed + * height to the `.md-virtual-repeat-container` class in order to make it work properly. Since virtual + * scrolling is working with fixed height. + * @param {String=} alternateHeaders some table cards may require headers with actions instead of titles. + * Two possible approaches to this are to display persistent actions, or a contextual header that activates + * when items are selected + * + * Assignable values are: + * + * - 'contextual' - when set table will have kind of dynamic header. E.g.: When selecting rows, the header will + * change and it'll show the number of selected rows and a delete icon on the right. + * - 'persistentActions' - (not implemented yet) + * + * @param {function(rows)=} deleteRowCallback callback function when deleting rows. + * At default an array of the deleted row's data will be passed as the argument. + * When `table-row-id` set for the deleted row then that value will be passed. + * + * @param {function(rows)=} selectedRowCallback callback function when selecting rows. + * At default an array of the selected row's data will be passed as the argument. + * When `table-row-id` set for the selected row then that value will be passed. + * + * @param {boolean=} animateSortIcon sort icon will be animated on change + * @param {boolean=} rippleEffect ripple effect will be applied on the columns when clicked (not implemented yet) + * @param {boolean=} paginatedRows if set then basic pagination will applied to the bottom of the table. + * + * Properties: + * + * - `{boolean=}` `isEnabled` - enables pagination + * - `{array}` `rowsPerPageValues` - set page sizes. Example: [5,10,20] + * + * @param {object=} mdtRow passing rows data through this attribute will initialize the table with data. Additional + * benefit instead of using `mdt-row` element directive is that it makes possible to listen on data changes. + * + * Properties: + * + * - `{array}` `data` - the input data for rows + * - `{integer|string=}` `table-row-id-key` - the uniq identifier for a row + * - `{function(rowData)=}` `table-row-class-name` - callback to specify the class name of a row + * - `{array}` `column-keys` - specifying property names for the passed data array. Makes it possible to + * configure which property assigned to which column in the table. The list should provided at the same order + * as it was specified inside `mdt-header-row` element directive. + * + * @param {function(page, pageSize, options)=} mdtRowPaginator providing the data for the table by a function. Should set a + * function which returns a promise when it's called. When the function is called, these parameters will be + * passed: `page` and `pageSize` which can help implementing an ajax-based paging, and `options` which is providing + * more information. + * + * Currently these are available from options: + * - `array` `columnFilter` - an array of the filtered column sets (todo: create a demo for it) + * - `array` `columnSort` - an array of the sorted column sets. You can inspect which column did you + * sorted and if its in asc or desc order (todo: create a demo for it) + * + * @param {string=} mdtRowPaginatorErrorMessage overrides default error message when promise gets rejected by the + * paginator function. + * + * @param {string=} mdtRowPaginatorNoResultsMessage overrides default 'no results' message. + * + * @param {function(loadPageCallback)=} mdtTriggerRequest provide a callback function for manually triggering an + * ajax request. Can be useful when you want to populate the results in the table manually. (e.g.: having a + * search field in your page which then can trigger a new request in the table to show the results based on + * that filter. + * + * @param {object=} mdtTranslations accepts various key-value pairs for custom translations. + * + * @param {boolean=} mdtLoadingIndicator if set then loading indicator can be customised + * + * Properties: + * + * - `{string=}` `color` - passing a css compatible format as a color will set the color for the loading indicator + * + * @example + *- * - * - *- * - *Product name - *Creator - *Last Update - *
+ *+ */ + mdtTableDirective.$inject = ['TableDataStorageFactory', 'EditCellFeature', 'SelectableRowsFeature', 'PaginationFeature', 'ColumnSelectorFeature', '_']; + function mdtTableDirective(TableDataStorageFactory, + EditCellFeature, + SelectableRowsFeature, + PaginationFeature, + ColumnSelectorFeature, + _){ + return { + restrict: 'E', + templateUrl: '/main/templates/mdtTable.html', + transclude: true, + scope: { + tableCard: '=', + selectableRows: '=', + alternateHeaders: '=', + deleteRowCallback: '&', + selectedRowCallback: '&', + saveRowCallback: '&', + animateSortIcon: '=', + rippleEffect: '=', + paginatedRows: '=', + mdtRow: '=', + mdtRowPaginator: '&?', + mdtRowPaginatorErrorMessage:'@', + mdtRowPaginatorNoResultsMessage:'@', + virtualRepeat: '=', + mdtTriggerRequest: '&?', + mdtTranslations: '=?', + mdtLoadingIndicator: '=?' + }, + controller: ['$scope', function mdtTable($scope){ + var vm = this; - TableDataStorageFactory.$inject = ['$log', '_']; - function TableDataStorageFactory($log, _){ + $scope.rippleEffectCallback = function(){ + return $scope.rippleEffect ? $scope.rippleEffect : false; + }; - function TableDataStorageService(){ - this.storage = []; - this.header = []; - this.customCells = {}; - } + _setDefaultTranslations(); + _initTableStorage(); - TableDataStorageService.prototype.addHeaderCellData = function(ops){ - this.header.push(ops); - }; + PaginationFeature.initFeature($scope, vm); + ColumnSelectorFeature.initFeature($scope, vm); - TableDataStorageService.prototype.addRowData = function(explicitRowId, rowArray, className){ - if(!(rowArray instanceof Array)){ - $log.error('`rowArray` parameter should be array'); - return; - } + _processData(); - this.storage.push({ - rowId: explicitRowId, - optionList: { - selected: false, - deleted: false, - visible: true, - className: className || false - }, - data: rowArray - }); - }; + // initialization of the storage service + function _initTableStorage(){ + vm.dataStorage = TableDataStorageFactory.getInstance(); + } - TableDataStorageService.prototype.getRowData = function(index){ - if(!this.storage[index]){ - $log.error('row is not exists at index: '+index); - return; - } + // set translations or fallback to a default value + function _setDefaultTranslations(){ + $scope.mdtTranslations = $scope.mdtTranslations || {}; - return this.storage[index].data; - }; + $scope.mdtTranslations.rowsPerPage = $scope.mdtTranslations.rowsPerPage || 'Rows per page:'; - TableDataStorageService.prototype.getRowOptions = function(index){ - if(!this.storage[index]){ - $log.error('row is not exists at index: '+index); - return; - } + $scope.mdtTranslations.largeEditDialog = $scope.mdtTranslations.largeEditDialog || {}; + $scope.mdtTranslations.largeEditDialog.saveButtonLabel = $scope.mdtTranslations.largeEditDialog.saveButtonLabel || 'Save'; + $scope.mdtTranslations.largeEditDialog.cancelButtonLabel = $scope.mdtTranslations.largeEditDialog.cancelButtonLabel || 'Cancel'; + } - return this.storage[index].optionList; - }; + // fill storage with values if set + function _processData(){ + if(_.isEmpty($scope.mdtRow)) { + return; + } - TableDataStorageService.prototype.setAllRowsSelected = function(isSelected, isPaginationEnabled){ - if(typeof isSelected === 'undefined'){ - $log.error('`isSelected` parameter is required'); - return; - } + //local search/filter + if (angular.isUndefined($scope.mdtRowPaginator)) { + $scope.$watch('mdtRow', function (mdtRow) { + vm.dataStorage.storage = []; - _.each(this.storage, function(rowData){ - if(isPaginationEnabled) { - if (rowData.optionList.visible) { - rowData.optionList.selected = isSelected ? true : false; + _addRawDataToStorage(mdtRow['data']); + }, true); + }else{ + //if it's used for 'Ajax pagination' } - }else{ - rowData.optionList.selected = isSelected ? true : false; } - }); - }; - - TableDataStorageService.prototype.isAnyRowSelected = function(){ - return _.some(this.storage, function(rowData){ - return rowData.optionList.selected === true && rowData.optionList.deleted === false; - }); - }; - TableDataStorageService.prototype.getNumberOfSelectedRows = function(){ - var res = _.countBy(this.storage, function(rowData){ - return rowData.optionList.selected === true && rowData.optionList.deleted === false ? 'selected' : 'unselected'; - }); + function _addRawDataToStorage(data){ + var rowId; + var columnValues = []; + _.each(data, function(row){ + rowId = _.get(row, $scope.mdtRow['table-row-id-key']); + columnValues = []; - return res.selected ? res.selected : 0; - }; + _.each($scope.mdtRow['column-keys'], function(columnKey){ + columnValues.push({ + attributes: { + editableField: false + }, + rowId: rowId, + columnKey: columnKey, + value: _.get(row, columnKey) + }); + }); - TableDataStorageService.prototype.deleteSelectedRows = function(){ - var deletedRows = []; + vm.dataStorage.addRowData(rowId, columnValues); + }); + } + }], + link: function($scope, element, attrs, ctrl, transclude){ + $scope.dataStorage = ctrl.dataStorage; - _.each(this.storage, function(rowData){ - if(rowData.optionList.selected && rowData.optionList.deleted === false){ + _injectContentIntoTemplate(); - if(rowData.rowId){ - deletedRows.push(rowData.rowId); + _initEditCellFeature(); + _initSelectableRowsFeature(); - //Fallback when no id was specified - } else{ - deletedRows.push(rowData.data); - } + PaginationFeature.startFeature(ctrl); + ColumnSelectorFeature.initFeatureHeaderValues($scope.dataStorage.header, ctrl.columnSelectorFeature); - rowData.optionList.deleted = true; - } - }); + function _injectContentIntoTemplate(){ + transclude(function (clone) { + var headings = []; + var body = []; + var customCell = []; - return deletedRows; - }; + // Use plain JS to append content + _.each(clone, function (child) { - TableDataStorageService.prototype.getSelectedRows = function(){ - var selectedRows = []; + if ( child.classList !== undefined ) { + if ( child.classList.contains('theadTrRow')) { + headings.push(child); + } + else if( child.classList.contains('customCell') ) { + customCell.push(child); + } + else { + body.push(child); + } + } else { + body.push(child); + } + }); - _.each(this.storage, function(rowData){ - if(rowData.optionList.selected && rowData.optionList.deleted === false){ + var reader = element[0].querySelector('.mdtTable-reader'); - if(rowData.rowId){ - selectedRows.push(rowData.rowId); + _.each(headings, function (heading) { + reader.appendChild( heading ); + }); - //Fallback when no id was specified - } else{ - selectedRows.push(rowData.data); - } + _.each(body, function (item) { + reader.appendChild( item ); + }); + }); } - }); - - return selectedRows; - }; - - TableDataStorageService.prototype.getSavedRowData = function(rowData){ - var rawRowData = []; - - _.each(rowData.data, function(aCell){ - rawRowData.push(aCell.value); - }); - return rawRowData; - }; + function _initEditCellFeature(){ + //TODO: make it possible to only register feature if there is at least + // one column which requires it. + // for that we need to change the place where we register edit-row. + // Remove mdt-row attributes --> do it in mdt-row attribute directive on mdtTable + EditCellFeature.addRequiredFunctions($scope, ctrl); + } - return { - getInstance: function(){ - return new TableDataStorageService(); + function _initSelectableRowsFeature(){ + SelectableRowsFeature.getInstance({ + $scope: $scope, + ctrl: ctrl + }); + } } }; } angular .module('mdDataTable') - .factory('TableDataStorageFactory', TableDataStorageFactory); + .directive('mdtTable', mdtTableDirective); }()); + (function(){ 'use strict'; @@ -1519,99 +1519,6 @@ (function(){ 'use strict'; - function ColumnSelectorFeature() { - - var service = this; - - /** - * This is the first entry point when we initialize the feature. - * - * The method adds feature-related variable to the passed object. - * - * @param cellDataToStore - */ - service.appendHeaderCellData = function(cellDataToStore, columnSelectorFeature, isColumnExcludedFromColumnSelector) { - if(!columnSelectorFeature.isEnabled){ - return; - } - - cellDataToStore.columnSelectorFeature = {}; - - if(isColumnExcludedFromColumnSelector){ - cellDataToStore.columnSelectorFeature.isExcluded = true; - }else{ - cellDataToStore.columnSelectorFeature.isExcluded = false; - } - }; - - /** - * This is the first entry point when we initialize the feature. - * - * The method adds feature-related variable to the passed object. - * - * @param cellDataToStore - */ - service.initFeature = function(scope, vm) { - //TODO: backward compatible when there is only a string input - scope.columnSelectorFeature = {}; - - if(scope.tableCard && scope.tableCard.columnSelector){ - scope.columnSelectorFeature.isEnabled = true; - }else{ - scope.columnSelectorFeature.isEnabled = false; - } - - vm.columnSelectorFeature = scope.columnSelectorFeature; - }; - - /** - * This is the second entry point when we initialize the feature. - * - * The method adds feature-related variable to the passed header rows array. - * - * @param headerRowsData - */ - service.initFeatureHeaderValues = function(headerRowsData, columnSelectorFeature){ - if(columnSelectorFeature && columnSelectorFeature.isEnabled){ - _.each(headerRowsData, function(item){ - item.columnSelectorFeature.isVisible =true; - }); - } - }; - - /** - * Set the position of the panel. It's required to attach it to the outer container - * of the component because otherwise some parts of the panel can became partially or fully hidden - * (e.g.: when table has only one row to show) - */ - service.positionElement = function(element){ - var elementToPosition = element.parent().find('.mdt-column-chooser-button'); - var elementPosition = elementToPosition.offset(); - var rt = ($(window).width() - (elementPosition.left + elementToPosition.outerWidth())); - - var targetMetrics = { - top: elementPosition.top + 60, - right: rt - }; - - element.css('position', 'absolute'); - element.detach().appendTo('body'); - - element.css({ - top: targetMetrics.top + 'px', - right: targetMetrics.right + 'px', - position:'absolute' - }); - } - } - - angular - .module('mdDataTable') - .service('ColumnSelectorFeature', ColumnSelectorFeature); -}()); -(function(){ - 'use strict'; - ColumnFilterFeature.$inject = ['ColumnSortFeature', 'PaginatorTypeProvider']; function ColumnFilterFeature(ColumnSortFeature, PaginatorTypeProvider){ @@ -1733,6 +1640,19 @@ } }; + service.resetFiltersForColumn = function(dataStorage, index){ + if(dataStorage.header[index].columnFilter + && dataStorage.header[index].columnFilter.isEnabled + && dataStorage.header[index].columnFilter.filtersApplied.length){ + + dataStorage.header[index].columnFilter.filtersApplied = []; + + return true; + } + + return false; + }; + /** * Set the position of the column filter panel. It's required to attach it to the outer container * of the component because otherwise some parts of the panel can became partially or fully hidden @@ -1953,159 +1873,129 @@ var ops = { controller: 'InlineEditModalCtrl', - targetEvent: ev, - clickOutsideToClose: true, - escapeToClose: true, - focusOnOpen: false, - locals: { - position: position, - cellData: JSON.parse(JSON.stringify(cellData)), - mdtTranslations: $scope.mdtTranslations - } - }; - - if(cellData.attributes.editableField === 'smallEditDialog'){ - ops.templateUrl = '/main/templates/smallEditDialog.html'; - }else{ - ops.templateUrl = '/main/templates/largeEditDialog.html'; - } - - var that = this; - $mdDialog.show(ops).then(function(cellValue){ - cellData.value = cellValue; - - that.saveRow(rowData); - }); - }; - } - } - - angular - .module('mdDataTable') - .service('EditCellFeature', EditCellFeature); -}()); -(function() { - 'use strict'; - - mdtColumnSelectorDirective.$inject = ['ColumnSelectorFeature']; - function mdtColumnSelectorDirective(ColumnSelectorFeature){ - return{ - restrict: 'E', - templateUrl: '/main/templates/mdtColumnSelector.html', - scope: true, - link: function($scope, element){ - ColumnSelectorFeature.positionElement(element); - - $scope.headerRowsData = _.map($scope.dataStorage.header, function(item){ - //excluded content should also be in, since we use the index of the array to apply the changes. Do not exclude them. - return { - columnName: item.columnName, - isVisible: item.columnSelectorFeature.isVisible, - isExcluded: item.columnSelectorFeature.isExcluded - }; - }); - - //destroying scope doesn't remove element, since it belongs to the body directly - $scope.$on('$destroy', function(){ - element.remove(); - }); - - $scope.checked = function (item) { - return item.isVisible; - }; - - $scope.toggle = function (item) { - item.isVisible = !item.isVisible; - }; - - $scope.selectAll = function($event){ - $event.preventDefault(); - - _.each($scope.headerRowsData, function(item){ - if(item.isExcluded){ - return; - } - - item.isVisible = true; - }); - }; - - $scope.clearAll = function($event){ - $event.preventDefault(); - - _.each($scope.headerRowsData, function(item){ - if(item.isExcluded){ - return; - } - - item.isVisible = false; - }); - }; - - $scope.isAllSelected = function(){ - var result = _.find($scope.headerRowsData, function(item){ - if(item.isExcluded){ - return false; - } - - return item.isVisible === false; - }); - - return result ? false : true; - }; - - $scope.isNothingSelected = function(){ - var result = _.find($scope.headerRowsData, function(item){ - if(item.isExcluded){ - return false; - } - - return item.isVisible === true; - }); - - return result ? false : true; + targetEvent: ev, + clickOutsideToClose: true, + escapeToClose: true, + focusOnOpen: false, + locals: { + position: position, + cellData: JSON.parse(JSON.stringify(cellData)), + mdtTranslations: $scope.mdtTranslations + } }; - $scope.confirmCallback = function(){ - _.each($scope.dataStorage.header, function(item, index){ - item.columnSelectorFeature.isVisible = $scope.headerRowsData[index].isVisible; - }); + if(cellData.attributes.editableField === 'smallEditDialog'){ + ops.templateUrl = '/main/templates/smallEditDialog.html'; + }else{ + ops.templateUrl = '/main/templates/largeEditDialog.html'; + } - $scope.columnSelectorFeature.isActive = false; - }; + var that = this; + $mdDialog.show(ops).then(function(cellValue){ + cellData.value = cellValue; - $scope.cancelCallback = function(){ - $scope.columnSelectorFeature.isActive = false; - }; - } + that.saveRow(rowData); + }); + }; } } angular .module('mdDataTable') - .directive('mdtColumnSelector', mdtColumnSelectorDirective); -})(); + .service('EditCellFeature', EditCellFeature); +}()); (function(){ 'use strict'; - mdtSortingIconsDirective.$inject = ['ColumnSortDirectionProvider']; - function mdtSortingIconsDirective(ColumnSortDirectionProvider){ - return { - restrict: 'E', - templateUrl: '/main/templates/cells/generateSortingIcons.html', - scope: { - data: '=', - size: '@' - }, - link: function($scope){ - $scope.ColumnSortDirectionProvider = ColumnSortDirectionProvider; + function ColumnSelectorFeature() { + + var service = this; + + /** + * This is the first entry point when we initialize the feature. + * + * The method adds feature-related variable to the passed object. + * + * @param cellDataToStore + */ + service.appendHeaderCellData = function(cellDataToStore, columnSelectorFeature, isColumnExcludedFromColumnSelector) { + if(!columnSelectorFeature.isEnabled){ + return; + } + + cellDataToStore.columnSelectorFeature = {}; + + if(isColumnExcludedFromColumnSelector){ + cellDataToStore.columnSelectorFeature.isExcluded = true; + }else{ + cellDataToStore.columnSelectorFeature.isExcluded = false; + } + }; + + /** + * This is the first entry point when we initialize the feature. + * + * The method adds feature-related variable to the passed object. + * + * @param cellDataToStore + */ + service.initFeature = function(scope, vm) { + //TODO: backward compatible when there is only a string input + scope.columnSelectorFeature = {}; + + if(scope.tableCard && scope.tableCard.columnSelector){ + scope.columnSelectorFeature.isEnabled = true; + }else{ + scope.columnSelectorFeature.isEnabled = false; + } + + vm.columnSelectorFeature = scope.columnSelectorFeature; + }; + + /** + * This is the second entry point when we initialize the feature. + * + * The method adds feature-related variable to the passed header rows array. + * + * @param headerRowsData + */ + service.initFeatureHeaderValues = function(headerRowsData, columnSelectorFeature){ + if(columnSelectorFeature && columnSelectorFeature.isEnabled){ + _.each(headerRowsData, function(item){ + item.columnSelectorFeature.isVisible =true; + }); } }; + + /** + * Set the position of the panel. It's required to attach it to the outer container + * of the component because otherwise some parts of the panel can became partially or fully hidden + * (e.g.: when table has only one row to show) + */ + service.positionElement = function(element){ + var elementToPosition = element.parent().find('.mdt-column-chooser-button'); + var elementPosition = elementToPosition.offset(); + var rt = ($(window).width() - (elementPosition.left + elementToPosition.outerWidth())); + + var targetMetrics = { + top: elementPosition.top + 55, + right: rt + }; + + element.css('position', 'absolute'); + element.detach().appendTo('body'); + + element.css({ + top: targetMetrics.top + 'px', + right: targetMetrics.right + 'px', + position:'absolute' + }); + } } angular .module('mdDataTable') - .directive('mdtSortingIcons', mdtSortingIconsDirective); + .service('ColumnSelectorFeature', ColumnSelectorFeature); }()); (function() { 'use strict'; @@ -2319,6 +2209,28 @@ (function(){ 'use strict'; + mdtSortingIconsDirective.$inject = ['ColumnSortDirectionProvider']; + function mdtSortingIconsDirective(ColumnSortDirectionProvider){ + return { + restrict: 'E', + templateUrl: '/main/templates/cells/generateSortingIcons.html', + scope: { + data: '=', + size: '@' + }, + link: function($scope){ + $scope.ColumnSortDirectionProvider = ColumnSortDirectionProvider; + } + }; + } + + angular + .module('mdDataTable') + .directive('mdtSortingIcons', mdtSortingIconsDirective); +}()); +(function(){ + 'use strict'; + /** * @name ColumnSortDirectionProvider * @returns possible values for different type of paginators @@ -2334,3 +2246,124 @@ .module('mdDataTable') .value('ColumnSortDirectionProvider', ColumnSortDirectionProvider); })(); + +(function() { + 'use strict'; + + mdtColumnSelectorDirective.$inject = ['ColumnSelectorFeature', 'ColumnFilterFeature', 'PaginatorTypeProvider']; + function mdtColumnSelectorDirective(ColumnSelectorFeature, ColumnFilterFeature, PaginatorTypeProvider){ + return{ + restrict: 'E', + templateUrl: '/main/templates/mdtColumnSelector.html', + scope: true, + link: function($scope, element){ + ColumnSelectorFeature.positionElement(element); + + $scope.headerRowsData = _.map($scope.dataStorage.header, function(item){ + //excluded content should also be in, since we use the index of the array to apply the changes. Do not exclude them. + return { + columnName: item.columnName, + isVisible: item.columnSelectorFeature.isVisible, + isExcluded: item.columnSelectorFeature.isExcluded + }; + }); + + //destroying scope doesn't remove element, since it belongs to the body directly + $scope.$on('$destroy', function(){ + element.remove(); + }); + + $scope.checked = function (item) { + return item.isVisible; + }; + + $scope.toggle = function (item) { + item.isVisible = !item.isVisible; + }; + + $scope.selectAll = function($event){ + $event.preventDefault(); + + _.each($scope.headerRowsData, function(item){ + if(item.isExcluded){ + return; + } + + item.isVisible = true; + }); + }; + + $scope.clearAll = function($event){ + $event.preventDefault(); + + _.each($scope.headerRowsData, function(item){ + if(item.isExcluded){ + return; + } + + item.isVisible = false; + }); + }; + + $scope.isAllSelected = function(){ + var result = _.find($scope.headerRowsData, function(item){ + if(item.isExcluded){ + return false; + } + + return item.isVisible === false; + }); + + return result ? false : true; + }; + + $scope.isNothingSelected = function(){ + var result = _.find($scope.headerRowsData, function(item){ + if(item.isExcluded){ + return false; + } + + return item.isVisible === true; + }); + + return result ? false : true; + }; + + $scope.confirmCallback = function(params){ + var paginator = params.paginator; + var isAnyResetHappened = false; + + _.each($scope.dataStorage.header, function(item, index){ + item.columnSelectorFeature.isVisible = $scope.headerRowsData[index].isVisible; + + if(!item.columnSelectorFeature.isVisible){ + var result = ColumnFilterFeature.resetFiltersForColumn($scope.dataStorage, index); + + if(result){ + isAnyResetHappened = true; + } + } + }); + + $scope.columnSelectorFeature.isActive = false; + + if(isAnyResetHappened){ + if(paginator.paginatorType === PaginatorTypeProvider.AJAX){ + paginator.getFirstPage(); + }else{ + // no support for non-ajax yet + } + } + }; + + $scope.cancelCallback = function(){ + $scope.columnSelectorFeature.isActive = false; + }; + } + } + } + + angular + .module('mdDataTable') + .directive('mdtColumnSelector', mdtColumnSelectorDirective); +})(); \ No newline at end of file+ * + * + *+ * + *Product name + *Creator + *Last Update + *