angular-mesa
Advanced tools
Comparing version 2.9.3 to 2.10.0
@@ -27,2 +27,4 @@ declare namespace angular.apMesa { | ||
filter?: ITableFilterer | string; | ||
// Defines the placeholder text for the filter input, when filter is enabled | ||
filterPlaceholder?: string; | ||
// or string no '' If specified, defines cell format function. See the Cell Formatting section below. | ||
@@ -127,2 +129,9 @@ format?: ITableFormatter | string; | ||
maxPageLinks?: number; | ||
// Async server-side interaction support | ||
getData?: ( | ||
offset: number, | ||
limit: number, | ||
activeFilters: { column: ITableColumn; value: string; }[], | ||
activeSorts: { column: ITableColumn; direction: 'ASC' | 'DESC' }[] | ||
) => ng.IPromise<{ total: number; rows: any[]; }> | ||
} | ||
@@ -129,0 +138,0 @@ interface IRowScope extends ng.IScope { |
{ | ||
"name": "angular-mesa", | ||
"version": "2.9.3", | ||
"version": "2.10.0", | ||
"main": [ | ||
@@ -5,0 +5,0 @@ "./dist/ap-mesa.js", |
@@ -1,1 +0,2 @@ | ||
"use strict";angular.module("apMesa",["apMesa.templates","ui.sortable","ngSanitize","apMesa.directives.apMesa"]),angular.module("apMesa.controllers.ApMesaController",["apMesa.services.apMesaSortFunctions","apMesa.services.apMesaFilterFunctions","apMesa.services.apMesaFormatFunctions"]).controller("ApMesaController",["$scope","$element","apMesaFormatFunctions","apMesaSortFunctions","apMesaFilterFunctions","$log","$window","$filter","$timeout",function(a,b,c,d,e,f,g,h,i){function j(b){for(var c=a.persistentState.sortOrder.length,d=0;c>d;d++)if(a.persistentState.sortOrder[d].id===b)return d}function k(b){var c=j(b);return c>-1?a.persistentState.sortOrder[c]:void 0}a.getSelectableRows=function(){var b=h("apMesaRowFilter");return angular.isArray(a.rows)?b(a.rows,a.columns,a.persistentState,a.transientState):[]},a.isSelectedAll=function(){if(!angular.isArray(a.rows)||!angular.isArray(a.selected))return!1;var b=a.getSelectableRows();return b.length>0&&b.length===a.selected.length},a.selectAll=function(){a.deselectAll();var b=a.getSelectableRows();if(!(b.length<=0)){for(var c=a.columns,d=null,e=null,f=0;f<c.length;f++)if(c[f].selector){d=c[f].key,e=c[f].selectObject;break}if(!d)throw new Error("Unable to find selector column key for selectAll");for(var f=0;f<b.length;f++)a.selected.push(e?b[f]:b[f][d])}},a.deselectAll=function(){for(;a.selected.length>0;)a.selected.pop()},a.toggleSelectAll=function(b){var c=b.target;c.checked?a.selectAll():a.deselectAll()},a.addSort=function(b,c){var d=k(b);d?d.dir=c:a.persistentState.sortOrder.push({id:b,dir:c})},a.removeSort=function(b){var c=j(b);-1!==c&&a.persistentState.sortOrder.splice(c,1)},a.clearSort=function(){a.persistentState.sortOrder=[]},a.hasFilterFields=function(){if(!a.columns)return!1;for(var b=a.columns.length-1;b>=0;b--)if("undefined"!=typeof a.columns[b].filter)return!0;return!1},a.clearAndFocusSearch=function(c){a.persistentState.searchTerms[c]="",b.find("tr.ap-mesa-filter-row th.column-"+c+" input").focus()},a.toggleSort=function(b,c){if(c.sort){var d=k(c.id);if(b.shiftKey)d?"+"===d.dir?d.dir="-":"-"===d.dir&&a.removeSort(c.id):a.addSort(c.id,"+");else{var e=d?d.dir:"";a.clearSort(),"+"===e?a.addSort(c.id,"-"):a.addSort(c.id,"+")}a.saveToStorage()}},a.getSortClass=function(b){var c=a.options.sortClasses;return"+"===b?c[1]:"-"===b?c[2]:c[0]},a.setColumns=function(b){a.columns=b,a.columns.forEach(function(a){var b=a.format;if("function"!=typeof b)if("string"==typeof b)if("function"==typeof c[b])a.format=c[b];else try{a.format=h(b)}catch(g){delete a.format,f.warn("format function reference in column(id="+a.id+') was not found in built-in format functions or $filters. format function given: "'+b+'". Available built-ins: '+Object.keys(c).join(",")+". If you supplied a $filter, ensure it is available on this module")}else delete a.format;var i=a.sort;"function"!=typeof i&&("string"==typeof i?"function"==typeof d[i]?a.sort=d[i](a.key):(delete a.sort,f.warn("sort function reference in column(id="+a.id+') was not found in built-in sort functions. sort function given: "'+i+'". Available built-ins: '+Object.keys(d).join(",")+". ")):delete a.sort);var j=a.filter;"function"!=typeof j&&("string"==typeof j?"function"==typeof e[j]?a.filter=e[j]:(delete a.filter,f.warn("filter function reference in column(id="+a.id+') was not found in built-in filter functions. filter function given: "'+j+'". Available built-ins: '+Object.keys(e).join(",")+". ")):delete a.filter)})},a.startColumnResize=function(b,c){function d(a){var b=a.pageX,c=b-f;e=j+c,h.css("width",e+"px")}b.preventDefault(),b.originalEvent.preventDefault(),b.stopPropagation();var e=!1,f=b.pageX,h=$('<div class="column-resizer-marquee"></div>'),i=$(b.target).parent("th");i.append(h);var j=i.outerWidth();h.css({width:j+"px",height:i.outerHeight()+"px"}),$(g).on("mousemove",d),$(g).one("mouseup",function(b){b.stopPropagation(),h.remove(),$(g).off("mousemove",d),e===!1?delete c.width:c.width=Math.max(e,0),a.$apply()})},a.sortableOptions={axis:"x",handle:".column-text",helper:"clone",placeholder:"ap-mesa-column-placeholder",distance:5},a.getActiveColCount=function(){var b=0;return a.columns.forEach(function(a){a.disabled||b++}),b},a.saveToStorage=function(){if(a.storage){var b={};["sortOrder","searchTerms"].forEach(function(c){b[c]=a.persistentState[c]}),b.columns=a.columns.map(function(a){return{id:a.id,disabled:!!a.disabled}}),b.options={},["rowLimit","pagingScheme","storageHash"].forEach(function(c){b.options[c]=a.options[c]}),a.storage.setItem(a.storageKey,JSON.stringify(b))}},a.loadFromStorage=function(){if(a.storage){var b=a.storage.getItem(a.storageKey);if(b){var c;try{if(c=JSON.parse(b),c.options.storageHash!==a.options.storageHash)return;["sortOrder","searchTerms"].forEach(function(b){a.persistentState[b]=c[b]});var d=c.columns.map(function(a){return a.id});a.columns.sort(function(a,b){var c=-1===d.indexOf(a.id),e=-1===d.indexOf(b.id);return c&&e?0:c?1:e?-1:d.indexOf(a.id)-d.indexOf(b.id)}),a.columns.forEach(function(a,b){["disabled"].forEach(function(d){a[d]=c.columns[b][d]})}),["rowLimit","pagingScheme","storageHash"].forEach(function(b){a.options[b]=c.options[b]})}catch(e){f.warn("Loading from storage failed!")}}}}}]),function(){function a(a){if("object"!=typeof a)return a;for(var b=1,c=arguments.length;c>b;b++){var d=arguments[b];for(var e in d)void 0===a[e]&&(a[e]=d[e])}return a}var b={bgSizeMultiplier:1,rowPadding:300,bodyHeight:300,fixedHeight:!1,defaultRowHeight:40,scrollDebounce:100,scrollDivisor:1,loadingText:"loading",loadingError:!1,noRowsText:"no rows",pagingStrategy:"SCROLL",rowsPerPage:10,rowsPerPageChoices:[10,25,50,100],rowsPerPageMessage:"rows per page",showRowsPerPageCtrls:!0,maxPageLinks:8,sortClasses:["glyphicon glyphicon-sort","glyphicon glyphicon-chevron-up","glyphicon glyphicon-chevron-down"],onRegisterApi:function(a){}};angular.module("apMesa.directives.apMesa",["apMesa.controllers.ApMesaController","apMesa.directives.apMesaRows","apMesa.directives.apMesaDummyRows","apMesa.directives.apMesaExpandable","apMesa.directives.apMesaPaginationCtrls","apMesa.directives.apMesaThTitle"]).provider("apMesa",function(){this.setDefaultOptions=function(c){b=a(c,b)},this.$get=[function(){return{getDefaultOptions:function(){return b},setDefaultOptions:function(c){b=a(c,b)}}}]}).directive("apMesa",["$log","$timeout","$q","apMesa",function(c,d,e,f){function g(a,b,c){var e,f,g,h,i,j=function(){var k=Date.now()-h;b>k&&k>0?e=d(j,b-k):(e=null,c||(i=a.apply(g,f),e||(g=f=null)))};return function(){g=this,f=arguments,h=Date.now();var k=c&&!e;return e||(e=d(j,b)),k&&(i=a.apply(g,f),g=f=null),i}}function h(a){var c=b.rowsPerPage;a.options&&a.options.rowsPerPage&&(c=a.options.rowsPerPage),a.persistentState={rowLimit:c,searchTerms:{},sortOrder:[]},a.transientState={filterCount:a.rows?a.rows.length:0,rowOffset:0,pageOffset:0,expandedRows:{},expandedRowHeights:{}},a.$broadcast("apMesa:stateReset")}function i(b){if(void 0!==b.options&&b.options.hasOwnProperty("getter")&&"function"!=typeof b.options.getter)throw new Error('"getter" in "options" should be a function!');b.options=b.options||{};var c=b.trackBy?{trackBy:b.trackBy}:{};a(b.options,c,f.getDefaultOptions()),j(b)}function j(a){a.options.initialSorts&&angular.forEach(a.options.initialSorts,function(b){a.addSort(b.id,b.dir)})}function k(a){a._columns&&a._columns.length&&(a.columns=angular.copy(a._columns),a.setColumns(a.columns),h(a))}function l(a){k(a),h(a),i(a)}function m(a,b){var f=[];a.scrollDiv=b.find(".mesa-rows-table-wrapper"),a.$watch("_columns",function(b,c){b!==a.columns&&(k(a),j(a))}),a.$watch("options",function(b,c){h(a),i(a)}),a.$watch("options.storage",function(b){if(b){if(!a.options.storageKey)throw new Error("apMesa: the storage option requires the storageKey option as well. See the README.");a.storage=a.options.storage,a.storageKey=a.options.storageKey,a.loadFromStorage(),f.push(a.$watchCollection("columns",a.saveToStorage)),f.push(a.$watchCollection("persistentState.searchTerms",a.saveToStorage))}else f.length&&(f.forEach(function(a){a()}),f=[])});var l;a.$watch("options.fillHeight",function(c){"SCROLL"===a.options.pagingStrategy&&(c?(l=a.$on("apMesa:resize",function(){a.options.bodyHeight=b.parent().height()-b.find(".mesa-header-table").outerHeight(!0)}),a.$emit("apMesa:resize")):l&&l())}),a.$watch("options.bodyHeight",function(){"SCROLL"===a.options.pagingStrategy&&(a.calculateRowLimit(),a.tbodyNgStyle={},a.tbodyNgStyle[a.options.fixedHeight?"height":"max-height"]=a.options.bodyHeight+"px",a.saveToStorage())}),a.$watch("transientState.filterCount",function(){a.options&&"SCROLL"===a.options.pagingStrategy&&a.onScroll()}),a.$watch("rowHeight",function(c){b.find("tr.ap-mesa-dummy-row").css("background-size","auto "+c*a.options.bgSizeMultiplier+"px")}),a.$watch("options.loadingPromise",function(b){angular.isObject(b)&&"function"==typeof b.then&&(a.api.setLoading(!0),b.then(function(){a.options.loadingError=!1,a.api.setLoading(!1)},function(b){a.options.loadingError=!0,a.api.setLoading(!1),c.warn("Failed loading table data: "+b)}))}),a.$watch("options.rowsPerPage",function(b,c){if(a.calculateRowLimit(),b!==c){var d=Math.floor(a.transientState.filterCount/a.options.rowsPerPage);a.transientState.pageOffset=Math.min(d,a.transientState.pageOffset)}}),a.$watch("options.pagingStrategy",function(b){"SCROLL"===b&&(a.scrollDiv.off("scroll"),a.scrollDiv.on("scroll",a.onScroll))}),a.$watch("persistentState.sortOrder",function(b){b&&(a.sortDirection={},b.forEach(function(b){a.sortDirection[b.id]=b.dir}))},!0);var m,n=g(function(){a.calculateRowLimit();var b=a.scrollDiv[0].scrollTop-a.options.rowPadding,c=a.rowHeight;if(0===c)return!1;var d=0,e=0,f=Object.keys(a.transientState.expandedRows).map(function(a){return parseInt(a)}).sort();f.push(a.transientState.filterCount);for(var g=0;g<=f.length;g++){var h=f[g],i=(h-d)*c;if(e+i>=b){d+=Math.floor((b-e)/c);break}e+=i;var j=a.transientState.expandedRowHeights[h];if(e+=j,d=h,e>=b){d--;break}}a.transientState.rowOffset=Math.max(0,d),m.resolve(),m=null,a.options.scrollingPromise=null,a.$digest()},a.options.scrollDebounce);a.onScroll=function(){m||(m=e.defer(),a.options.scrollingPromise=m.promise),n()},a.calculateRowLimit=function(){var b=a.scrollDiv.find(".ap-mesa-rendered-rows tr").height();a.rowHeight=b||a.options.defaultRowHeight||20,"SCROLL"===a.options.pagingStrategy?a.persistentState.rowLimit=Math.ceil((a.options.bodyHeight+2*a.options.rowPadding)/a.rowHeight):"PAGINATE"===a.options.pagingStrategy&&(a.persistentState.rowLimit=a.options.rowsPerPage)},d(function(){a.calculateRowLimit()},0),a.api={isSelectedAll:a.isSelectedAll,selectAll:a.selectAll,deselectAll:a.deselectAll,toggleSelectAll:a.toggleSelectAll,setLoading:function(b,c){a.options.loading=b,c&&a.$digest()}},a.options.onRegisterApi(a.api)}return{templateUrl:"src/templates/apMesa.tpl.html",restrict:"EA",replace:!0,scope:{_columns:"=columns",rows:"=",classes:"@tableClass",selected:"=",options:"=?",trackBy:"@?"},controller:"ApMesaController",compile:function(a){var b=a.attr("track-by");return b&&a.find(".ap-mesa-rendered-rows").attr("track-by",b),{pre:l,post:m}}}}])}(),angular.module("apMesa.directives.apMesaCell",["apMesa.directives.apMesaSelector"]).directive("apMesaCell",["$compile",function(a){function b(b,c){b.$watch("column",function(d){var e="";if(d.template)e=d.template;else if(d.templateUrl)e="<div ng-include=\"'"+d.templateUrl+"'\"></div>";else if(d.selector===!0)e='<input type="checkbox" ng-checked="selected.indexOf(column.selectObject ? row : row[column.key]) >= 0" ap-mesa-selector class="ap-mesa-selector" />';else if(d.ngFilter)e="{{ row[column.key] | "+d.ngFilter+":row }}";else if(d.format){var f=void 0!==b.options&&{}.hasOwnProperty.call(b.options,"getter")?"options.getter(column.key, row)":"row[column.key]";e="{{ column.format("+f+", row, column, options) }}"}else e=void 0!==b.options&&{}.hasOwnProperty.call(b.options,"getter")?"{{ options.getter(column.key, row) }}":"{{ row[column.key] }}";c.html(e),a(c.contents())(b)})}return{scope:!0,link:b}}]),angular.module("apMesa.directives.apMesaDummyRows",[]).directive("apMesaDummyRows",function(){return{template:'<tr class="ap-mesa-dummy-row" ng-style="{ height: dummyRowHeight + \'px\'}"><td ng-show="dummyRowHeight" ng-attr-colspan="{{columns.length}}"></td></tr>',scope:!0,link:function(a,b,c){a.$watch(c.apMesaDummyRows,function(b){var c=(b[1]-b[0])*a.rowHeight;for(var d in a.transientState.expandedRows){var e=parseInt(d);e>=b[0]&&e<b[1]&&(c+=a.transientState.expandedRowHeights[d])}a.dummyRowHeight=c})}}}),angular.module("apMesa.directives.apMesaExpandable",[]).directive("apMesaExpandable",["$compile",function(a){return{scope:!1,link:function(b,c,d){b.$watch("row",function(){var d;if(b.options.expandableTemplateUrl)d=angular.element('<div ng-include="options.expandableTemplateUrl" onload="refreshExpandedHeight(true)"></div>');else{if(!b.options.expandableTemplate)return;d=angular.element(b.options.expandableTemplate)}a(d)(b),c.html(""),c.append(d)})}}}]),angular.module("apMesa.directives.apMesaPaginationCtrls",[]).directive("apMesaPaginationCtrls",["$timeout",function(a){return{templateUrl:"src/templates/apMesaPaginationCtrls.tpl.html",scope:!0,link:function(a,b){function c(){var b=[],c=Math.ceil(a.transientState.filterCount/a.options.rowsPerPage),d=a.transientState.pageOffset,e=Math.max(5,a.options.maxPageLinks);if(e>=c)for(var f=0;c>f;f++)b.push({gap:!1,page:f,current:d===f});else if(e-2>d){for(var f=0;e-2>f;f++)b.push({gap:!1,page:f,current:d===f});b.push({gap:!0,page:-1,current:!1},{gap:!1,page:c-1,current:!1})}else if(e-2>=c-d){b.push({gap:!1,page:0,current:!1},{gap:!0,page:-1,current:!1});for(var g=c-(e-2),f=g;c>f;f++)b.push({gap:!1,page:f,current:d===f})}else{b.push({gap:!1,page:0,current:!1},{gap:!0,page:-1,current:!1});for(var h=e-4,f=0;h>0;f++){var i=f%2?(f+1)/2:-(f/2),j=d+i;i>=0?b.push({gap:!1,page:j,current:0===i}):b.splice(2,0,{gap:!1,page:j,current:!1}),--h}b.push({gap:!0,page:-1,current:!1},{gap:!1,page:c-1,current:!1})}a.pageLinks=b,a.lastPage=c-1}a.$watch("transientState.filterCount",c),a.$watch("options.rowsPerPage",c),a.$watch("transientState.pageOffset",c),a.goBack=function(){0!==a.transientState.pageOffset&&a.transientState.pageOffset--},a.goForward=function(){a.transientState.pageOffset!==a.lastPage&&a.transientState.pageOffset++}}}}]),angular.module("apMesa.directives.apMesaRow",["apMesa.directives.apMesaCell"]).directive("apMesaRow",["$timeout",function(a){return{template:'<td ng-repeat="column in columns track by column.id" class="ap-mesa-cell col-{{column.id}}" ap-mesa-cell></td>',scope:!1,link:function(b,c){var d=b.$index+b.transientState.rowOffset;b.rowIsExpanded=!!b.transientState.expandedRows[d],b.toggleRowExpand=function(){b.transientState.expandedRows[d]=b.rowIsExpanded=!b.transientState.expandedRows[d],b.transientState.expandedRows[d]?b.refreshExpandedHeight(!1):(delete b.transientState.expandedRows[d],delete b.transientState.expandedRowHeights[d])},b.refreshExpandedHeight=function(e){a(function(){var a=c.next("tr.ap-mesa-expand-panel").height();b.transientState.expandedRowHeights[d]=a})},b.$watch("transientState.expandedRows",function(a,c){a!==c&&(b.rowIsExpanded=!1)})}}}]),angular.module("apMesa.directives.apMesaRows",["apMesa.directives.apMesaRow","apMesa.filters.apMesaRowFilter","apMesa.filters.apMesaRowSorter"]).directive("apMesaRows",["$filter","$timeout",function(a,b){function c(a){if(!a.rows||!a.columns)return[];var b,c;if(b=e(a.rows,a.columns,a.persistentState,a.transientState,a.options),b=f(b,a.columns,a.persistentState.sortOrder,a.options),"SCROLL"===a.options.pagingStrategy)b=g(b,Math.floor(a.transientState.rowOffset)-a.transientState.filterCount),b=g(b,a.persistentState.rowLimit+Math.ceil(a.transientState.rowOffset%1)),c=a.transientState.rowOffset;else if("PAGINATE"===a.options.pagingStrategy){var d=a.transientState.pageOffset*a.persistentState.rowLimit;b=b.slice(d,d+a.persistentState.rowLimit),c=d}return b.forEach(function(a){a.$$$index=c++}),b}function d(a){var b=function(b,d){b!==d&&(a.visible_rows=c(a),a.transientState.expandedRows={})},d=function(b,d){b!==d&&(a.visible_rows=c(a))};a.$watch("persistentState.searchTerms",b,!0),a.$watch("[transientState.rowOffset, persistentState.rowLimit, transientState.pageOffset]",d),a.$watch("transientState.filterCount",b),a.$watch("persistentState.sortOrder",b,!0),a.$watch("rows",function(a){angular.isArray(a)&&b(!0,!1)}),b(!0,!1)}var e=a("apMesaRowFilter"),f=a("apMesaRowSorter"),g=a("limitTo");return{restrict:"A",templateUrl:"src/templates/apMesaRows.tpl.html",compile:function(a,b){var c=a.find("tr[ng-repeat-start]"),e=c.attr("ng-repeat-start");return e+=b.trackBy?" track by row[options.trackBy]":" track by row.$$$index",c.attr("ng-repeat-start",e),d}}}]),angular.module("apMesa.directives.apMesaSelector",[]).directive("apMesaSelector",function(){return{restrict:"A",scope:!1,link:function(a,b){var c=a.selected,d=a.row,e=a.column;b.on("click",function(){var b=c.indexOf(e.selectObject?d:d[e.key]);b>=0?c.splice(b,1):c.push(e.selectObject?d:d[e.key]),a.$apply()})}}}),angular.module("apMesa.directives.apMesaThTitle",[]).directive("apMesaThTitle",["$compile",function(a){function b(b,c){var d=b.column,e="<span>{{ column.id }}</span>";angular.isString(d.labelTemplateUrl)?e="<span ng-include=\"'"+d.labelTemplateUrl+"'\"></span>":angular.isString(d.labelTemplate)?e="<span>"+d.labelTemplate+"</span>":angular.isString(d.label)&&(e="<span>{{ column.label }}</span>"),c.html(e),a(c.contents())(b)}return{link:b}}]),angular.module("apMesa.filters.apMesaRowFilter",["apMesa.services.apMesaFilterFunctions"]).filter("apMesaRowFilter",["apMesaFilterFunctions","$log",function(a,b){return function(c,d,e,f,g){var h,i=c;return h=d.filter(function(c){var d=e.searchTerms[c.id];if(e.searchTerms.hasOwnProperty(c.id)&&"string"==typeof d){if(!d.trim())return!1;if("function"==typeof c.filter)return!0;var f=a[c.filter];if("function"==typeof f)return c.filter=f,!0;b.warn('apMesa: The filter function "'+c.filter+'" specified by column(id='+c.id+').filter was not found in predefined tableFilterFunctions. Available filters: "'+Object.keys(a).join('","')+'"')}return!1}),h.length&&(i=c.filter(function(a){for(var b=h.length-1;b>=0;b--){var c=h[b],d=c.filter,f=e.searchTerms[c.id],i=void 0!==g&&{}.hasOwnProperty.call(g,"getter")?g.getter(c.key,a):a[c.key],j="function"==typeof c.format?c.format(i,a,c,g):i;if(!d(f,i,j,a,c,g))return!1}return!0})),f.filterCount=i.length,i}}]),angular.module("apMesa.filters.apMesaRowSorter",[]).filter("apMesaRowSorter",function(){function a(a,c){if(b.hasOwnProperty(c))return b[c];for(var d=a.length-1;d>=0;d--)if(a[d].id===c)return b[c]=a[d],a[d]}var b={};return function(b,c,d,e){if(!d.length)return b;for(var f=[],g=0;g<b.length;g++)f.push(b[g]);return f.sort(function(b,f){for(var g=0;g<d.length;g++){var h=d[g],i=a(c,h.id),j=h.dir;if(i&&i.sort){var k=i.sort,l="+"===j?k(b,f,e,i):k(f,b,e,i);if(0!==l)return l}}return 0})}}),angular.module("apMesa.services.apMesaFilterFunctions",[]).service("apMesaFilterFunctions",function(){function a(a,b){a=a.toLowerCase().trim(),b=String(b).toLowerCase();var c=a[0];return"!"===c?(a=a.substr(1),""===a?!0:-1===b.indexOf(a)):"="===c?(a=a.substr(1),a===b.trim()):(a=a.replace("\\!","!"),a=a.replace("\\=","="),-1!==b.indexOf(a))}function b(b,c,d,e){return a(b,d,d,e)}function c(a,b){b=parseFloat(b),a=a.trim();var c=a.substr(0,2),d=a[0],e=1*a.substr(1),f=1*a.substr(2);return"<="===c?f>=b:">="===c?b>=f:"<"===d?e>b:">"===d?b>e:"~"===d?Math.round(b)===e:"="===d?e===b:b.toString().indexOf(a.toString())>-1}function d(a,b,d){return c(a,d)}function e(a){for(var b=a.trim().split(","),c=0,d=0;d<b.length;d++){var e=b[d].trim(),f=h.exec(e);if(f){var i=1*f[1],j=f[2].replace(/s$/,"");g.hasOwnProperty(j)&&(c+=i*g[j])}}return c}function f(a,b){if(a=a.trim(),!a)return!0;b*=1;var c,d,f=new Date,h=+f,i=a[0],j=a.substr(1).trim();if("<"===i)return c=h-e(j),b>c;if(">"===i)return d=h-e(j),d>b;if("today"===a)return new Date(b).toDateString()===f.toDateString();if("yesterday"===a)return new Date(b).toDateString()===new Date(h-g.d).toDateString();var k=new Date(a);return isNaN(k)?!1:new Date(b).toDateString()===k.toDateString()}a.placeholder=b.placeholder="string search",a.title=b.title='Search by text, eg. "foo". Use "!" to exclude and "=" to match exact text, e.g. "!bar" or "=baz".',c.placeholder=d.placeholder="number search",c.title=d.title='Search by number, e.g. "123". Optionally use comparator expressions like ">=10" or "<1000". Use "~" for approx. int values, eg. "~3" will match "3.2"';var g={};g.second=g.sec=g.s=1e3,g.minute=g.min=g.m=60*g.second,g.hour=g.hr=g.h=60*g.minute,g.day=g.d=24*g.hour,g.week=g.wk=g.w=7*g.day,g.month=4*g.week,g.year=g.yr=g.y=365*g.day;var h=/(\d+(?:\.\d+)?)\s*([a-z]+)/;return f.placeholder="date search",f.title='Search by date. Enter a date string (RFC2822 or ISO 8601 date). You can also type "today", "yesterday", "> 2 days ago", "< 1 day 2 hours ago", etc.',{like:a,likeFormatted:b,number:c,numberFormatted:d,date:f}}),angular.module("apMesa.services.apMesaFormatFunctions",[]).service("apMesaFormatFunctions",function(){return{}}),angular.module("apMesa.services.apMesaSortFunctions",[]).service("apMesaSortFunctions",function(){return{number:function(a){return function(b,c,d){var e,f;return void 0!==d&&{}.hasOwnProperty.call(d,"getter")?(e=d.getter(a,b),f=d.getter(a,c)):(e=b[a],f=c[a]),1*e-1*f}},string:function(a){return function(b,c,d){var e,f;return void 0!==d&&{}.hasOwnProperty.call(d,"getter")?(e=d.getter(a,b),f=d.getter(a,c)):(e=b[a],f=c[a]),e.toString().toLowerCase().localeCompare(f.toString().toLowerCase())}},stringFormatted:function(a){return function(b,c,d,e){var f,g;return void 0!==d&&{}.hasOwnProperty.call(d,"getter")?(f=d.getter(a,b),g=d.getter(a,c)):(f=b[a],g=c[a]),f=e.format(f,b,e),g=e.format(g,c,e),f.toString().toLowerCase().localeCompare(g.toString().toLowerCase())}},numberFormatted:function(a){return function(b,c,d,e){var f,g;return void 0!==d&&{}.hasOwnProperty.call(d,"getter")?(f=d.getter(a,b),g=d.getter(a,c)):(f=b[a],g=c[a]),f=e.format(f,b,e),g=e.format(g,c,e),1*f-1*g}}}}),angular.module("apMesa.templates",["src/templates/apMesa.tpl.html","src/templates/apMesaDummyRows.tpl.html","src/templates/apMesaPaginationCtrls.tpl.html","src/templates/apMesaRows.tpl.html"]),angular.module("src/templates/apMesa.tpl.html",[]).run(["$templateCache",function(a){a.put("src/templates/apMesa.tpl.html",'<div class="ap-mesa-wrapper">\n <table ng-class="classes" class="ap-mesa mesa-header-table">\n <thead>\n <tr ui-sortable="sortableOptions" ng-model="columns">\n <th\n scope="col"\n ng-repeat="column in columns"\n ng-click="toggleSort($event,column)"\n ng-class="{\'sortable-column\' : column.sort, \'select-column\': column.selector, \'is-sorting\': sortDirection[column.id] }"\n ng-attr-title="{{ column.title || \'\' }}"\n ng-style="{ width: column.width, \'min-width\': column.width, \'max-width\': column.width }"\n >\n <span class="column-text">\n <input ng-if="column.selector" type="checkbox" ng-checked="isSelectedAll()" ng-click="toggleSelectAll($event)" />\n <span\n ng-if="column.sort"\n title="This column is sortable. Click to toggle sort order. Hold shift while clicking multiple columns to stack sorting."\n class="sorting-icon {{ getSortClass( sortDirection[column.id] ) }}"\n ></span>\n <span ap-mesa-th-title></span>\n </span>\n <span\n ng-if="!column.lockWidth"\n ng-class="{\'discreet-width\': !!column.width, \'column-resizer\': true}"\n title="Click and drag to set discreet width. Click once to clear discreet width."\n ng-mousedown="startColumnResize($event, column)"\n >\n \n </span>\n </th>\n </tr>\n <tr ng-if="hasFilterFields()" class="ap-mesa-filter-row">\n <td ng-repeat="column in columns" ng-class="\'column-\' + column.id">\n <input\n type="text"\n ng-if="(column.filter)"\n ng-model="persistentState.searchTerms[column.id]"\n ng-attr-placeholder="{{ column.filter && column.filter.placeholder }}"\n ng-attr-title="{{ column.filter && column.filter.title }}"\n ng-class="{\'active\': persistentState.searchTerms[column.id] }"\n >\n <button\n ng-if="(column.filter)"\n ng-show="persistentState.searchTerms[column.id]"\n class="clear-search-btn"\n role="button"\n type="button"\n ng-click="clearAndFocusSearch(column.id)"\n >\n ×\n </button>\n\n </td>\n </tr>\n </thead>\n </table>\n <div class="mesa-rows-table-wrapper" ng-style="tbodyNgStyle">\n <table ng-class="classes" class="ap-mesa mesa-rows-table">\n <thead>\n <th\n scope="col"\n ng-repeat="column in columns"\n ng-style="{ width: column.width, \'min-width\': column.width, \'max-width\': column.width }"\n ></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-if="visible_rows.length === 0 || options.loading">\n <td ng-attr-colspan="{{columns.length}}" class="space-holder-row-cell">\n <div ng-if="options.loadingError">\n <div ng-if="!options.loading && options.loadingErrorTemplateUrl" ng-include="options.loadingErrorTemplateUrl"></div>\n <div ng-if="!options.loading && !options.loadingErrorTemplateUrl">{{ options.loadingErrorText }}</div>\n </div>\n <div ng-if="!options.loadingError">\n <div ng-if="options.loading && options.loadingTemplateUrl" ng-include="options.loadingTemplateUrl"></div>\n <div ng-if="options.loading && !options.loadingTemplateUrl">{{ options.loadingText }}</div>\n <div ng-if="!options.loading && options.noRowsTemplateUrl" ng-include="options.noRowsTemplateUrl"></div>\n <div ng-if="!options.loading && !options.noRowsTemplateUrl">{{ options.noRowsText }}</div>\n </div>\n </td>\n </tr>\n </tbody>\n <tbody ng-if="options.pagingStrategy === \'SCROLL\'" ng-show="!options.loading" ap-mesa-dummy-rows="[0,transientState.rowOffset]" columns="columns" cell-content="..."></tbody>\n <tbody ng-show="!options.loading" ap-mesa-rows class="ap-mesa-rendered-rows"></tbody>\n <tbody ng-if="options.pagingStrategy === \'SCROLL\'" ng-show="!options.loading" ap-mesa-dummy-rows="[transientState.rowOffset + visible_rows.length, transientState.filterCount]" columns="columns" cell-content="..."></tbody>\n </table>\n </div>\n <div class="ap-mesa-pagination" ng-if="options.pagingStrategy === \'PAGINATE\'" ap-mesa-pagination-ctrls></div>\n</div>\n')}]),angular.module("src/templates/apMesaDummyRows.tpl.html",[]).run(["$templateCache",function(a){a.put("src/templates/apMesaDummyRows.tpl.html","")}]),angular.module("src/templates/apMesaPaginationCtrls.tpl.html",[]).run(["$templateCache",function(a){a.put("src/templates/apMesaPaginationCtrls.tpl.html",'<ul class="pagination" ng-if="lastPage > 0">\n <li ng-class="{ \'disabled\': transientState.pageOffset === 0 }">\n <a ng-click="goBack()" >«</a>\n </li>\n <li ng-repeat="link in pageLinks" ng-class="{ \'active\': link.current, \'disabled\': link.gap }">\n <a ng-if="!link.gap" ng-click="transientState.pageOffset = link.page">{{ link.page + 1 }}</a>\n <a ng-if="link.gap" href="">…</a>\n </li>\n <li ng-class="{ \'disabled\': transientState.pageOffset === lastPage }">\n <a ng-click="goForward()" >»</a>\n </li>\n</ul>\n<span class="rows-per-page-ctrl">\n <span class="rows-per-page-msg">{{ options.rowsPerPageMessage }}</span>\n <ul class="pagination" ng-if="options.showRowsPerPageCtrls">\n <li ng-repeat="limit in options.rowsPerPageChoices" ng-class="{\'active\': options.rowsPerPage === limit}">\n <a ng-click="options.rowsPerPage = limit">{{ limit }}</a>\n </li>\n </ul>\n</span>\n')}]),angular.module("src/templates/apMesaRows.tpl.html",[]).run(["$templateCache",function(a){a.put("src/templates/apMesaRows.tpl.html",'<tr ng-repeat-start="row in visible_rows" ng-attr-class="{{ (transientState.rowOffset + $index) % 2 ? \'odd\' : \'even\' }}" ap-mesa-row></tr>\n<tr ng-repeat-end ng-if="rowIsExpanded" class="ap-mesa-expand-panel">\n <td ap-mesa-expandable ng-attr-colspan="{{ columns.length }}"></td>\n</tr>\n')}]); | ||
"use strict";angular.module("apMesa",["apMesa.templates","ui.sortable","ngSanitize","apMesa.directives.apMesa"]),angular.module("apMesa.controllers.ApMesaController",["apMesa.services.apMesaSortFunctions","apMesa.services.apMesaFilterFunctions","apMesa.services.apMesaFormatFunctions"]).controller("ApMesaController",["$scope","$element","apMesaFormatFunctions","apMesaSortFunctions","apMesaFilterFunctions","$log","$window","$filter","$timeout",function(a,b,c,d,e,f,g,h,i){function j(b){for(var c=a.persistentState.sortOrder.length,d=0;c>d;d++)if(a.persistentState.sortOrder[d].id===b)return d}function k(b){var c=j(b);return c>-1?a.persistentState.sortOrder[c]:void 0}a.getSelectableRows=function(){var b=h("apMesaRowFilter");return angular.isArray(a.rows)?b(a.rows,a.columns,a.persistentState,a.transientState):[]},a.isSelectedAll=function(){if(!angular.isArray(a.rows)||!angular.isArray(a.selected))return!1;var b=a.getSelectableRows();return b.length>0&&b.length===a.selected.length},a.selectAll=function(){a.deselectAll();var b=a.getSelectableRows();if(!(b.length<=0)){for(var c=a.columns,d=null,e=null,f=0;f<c.length;f++)if(c[f].selector){d=c[f].key,e=c[f].selectObject;break}if(!d)throw new Error("Unable to find selector column key for selectAll");for(var f=0;f<b.length;f++)a.selected.push(e?b[f]:b[f][d])}},a.deselectAll=function(){for(;a.selected.length>0;)a.selected.pop()},a.toggleSelectAll=function(b){var c=b.target;c.checked?a.selectAll():a.deselectAll()},a.addSort=function(b,c){var d=k(b);d?d.dir=c:a.persistentState.sortOrder.push({id:b,dir:c})},a.removeSort=function(b){var c=j(b);-1!==c&&a.persistentState.sortOrder.splice(c,1)},a.clearSort=function(){a.persistentState.sortOrder=[]},a.hasFilterFields=function(){if(!a.columns)return!1;for(var b=a.columns.length-1;b>=0;b--)if("undefined"!=typeof a.columns[b].filter)return!0;return!1},a.clearAndFocusSearch=function(c){a.persistentState.searchTerms[c]="",b.find("tr.ap-mesa-filter-row th.column-"+c+" input").focus()},a.toggleSort=function(b,c){if(c.sort){var d=k(c.id);if(b.shiftKey)d?"+"===d.dir?d.dir="-":"-"===d.dir&&a.removeSort(c.id):a.addSort(c.id,"+");else{var e=d?d.dir:"";a.clearSort(),"+"===e?a.addSort(c.id,"-"):a.addSort(c.id,"+")}a.saveToStorage()}},a.getSortClass=function(b){var c=a.options.sortClasses;return"+"===b?c[1]:"-"===b?c[2]:c[0]},a.setColumns=function(b){try{a.columns=b,a.columns.forEach(function(b){var g=b.format;if("function"!=typeof g)if("string"==typeof g)if("function"==typeof c[g])b.format=c[g];else try{b.format=h(g)}catch(i){delete b.format,f.warn("format function reference in column(id="+b.id+') was not found in built-in format functions or $filters. format function given: "'+g+'". Available built-ins: '+Object.keys(c).join(",")+". If you supplied a $filter, ensure it is available on this module")}else delete b.format;if(!a.options.getData){var j=b.sort;"function"!=typeof j&&("string"==typeof j?"function"==typeof d[j]?b.sort=d[j](b.key):(delete b.sort,f.warn("sort function reference in column(id="+b.id+') was not found in built-in sort functions. sort function given: "'+j+'". Available built-ins: '+Object.keys(d).join(",")+". ")):delete b.sort);var k=b.filter;"function"!=typeof k&&("string"==typeof k?"function"==typeof e[k]?b.filter=e[k]:(delete b.filter,f.warn("filter function reference in column(id="+b.id+') was not found in built-in filter functions. filter function given: "'+k+'". Available built-ins: '+Object.keys(e).join(",")+". ")):delete b.filter)}})}catch(g){console.log(g.message)}},a.startColumnResize=function(b,c){function d(a){var b=a.pageX,c=b-f;e=j+c,h.css("width",e+"px")}b.preventDefault(),b.originalEvent.preventDefault(),b.stopPropagation();var e=!1,f=b.pageX,h=$('<div class="column-resizer-marquee"></div>'),i=$(b.target).parent("th");i.append(h);var j=i.outerWidth();h.css({width:j+"px",height:i.outerHeight()+"px"}),$(g).on("mousemove",d),$(g).one("mouseup",function(b){b.stopPropagation(),h.remove(),$(g).off("mousemove",d),e===!1?delete c.width:c.width=Math.max(e,0),a.$apply()})},a.sortableOptions={axis:"x",handle:".column-text",helper:"clone",placeholder:"ap-mesa-column-placeholder",distance:5},a.getActiveColCount=function(){var b=0;return a.columns.forEach(function(a){a.disabled||b++}),b},a.saveToStorage=function(){if(a.storage){var b={};["sortOrder","searchTerms"].forEach(function(c){b[c]=a.persistentState[c]}),b.columns=a.columns.map(function(a){return{id:a.id,disabled:!!a.disabled}}),b.options={},["rowLimit","pagingScheme","storageHash"].forEach(function(c){b.options[c]=a.options[c]}),a.storage.setItem(a.storageKey,JSON.stringify(b))}},a.loadFromStorage=function(){if(a.storage){var b=a.storage.getItem(a.storageKey);if(b){var c;try{if(c=JSON.parse(b),c.options.storageHash!==a.options.storageHash)return;["sortOrder","searchTerms"].forEach(function(b){a.persistentState[b]=c[b]});var d=c.columns.map(function(a){return a.id});a.columns.sort(function(a,b){var c=-1===d.indexOf(a.id),e=-1===d.indexOf(b.id);return c&&e?0:c?1:e?-1:d.indexOf(a.id)-d.indexOf(b.id)}),a.columns.forEach(function(a,b){["disabled"].forEach(function(d){a[d]=c.columns[b][d]})}),["rowLimit","pagingScheme","storageHash"].forEach(function(b){a.options[b]=c.options[b]})}catch(e){f.warn("Loading from storage failed!")}}}}}]),function(){function a(a){if("object"!=typeof a)return a;for(var b=1,c=arguments.length;c>b;b++){var d=arguments[b];for(var e in d)void 0===a[e]&&(a[e]=d[e])}return a}var b={bgSizeMultiplier:1,rowPadding:300,bodyHeight:300,fixedHeight:!1,defaultRowHeight:40,scrollDebounce:100,scrollDivisor:1,loadingText:void 0,noRowsText:"No data.",pagingStrategy:"SCROLL",rowsPerPage:10,rowsPerPageChoices:[10,25,50,100],rowsPerPageMessage:"rows per page",showRowsPerPageCtrls:!0,maxPageLinks:8,sortClasses:["glyphicon glyphicon-sort","glyphicon glyphicon-chevron-up","glyphicon glyphicon-chevron-down"],onRegisterApi:function(a){}};angular.module("apMesa.directives.apMesa",["apMesa.controllers.ApMesaController","apMesa.directives.apMesaRows","apMesa.directives.apMesaDummyRows","apMesa.directives.apMesaExpandable","apMesa.directives.apMesaPaginationCtrls","apMesa.directives.apMesaStatusDisplay","apMesa.directives.apMesaThTitle","apMesa.services.apMesaDebounce"]).provider("apMesa",function(){this.setDefaultOptions=function(c){b=a(c,b)},this.$get=[function(){return{getDefaultOptions:function(){return b},setDefaultOptions:function(c){b=a(c,b)}}}]}).directive("apMesa",["$log","$timeout","$q","apMesa","apMesaDebounce",function(c,d,e,f,g){function h(a){var c=b.rowsPerPage;if(a.options&&a.options.rowsPerPage&&(c=a.options.rowsPerPage),a.persistentState={rowLimit:c,searchTerms:{},sortOrder:[]},a.transientState={rowHeightIsCalculated:!1,filterCount:a.rows?a.rows.length:0,rowOffset:0,pageOffset:0,expandedRows:{},expandedRowHeights:{},columnLookup:{},loadingError:null,loading:!1},a.columns.length){var d=a.transientState.columnLookup;a.columns.forEach(function(a){d[a.id]=a})}a.$broadcast("apMesa:stateReset")}function i(b){if(void 0!==b.options&&b.options.hasOwnProperty("getter")&&"function"!=typeof b.options.getter)throw new Error('"getter" in "options" should be a function!');b.options=b.options||{};var c=b.trackBy?{trackBy:b.trackBy}:{};a(b.options,c,f.getDefaultOptions()),j(b)}function j(a){a.options.initialSorts&&angular.forEach(a.options.initialSorts,function(b){a.addSort(b.id,b.dir)})}function k(a){a._columns&&a._columns.length&&(a.columns=angular.copy(a._columns),a.setColumns(a.columns),h(a))}function l(a){i(a),k(a),h(a)}function m(a,b){var f=[];a.scrollDiv=b.find(".mesa-rows-table-wrapper"),a.$watch("_columns",function(b,c){b!==a.columns&&(k(a),j(a))}),a.$watch("options",function(b,c){h(a),i(a)}),a.$watch("options.storage",function(b){if(b){if(!a.options.storageKey)throw new Error("apMesa: the storage option requires the storageKey option as well. See the README.");a.storage=a.options.storage,a.storageKey=a.options.storageKey,a.loadFromStorage(),f.push(a.$watchCollection("columns",a.saveToStorage)),f.push(a.$watchCollection("persistentState.searchTerms",a.saveToStorage))}else f.length&&(f.forEach(function(a){a()}),f=[])});var l;a.$watch("options.fillHeight",function(c){"SCROLL"===a.options.pagingStrategy&&(c?(l=a.$on("apMesa:resize",function(){a.options.bodyHeight=b.parent().height()-b.find(".mesa-header-table").outerHeight(!0)}),a.$emit("apMesa:resize")):l&&l())}),a.$watch("options.bodyHeight",function(){"SCROLL"===a.options.pagingStrategy&&(a.calculateRowLimit(),a.tbodyNgStyle={},a.tbodyNgStyle[a.options.fixedHeight?"height":"max-height"]=a.options.bodyHeight+"px",a.saveToStorage())}),a.$watch("transientState.filterCount",function(){a.options&&"SCROLL"===a.options.pagingStrategy&&a.onScroll()}),a.$watch("rowHeight",function(c){b.find("tr.ap-mesa-dummy-row").css("background-size","auto "+c*a.options.bgSizeMultiplier+"px")}),a.$watch("options.loadingPromise",function(b){angular.isObject(b)&&"function"==typeof b.then&&(a.api.setLoading(!0),b.then(function(b){a.transientState.loadingError=!1,a.api.setLoading(!1),angular.isArray(b)&&(a.rows=b)},function(b){a.transientState.loadingError=!0,a.api.setLoading(!1),c.warn("Failed loading table data: "+b)}))}),a.$watch("options.rowsPerPage",function(b,c){if(a.calculateRowLimit(),b!==c){var d=Math.floor(a.transientState.filterCount/a.options.rowsPerPage);a.transientState.pageOffset=Math.min(d,a.transientState.pageOffset)}}),a.$watch("options.pagingStrategy",function(b){"SCROLL"===b&&(a.scrollDiv.off("scroll"),a.scrollDiv.on("scroll",a.onScroll))}),a.$watch("persistentState.sortOrder",function(b){b&&(a.sortDirection={},b.forEach(function(b){a.sortDirection[b.id]=b.dir}))},!0);var m,n=g(function(){a.calculateRowLimit();var b=a.scrollDiv[0].scrollTop-a.options.rowPadding,c=a.rowHeight;if(0===c)return!1;var d=0,e=0,f=Object.keys(a.transientState.expandedRows).map(function(a){return parseInt(a)}).sort();f.push(a.transientState.filterCount);for(var g=0;g<=f.length;g++){var h=f[g],i=(h-d)*c;if(e+i>=b){d+=Math.floor((b-e)/c);break}e+=i;var j=a.transientState.expandedRowHeights[h];if(e+=j,d=h,e>=b){d--;break}}a.transientState.rowOffset=Math.max(0,d),m.resolve(),m=null,a.options.scrollingPromise=null,a.$digest()},a.options.scrollDebounce);a.onScroll=function(){m||(m=e.defer(),a.options.scrollingPromise=m.promise),n()},a.calculateRowLimit=function(){var b=a.scrollDiv.find(".ap-mesa-rendered-rows tr").height();a.rowHeight=b||a.options.defaultRowHeight||20,!a.transientState.rowHeightIsCalculated&&b&&(a.transientState.rowHeightIsCalculated=!0),"SCROLL"===a.options.pagingStrategy?a.persistentState.rowLimit=Math.ceil((a.options.bodyHeight+2*a.options.rowPadding)/a.rowHeight):"PAGINATE"===a.options.pagingStrategy&&(a.persistentState.rowLimit=a.options.rowsPerPage)},a.resetOffset=function(){"SCROLL"===a.options.pagingStrategy?(a.scrollDiv[0].scrollTop=0,a.transientState.rowOffset=0):"PAGINATE"===a.options.pagingStrategy&&(a.transientState.pageOffset=0,a.transientState.rowOffset=0)},d(function(){a.calculateRowLimit()},0),a.api={isSelectedAll:a.isSelectedAll,selectAll:a.selectAll,deselectAll:a.deselectAll,toggleSelectAll:a.toggleSelectAll,setLoading:function(b,c){a.transientState.loading=b,c&&a.$digest()}},a.options.onRegisterApi(a.api)}return{templateUrl:"src/templates/apMesa.tpl.html",restrict:"EA",replace:!0,scope:{_columns:"=columns",rows:"=",classes:"@tableClass",selected:"=",options:"=?",trackBy:"@?"},controller:"ApMesaController",compile:function(a){var b=a.attr("track-by");return b&&a.find(".ap-mesa-rendered-rows").attr("track-by",b),{pre:l,post:m}}}}])}(),angular.module("apMesa.directives.apMesaCell",["apMesa.directives.apMesaSelector"]).directive("apMesaCell",["$compile",function(a){function b(b,c){b.$watch("column",function(d){var e="";if(d.template)e=d.template;else if(d.templateUrl)e="<div ng-include=\"'"+d.templateUrl+"'\"></div>";else if(d.selector===!0)e='<input type="checkbox" ng-checked="selected.indexOf(column.selectObject ? row : row[column.key]) >= 0" ap-mesa-selector class="ap-mesa-selector" />';else if(d.ngFilter)e="{{ row[column.key] | "+d.ngFilter+":row }}";else if(d.format){var f=void 0!==b.options&&{}.hasOwnProperty.call(b.options,"getter")?"options.getter(column.key, row)":"row[column.key]";e="{{ column.format("+f+", row, column, options) }}"}else e=void 0!==b.options&&{}.hasOwnProperty.call(b.options,"getter")?"{{ options.getter(column.key, row) }}":"{{ row[column.key] }}";c.html(e),a(c.contents())(b)})}return{scope:!0,link:b}}]),angular.module("apMesa.directives.apMesaDummyRows",[]).directive("apMesaDummyRows",function(){return{template:'<tr class="ap-mesa-dummy-row" ng-style="{ height: dummyRowHeight + \'px\'}"><td ng-show="dummyRowHeight" ng-attr-colspan="{{columns.length}}"></td></tr>',scope:!0,link:function(a,b,c){a.$on("angular-mesa:update-dummy-rows",function(){var b=a.$eval(c.apMesaDummyRows),d=(b[1]-b[0])*a.rowHeight;for(var e in a.transientState.expandedRows){var f=parseInt(e);f>=b[0]&&f<b[1]&&(d+=a.transientState.expandedRowHeights[e])}a.dummyRowHeight=d})}}}),angular.module("apMesa.directives.apMesaExpandable",[]).directive("apMesaExpandable",["$compile",function(a){return{scope:!1,link:function(b,c,d){b.$watch("row",function(){var d;if(b.options.expandableTemplateUrl)d=angular.element('<div ng-include="options.expandableTemplateUrl" onload="refreshExpandedHeight(true)"></div>');else{if(!b.options.expandableTemplate)return;d=angular.element(b.options.expandableTemplate)}a(d)(b),c.html(""),c.append(d)})}}}]),angular.module("apMesa.directives.apMesaPaginationCtrls",[]).directive("apMesaPaginationCtrls",["$timeout",function(a){return{templateUrl:"src/templates/apMesaPaginationCtrls.tpl.html",scope:!0,link:function(a,b){function c(){var b=[],c=Math.ceil(a.transientState.filterCount/a.options.rowsPerPage),d=a.transientState.pageOffset,e=Math.max(5,a.options.maxPageLinks);if(e>=c)for(var f=0;c>f;f++)b.push({gap:!1,page:f,current:d===f});else if(e-2>d){for(var f=0;e-2>f;f++)b.push({gap:!1,page:f,current:d===f});b.push({gap:!0,page:-1,current:!1},{gap:!1,page:c-1,current:!1})}else if(e-2>=c-d){b.push({gap:!1,page:0,current:!1},{gap:!0,page:-1,current:!1});for(var g=c-(e-2),f=g;c>f;f++)b.push({gap:!1,page:f,current:d===f})}else{b.push({gap:!1,page:0,current:!1},{gap:!0,page:-1,current:!1});for(var h=e-4,f=0;h>0;f++){var i=f%2?(f+1)/2:-(f/2),j=d+i;i>=0?b.push({gap:!1,page:j,current:0===i}):b.splice(2,0,{gap:!1,page:j,current:!1}),--h}b.push({gap:!0,page:-1,current:!1},{gap:!1,page:c-1,current:!1})}a.pageLinks=b,a.lastPage=c-1}a.$watch("transientState.filterCount",c),a.$watch("options.rowsPerPage",c),a.$watch("transientState.pageOffset",c),a.goBack=function(){0!==a.transientState.pageOffset&&a.transientState.pageOffset--},a.goForward=function(){a.transientState.pageOffset!==a.lastPage&&a.transientState.pageOffset++}}}}]),angular.module("apMesa.directives.apMesaRow",["apMesa.directives.apMesaCell"]).directive("apMesaRow",["$timeout",function(a){return{template:'<td ng-repeat="column in columns track by column.id" class="ap-mesa-cell col-{{column.id}}" ap-mesa-cell></td>',scope:!1,link:function(b,c){var d=b.$index+b.transientState.rowOffset;b.rowIsExpanded=!!b.transientState.expandedRows[d],b.toggleRowExpand=function(){b.transientState.expandedRows[d]=b.rowIsExpanded=!b.transientState.expandedRows[d],b.transientState.expandedRows[d]?b.refreshExpandedHeight(!1):(delete b.transientState.expandedRows[d],delete b.transientState.expandedRowHeights[d])},b.refreshExpandedHeight=function(e){a(function(){var a=c.next("tr.ap-mesa-expand-panel").height();b.transientState.expandedRowHeights[d]=a})},b.$watch("transientState.expandedRows",function(a,c){a!==c&&(b.rowIsExpanded=!1)})}}}]),angular.module("apMesa.directives.apMesaRows",["apMesa.directives.apMesaRow","apMesa.filters.apMesaRowFilter","apMesa.filters.apMesaRowSorter","apMesa.services.apMesaDebounce"]).directive("apMesaRows",["$filter","$timeout","apMesaDebounce","$rootScope",function(a,b,c,d){function e(a){if(!a.rows||!a.columns)return[];var b,c;if(b=g(a.rows,a.columns,a.persistentState,a.transientState,a.options),b=h(b,a.columns,a.persistentState.sortOrder,a.options,a.transientState),"SCROLL"===a.options.pagingStrategy)b=i(b,Math.floor(a.transientState.rowOffset)-a.transientState.filterCount),b=i(b,a.persistentState.rowLimit+Math.ceil(a.transientState.rowOffset%1)),c=a.transientState.rowOffset;else if("PAGINATE"===a.options.pagingStrategy){var e=a.transientState.pageOffset*a.persistentState.rowLimit;b=b.slice(e,e+a.persistentState.rowLimit),c=e}b.forEach(function(a){a.$$$index=c++}),a.visible_rows=b,d.$broadcast("angular-mesa:update-dummy-rows")}function f(a){var b=function(b,c){b!==c&&(a.options.getData?j(a):e(a),a.transientState.expandedRows={})},c=function(b,c){b!==c&&(a.options.getData?j(a):e(a))};a.$watch("persistentState.searchTerms",function(c,d){angular.equals(c,d)||a.resetOffset(),b(c,d)},!0),a.$watch("persistentState.sortOrder",function(c,d){angular.equals(c,d)||a.resetOffset(),b(c,d)},!0),a.$watch("transientState.rowOffset",function(b,d){"SCROLL"===a.options.pagingStrategy&&c(b,d)}),a.$watch("persistentState.rowLimit",function(b,d){a.options.getData&&a.transientState.rowHeightIsCalculated||c(b,d)}),a.$watch("transientState.pageOffset",function(a,b){c(a,b)}),a.$watch("transientState.filterCount",function(c,d){a.options.getData||b(c,d)}),a.$watch("rows",function(a){angular.isArray(a)&&b(!0,!1)}),a.$watch("options.getData",function(a){angular.isFunction(a)&&b(!0,!1)})}var g=a("apMesaRowFilter"),h=a("apMesaRowSorter"),i=a("limitTo"),j=c(function(a){var b;"SCROLL"===a.options.pagingStrategy?b=a.transientState.rowOffset:"PAGINATE"===a.options.pagingStrategy&&(b=a.transientState.pageOffset*a.persistentState.rowLimit);var c=a.persistentState.searchTerms,e=a.columns.filter(function(a){return!!c[a.id]}).map(function(a){return{column:a,value:c[a.id]}}),f=a.persistentState.sortOrder.map(function(b){return{column:a.transientState.columnLookup[b.id],direction:"+"===b.dir?"ASC":"DESC"}});a.transientState.loadingError=!1,a.api.setLoading(!0);var g=a.transientState.getDataPromise=a.options.getData(b,a.persistentState.rowLimit,e,f).then(function(c){if(g===a.transientState.getDataPromise){var e=c.total,f=c.rows,h=b;a.transientState.rowOffset=b,a.transientState.filterCount=e,a.visible_rows=f,f.forEach(function(a){a.$$$index=h++}),a.transientState.getDataPromise=null,a.api.setLoading(!1),d.$broadcast("angular-mesa:update-dummy-rows")}},function(b){a.transientState.getDataPromise=null,a.transientState.loadingError=!0,a.api.setLoading(!1)})},200,{leading:!1,trailing:!0});return{restrict:"A",templateUrl:"src/templates/apMesaRows.tpl.html",compile:function(a,b){var c=a.find("tr[ng-repeat-start]"),d=c.attr("ng-repeat-start");return d+=b.trackBy?" track by row[options.trackBy]":" track by row.$$$index",c.attr("ng-repeat-start",d),f}}}]),angular.module("apMesa.directives.apMesaSelector",[]).directive("apMesaSelector",function(){return{restrict:"A",scope:!1,link:function(a,b){var c=a.selected,d=a.row,e=a.column;b.on("click",function(){var b=c.indexOf(e.selectObject?d:d[e.key]);b>=0?c.splice(b,1):c.push(e.selectObject?d:d[e.key]),a.$apply()})}}}),angular.module("apMesa.directives.apMesaStatusDisplay",[]).directive("apMesaStatusDisplay",function(){return{replace:!0,templateUrl:"src/templates/apMesaStatusDisplay.tpl.html"}}),angular.module("apMesa.directives.apMesaThTitle",[]).directive("apMesaThTitle",["$compile",function(a){function b(b,c){var d=b.column,e="<span>{{ column.id }}</span>";angular.isString(d.labelTemplateUrl)?e="<span ng-include=\"'"+d.labelTemplateUrl+"'\"></span>":angular.isString(d.labelTemplate)?e="<span>"+d.labelTemplate+"</span>":angular.isString(d.label)&&(e="<span>{{ column.label }}</span>"),c.html(e),a(c.contents())(b)}return{link:b}}]),angular.module("apMesa.filters.apMesaRowFilter",["apMesa.services.apMesaFilterFunctions"]).filter("apMesaRowFilter",["apMesaFilterFunctions","$log",function(a,b){return function(c,d,e,f,g){var h,i=c;return h=d.filter(function(c){var d=e.searchTerms[c.id];if("string"==typeof d){if(!d.trim())return!1;if("function"==typeof c.filter)return!0;var f=a[c.filter];if("function"==typeof f)return c.filter=f,!0;b.warn('apMesa: The filter function "'+c.filter+'" specified by column(id='+c.id+').filter was not found in predefined tableFilterFunctions. Available filters: "'+Object.keys(a).join('","')+'"')}return!1}),h.length&&(i=c.filter(function(a){for(var b=h.length-1;b>=0;b--){var c=h[b],d=c.filter,f=e.searchTerms[c.id],i=void 0!==g&&{}.hasOwnProperty.call(g,"getter")?g.getter(c.key,a):a[c.key],j="function"==typeof c.format?c.format(i,a,c,g):i;if(!d(f,i,j,a,c,g))return!1}return!0})),f.filterCount=i.length,i}}]),angular.module("apMesa.filters.apMesaRowSorter",[]).filter("apMesaRowSorter",function(){return function(a,b,c,d,e){if(!c.length)return a;for(var f=[],g=0;g<a.length;g++)f.push(a[g]);return f.sort(function(a,b){for(var f=0;f<c.length;f++){var g=c[f],h=e.columnLookup[g.id],i=g.dir;if(h&&h.sort){var j=h.sort,k="+"===i?j(a,b,d,h):j(b,a,d,h);if(0!==k)return k}}return 0})}}),angular.module("apMesa.services.apMesaDebounce",[]).factory("apMesaDebounce",["$timeout",function(a){function b(b,d,e){function h(a){var c=q,d=r;return q=r=void 0,z=a,w=b.apply(d,c)}function i(b){return z=b,x=a(l,d),A?h(b):w}function j(a){var b=a-y,c=a-z,e=d-b;return B?u(e,s-c):e}function k(a){var b=a-y,c=a-z;return void 0===y||b>=d||0>b||B&&c>=s}function l(){var b=v();return k(b)?m(b):void(x=a(l,j(b)))}function m(a){return x=void 0,C&&q?h(a):(q=r=void 0,w)}function n(){void 0!==x&&a.cancel(x),z=0,q=y=r=x=void 0}function o(){return void 0===x?w:m(v())}function p(){var b=v(),c=k(b);if(q=arguments,r=this,y=b,c){if(void 0===x)return i(y);if(B)return x=a(l,d),h(y)}return void 0===x&&(x=a(l,d)),w}var q,r,s,w,x,y,z=0,A=!1,B=!1,C=!0;if("function"!=typeof b)throw new TypeError(g);return d=f(d)||0,c(e)&&(A=!!e.leading,B="maxWait"in e,s=B?t(f(e.maxWait)||0,d):s,C="trailing"in e?!!e.trailing:C),p.cancel=n,p.flush=o,p}function c(a){var b=typeof a;return!!a&&("object"==b||"function"==b)}function d(a){return!!a&&"object"==typeof a}function e(a){return"symbol"==typeof a||d(a)&&s.call(a)==i}function f(a){if("number"==typeof a)return a;if(e(a))return h;if(c(a)){var b="function"==typeof a.valueOf?a.valueOf():a;a=c(b)?b+"":b}if("string"!=typeof a)return 0===a?a:+a;a=a.replace(j,"");var d=l.test(a);return d||m.test(a)?n(a.slice(2),d?2:8):k.test(a)?h:+a}var g="Expected a function",h=NaN,i="[object Symbol]",j=/^\s+|\s+$/g,k=/^[-+]0x[0-9a-f]+$/i,l=/^0b[01]+$/i,m=/^0o[0-7]+$/i,n=parseInt,o="object"==typeof global&&global&&global.Object===Object&&global,p="object"==typeof self&&self&&self.Object===Object&&self,q=o||p||Function("return this")(),r=Object.prototype,s=r.toString,t=Math.max,u=Math.min,v=function(){return q.Date.now()};return b}]),angular.module("apMesa.services.apMesaFilterFunctions",[]).service("apMesaFilterFunctions",function(){function a(a,b){a=a.toLowerCase().trim(),b=String(b).toLowerCase();var c=a[0];return"!"===c?(a=a.substr(1),""===a?!0:-1===b.indexOf(a)):"="===c?(a=a.substr(1),a===b.trim()):(a=a.replace("\\!","!"),a=a.replace("\\=","="),-1!==b.indexOf(a))}function b(b,c,d,e){return a(b,d,d,e)}function c(a,b){b=parseFloat(b),a=a.trim();var c=a.substr(0,2),d=a[0],e=1*a.substr(1),f=1*a.substr(2);return"<="===c?f>=b:">="===c?b>=f:"<"===d?e>b:">"===d?b>e:"~"===d?Math.round(b)===e:"="===d?e===b:b.toString().indexOf(a.toString())>-1}function d(a,b,d){return c(a,d)}function e(a){for(var b=a.trim().split(","),c=0,d=0;d<b.length;d++){var e=b[d].trim(),f=h.exec(e);if(f){var i=1*f[1],j=f[2].replace(/s$/,"");g.hasOwnProperty(j)&&(c+=i*g[j])}}return c}function f(a,b){if(a=a.trim(),!a)return!0;b*=1;var c,d,f=new Date,h=+f,i=a[0],j=a.substr(1).trim();if("<"===i)return c=h-e(j),b>c;if(">"===i)return d=h-e(j),d>b;if("today"===a)return new Date(b).toDateString()===f.toDateString();if("yesterday"===a)return new Date(b).toDateString()===new Date(h-g.d).toDateString();var k=new Date(a);return isNaN(k)?!1:new Date(b).toDateString()===k.toDateString()}a.placeholder=b.placeholder="string search",a.title=b.title='Search by text, eg. "foo". Use "!" to exclude and "=" to match exact text, e.g. "!bar" or "=baz".',c.placeholder=d.placeholder="number search",c.title=d.title='Search by number, e.g. "123". Optionally use comparator expressions like ">=10" or "<1000". Use "~" for approx. int values, eg. "~3" will match "3.2"';var g={};g.second=g.sec=g.s=1e3,g.minute=g.min=g.m=60*g.second,g.hour=g.hr=g.h=60*g.minute,g.day=g.d=24*g.hour,g.week=g.wk=g.w=7*g.day,g.month=4*g.week,g.year=g.yr=g.y=365*g.day;var h=/(\d+(?:\.\d+)?)\s*([a-z]+)/;return f.placeholder="date search",f.title='Search by date. Enter a date string (RFC2822 or ISO 8601 date). You can also type "today", "yesterday", "> 2 days ago", "< 1 day 2 hours ago", etc.',{like:a,likeFormatted:b,number:c,numberFormatted:d,date:f}}),angular.module("apMesa.services.apMesaFormatFunctions",[]).service("apMesaFormatFunctions",function(){return{}}),angular.module("apMesa.services.apMesaSortFunctions",[]).service("apMesaSortFunctions",function(){return{number:function(a){return function(b,c,d){var e,f;return void 0!==d&&{}.hasOwnProperty.call(d,"getter")?(e=d.getter(a,b),f=d.getter(a,c)):(e=b[a],f=c[a]),1*e-1*f}},string:function(a){return function(b,c,d){var e,f;return void 0!==d&&{}.hasOwnProperty.call(d,"getter")?(e=d.getter(a,b),f=d.getter(a,c)):(e=b[a],f=c[a]),e.toString().toLowerCase().localeCompare(f.toString().toLowerCase())}},stringFormatted:function(a){return function(b,c,d,e){var f,g;return void 0!==d&&{}.hasOwnProperty.call(d,"getter")?(f=d.getter(a,b),g=d.getter(a,c)):(f=b[a],g=c[a]),f=e.format(f,b,e),g=e.format(g,c,e),f.toString().toLowerCase().localeCompare(g.toString().toLowerCase())}},numberFormatted:function(a){return function(b,c,d,e){var f,g;return void 0!==d&&{}.hasOwnProperty.call(d,"getter")?(f=d.getter(a,b),g=d.getter(a,c)):(f=b[a],g=c[a]),f=e.format(f,b,e),g=e.format(g,c,e),1*f-1*g}}}}),angular.module("apMesa.templates",["src/templates/apMesa.tpl.html","src/templates/apMesaDummyRows.tpl.html","src/templates/apMesaPaginationCtrls.tpl.html","src/templates/apMesaRows.tpl.html","src/templates/apMesaStatusDisplay.tpl.html"]),angular.module("src/templates/apMesa.tpl.html",[]).run(["$templateCache",function(a){a.put("src/templates/apMesa.tpl.html","<div class=\"ap-mesa-wrapper\" ng-class=\"{\n'paging-strategy-paginate': options.pagingStrategy === 'PAGINATE',\n'paging-strategy-scroll': options.pagingStrategy === 'SCROLL'\n}\">\n"+' <table ng-class="classes" class="ap-mesa mesa-header-table">\n <thead>\n <tr ui-sortable="sortableOptions" ng-model="columns">\n <th\n scope="col"\n ng-repeat="column in columns"\n ng-click="toggleSort($event,column)"\n ng-class="{\'sortable-column\' : column.sort, \'select-column\': column.selector, \'is-sorting\': sortDirection[column.id] }"\n ng-attr-title="{{ column.title || \'\' }}"\n ng-style="{ width: column.width, \'min-width\': column.width, \'max-width\': column.width }"\n >\n <span class="column-text">\n <input ng-if="column.selector" type="checkbox" ng-checked="isSelectedAll()" ng-click="toggleSelectAll($event)" />\n <span\n ng-if="column.sort"\n title="This column is sortable. Click to toggle sort order. Hold shift while clicking multiple columns to stack sorting."\n class="sorting-icon {{ getSortClass( sortDirection[column.id] ) }}"\n ></span>\n <span ap-mesa-th-title></span>\n </span>\n <span\n ng-if="!column.lockWidth"\n ng-class="{\'discreet-width\': !!column.width, \'column-resizer\': true}"\n title="Click and drag to set discreet width. Click once to clear discreet width."\n ng-mousedown="startColumnResize($event, column)"\n >\n \n </span>\n </th>\n </tr>\n <tr ng-if="hasFilterFields()" class="ap-mesa-filter-row">\n <td ng-repeat="column in columns" ng-class="\'column-\' + column.id">\n <input\n type="text"\n ng-if="(column.filter)"\n ng-model="persistentState.searchTerms[column.id]"\n ng-attr-placeholder="{{ column.filterPlaceholder ? column.filterPlaceholder : (column.filter.placeholder || \'filter\') }}"\n ng-attr-title="{{ column.filter && column.filter.title }}"\n ng-class="{\'active\': persistentState.searchTerms[column.id] }"\n >\n <button\n ng-if="(column.filter)"\n ng-show="persistentState.searchTerms[column.id]"\n class="clear-search-btn"\n role="button"\n type="button"\n ng-click="clearAndFocusSearch(column.id)"\n >\n ×\n </button>\n\n </td>\n </tr>\n </thead>\n </table>\n <div ap-mesa-status-display></div>\n <div class="mesa-rows-table-wrapper" ng-style="tbodyNgStyle" ng-hide="transientState.loadingError">\n <table ng-class="classes" class="ap-mesa mesa-rows-table">\n <thead>\n <th\n scope="col"\n ng-repeat="column in columns"\n ng-style="{ width: column.width, \'min-width\': column.width, \'max-width\': column.width }"\n ></th>\n </tr>\n </thead>\n <tbody ng-if="options.pagingStrategy === \'SCROLL\'" ap-mesa-dummy-rows="[0,transientState.rowOffset]" columns="columns" cell-content="..."></tbody>\n <tbody ap-mesa-rows class="ap-mesa-rendered-rows"></tbody>\n <tbody ng-if="options.pagingStrategy === \'SCROLL\'" ap-mesa-dummy-rows="[transientState.rowOffset + visible_rows.length, transientState.filterCount]" columns="columns" cell-content="..."></tbody>\n </table>\n </div>\n <div class="ap-mesa-pagination" ng-if="options.pagingStrategy === \'PAGINATE\'" ap-mesa-pagination-ctrls></div>\n</div>\n')}]),angular.module("src/templates/apMesaDummyRows.tpl.html",[]).run(["$templateCache",function(a){a.put("src/templates/apMesaDummyRows.tpl.html","")}]),angular.module("src/templates/apMesaPaginationCtrls.tpl.html",[]).run(["$templateCache",function(a){a.put("src/templates/apMesaPaginationCtrls.tpl.html",'<ul class="pagination" ng-if="lastPage > 0">\n <li ng-class="{ \'disabled\': transientState.pageOffset === 0 }">\n <a ng-click="goBack()" >«</a>\n </li>\n <li ng-repeat="link in pageLinks" ng-class="{ \'active\': link.current, \'disabled\': link.gap }">\n <a ng-if="!link.gap" ng-click="transientState.pageOffset = link.page">{{ link.page + 1 }}</a>\n <a ng-if="link.gap" href="">…</a>\n </li>\n <li ng-class="{ \'disabled\': transientState.pageOffset === lastPage }">\n <a ng-click="goForward()" >»</a>\n </li>\n</ul>\n<span class="rows-per-page-ctrl">\n <span class="rows-per-page-msg">{{ options.rowsPerPageMessage }}</span>\n <ul class="pagination" ng-if="options.showRowsPerPageCtrls">\n <li ng-repeat="limit in options.rowsPerPageChoices" ng-class="{\'active\': options.rowsPerPage === limit}">\n <a ng-click="options.rowsPerPage = limit">{{ limit }}</a>\n </li>\n </ul>\n</span>\n')}]),angular.module("src/templates/apMesaRows.tpl.html",[]).run(["$templateCache",function(a){a.put("src/templates/apMesaRows.tpl.html",'<tr ng-repeat-start="row in visible_rows" ng-attr-class="{{ (transientState.rowOffset + $index) % 2 ? \'odd\' : \'even\' }}" ap-mesa-row></tr>\n<tr ng-repeat-end ng-if="rowIsExpanded" class="ap-mesa-expand-panel">\n <td ap-mesa-expandable ng-attr-colspan="{{ columns.length }}"></td>\n</tr>\n')}]),angular.module("src/templates/apMesaStatusDisplay.tpl.html",[]).run(["$templateCache",function(a){a.put("src/templates/apMesaStatusDisplay.tpl.html",'<div class="ap-mesa-status-display-wrapper" ng-class="{\n loading: transientState.loading,\n error: transientState.loadingError,\n \'has-rows\': visible_rows.length && !transientState.loadingError\n}">\n\n <!-- LOADING -->\n <div ng-if="transientState.loading" class="ap-mesa-loading-display">\n \n <!-- user-provided -->\n <div ng-if="options.loadingTemplateUrl" ng-include="options.loadingTemplateUrl"></div>\n <div ng-if="options.loadingText">{{ options.loadingText }}</div>\n \n <!-- default -->\n <div ng-if="!options.asyncLoadingTemplateUrl && !options.asyncLoadingTemplate" class="ap-mesa-status-display">\n <div class="ap-mesa-status-display-inner"></div>\n </div>\n\n </div>\n \n <!-- ERROR -->\n <div ng-if="transientState.loadingError" class="ap-mesa-error-display">\n <div ng-if="options.loadingErrorTemplateUrl" ng-include="options.loadingErrorTemplateUrl"></div>\n <div ng-if="options.loadingErrorText">{{ options.loadingErrorText }}</div>\n <div ng-if="!options.loadingErrorTemplateUrl && !options.loadingErrorText" class="ap-mesa-error-display-inner">An error occurred.</div>\n </div>\n\n <!-- NO DATA -->\n <div ng-if="!transientState.loading && !transientState.loadingError && visible_rows.length === 0" class="ap-mesa-no-data-display">\n <div ng-if="options.noRowsTemplateUrl" ng-include="options.noRowsTemplateUrl"></div>\n <div ng-if="!options.noRowsTemplateUrl">{{ options.noRowsText }}</div>\n </div>\n</div>'); | ||
}]); |
{ | ||
"name": "angular-mesa", | ||
"version": "2.9.3", | ||
"version": "2.10.0", | ||
"license": "Apache License, v2.0", | ||
@@ -5,0 +5,0 @@ "dependencies": {}, |
@@ -15,2 +15,3 @@ angular-mesa | ||
- pagination | ||
- server-side interaction support | ||
@@ -102,2 +103,3 @@ Installation | ||
| maxPageLinks | `number` | 8 | Number of page links to display when paginating. | | ||
| getData | `function` | undefined | Specify a function which returns a promise of row data. See *Server-side Interaction* below. | | ||
@@ -166,2 +168,3 @@ The options object is also the correct place to pass arbitrary data to table cell templates because it will be available as `options` in the table cell template scope. For example, if you want a click in a cell to call a function that is | ||
| filter | `function` or `string` | no | undefined | If specified, defines row filter function this column uses. See *Row Filtering* below. | | ||
| filterPlaceholder | `string` | no | 'filter' | If specified, defines the placeholder text for the filter input. See *Row Filtering* below. | | ||
| format | `function` or `string` | no | '' | If specified, defines cell format function. See the *Cell Formatting* section below. | | ||
@@ -325,2 +328,43 @@ | width | `string` or `number` | no | 'auto' | width of column, can include units, e.g. '30px' | | ||
Server-side Interaction | ||
----------------------- | ||
You have the option to specify a `getData` function on your table options object which will enable server-side interaction. It must implement the following function signature (see inline explanation): | ||
```javascript | ||
function getData (offset, limit, activeFilters, activeSorts) { | ||
// offset and limit are numbers, indicating the subset of the total | ||
// result set, given the filter and sort states | ||
// activeFilters is an array of objects, each containing the string that the user has entered into the | ||
// filter text input, as well as the corresponding column definition object, e.g.: | ||
// [ | ||
// { value: 'im typing', column: [COLUMN DEF OBJECT] }, | ||
// { value: 'me too thanks', column: [COLUMN DEF OBJECT] }, | ||
// ] | ||
// Note that columns whose filter inputs are empty will not show up here. | ||
// activeSorts is an array of objects similar to activeFilters, except that instead of `value` field | ||
// there is a `direction` field that will either be 'ASC' or 'DESC'. Note that the order of this | ||
// array reflects the order that the user chose to sort columns on (stacked sorting). | ||
// This function should return a promise that resolves with an object that looks like this: | ||
// { | ||
// total: [NUMBER OF TOTAL ROWS BEFORE LIMIT], | ||
// rows: [ARRAY OF ROWS FOR GIVEN OFFSET, LIMIT, SORT, FILTERS] | ||
// } | ||
} | ||
``` | ||
Note that when `getData` is specified, angular-mesa only checks the `filter` and `sort` fields in the column definition objects for "truthiness".It does not perform any sort of sorting and filtering itself; that is left up to the server to do. | ||
Also note that the `angular-mesa.d.ts` typescript definition file has a more formal signature for this function that may help if you are familiar with TS. | ||
Browser Support | ||
@@ -327,0 +371,0 @@ --------------- |
@@ -188,2 +188,3 @@ /* | ||
$scope.setColumns = function(columns) { | ||
try { | ||
$scope.columns = columns; | ||
@@ -217,40 +218,45 @@ $scope.columns.forEach(function(column) { | ||
// sort | ||
var sort = column.sort; | ||
if (typeof sort !== 'function') { | ||
if (typeof sort === 'string') { | ||
if (typeof sorts[sort] === 'function') { | ||
column.sort = sorts[sort](column.key); | ||
} | ||
else { | ||
if (!$scope.options.getData) { | ||
// sort | ||
var sort = column.sort; | ||
if (typeof sort !== 'function') { | ||
if (typeof sort === 'string') { | ||
if (typeof sorts[sort] === 'function') { | ||
column.sort = sorts[sort](column.key); | ||
} | ||
else { | ||
delete column.sort; | ||
$log.warn('sort function reference in column(id=' + column.id + ') ' + | ||
'was not found in built-in sort functions. ' + | ||
'sort function given: "' + sort + '". ' + | ||
'Available built-ins: ' + Object.keys(sorts).join(',') + '. '); | ||
} | ||
} else { | ||
delete column.sort; | ||
$log.warn('sort function reference in column(id=' + column.id + ') ' + | ||
'was not found in built-in sort functions. ' + | ||
'sort function given: "' + sort + '". ' + | ||
'Available built-ins: ' + Object.keys(sorts).join(',') + '. '); | ||
} | ||
} else { | ||
delete column.sort; | ||
} | ||
} | ||
// filter | ||
var filter = column.filter; | ||
if (typeof filter !== 'function') { | ||
if (typeof filter === 'string') { | ||
if (typeof filters[filter] === 'function') { | ||
column.filter = filters[filter]; | ||
} | ||
else { | ||
// filter | ||
var filter = column.filter; | ||
if (typeof filter !== 'function') { | ||
if (typeof filter === 'string') { | ||
if (typeof filters[filter] === 'function') { | ||
column.filter = filters[filter]; | ||
} | ||
else { | ||
delete column.filter; | ||
$log.warn('filter function reference in column(id=' + column.id + ') ' + | ||
'was not found in built-in filter functions. ' + | ||
'filter function given: "' + filter + '". ' + | ||
'Available built-ins: ' + Object.keys(filters).join(',') + '. '); | ||
} | ||
} else { | ||
delete column.filter; | ||
$log.warn('filter function reference in column(id=' + column.id + ') ' + | ||
'was not found in built-in filter functions. ' + | ||
'filter function given: "' + filter + '". ' + | ||
'Available built-ins: ' + Object.keys(filters).join(',') + '. '); | ||
} | ||
} else { | ||
delete column.filter; | ||
} | ||
} | ||
}); | ||
} catch (e) { | ||
console.log(e.message); | ||
} | ||
}; | ||
@@ -257,0 +263,0 @@ |
@@ -12,5 +12,4 @@ (function() { | ||
scrollDivisor: 1, | ||
loadingText: 'loading', | ||
loadingError: false, | ||
noRowsText: 'no rows', | ||
loadingText: undefined, | ||
noRowsText: 'No data.', | ||
pagingStrategy: 'SCROLL', | ||
@@ -53,3 +52,5 @@ rowsPerPage: 10, // for when pagingStrategy === 'PAGINATE' | ||
'apMesa.directives.apMesaPaginationCtrls', | ||
'apMesa.directives.apMesaThTitle' | ||
'apMesa.directives.apMesaStatusDisplay', | ||
'apMesa.directives.apMesaThTitle', | ||
'apMesa.services.apMesaDebounce' | ||
]) | ||
@@ -71,40 +72,4 @@ .provider('apMesa', function ApMesaService() { | ||
}) | ||
.directive('apMesa', ['$log', '$timeout', '$q', 'apMesa', function ($log, $timeout, $q, apMesa) { | ||
.directive('apMesa', ['$log', '$timeout', '$q', 'apMesa', 'apMesaDebounce', function ($log, $timeout, $q, apMesa, debounce) { | ||
function debounce(func, wait, immediate) { | ||
var timeout, args, context, timestamp, result; | ||
var later = function() { | ||
var last = Date.now() - timestamp; | ||
if (last < wait && last > 0) { | ||
timeout = $timeout(later, wait - last); | ||
} else { | ||
timeout = null; | ||
if (!immediate) { | ||
result = func.apply(context, args); | ||
if (!timeout) { | ||
context = args = null; | ||
} | ||
} | ||
} | ||
}; | ||
return function() { | ||
context = this; | ||
args = arguments; | ||
timestamp = Date.now(); | ||
var callNow = immediate && !timeout; | ||
if (!timeout) { | ||
timeout = $timeout(later, wait); | ||
} | ||
if (callNow) { | ||
result = func.apply(context, args); | ||
context = args = null; | ||
} | ||
return result; | ||
}; | ||
} | ||
function resetState(scope) { | ||
@@ -124,4 +89,4 @@ | ||
// Holds filtered rows count | ||
scope.transientState = { | ||
rowHeightIsCalculated: false, | ||
filterCount: scope.rows ? scope.rows.length : 0, | ||
@@ -131,5 +96,15 @@ rowOffset: 0, | ||
expandedRows: {}, | ||
expandedRowHeights: {} | ||
expandedRowHeights: {}, | ||
columnLookup: {}, | ||
loadingError: null, | ||
loading: false | ||
}; | ||
if (scope.columns.length) { | ||
var lookup = scope.transientState.columnLookup; | ||
scope.columns.forEach(function(column) { | ||
lookup[column.id] = column; | ||
}); | ||
} | ||
scope.$broadcast('apMesa:stateReset'); | ||
@@ -151,2 +126,3 @@ } | ||
defaults(scope.options, trackByOverride, apMesa.getDefaultOptions()); | ||
initSorts(scope); | ||
@@ -173,5 +149,5 @@ } | ||
function preLink(scope) { | ||
initOptions(scope); | ||
resetColumns(scope); | ||
resetState(scope); | ||
initOptions(scope); | ||
} | ||
@@ -258,7 +234,10 @@ | ||
scope.api.setLoading(true); | ||
promise.then(function () { | ||
scope.options.loadingError = false; | ||
promise.then(function (data) { | ||
scope.transientState.loadingError = false; | ||
scope.api.setLoading(false); | ||
if (angular.isArray(data)) { | ||
scope.rows = data; | ||
} | ||
}, function (reason) { | ||
scope.options.loadingError = true; | ||
scope.transientState.loadingError = true; | ||
scope.api.setLoading(false); | ||
@@ -368,2 +347,5 @@ $log.warn('Failed loading table data: ' + reason); | ||
scope.rowHeight = rowHeight || scope.options.defaultRowHeight || 20; | ||
if (!scope.transientState.rowHeightIsCalculated && rowHeight) { | ||
scope.transientState.rowHeightIsCalculated = true; | ||
} | ||
if (scope.options.pagingStrategy === 'SCROLL') { | ||
@@ -376,2 +358,12 @@ scope.persistentState.rowLimit = Math.ceil((scope.options.bodyHeight + scope.options.rowPadding*2) / scope.rowHeight); | ||
scope.resetOffset = function() { | ||
if (scope.options.pagingStrategy === 'SCROLL') { | ||
scope.scrollDiv[0].scrollTop = 0; | ||
scope.transientState.rowOffset = 0; | ||
} else if (scope.options.pagingStrategy === 'PAGINATE') { | ||
scope.transientState.pageOffset = 0; | ||
scope.transientState.rowOffset = 0; | ||
} | ||
} | ||
// Wait for a render | ||
@@ -391,3 +383,3 @@ $timeout(function() { | ||
setLoading: function(isLoading, triggerDigest) { | ||
scope.options.loading = isLoading; | ||
scope.transientState.loading = isLoading; | ||
if (triggerDigest) { | ||
@@ -394,0 +386,0 @@ scope.$digest(); |
@@ -34,3 +34,4 @@ /* | ||
scope.$watch(attrs.apMesaDummyRows, function(offsetRange) { | ||
scope.$on('angular-mesa:update-dummy-rows', function() { | ||
var offsetRange = scope.$eval(attrs.apMesaDummyRows); | ||
var rowsHeight = (offsetRange[1] - offsetRange[0]) * scope.rowHeight; | ||
@@ -37,0 +38,0 @@ for (var k in scope.transientState.expandedRows) { |
@@ -21,6 +21,7 @@ /* | ||
'apMesa.filters.apMesaRowFilter', | ||
'apMesa.filters.apMesaRowSorter' | ||
'apMesa.filters.apMesaRowSorter', | ||
'apMesa.services.apMesaDebounce' | ||
]) | ||
.directive('apMesaRows', function($filter, $timeout) { | ||
.directive('apMesaRows', ['$filter', '$timeout', 'apMesaDebounce', '$rootScope', function($filter, $timeout, debounce, $rootScope) { | ||
@@ -31,3 +32,8 @@ var tableRowFilter = $filter('apMesaRowFilter'); | ||
function calculateVisibleRows(scope) { | ||
/** | ||
* Updates the visible_rows array on the scope synchronously. | ||
* @param {ng.IScope} scope The scope of the particular apMesaRows instance. | ||
* @return {void} | ||
*/ | ||
function updateVisibleRows(scope) { | ||
@@ -46,3 +52,3 @@ // sanity check | ||
// sort rows | ||
visible_rows = tableRowSorter(visible_rows, scope.columns, scope.persistentState.sortOrder, scope.options); | ||
visible_rows = tableRowSorter(visible_rows, scope.columns, scope.persistentState.sortOrder, scope.options, scope.transientState); | ||
@@ -65,5 +71,69 @@ // limit rows | ||
return visible_rows; | ||
scope.visible_rows = visible_rows; | ||
$rootScope.$broadcast('angular-mesa:update-dummy-rows'); | ||
} | ||
/** | ||
* Updates the visible_rows array on the scope asynchronously, using the options.getData function (when present). | ||
* @param {ng.IScope} scope The scope of the particular apMesaRows instance | ||
* @return {ng.IPromise} Returns the promise of the request | ||
*/ | ||
var updateVisibleRowsAsync = debounce(function(scope) { | ||
// get offset | ||
var offset; | ||
if (scope.options.pagingStrategy === 'SCROLL') { | ||
offset = scope.transientState.rowOffset; | ||
} else if (scope.options.pagingStrategy === 'PAGINATE') { | ||
offset = scope.transientState.pageOffset * scope.persistentState.rowLimit; | ||
} | ||
// get active filter | ||
var searchTerms = scope.persistentState.searchTerms; | ||
var activeFilters = scope.columns | ||
.filter(function(column) { | ||
return !! searchTerms[column.id]; | ||
}) | ||
.map(function(column) { | ||
return { column: column, value: searchTerms[column.id] }; | ||
}); | ||
// get active sorts | ||
var activeSorts = scope.persistentState.sortOrder.map(function(sortItem) { | ||
return { | ||
column: scope.transientState.columnLookup[sortItem.id], | ||
direction: sortItem.dir === '+' ? 'ASC' : 'DESC' | ||
}; | ||
}); | ||
scope.transientState.loadingError = false; | ||
scope.api.setLoading(true); | ||
var getDataPromise = scope.transientState.getDataPromise = scope.options.getData( | ||
offset, | ||
scope.persistentState.rowLimit, | ||
activeFilters, | ||
activeSorts | ||
).then(function(res) { | ||
if (getDataPromise !== scope.transientState.getDataPromise) { | ||
// new request made, cancelling this one | ||
return; | ||
} | ||
var total = res.total; | ||
var rows = res.rows; | ||
var i = offset; | ||
scope.transientState.rowOffset = offset; | ||
scope.transientState.filterCount = total; | ||
scope.visible_rows = rows; | ||
rows.forEach(function(row) { | ||
row.$$$index = i++; | ||
}); | ||
scope.transientState.getDataPromise = null; | ||
scope.api.setLoading(false); | ||
$rootScope.$broadcast('angular-mesa:update-dummy-rows'); | ||
}, function(e) { | ||
scope.transientState.getDataPromise = null; | ||
scope.transientState.loadingError = true; | ||
scope.api.setLoading(false); | ||
}); | ||
}, 200, { leading: false, trailing: true }); | ||
function link(scope) { | ||
@@ -75,3 +145,8 @@ | ||
} | ||
scope.visible_rows = calculateVisibleRows(scope); | ||
if (!scope.options.getData) { | ||
updateVisibleRows(scope); | ||
} else { | ||
updateVisibleRowsAsync(scope); | ||
} | ||
scope.transientState.expandedRows = {}; | ||
@@ -84,9 +159,42 @@ }; | ||
} | ||
scope.visible_rows = calculateVisibleRows(scope); | ||
} | ||
if (!scope.options.getData) { | ||
updateVisibleRows(scope); | ||
} else { | ||
updateVisibleRowsAsync(scope); | ||
} | ||
}; | ||
scope.$watch('persistentState.searchTerms', updateHandler, true); | ||
scope.$watch('[transientState.rowOffset, persistentState.rowLimit, transientState.pageOffset]', updateHandlerWithoutClearingCollapsed); | ||
scope.$watch('transientState.filterCount', updateHandler); | ||
scope.$watch('persistentState.sortOrder', updateHandler, true); | ||
// Watchers that trigger updates to visible rows | ||
scope.$watch('persistentState.searchTerms', function(nv, ov) { | ||
if (!angular.equals(nv, ov)) { | ||
scope.resetOffset(); | ||
} | ||
updateHandler(nv, ov); | ||
}, true); | ||
scope.$watch('persistentState.sortOrder', function(nv, ov) { | ||
if (!angular.equals(nv, ov)) { | ||
scope.resetOffset(); | ||
} | ||
updateHandler(nv, ov); | ||
}, true); | ||
scope.$watch('transientState.rowOffset', function(nv, ov) { | ||
if (scope.options.pagingStrategy === 'SCROLL') { | ||
updateHandlerWithoutClearingCollapsed(nv, ov); | ||
} | ||
}); | ||
scope.$watch('persistentState.rowLimit', function(nv, ov) { | ||
if (scope.options.getData && scope.transientState.rowHeightIsCalculated) { | ||
return; | ||
} | ||
updateHandlerWithoutClearingCollapsed(nv, ov); | ||
}); | ||
scope.$watch('transientState.pageOffset', function(nv, ov) { | ||
updateHandlerWithoutClearingCollapsed(nv, ov); | ||
}); | ||
scope.$watch('transientState.filterCount', function(nv, ov) { | ||
if (!scope.options.getData) { | ||
updateHandler(nv, ov); | ||
} | ||
}); | ||
scope.$watch('rows', function(newRows) { | ||
@@ -97,3 +205,7 @@ if (angular.isArray(newRows)) { | ||
}); | ||
updateHandler(true, false); | ||
scope.$watch('options.getData', function(getData) { | ||
if (angular.isFunction(getData)) { | ||
updateHandler(true, false); | ||
} | ||
}); | ||
} | ||
@@ -112,2 +224,2 @@ | ||
}; | ||
}); | ||
}]); |
@@ -31,3 +31,3 @@ /* | ||
var term = persistentState.searchTerms[column.id]; | ||
if (persistentState.searchTerms.hasOwnProperty(column.id) && typeof term === 'string') { | ||
if (typeof term === 'string') { | ||
@@ -34,0 +34,0 @@ // filter empty strings and whitespace |
@@ -21,15 +21,3 @@ /* | ||
.filter('apMesaRowSorter', function() { | ||
var column_cache = {}; | ||
function getColumn(columns,id) { | ||
if (column_cache.hasOwnProperty(id)) { | ||
return column_cache[id]; | ||
} | ||
for (var i = columns.length - 1; i >= 0; i--) { | ||
if (columns[i].id === id) { | ||
column_cache[id] = columns[i]; | ||
return columns[i]; | ||
} | ||
} | ||
} | ||
return function tableRowSorter(rows, columns, sortOrder, options) { | ||
return function tableRowSorter(rows, columns, sortOrder, options, transientState) { | ||
if (!sortOrder.length) { | ||
@@ -43,3 +31,3 @@ return rows; | ||
var sortItem = sortOrder[i]; | ||
var column = getColumn(columns,sortItem.id); | ||
var column = transientState.columnLookup[sortItem.id]; | ||
var dir = sortItem.dir; | ||
@@ -46,0 +34,0 @@ if (column && column.sort) { |
@@ -9,2 +9,3 @@ 'use strict'; | ||
compile, | ||
timeout, | ||
genRows, | ||
@@ -31,3 +32,3 @@ columns, | ||
beforeEach(inject(function ($compile, $rootScope) { | ||
beforeEach(inject(function ($compile, $rootScope, $timeout) { | ||
// Format functions | ||
@@ -77,2 +78,3 @@ function inches2feet(inches){ | ||
compile = $compile; | ||
timeout = $timeout; | ||
@@ -96,4 +98,11 @@ // Table columns | ||
element = compile(element)(scope); | ||
timeout.flush(); | ||
scope.$digest(); | ||
isoScope = element.isolateScope(); | ||
// for (var k in isoScope) { | ||
// if (isoScope.hasOwnProperty(k)) { | ||
// // console.log('k: ', k, 'scope[k]', isoScope[k]); | ||
// console.log(k); | ||
// } | ||
// } | ||
}; | ||
@@ -131,2 +140,3 @@ | ||
scope.my_table_data = genRows(30); | ||
timeout.flush(); | ||
scope.$apply(); | ||
@@ -133,0 +143,0 @@ var expected = scope.my_table_data[0].first_name; |
@@ -5,3 +5,3 @@ 'use strict'; | ||
var sandbox, sorter, columns, rows, numSort, numSort2, stringSort, sortOrder; | ||
var sandbox, sorter, columns, rows, numSort, numSort2, stringSort, sortOrder, transientState; | ||
@@ -36,2 +36,8 @@ beforeEach(module('apMesa')); | ||
]; | ||
transientState = { | ||
columnLookup: {} | ||
}; | ||
columns.forEach(function(column) { | ||
transientState.columnLookup[column.id] = column; | ||
}); | ||
})); | ||
@@ -48,3 +54,3 @@ | ||
it('should return all rows if no sorting is active', function() { | ||
expect(sorter(rows,columns,[],{})).to.equal(rows); | ||
expect(sorter(rows,columns,[],{}, transientState)).to.equal(rows); | ||
}); | ||
@@ -56,3 +62,3 @@ | ||
var result = sorter(rows,columns,sortOrder); | ||
var result = sorter(rows, columns, sortOrder, {}, transientState); | ||
var idxs = result.map(function(r){ return r.index; }); | ||
@@ -67,3 +73,3 @@ expect(idxs).to.eql([2,1,3,0]); | ||
var result = sorter(rows,columns,sortOrder); | ||
var result = sorter(rows,columns,sortOrder, {}, transientState); | ||
var idxs = result.map(function(r){ return r.index; }); | ||
@@ -77,3 +83,3 @@ expect(idxs).to.eql([0,1,3,2]); | ||
var result = sorter(rows,columns,sortOrder); | ||
var result = sorter(rows,columns,sortOrder, {}, transientState); | ||
var idxs = result.map(function(r){ return r.index; }); | ||
@@ -80,0 +86,0 @@ expect(idxs).to.eql([0,1,3,2]); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
754021
81
12308
0
372