diff --git a/brewman/static/scripts/product.js b/brewman/static/scripts/product.js index a2ba4a5d..4f3acb96 100644 --- a/brewman/static/scripts/product.js +++ b/brewman/static/scripts/product.js @@ -1,12 +1,11 @@ 'use strict'; -var ProductListCtrl = ['$scope', '$location', '$routeParams', 'products', function ($scope, $location, $routeParams, products) { +var ProductListCtrl = ['$scope', '$location', '$routeParams', '$filter', 'products', function ($scope, $location, $routeParams, $filter, products) { $scope.search = $routeParams.q || ''; $scope.show_extended = false; $scope.info = products; $scope.isTrue = function (value) { - value = value.toLowerCase(); return !_.any(['f', 'fa', 'fal', 'fals', 'false', 'n', 'no', '0'], function (item) { return item === value; }); @@ -16,29 +15,56 @@ var ProductListCtrl = ['$scope', '$location', '$routeParams', 'products', functi $scope.filterProducts(newValue); }, true); - $scope.parseFilterString = function (q, defaultKey) { - var re = /((([^ ]+):\s*('[^':]+'|"[^":]+"|[^ ]+))|[^ ]+[^: '"]*)/g; - var matches = []; - if (angular.isUndefined(defaultKey)) { - defaultKey = 'n'; - } + $scope.comparator = { + 'def': 'n', + 'n': {'Col': 'Name', 'Comparator': function (obj, text) { + return obj.toLowerCase().indexOf(text) > -1; + }}, + 'a': {'Col': 'IsActive', 'Comparator': function (obj, text) { + return obj === $scope.isTrue(text); + }}, + 'u': {'Col': 'Units', 'Comparator': function (obj, text) { + return obj.toLowerCase().indexOf(text) > -1; + }}, + 't': {'Col': 'ProductGroup', 'Comparator': function (obj, text) { + return obj.toLowerCase().indexOf(text) > -1; + }} + }; + $scope.sorter = { + 'c': 'Code', + 'n': 'Name', + 'u': 'Units', + 'p': 'Price', + 't': 'ProductGroup', + 'a': 'IsActive' + }; + $scope.parseFilterString = function (q, defaultKey, comparator, sorter) { + var re = /((([^ ]+):\s*('[^':]+'|"[^":]+"|[^ ]+))|[^ ]+[^: '"]*)/g, + matches = [], + sorting = []; + + defaultKey = comparator[defaultKey || comparator.def]; var m = q.match(re); _.forEach(m, function (item) { - item = item.toLowerCase(); + item = item.trim(); if (item.indexOf(':') === -1) { - matches.push({'key': defaultKey, 'value': item}); + if ((item.length > 1) && (item.charAt(0) === '+' || item.charAt(0) === '-') && (item.substr(1) in sorter)) { + sorting.push(item.charAt(0) + sorter[item.substr(1)]); + } else if (item.length > 2) { + matches.push({'Col': defaultKey.Col, 'Comparator': defaultKey.Comparator, 'Value': item}); + } } else { var key = item.substr(0, item.indexOf(':')).toLowerCase(); var value = item.substr(item.indexOf(':') + 1, item.length).trim().toLowerCase(); - if (value.indexOf("'") !== 0 || value.indexOf('"') !== 0) { - value = value.substring(1, value.length - 2).trim(); + if (value.indexOf("'") !== -1 || value.indexOf('"') !== -1) { + value = value.substring(1, value.length - 1).trim(); } - if (key !== '' && value !== '') { - matches.push({'key': key, 'value': value}); + if (key !== '' && value !== '' && key in comparator) { + matches.push({'Col': comparator.Col, 'Comparator': comparator[key], 'Value': item}); } } }); - return matches; + return {'q': matches, 'o': sorting}; }; $scope.filterProducts = _.debounce(function (q) { @@ -50,42 +76,26 @@ var ProductListCtrl = ['$scope', '$location', '$routeParams', 'products', functi $location.path('/Products').search({'q': q}).replace(); } $scope.$apply(function () { - var matches = $scope.parseFilterString(q); - $scope.show_extended = _.any(matches, function (item) { + var matches = $scope.parseFilterString(q, 'n', $scope.comparator, $scope.sorter); + $scope.show_extended = _.any(matches.q, function (item) { return ((item.key === 'e' || item.key === 'ext') && $scope.isTrue(item.value)); }); - $scope.products = $scope.doFilter(q, matches); + + $scope.products = $scope.doFilter(q, $scope.info, matches.q, matches.o); + }); } }, 350); - $scope.doFilter = _.memoize(function (q, matches) { - var i, len = matches.length; - if (len <= 0) { - return $scope.info; - } - return _.filter($scope.info, function (item) { - for (i = 0; i < len; i++) { - var match = matches[i]; - if (match.key === 'n') { - if (item.Name.toLowerCase().indexOf(match.value) === -1) { - return false; - } - } else if (match.key === 'a') { - if (item.IsActive !== $scope.isTrue(match.value)) { - return false; - } - } else if (match.key === 'u') { - if (item.Units.toLowerCase().indexOf(match.value) === -1) { - return false; - } - } else if (match.key === 'g') { - if (item.ProductGroup.toLowerCase().indexOf(match.value) === -1) { - return false; - } - } - } - return true; + $scope.doFilter = _.memoize(function (q, array, filterExpressions, sortPredicates) { + var filterCount = filterExpressions.length; + var arrayCopy = filterCount === 0 ? array : _.filter($scope.info, function (item) { + return _.every(filterExpressions, function (expression) { + return expression.Comparator(item[expression.Col], expression.Value); + }); }); + arrayCopy = sortPredicates.length === 0 ? arrayCopy : $filter('orderBy')(arrayCopy, sortPredicates); + return arrayCopy; + }); }];