{"version":3,"sources":["smart-table.min.js"],"names":["ng","undefined","module","run","$templateCache","put","constant","pagination","template","itemsByPage","displayedPages","search","delay","inputEvent","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","isString","trim","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","predicateExpression","stSearch","bind","evt","originalEvent","cancel","target","stSelectMode","$apply","addClass","removeClass","func","getter","isArray","stSort","sortDefault","classAscent","stClassAscent","classDescent","stClassDescent","stateClasses","stSkipNatural","stDescendingFirst","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 },\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 input = ng.isString(input) ? input.trim() : input;\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\n attr.$observe('stSearch', function (newValue, oldValue) {\n var input = element[0].value;\n if (newValue !== oldValue && input) {\n ctrl.tableState().search = {};\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 tableCtrl.search(evt.target.value, 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 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(func, 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 } else {\n index = newValue.reverse === true ? 2 : 1;\n element\n .removeClass(stateClasses[index % 2])\n .addClass(stateClasses[index - 1]);\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);"]}