{"version":3,"sources":["smart-table.min.js"],"names":["ng","undefined","module","run","$templateCache","put","constant","pagination","template","itemsByPage","displayedPages","search","delay","inputEvent","trimSearch","select","mode","selectedClass","sort","ascentClass","descentClass","descendingFirst","skipNatural","pipe","controller","$scope","$parse","$filter","$attrs","copyRefs","src","concat","updateSafeCopy","safeCopy","safeGetter","pipeAfterSafeCopy","ctrl","deepDelete","object","path","indexOf","partials","split","key","pop","parentPath","join","parentObject","Object","keys","length","filtered","lastSelected","propertyName","stTable","displayGetter","displaySetter","assign","orderBy","filter","tableState","start","totalItemCount","this","stSafeSrc","$watch","safeSrc","newValue","oldValue","sortBy","predicate","reverse","isFunction","functionName","name","input","comparator","predicateObject","prop","output","number","numberOfPages","Math","ceil","slice","parseInt","row","rows","index","isSelected","getFilteredCollection","setFilterFunction","filterName","setSortFunction","sortFunctionName","preventPipeOnWatch","directive","restrict","link","scope","element","attr","stSetFilter","stSetSort","stConfig","$timeout","require","tableCtrl","promise","throttle","stDelay","event","stInputEvent","$observe","value","isString","trim","predicateExpression","stSearch","bind","evt","originalEvent","cancel","target","stSelectMode","$apply","addClass","removeClass","func","getter","isArray","stSort","sortDefault","classAscent","stClassAscent","classDescent","stClassDescent","stateClasses","stSkipNatural","stDescendingFirst","ariaSort","stSortDefault","$eval","stItemsByPage","stDisplayedPages","stPageChange","templateUrl","attrs","stTemplate","redraw","end","i","paginationState","prevPage","currentPage","floor","max","abs","pages","numPages","push","newPage","selectPage","page","config","stPipe","pre","pipePromise","post","angular"],"mappings":"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","file":"smart-table.min.js","sourcesContent":["(function (ng, undefined){\n 'use strict';\n\nng.module('smart-table', []).run(['$templateCache', function ($templateCache) {\n $templateCache.put('template/smart-table/pagination.html',\n '');\n}]);\n\n\nng.module('smart-table')\n .constant('stConfig', {\n pagination: {\n template: 'template/smart-table/pagination.html',\n itemsByPage: 10,\n displayedPages: 5\n },\n search: {\n delay: 400, // ms\n inputEvent: 'input',\n trimSearch: false\n },\n select: {\n mode: 'single',\n selectedClass: 'st-selected'\n },\n sort: {\n ascentClass: 'st-sort-ascent',\n descentClass: 'st-sort-descent',\n descendingFirst: false,\n skipNatural: false,\n delay:300\n },\n pipe: {\n delay: 100 //ms\n }\n });\nng.module('smart-table').controller('stTableController', [\n '$scope',\n '$parse',\n '$filter',\n '$attrs',\n function StTableController($scope, $parse, $filter, $attrs) {\n var propertyName = $attrs.stTable;\n var displayGetter = $parse(propertyName);\n var displaySetter = displayGetter.assign;\n var safeGetter;\n var orderBy = $filter('orderBy');\n var filter = $filter('filter');\n var safeCopy = copyRefs(displayGetter($scope));\n var tableState = {\n sort: {},\n search: {},\n pagination: { start: 0, totalItemCount: 0 }\n };\n var filtered;\n var pipeAfterSafeCopy = true;\n var ctrl = this;\n var lastSelected;\n\n function copyRefs(src) {\n return src ? [].concat(src) : [];\n }\n\n function updateSafeCopy() {\n safeCopy = copyRefs(safeGetter($scope));\n if (pipeAfterSafeCopy === true) {\n ctrl.pipe();\n }\n }\n\n function deepDelete(object, path) {\n if (path.indexOf('.') != -1) {\n var partials = path.split('.');\n var key = partials.pop();\n var parentPath = partials.join('.');\n var parentObject = $parse(parentPath)(object);\n delete parentObject[key];\n if (Object.keys(parentObject).length == 0) {\n deepDelete(object, parentPath);\n }\n } else {\n delete object[path];\n }\n }\n\n if ($attrs.stSafeSrc) {\n safeGetter = $parse($attrs.stSafeSrc);\n $scope.$watch(\n function() {\n var safeSrc = safeGetter($scope);\n return safeSrc && safeSrc.length ? safeSrc[0] : undefined;\n },\n function(newValue, oldValue) {\n if (newValue !== oldValue) {\n updateSafeCopy();\n }\n }\n );\n $scope.$watch(\n function() {\n var safeSrc = safeGetter($scope);\n return safeSrc ? safeSrc.length : 0;\n },\n function(newValue, oldValue) {\n if (newValue !== safeCopy.length) {\n updateSafeCopy();\n }\n }\n );\n $scope.$watch(\n function() {\n return safeGetter($scope);\n },\n function(newValue, oldValue) {\n if (newValue !== oldValue) {\n tableState.pagination.start = 0;\n updateSafeCopy();\n }\n }\n );\n }\n\n /**\n * sort the rows\n * @param {Function | String} predicate - function or string which will be used as predicate for the sorting\n * @param [reverse] - if you want to reverse the order\n */\n this.sortBy = function sortBy(predicate, reverse) {\n tableState.sort.predicate = predicate;\n tableState.sort.reverse = reverse === true;\n\n if (ng.isFunction(predicate)) {\n tableState.sort.functionName = predicate.name;\n } else {\n delete tableState.sort.functionName;\n }\n\n tableState.pagination.start = 0;\n return this.pipe();\n };\n\n /**\n * search matching rows\n * @param {String} input - the input string\n * @param {String} [predicate] - the property name against you want to check the match, otherwise it will search on all properties\n * @param {String | Function } [comparator] - a comparator to pass to the filter for the (pass true for stric mode)\n */\n this.search = function search(input, predicate, comparator) {\n var predicateObject = tableState.search.predicateObject || {};\n var prop = predicate ? predicate : '$';\n\n $parse(prop).assign(predicateObject, input);\n // to avoid to filter out null value\n if (!input) {\n deepDelete(predicateObject, prop);\n }\n tableState.search.predicateObject = predicateObject;\n tableState.pagination.start = 0;\n return this.pipe();\n };\n\n /**\n * this will chain the operations of sorting and filtering based on the current table state (sort options, filtering, ect)\n */\n this.pipe = function pipe() {\n var pagination = tableState.pagination;\n var output;\n filtered = tableState.search.predicateObject\n ? filter(safeCopy, tableState.search.predicateObject)\n : safeCopy;\n if (tableState.sort.predicate) {\n filtered = orderBy(\n filtered,\n tableState.sort.predicate,\n tableState.sort.reverse\n );\n }\n pagination.totalItemCount = filtered.length;\n if (pagination.number !== undefined) {\n pagination.numberOfPages = filtered.length > 0\n ? Math.ceil(filtered.length / pagination.number)\n : 1;\n pagination.start = pagination.start >= filtered.length\n ? (pagination.numberOfPages - 1) * pagination.number\n : pagination.start;\n output = filtered.slice(\n pagination.start,\n pagination.start + parseInt(pagination.number)\n );\n }\n displaySetter($scope, output || filtered);\n };\n\n /**\n * select a dataRow (it will add the attribute isSelected to the row object)\n * @param {Object} row - the row to select\n * @param {String} [mode] - \"single\" or \"multiple\" (multiple by default)\n */\n this.select = function select(row, mode) {\n var rows = copyRefs(displayGetter($scope));\n var index = rows.indexOf(row);\n if (index !== -1) {\n if (mode === 'single') {\n row.isSelected = row.isSelected !== true;\n if (lastSelected) {\n lastSelected.isSelected = false;\n }\n lastSelected = row.isSelected === true ? row : undefined;\n } else {\n rows[index].isSelected = !rows[index].isSelected;\n }\n }\n };\n\n /**\n * take a slice of the current sorted/filtered collection (pagination)\n *\n * @param {Number} start - start index of the slice\n * @param {Number} number - the number of item in the slice\n */\n this.slice = function splice(start, number) {\n tableState.pagination.start = start;\n tableState.pagination.number = number;\n return this.pipe();\n };\n\n /**\n * return the current state of the table\n * @returns {{sort: {}, search: {}, pagination: {start: number}}}\n */\n this.tableState = function getTableState() {\n return tableState;\n };\n\n this.getFilteredCollection = function getFilteredCollection() {\n return filtered || safeCopy;\n };\n\n /**\n * Use a different filter function than the angular FilterFilter\n * @param filterName the name under which the custom filter is registered\n */\n this.setFilterFunction = function setFilterFunction(filterName) {\n filter = $filter(filterName);\n };\n\n /**\n * Use a different function than the angular orderBy\n * @param sortFunctionName the name under which the custom order function is registered\n */\n this.setSortFunction = function setSortFunction(sortFunctionName) {\n orderBy = $filter(sortFunctionName);\n };\n\n /**\n * Usually when the safe copy is updated the pipe function is called.\n * Calling this method will prevent it, which is something required when using a custom pipe function\n */\n this.preventPipeOnWatch = function preventPipe() {\n pipeAfterSafeCopy = false;\n };\n }\n]).directive('stTable', function() {\n return {\n restrict: 'A',\n controller: 'stTableController',\n link: function(scope, element, attr, ctrl) {\n if (attr.stSetFilter) {\n ctrl.setFilterFunction(attr.stSetFilter);\n }\n\n if (attr.stSetSort) {\n ctrl.setSortFunction(attr.stSetSort);\n }\n }\n };\n});\n\nng.module('smart-table')\n .directive('stSearch', ['stConfig', '$timeout','$parse', function (stConfig, $timeout, $parse) {\n return {\n require: '^stTable',\n link: function (scope, element, attr, ctrl) {\n var tableCtrl = ctrl;\n var promise = null;\n var throttle = attr.stDelay || stConfig.search.delay;\n var event = attr.stInputEvent || stConfig.search.inputEvent;\n var trimSearch = attr.trimSearch || stConfig.search.trimSearch;\n\n attr.$observe('stSearch', function (newValue, oldValue) {\n var input = element[0].value;\n if (newValue !== oldValue && input) {\n ctrl.tableState().search = {};\n input = ng.isString(input) && trimSearch ? input.trim() : input;\n tableCtrl.search(input, newValue);\n }\n });\n\n //table state -> view\n scope.$watch(function () {\n return ctrl.tableState().search;\n }, function (newValue, oldValue) {\n var predicateExpression = attr.stSearch || '$';\n if (newValue.predicateObject && $parse(predicateExpression)(newValue.predicateObject) !== element[0].value) {\n element[0].value = $parse(predicateExpression)(newValue.predicateObject) || '';\n }\n }, true);\n\n // view -> table state\n element.bind(event, function (evt) {\n evt = evt.originalEvent || evt;\n if (promise !== null) {\n $timeout.cancel(promise);\n }\n\n promise = $timeout(function () {\n var input = evt.target.value;\n input = ng.isString(input) && trimSearch ? input.trim() : input;\n tableCtrl.search(input, attr.stSearch || '');\n promise = null;\n }, throttle);\n });\n }\n };\n }]);\n\nng.module('smart-table')\n .directive('stSelectRow', ['stConfig', function (stConfig) {\n return {\n restrict: 'A',\n require: '^stTable',\n scope: {\n row: '=stSelectRow'\n },\n link: function (scope, element, attr, ctrl) {\n var mode = attr.stSelectMode || stConfig.select.mode;\n element.bind('click', function () {\n scope.$apply(function () {\n ctrl.select(scope.row, mode);\n });\n });\n\n scope.$watch('row.isSelected', function (newValue) {\n if (newValue === true) {\n element.addClass(stConfig.select.selectedClass);\n } else {\n element.removeClass(stConfig.select.selectedClass);\n }\n });\n }\n };\n }]);\n\nng.module('smart-table')\n .directive('stSort', ['stConfig', '$parse', '$timeout', function (stConfig, $parse, $timeout) {\n return {\n restrict: 'A',\n require: '^stTable',\n link: function (scope, element, attr, ctrl) {\n\n var predicate = attr.stSort;\n var getter = $parse(predicate);\n var index = 0;\n var classAscent = attr.stClassAscent || stConfig.sort.ascentClass;\n var classDescent = attr.stClassDescent || stConfig.sort.descentClass;\n var stateClasses = [classAscent, classDescent];\n var sortDefault;\n var skipNatural = attr.stSkipNatural !== undefined ? attr.stSkipNatural : stConfig.sort.skipNatural;\n var descendingFirst = attr.stDescendingFirst !== undefined ? attr.stDescendingFirst : stConfig.sort.descendingFirst;\n var promise = null;\n var throttle = attr.stDelay || stConfig.sort.delay;\n\n // set aria attributes\n var ariaSort = 'aria-sort';\n var ariaSortNone = 'none';\n var ariaSortAscending = 'ascending';\n var ariaSortDescending = 'descending';\n element\n .attr('role', 'columnheader')\n .attr(ariaSort, ariaSortNone);\n\n if (attr.stSortDefault) {\n sortDefault = scope.$eval(attr.stSortDefault) !== undefined ? scope.$eval(attr.stSortDefault) : attr.stSortDefault;\n }\n\n //view --> table state\n function sort () {\n if (descendingFirst) {\n index = index === 0 ? 2 : index - 1;\n } else {\n index++;\n }\n\n var func;\n predicate = ng.isFunction(getter(scope)) || ng.isArray(getter(scope)) ? getter(scope) : attr.stSort;\n if (index % 3 === 0 && !!skipNatural !== true) {\n //manual reset\n index = 0;\n ctrl.tableState().sort = {};\n ctrl.tableState().pagination.start = 0;\n func = ctrl.pipe.bind(ctrl);\n } else {\n func = ctrl.sortBy.bind(ctrl, predicate, index % 2 === 0);\n }\n if (promise !== null) {\n $timeout.cancel(promise);\n }\n if (throttle < 0) {\n func();\n } else {\n promise = $timeout(function(){\n func();\n }, throttle);\n }\n }\n\n element.bind('click', function sortClick () {\n if (predicate) {\n scope.$apply(sort);\n }\n });\n\n if (sortDefault) {\n index = sortDefault === 'reverse' ? 1 : 0;\n sort();\n }\n\n //table state --> view\n scope.$watch(function () {\n return ctrl.tableState().sort;\n }, function (newValue) {\n if (newValue.predicate !== predicate) {\n index = 0;\n element\n .removeClass(classAscent)\n .removeClass(classDescent)\n .attr(ariaSort, ariaSortNone);\n } else {\n index = newValue.reverse === true ? 2 : 1;\n element\n .removeClass(stateClasses[index % 2])\n .addClass(stateClasses[index - 1])\n .attr(ariaSort, newValue.reverse ? ariaSortAscending : ariaSortDescending);\n }\n }, true);\n }\n };\n }]);\n\nng.module('smart-table')\n .directive('stPagination', ['stConfig', function (stConfig) {\n return {\n restrict: 'EA',\n require: '^stTable',\n scope: {\n stItemsByPage: '=?',\n stDisplayedPages: '=?',\n stPageChange: '&'\n },\n templateUrl: function (element, attrs) {\n if (attrs.stTemplate) {\n return attrs.stTemplate;\n }\n return stConfig.pagination.template;\n },\n link: function (scope, element, attrs, ctrl) {\n\n scope.stItemsByPage = scope.stItemsByPage ? +(scope.stItemsByPage) : stConfig.pagination.itemsByPage;\n scope.stDisplayedPages = scope.stDisplayedPages ? +(scope.stDisplayedPages) : stConfig.pagination.displayedPages;\n\n scope.currentPage = 1;\n scope.pages = [];\n\n function redraw () {\n var paginationState = ctrl.tableState().pagination;\n var start = 1;\n var end;\n var i;\n var prevPage = scope.currentPage;\n scope.totalItemCount = paginationState.totalItemCount;\n scope.currentPage = Math.floor(paginationState.start / paginationState.number) + 1;\n\n start = Math.max(start, scope.currentPage - Math.abs(Math.floor(scope.stDisplayedPages / 2)));\n end = start + scope.stDisplayedPages;\n\n if (end > paginationState.numberOfPages) {\n end = paginationState.numberOfPages + 1;\n start = Math.max(1, end - scope.stDisplayedPages);\n }\n\n scope.pages = [];\n scope.numPages = paginationState.numberOfPages;\n\n for (i = start; i < end; i++) {\n scope.pages.push(i);\n }\n\n if (prevPage !== scope.currentPage) {\n scope.stPageChange({newPage: scope.currentPage});\n }\n }\n\n //table state --> view\n scope.$watch(function () {\n return ctrl.tableState().pagination;\n }, redraw, true);\n\n //scope --> table state (--> view)\n scope.$watch('stItemsByPage', function (newValue, oldValue) {\n if (newValue !== oldValue) {\n scope.selectPage(1);\n }\n });\n\n scope.$watch('stDisplayedPages', redraw);\n\n //view -> table state\n scope.selectPage = function (page) {\n if (page > 0 && page <= scope.numPages) {\n ctrl.slice((page - 1) * scope.stItemsByPage, scope.stItemsByPage);\n }\n };\n\n if (!ctrl.tableState().pagination.number) {\n ctrl.slice(0, scope.stItemsByPage);\n }\n }\n };\n }]);\n\nng.module('smart-table')\n .directive('stPipe', ['stConfig', '$timeout', function (config, $timeout) {\n return {\n require: 'stTable',\n scope: {\n stPipe: '='\n },\n link: {\n\n pre: function (scope, element, attrs, ctrl) {\n\n var pipePromise = null;\n\n if (ng.isFunction(scope.stPipe)) {\n ctrl.preventPipeOnWatch();\n ctrl.pipe = function () {\n\n if (pipePromise !== null) {\n $timeout.cancel(pipePromise)\n }\n\n pipePromise = $timeout(function () {\n scope.stPipe(ctrl.tableState(), ctrl);\n }, config.pipe.delay);\n\n return pipePromise;\n }\n }\n },\n\n post: function (scope, element, attrs, ctrl) {\n ctrl.pipe();\n }\n }\n };\n }]);\n\n})(angular);"]}