(function () {
'use strict';
angular
.module('fedramp.components')
.component('gridSort', {
templateUrl: 'templates/components/grid-sort.html',
require: {
gridController: '^grid'
},
controller: GridSort,
controllerAs: 'controller',
bindings: {
name: '@',
property: '@',
caseSensitive: '@',
header: '@',
default: '@'
}
});
GridSort.$inject = ['$log', '$parse', '$element'];
/**
* Used to sort items within a grid. Requires to be nested within a [Grid]{@link Components.Grid} component.
* @constructor
* @memberof Components
* @example <grid-sort property="provider" header="Provider"></grid-sort>
*/
function GridSort ($log, $parse, $element) {
var self = this;
self.activated = null;
self.asc = true;
self.$onInit = $onInit;
self.sort = sort;
self.highlight = highlight;
self.toggleSort = toggleSort;
self.clear = clear;
function $onInit () {
if (!self.name) {
throw 'Name must be specified for sort filter';
}
if (self.property) {
self.sortFunc = sortFunc;
}
restoreState();
self.gridController.addSort(self);
}
/**
* Stores the sort information to the grid state.
*
* @public
* @memberof Components.GridSort
*/
function saveState () {
// Merge any existing parameters
var existingParams =
angular.extend(
self.gridController.state, {
'sort': (self.asc ? '' : '-') + self.name
});
// Update url
if (self.gridController.saveState) {
self.gridController.state.sort = (self.asc ? '' : '-') + self.name;
}
self.gridController.doUpdate();
}
/**
* Restores the latest saved sort.
*
* @public
* @memberof Components.GridSort
*/
function restoreState () {
var sortParam = self.gridController.state.sort;
if (!sortParam) {
loadDefaultSort();
return;
}
var m = sortParam.match(/(-)?(.*)/);
if (m[2] !== self.name) {
return;
}
self.asc = (m[1] === undefined);
self.activated = true;
self.sort(self.asc);
}
/**
* Loads a specified default sort. This is to ensure a grid applies a sort when first loaded.
*
* @public
* @memberof Components.GridSort
*/
function loadDefaultSort () {
if (self.default) {
// Parse if default should be in asc/desc
self.asc = self.default.split('-').reduce(function (p, c) {
return false;
});
self.sort(self.asc);
}
}
/**
* Sorts a list of items in the grid controller by the property for this particular
* grid sort.
*
* @public
* @memberof Components.GridSort
* @param {boolean} doAscending
* Sort direction to use
*/
function sort (doAscending) {
self.activated = angular.isDefined(doAscending);
self.asc = doAscending;
self.gridController.activeSort = self;
self.gridController.items.sort(self.sortFunc);
$element.addClass('sort-selected');
// Update state of all sorts
self.gridController.updateSort();
saveState();
}
/**
* Toggles the sort. To maintain a consistent interaction, we always set the toggle to ascending
* if the sort is not activated. This case would be hit when the user has clicked on the sort for the
* first time or after another sort.
*
* @public
* @memberof Components.GridSort
*/
function toggleSort () {
if (!self.activated) {
self.sort(true);
return;
}
self.sort(!self.asc);
}
/**
* Performs a generic sort.
*
* @public
* @memberof Components.GridSort
*/
function sortFunc (_a, _b) {
// Enables to sort on multiple properties for a specific grid sort.
var props = self.property.split(',');
for (var x = 0; x < props.length; x++) {
var a = $parse(props[x])(_a);
var b = $parse(props[x])(_b);
// If we're dealing with numbers, delegate to number sort func
if (angular.isNumber(a)) {
return numberSortFunc(a, b);
}
if (angular.isArray(a)) {
a = a.join(',');
b = b.join(',');
}
// Normalize everything and make it all lowercase for fair comparison
a = a.toLowerCase();
b = b.toLowerCase();
if (a < b) {
return self.asc ? -1 : 1;
}
if (a > b) {
return self.asc ? 1 : -1;
}
}
return 0;
}
/**
* Handles generic numerical sort.
*/
function numberSortFunc (a, b) {
if (self.asc) {
return a - b;
}
return b - a;
}
/**
* Determines whether to highlight sort selected option.
*/
function highlight (asc) {
if (!self.activated) {
return false;
}
if (self !== self.gridController.activeSort) {
return false;
}
if (self.asc === asc) {
return true;
}
return false;
}
/**
* Clears the sorting.
*
* @public
* @memberof Components.GridSort
*/
function clear () {
self.activated = false;
$element.removeClass('sort-selected');
}
}
})();